Skip to content

Commit 9dc4bef

Browse files
yegappanbrammool
authored andcommitted
patch 8.2.3288: cannot easily access namespace dictionaries from Lua
Problem: Cannot easily access namespace dictionaries from Lua. Solution: Add vim.g, vim.b, etc. (Yegappan Lakshmanan, closes #8693, from NeoVim)
1 parent 5794223 commit 9dc4bef

4 files changed

Lines changed: 414 additions & 0 deletions

File tree

runtime/doc/if_lua.txt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,38 @@ Vim evaluation and command execution, and others.
211211
vim.lua_version The Lua version Vim was compiled with, in the
212212
form {major}.{minor}.{patch}, e.g. "5.1.4".
213213

214+
*lua-vim-variables*
215+
The Vim editor global dictionaries |g:| |w:| |b:| |t:| |v:| can be accessed
216+
from Lua conveniently and idiomatically by referencing the `vim.*` Lua tables
217+
described below. In this way you can easily read and modify global Vimscript
218+
variables from Lua.
219+
220+
Example: >
221+
222+
vim.g.foo = 5 -- Set the g:foo Vimscript variable.
223+
print(vim.g.foo) -- Get and print the g:foo Vimscript variable.
224+
vim.g.foo = nil -- Delete (:unlet) the Vimscript variable.
225+
226+
vim.g *vim.g*
227+
Global (|g:|) editor variables.
228+
Key with no value returns `nil`.
229+
230+
vim.b *vim.b*
231+
Buffer-scoped (|b:|) variables for the current buffer.
232+
Invalid or unset key returns `nil`.
233+
234+
vim.w *vim.w*
235+
Window-scoped (|w:|) variables for the current window.
236+
Invalid or unset key returns `nil`.
237+
238+
vim.t *vim.t*
239+
Tabpage-scoped (|t:|) variables for the current tabpage.
240+
Invalid or unset key returns `nil`.
241+
242+
vim.v *vim.v*
243+
|v:| variables.
244+
Invalid or unset key returns `nil`.
245+
214246
==============================================================================
215247
3. List userdata *lua-list*
216248

src/if_lua.c

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1777,6 +1777,122 @@ luaV_debug(lua_State *L)
17771777
}
17781778
}
17791779

1780+
static dict_T *
1781+
luaV_get_var_scope(lua_State *L)
1782+
{
1783+
const char *scope = luaL_checkstring(L, 1);
1784+
dict_T *dict = NULL;
1785+
1786+
if (STRICMP((char *)scope, "g") == 0)
1787+
dict = get_globvar_dict();
1788+
else if (STRICMP((char *)scope, "v") == 0)
1789+
dict = get_vimvar_dict();
1790+
else if (STRICMP((char *)scope, "b") == 0)
1791+
dict = curbuf->b_vars;
1792+
else if (STRICMP((char *)scope, "w") == 0)
1793+
dict = curwin->w_vars;
1794+
else if (STRICMP((char *)scope, "t") == 0)
1795+
dict = curtab->tp_vars;
1796+
else
1797+
{
1798+
luaL_error(L, "invalid scope %s", scope);
1799+
return NULL;
1800+
}
1801+
1802+
return dict;
1803+
}
1804+
1805+
static int
1806+
luaV_setvar(lua_State *L)
1807+
{
1808+
dict_T *dict;
1809+
dictitem_T *di;
1810+
size_t len;
1811+
char *name;
1812+
int del;
1813+
char *error = NULL;
1814+
1815+
name = (char *)luaL_checklstring(L, 3, &len);
1816+
del = (lua_gettop(L) < 4) || lua_isnil(L, 4);
1817+
1818+
dict = luaV_get_var_scope(L);
1819+
if (dict == NULL)
1820+
return 0;
1821+
1822+
di = dict_find(dict, (char_u *)name, len);
1823+
if (di != NULL)
1824+
{
1825+
if (di->di_flags & DI_FLAGS_RO)
1826+
error = "variable is read-only";
1827+
else if (di->di_flags & DI_FLAGS_LOCK)
1828+
error = "variable is locked";
1829+
else if (del && di->di_flags & DI_FLAGS_FIX)
1830+
error = "variable is fixed";
1831+
if (error != NULL)
1832+
return luaL_error(L, error);
1833+
}
1834+
else if (dict->dv_lock)
1835+
return luaL_error(L, "Dictionary is locked");
1836+
1837+
if (del)
1838+
{
1839+
// Delete the key
1840+
if (di == NULL)
1841+
// Doesn't exist, nothing to do
1842+
return 0;
1843+
else
1844+
// Delete the entry
1845+
dictitem_remove(dict, di);
1846+
}
1847+
else
1848+
{
1849+
// Update the key
1850+
typval_T tv;
1851+
1852+
// Convert the lua value to a vimscript type in the temporary variable
1853+
lua_pushvalue(L, 4);
1854+
if (luaV_totypval(L, -1, &tv) == FAIL)
1855+
return luaL_error(L, "Couldn't convert lua value");
1856+
1857+
if (di == NULL)
1858+
{
1859+
// Need to create an entry
1860+
di = dictitem_alloc((char_u *)name);
1861+
if (di == NULL)
1862+
return 0;
1863+
// Update the value
1864+
copy_tv(&tv, &di->di_tv);
1865+
dict_add(dict, di);
1866+
} else
1867+
{
1868+
// Clear the old value
1869+
clear_tv(&di->di_tv);
1870+
// Update the value
1871+
copy_tv(&tv, &di->di_tv);
1872+
}
1873+
1874+
// Clear the temporary variable
1875+
clear_tv(&tv);
1876+
}
1877+
1878+
return 0;
1879+
}
1880+
1881+
static int
1882+
luaV_getvar(lua_State *L)
1883+
{
1884+
dict_T *dict = luaV_get_var_scope(L);
1885+
size_t len;
1886+
const char *name = luaL_checklstring(L, 3, &len);
1887+
1888+
dictitem_T *di = dict_find(dict, (char_u *)name, len);
1889+
if (di == NULL)
1890+
return 0; // nil
1891+
1892+
luaV_pushtypval(L, &di->di_tv);
1893+
return 1;
1894+
}
1895+
17801896
static int
17811897
luaV_command(lua_State *L)
17821898
{
@@ -2103,6 +2219,8 @@ static const luaL_Reg luaV_module[] = {
21032219
{"open", luaV_open},
21042220
{"type", luaV_type},
21052221
{"call", luaV_call},
2222+
{"_getvar", luaV_getvar},
2223+
{"_setvar", luaV_setvar},
21062224
{"lua_version", NULL},
21072225
{NULL, NULL}
21082226
};
@@ -2275,6 +2393,25 @@ luaV_pushversion(lua_State *L)
22752393
" last_vim_paths = cur_vim_paths\n"\
22762394
"end"
22772395

2396+
#define LUA_VIM_SETUP_VARIABLE_DICTS \
2397+
"do\n"\
2398+
" local function make_dict_accessor(scope)\n"\
2399+
" local mt = {}\n"\
2400+
" function mt:__newindex(k, v)\n"\
2401+
" return vim._setvar(scope, 0, k, v)\n"\
2402+
" end\n"\
2403+
" function mt:__index(k)\n"\
2404+
" return vim._getvar(scope, 0, k)\n"\
2405+
" end\n"\
2406+
" return setmetatable({}, mt)\n"\
2407+
" end\n"\
2408+
" vim.g = make_dict_accessor('g')\n"\
2409+
" vim.v = make_dict_accessor('v')\n"\
2410+
" vim.b = make_dict_accessor('b')\n"\
2411+
" vim.w = make_dict_accessor('w')\n"\
2412+
" vim.t = make_dict_accessor('t')\n"\
2413+
"end"
2414+
22782415
static int
22792416
luaopen_vim(lua_State *L)
22802417
{
@@ -2335,6 +2472,7 @@ luaopen_vim(lua_State *L)
23352472
// custom code
23362473
(void)luaL_dostring(L, LUA_VIM_FN_CODE);
23372474
(void)luaL_dostring(L, LUA_VIM_UPDATE_PACKAGE_PATHS);
2475+
(void)luaL_dostring(L, LUA_VIM_SETUP_VARIABLE_DICTS);
23382476

23392477
lua_getglobal(L, "vim");
23402478
lua_getfield(L, -1, "_update_package_paths");

0 commit comments

Comments
 (0)