diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 433a9fc266..fecdfd9bd0 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -254,6 +254,11 @@ arguments separated by " " (space) instead of "\t" (tab). < To see the LuaJIT version: >vim :lua =jit.version < +:{range}lua + Executes the |[range]| in the current buffer as Lua code. Unlike |:source|, + this will execute the specified lines regardless of the extension or + |'filetype'| of the buffer. + *:lua-heredoc* :lua << [trim] [{endmarker}] {script} diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 2212b9910b..40717f8ecf 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -340,6 +340,9 @@ The following changes to existing APIs or features add new behavior. • |:source| without arguments treats a buffer with its 'filetype' set to "lua" as Lua code regardless of its extension. +• |:lua| with a |[range]| executes that range in the current buffer as Lua code + regardless of its extension. + • |:checkhealth| buffer now implements |folding|. The initial folding status is defined by the 'foldenable' option. diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index 551d228862..1318eda5eb 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -1612,7 +1612,7 @@ module.cmds = { }, { command = 'lua', - flags = bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, EXTRA, CMDWIN, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_lua', }, diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index f48cab6739..3139e924a1 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -1649,6 +1649,15 @@ bool nlua_is_deferred_safe(void) void ex_lua(exarg_T *const eap) FUNC_ATTR_NONNULL_ALL { + if (eap->addr_count > 0 || *eap->arg == NUL) { + if (eap->addr_count > 0 && *eap->arg == NUL) { + cmd_source_buffer(eap, true); + } else { + semsg(_(e_invarg2), "exactly one of {chunk} and {range} required"); + } + return; + } + size_t len; char *code = script_get(eap, &len); if (eap->skip || code == NULL) { diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index 3f8e467118..77a22b6fd1 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -1779,7 +1779,7 @@ freeall: static void cmd_source(char *fname, exarg_T *eap) { if (eap != NULL && *fname == NUL) { - cmd_source_buffer(eap); + cmd_source_buffer(eap, false); } else if (eap != NULL && eap->forceit) { // ":source!": read Normal mode commands // Need to execute the commands directly. This is required at least @@ -1989,7 +1989,7 @@ static int source_using_linegetter(void *cookie, LineGetter fgetline, const char return retval; } -static void cmd_source_buffer(const exarg_T *const eap) +void cmd_source_buffer(const exarg_T *const eap, bool ex_lua) FUNC_ATTR_NONNULL_ALL { if (curbuf == NULL) { @@ -2012,9 +2012,10 @@ static void cmd_source_buffer(const exarg_T *const eap) .buf = ga.ga_data, .offset = 0, }; - if (strequal(curbuf->b_p_ft, "lua") + if (ex_lua || strequal(curbuf->b_p_ft, "lua") || (curbuf->b_fname && path_with_extension(curbuf->b_fname, "lua"))) { - nlua_source_using_linegetter(get_str_line, (void *)&cookie, ":source (no file)"); + char *name = ex_lua ? ":lua (no file)" : ":source (no file)"; + nlua_source_using_linegetter(get_str_line, (void *)&cookie, name); } else { source_using_linegetter((void *)&cookie, get_str_line, ":source (no file)"); } diff --git a/test/functional/lua/commands_spec.lua b/test/functional/lua/commands_spec.lua index 28a99a86f8..083f6f3541 100644 --- a/test/functional/lua/commands_spec.lua +++ b/test/functional/lua/commands_spec.lua @@ -55,6 +55,12 @@ describe(':lua command', function() ) end) it('throws catchable errors', function() + for _, cmd in ipairs({ 'lua', '1lua chunk' }) do + eq( + 'Vim(lua):E475: Invalid argument: exactly one of {chunk} and {range} required', + pcall_err(command, cmd) + ) + end eq( [[Vim(lua):E5107: Error loading lua [string ":lua"]:0: unexpected symbol near ')']], pcall_err(command, 'lua ()') @@ -192,6 +198,25 @@ describe(':lua command', function() exec_capture('=x(false)') ) end) + + it('works with range in current buffer', function() + local screen = Screen.new(40, 10) + screen:attach() + api.nvim_buf_set_lines(0, 0, 0, 0, { 'function x() print "hello" end', 'x()' }) + feed(':1,2lua') + screen:expect { + grid = [[ + function x() print "hello" end | + x() | + ^ | + {1:~ }|*6 + hello | + ]], + attr_ids = { + [1] = { foreground = Screen.colors.Blue, bold = true }, + }, + } + end) end) describe(':luado command', function()