@@ -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
17811897luaV_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
22792416luaopen_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