To: vim_dev@googlegroups.com Subject: Patch 8.2.3300 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3300 Problem: Lua: can only execute one Vim command at a time. Not easy to get the Vim version. Solution: Make vim.command() accept multiple lines. Add vim.version(). (Yegappan Lakshmanan, closes #8716) Files: runtime/doc/if_lua.txt, src/evalfunc.c, src/if_lua.c, src/proto/evalfunc.pro, src/testdir/test_lua.vim, src/testdir/test_shell.vim *** ../vim-8.2.3299/runtime/doc/if_lua.txt 2021-08-04 21:12:48.779060077 +0200 --- runtime/doc/if_lua.txt 2021-08-06 21:30:25.211652089 +0200 *************** *** 175,184 **** :lua print(type(l), vim.type(l)) :" list < ! vim.command({cmd}) Executes the vim (ex-mode) command {cmd}. Examples: > :lua vim.command"set tw=60" :lua vim.command"normal ddp" < vim.eval({expr}) Evaluates expression {expr} (see |expression|), converts the result to Lua, and returns it. --- 175,191 ---- :lua print(type(l), vim.type(l)) :" list < ! vim.command({cmds}) Executes one or more lines of Ex-mode commands ! in {cmds}. Examples: > :lua vim.command"set tw=60" :lua vim.command"normal ddp" + lua << trim END + vim.command([[ + new Myfile.js + call search('start') + ]]) + END < vim.eval({expr}) Evaluates expression {expr} (see |expression|), converts the result to Lua, and returns it. *************** *** 211,216 **** --- 218,229 ---- vim.lua_version The Lua version Vim was compiled with, in the form {major}.{minor}.{patch}, e.g. "5.1.4". + vim.version() Returns a Lua table with the Vim version. + The table will have the following keys: + major - major Vim version. + minor - minor Vim version. + patch - latest patch included. + *lua-vim-variables* The Vim editor global dictionaries |g:| |w:| |b:| |t:| |v:| can be accessed from Lua conveniently and idiomatically by referencing the `vim.*` Lua tables *** ../vim-8.2.3299/src/evalfunc.c 2021-08-05 22:48:08.524435481 +0200 --- src/evalfunc.c 2021-08-06 21:33:02.671222288 +0200 *************** *** 3365,3370 **** --- 3365,3412 ---- } /* + * Get next line from a string containing NL separated lines. + * Called by do_cmdline() to get the next line. + * Returns an allocated string, or NULL when at the end of the string. + */ + static char_u * + get_str_line( + int c UNUSED, + void *cookie, + int indent UNUSED, + getline_opt_T options UNUSED) + { + char_u *start = *(char_u **)cookie; + char_u *line; + char_u *p; + + p = start; + if (p == NULL || *p == NUL) + return NULL; + p = vim_strchr(p, '\n'); + if (p == NULL) + line = vim_strsave(start); + else + { + line = vim_strnsave(start, p - start); + p++; + } + + *(char_u **)cookie = p; + return line; + } + + /* + * Execute a series of Ex commands in 'str' + */ + void + execute_cmds_from_string(char_u *str) + { + do_cmdline(NULL, get_str_line, (void *)&str, + DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT|DOCMD_KEYTYPED); + } + + /* * Get next line from a list. * Called by do_cmdline() to get the next line. * Returns allocated string, or NULL for end of function. *** ../vim-8.2.3299/src/if_lua.c 2021-08-05 16:46:56.391218826 +0200 --- src/if_lua.c 2021-08-06 21:33:41.975115276 +0200 *************** *** 10,15 **** --- 10,16 ---- */ #include "vim.h" + #include "version.h" #include #include *************** *** 191,196 **** --- 192,198 ---- #define lua_rawget dll_lua_rawget #define lua_rawgeti dll_lua_rawgeti #define lua_createtable dll_lua_createtable + #define lua_settable dll_lua_settable #if LUA_VERSION_NUM >= 504 #define lua_newuserdatauv dll_lua_newuserdatauv #else *************** *** 302,307 **** --- 304,310 ---- int (*dll_lua_rawgeti) (lua_State *L, int idx, lua_Integer n); #endif void (*dll_lua_createtable) (lua_State *L, int narr, int nrec); + void (*dll_lua_settable) (lua_State *L, int idx); #if LUA_VERSION_NUM >= 504 void *(*dll_lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue); #else *************** *** 413,418 **** --- 416,422 ---- {"lua_rawget", (luaV_function) &dll_lua_rawget}, {"lua_rawgeti", (luaV_function) &dll_lua_rawgeti}, {"lua_createtable", (luaV_function) &dll_lua_createtable}, + {"lua_settable", (luaV_function) &dll_lua_settable}, #if LUA_VERSION_NUM >= 504 {"lua_newuserdatauv", (luaV_function) &dll_lua_newuserdatauv}, #else *************** *** 1819,1825 **** if (dict == NULL) return 0; ! di = dict_find(dict, (char_u *)name, len); if (di != NULL) { if (di->di_flags & DI_FLAGS_RO) --- 1823,1829 ---- if (dict == NULL) return 0; ! di = dict_find(dict, (char_u *)name, (int)len); if (di != NULL) { if (di->di_flags & DI_FLAGS_RO) *************** *** 1893,1900 **** dict_T *dict = luaV_get_var_scope(L); size_t len; const char *name = luaL_checklstring(L, 3, &len); - dictitem_T *di = dict_find(dict, (char_u *)name, len); if (di == NULL) return 0; // nil --- 1897,1904 ---- dict_T *dict = luaV_get_var_scope(L); size_t len; const char *name = luaL_checklstring(L, 3, &len); + dictitem_T *di = dict_find(dict, (char_u *)name, (int)len); if (di == NULL) return 0; // nil *************** *** 1905,1911 **** static int luaV_command(lua_State *L) { ! do_cmdline_cmd((char_u *) luaL_checkstring(L, 1)); update_screen(VALID); return 0; } --- 1909,1918 ---- static int luaV_command(lua_State *L) { ! char_u *s = vim_strsave((char_u *)luaL_checkstring(L, 1)); ! ! execute_cmds_from_string(s); ! vim_free(s); update_screen(VALID); return 0; } *************** *** 1914,1919 **** --- 1921,1927 ---- luaV_eval(lua_State *L) { typval_T *tv = eval_expr((char_u *) luaL_checkstring(L, 1), NULL); + if (tv == NULL) luaL_error(L, "invalid expression"); luaV_pushtypval(L, tv); free_tv(tv); *************** *** 2214,2219 **** --- 2222,2246 ---- return luaL_error(L, error); } + /* + * Return the Vim version as a Lua table + */ + static int + luaV_version(lua_State *L) + { + lua_newtable(L); + lua_pushstring(L, "major"); + lua_pushinteger(L, VIM_VERSION_MAJOR); + lua_settable(L, -3); + lua_pushstring(L, "minor"); + lua_pushinteger(L, VIM_VERSION_MINOR); + lua_settable(L, -3); + lua_pushstring(L, "patch"); + lua_pushinteger(L, highest_patch()); + lua_settable(L, -3); + return 1; + } + static const luaL_Reg luaV_module[] = { {"command", luaV_command}, {"eval", luaV_eval}, *************** *** 2230,2235 **** --- 2257,2263 ---- {"call", luaV_call}, {"_getvar", luaV_getvar}, {"_setvar", luaV_setvar}, + {"version", luaV_version}, {"lua_version", NULL}, {NULL, NULL} }; *** ../vim-8.2.3299/src/proto/evalfunc.pro 2021-08-02 20:06:44.351011164 +0200 --- src/proto/evalfunc.pro 2021-08-06 21:21:10.005197889 +0200 *************** *** 17,22 **** --- 17,23 ---- buf_T *get_buf_arg(typval_T *arg); win_T *get_optional_window(typval_T *argvars, int idx); void execute_redir_str(char_u *value, int value_len); + void execute_cmds_from_string(char_u *str); void execute_common(typval_T *argvars, typval_T *rettv, int arg_off); void f_exists(typval_T *argvars, typval_T *rettv); void f_has(typval_T *argvars, typval_T *rettv); *** ../vim-8.2.3299/src/testdir/test_lua.vim 2021-08-05 15:11:04.577422906 +0200 --- src/testdir/test_lua.vim 2021-08-06 21:21:10.005197889 +0200 *************** *** 1162,1165 **** --- 1162,1197 ---- %bw! endfunc + " Test for vim.version() + func Test_lua_vim_version() + lua << trim END + vimver = vim.version() + vimver_n = vimver.major * 100 + vimver.minor + END + call assert_equal(v:version, luaeval('vimver_n')) + endfunc + + " Test for running multiple commands using vim.command() + func Test_lua_multiple_commands() + lua << trim END + vim.command([[ + let Var1 = [] + for i in range(3) + let Var1 += [#{name: 'x'}] + endfor + augroup Luagroup + autocmd! + autocmd User Luatest echo 'Hello' + augroup END + ]]) + END + call assert_equal([{'name': 'x'}, {'name': 'x'}, {'name': 'x'}], Var1) + call assert_true(exists('#Luagroup')) + call assert_true(exists('#Luagroup#User#Luatest')) + augroup Luagroup + autocmd! + augroup END + augroup! Luagroup + endfunc + " vim: shiftwidth=2 sts=2 expandtab *** ../vim-8.2.3299/src/testdir/test_shell.vim 2021-06-30 20:54:30.696546341 +0200 --- src/testdir/test_shell.vim 2021-08-06 21:21:10.005197889 +0200 *************** *** 84,90 **** r !echo hello call assert_equal('hello', substitute(getline(2), '\W', '', 'g'), e[0]) catch ! call assert_report('Failed to run shell command, shell: ' .. e[0]) finally bwipe! endtry --- 84,91 ---- r !echo hello call assert_equal('hello', substitute(getline(2), '\W', '', 'g'), e[0]) catch ! call assert_report('Failed to run shell command, shell: ' .. e[0] ! \ .. ', caught ' .. v:exception) finally bwipe! endtry *** ../vim-8.2.3299/src/version.c 2021-08-05 22:48:08.528435474 +0200 --- src/version.c 2021-08-06 21:23:40.548772019 +0200 *************** *** 757,758 **** --- 757,760 ---- { /* Add new patch number below this line */ + /**/ + 3300, /**/ -- A mathematician is a device for turning coffee into theorems. Paul Erdos A computer programmer is a device for turning coffee into bugs. Bram Moolenaar /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///