aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml3
-rw-r--r--runtime/doc/api.txt3
-rw-r--r--src/nvim/api/vim.c2
-rw-r--r--src/nvim/ex_docmd.c25
-rw-r--r--src/nvim/lua/executor.c56
-rw-r--r--src/nvim/testdir/test_excmd.vim8
-rw-r--r--src/nvim/window.c1
-rw-r--r--test/functional/api/command_spec.lua133
-rw-r--r--test/functional/core/job_spec.lua1
-rw-r--r--test/functional/ui/inccommand_spec.lua102
-rw-r--r--test/functional/ui/winbar_spec.lua19
11 files changed, 345 insertions, 8 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 4657053167..16464426ee 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -120,7 +120,8 @@ jobs:
- if: "!cancelled()"
name: uncrustify
run: |
- ${{ env.CACHE_UNCRUSTIFY }} -c ./src/uncrustify.cfg -q --check $(find ./src/nvim -name "*.[ch]") >/dev/null
+ ${{ env.CACHE_UNCRUSTIFY }} -c ./src/uncrustify.cfg -q --replace --no-backup $(find ./src/nvim -name "*.[ch]")
+ git diff --color --exit-code
- if: "!cancelled()"
name: lualint
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 3ab7c77056..965b8e6492 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -743,6 +743,9 @@ nvim_create_user_command({name}, {command}, {*opts})
specified |<reg>|
• mods: (string) Command modifiers, if any
|<mods>|
+ • smods: (table) Command modifiers in a
+ structured format. Has the same structure as
+ the "mods" key of |nvim_parse_cmd()|.
{opts} Optional command attributes. See
|command-attributes| for more details. To use
boolean attributes (such as |:command-bang| or
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index dd0b75bbfb..5c3c16d6b0 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -2501,6 +2501,8 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
/// - count: (number) Any count supplied |<count>|
/// - reg: (string) The optional register, if specified |<reg>|
/// - mods: (string) Command modifiers, if any |<mods>|
+/// - smods: (table) Command modifiers in a structured format. Has the same
+/// structure as the "mods" key of |nvim_parse_cmd()|.
/// @param opts Optional command attributes. See |command-attributes| for more details. To use
/// boolean attributes (such as |:command-bang| or |:command-bar|) set the value to
/// "true". In addition to the string options listed in |:command-complete|, the
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 4b7958efa5..e6ee0046af 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -2751,6 +2751,8 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent)
{
int address_count = 1;
linenr_T lnum;
+ bool need_check_cursor = false;
+ int ret = FAIL;
// Repeat for all ',' or ';' separated addresses.
for (;;) {
@@ -2760,7 +2762,7 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent)
lnum = get_address(eap, &eap->cmd, eap->addr_type, eap->skip, silent,
eap->addr_count == 0, address_count++);
if (eap->cmd == NULL) { // error detected
- return FAIL;
+ goto theend;
}
if (lnum == MAXLNUM) {
if (*eap->cmd == '%') { // '%' - all lines
@@ -2799,14 +2801,14 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent)
// there is no Vim command which uses '%' and
// ADDR_WINDOWS or ADDR_TABS
*errormsg = _(e_invrange);
- return FAIL;
+ goto theend;
}
break;
case ADDR_TABS_RELATIVE:
case ADDR_UNSIGNED:
case ADDR_QUICKFIX:
*errormsg = _(e_invrange);
- return FAIL;
+ goto theend;
case ADDR_ARGUMENTS:
if (ARGCOUNT == 0) {
eap->line1 = eap->line2 = 0;
@@ -2831,19 +2833,19 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent)
// '*' - visual area
if (eap->addr_type != ADDR_LINES) {
*errormsg = _(e_invrange);
- return FAIL;
+ goto theend;
}
eap->cmd++;
if (!eap->skip) {
pos_T *fp = getmark('<', false);
if (check_mark(fp) == FAIL) {
- return FAIL;
+ goto theend;
}
eap->line1 = fp->lnum;
fp = getmark('>', false);
if (check_mark(fp) == FAIL) {
- return FAIL;
+ goto theend;
}
eap->line2 = fp->lnum;
eap->addr_count++;
@@ -2857,11 +2859,14 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent)
if (*eap->cmd == ';') {
if (!eap->skip) {
curwin->w_cursor.lnum = eap->line2;
+
// Don't leave the cursor on an illegal line or column, but do
// accept zero as address, so 0;/PATTERN/ works correctly.
+ // Check the cursor position before returning.
if (eap->line2 > 0) {
check_cursor();
}
+ need_check_cursor = true;
}
} else if (*eap->cmd != ',') {
break;
@@ -2877,7 +2882,13 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent)
eap->addr_count = 0;
}
}
- return OK;
+ ret = OK;
+
+theend:
+ if (need_check_cursor) {
+ check_cursor();
+ }
+ return ret;
}
/// Check for an Ex command with optional tail.
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 0009420281..a826dd07d3 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -40,6 +40,7 @@
#include "nvim/undo.h"
#include "nvim/version.h"
#include "nvim/vim.h"
+#include "nvim/window.h"
static int in_fast_callback = 0;
@@ -1913,6 +1914,61 @@ void nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap)
lua_pushstring(lstate, buf);
lua_setfield(lstate, -2, "mods");
+ lua_newtable(lstate); // smods table
+
+ lua_pushinteger(lstate, cmdmod.tab);
+ lua_setfield(lstate, -2, "tab");
+ lua_pushinteger(lstate, p_verbose);
+ lua_setfield(lstate, -2, "verbose");
+
+ if (cmdmod.split & WSP_ABOVE) {
+ lua_pushstring(lstate, "aboveleft");
+ } else if (cmdmod.split & WSP_BELOW) {
+ lua_pushstring(lstate, "belowright");
+ } else if (cmdmod.split & WSP_TOP) {
+ lua_pushstring(lstate, "topleft");
+ } else if (cmdmod.split & WSP_BOT) {
+ lua_pushstring(lstate, "botright");
+ } else {
+ lua_pushstring(lstate, "");
+ }
+ lua_setfield(lstate, -2, "split");
+
+ lua_pushboolean(lstate, cmdmod.split & WSP_VERT);
+ lua_setfield(lstate, -2, "vertical");
+ lua_pushboolean(lstate, msg_silent != 0);
+ lua_setfield(lstate, -2, "silent");
+ lua_pushboolean(lstate, emsg_silent != 0);
+ lua_setfield(lstate, -2, "emsg_silent");
+ lua_pushboolean(lstate, eap->did_sandbox);
+ lua_setfield(lstate, -2, "sandbox");
+ lua_pushboolean(lstate, cmdmod.save_ei != NULL);
+ lua_setfield(lstate, -2, "noautocmd");
+
+ typedef struct {
+ bool *set;
+ char *name;
+ } mod_entry_T;
+ static mod_entry_T mod_entries[] = {
+ { &cmdmod.browse, "browse" },
+ { &cmdmod.confirm, "confirm" },
+ { &cmdmod.hide, "hide" },
+ { &cmdmod.keepalt, "keepalt" },
+ { &cmdmod.keepjumps, "keepjumps" },
+ { &cmdmod.keepmarks, "keepmarks" },
+ { &cmdmod.keeppatterns, "keeppatterns" },
+ { &cmdmod.lockmarks, "lockmarks" },
+ { &cmdmod.noswapfile, "noswapfile" }
+ };
+
+ // The modifiers that are simple flags
+ for (size_t i = 0; i < ARRAY_SIZE(mod_entries); i++) {
+ lua_pushboolean(lstate, *mod_entries[i].set);
+ lua_setfield(lstate, -2, mod_entries[i].name);
+ }
+
+ lua_setfield(lstate, -2, "smods");
+
if (nlua_pcall(lstate, 1, 0)) {
nlua_error(lstate, _("Error executing Lua callback: %.*s"));
}
diff --git a/src/nvim/testdir/test_excmd.vim b/src/nvim/testdir/test_excmd.vim
index 8055a51a11..7dde8a0439 100644
--- a/src/nvim/testdir/test_excmd.vim
+++ b/src/nvim/testdir/test_excmd.vim
@@ -422,5 +422,13 @@ func Test_address_line_overflow()
bwipe!
endfunc
+" This was leaving the cursor in line zero
+func Test_using_zero_in_range()
+ new
+ norm o00
+ silent! 0;s/\%')
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 060f498f07..a41f3362d2 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -3993,6 +3993,7 @@ void win_init_size(void)
firstwin->w_height = ROWS_AVAIL;
firstwin->w_height_inner = firstwin->w_height - firstwin->w_winbar_height;
firstwin->w_height_outer = firstwin->w_height;
+ firstwin->w_winrow_off = firstwin->w_winbar_height;
topframe->fr_height = ROWS_AVAIL;
firstwin->w_width = Columns;
firstwin->w_width_inner = firstwin->w_width;
diff --git a/test/functional/api/command_spec.lua b/test/functional/api/command_spec.lua
index e4963e8a65..d6d75e93e4 100644
--- a/test/functional/api/command_spec.lua
+++ b/test/functional/api/command_spec.lua
@@ -120,6 +120,25 @@ describe('nvim_create_user_command', function()
line1 = 1,
line2 = 1,
mods = "",
+ smods = {
+ browse = false,
+ confirm = false,
+ emsg_silent = false,
+ hide = false,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = "",
+ tab = 0,
+ verbose = 0,
+ vertical = false,
+ },
range = 0,
count = 2,
reg = "",
@@ -135,6 +154,25 @@ describe('nvim_create_user_command', function()
line1 = 1,
line2 = 1,
mods = "",
+ smods = {
+ browse = false,
+ confirm = false,
+ emsg_silent = false,
+ hide = false,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = "",
+ tab = 0,
+ verbose = 0,
+ vertical = false,
+ },
range = 0,
count = 2,
reg = "",
@@ -150,6 +188,25 @@ describe('nvim_create_user_command', function()
line1 = 1,
line2 = 1,
mods = "",
+ smods = {
+ browse = false,
+ confirm = false,
+ emsg_silent = false,
+ hide = false,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = "",
+ tab = 0,
+ verbose = 0,
+ vertical = false,
+ },
range = 0,
count = 2,
reg = "",
@@ -165,6 +222,25 @@ describe('nvim_create_user_command', function()
line1 = 10,
line2 = 10,
mods = "botright",
+ smods = {
+ browse = false,
+ confirm = false,
+ emsg_silent = false,
+ hide = false,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = "botright",
+ tab = 0,
+ verbose = 0,
+ vertical = false,
+ },
range = 1,
count = 10,
reg = "",
@@ -180,6 +256,25 @@ describe('nvim_create_user_command', function()
line1 = 1,
line2 = 42,
mods = "",
+ smods = {
+ browse = false,
+ confirm = false,
+ emsg_silent = false,
+ hide = false,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = "",
+ tab = 0,
+ verbose = 0,
+ vertical = false,
+ },
range = 1,
count = 42,
reg = "",
@@ -195,6 +290,25 @@ describe('nvim_create_user_command', function()
line1 = 1,
line2 = 1,
mods = "",
+ smods = {
+ browse = false,
+ confirm = false,
+ emsg_silent = false,
+ hide = false,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = "",
+ tab = 0,
+ verbose = 0,
+ vertical = false,
+ },
range = 0,
count = 2,
reg = "",
@@ -222,6 +336,25 @@ describe('nvim_create_user_command', function()
line1 = 1,
line2 = 1,
mods = "",
+ smods = {
+ browse = false,
+ confirm = false,
+ emsg_silent = false,
+ hide = false,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = "",
+ tab = 0,
+ verbose = 0,
+ vertical = false,
+ },
range = 0,
count = 2,
reg = "",
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua
index cf24e570cb..461a69f357 100644
--- a/test/functional/core/job_spec.lua
+++ b/test/functional/core/job_spec.lua
@@ -682,6 +682,7 @@ describe('jobs', function()
-- User can explicitly set $NVIM_LOG_FILE, $VIM, $VIMRUNTIME.
eq('NVIM_LOG_FILE=Xtest_jobstart_env',
get_env_in_child_job('NVIM_LOG_FILE', { NVIM_LOG_FILE='Xtest_jobstart_env' }))
+ os.remove('Xtest_jobstart_env')
end)
describe('jobwait', function()
diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua
index fb80444430..a1ff778da1 100644
--- a/test/functional/ui/inccommand_spec.lua
+++ b/test/functional/ui/inccommand_spec.lua
@@ -1343,6 +1343,108 @@ describe(":substitute, inccommand=split", function()
]])
end)
+ it([[preview changes correctly with c_CTRL-R_= and c_CTRL-\_e]], function()
+ feed('gg')
+ feed(":1,2s/t/X")
+ screen:expect([[
+ Inc subs{12:X}itution on |
+ {12:X}wo lines |
+ Inc substitution on |
+ two lines |
+ |
+ {11:[No Name] [+] }|
+ |1| Inc subs{12:X}itution on |
+ |2| {12:X}wo lines |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :1,2s/t/X^ |
+ ]])
+
+ feed([[<C-R>='Y']])
+ -- preview should be unchanged during c_CTRL-R_= editing
+ screen:expect([[
+ Inc subs{12:X}itution on |
+ {12:X}wo lines |
+ Inc substitution on |
+ two lines |
+ |
+ {11:[No Name] [+] }|
+ |1| Inc subs{12:X}itution on |
+ |2| {12:X}wo lines |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ ={1:'Y'}^ |
+ ]])
+
+ feed('<CR>')
+ -- preview should be changed by the result of the expression
+ screen:expect([[
+ Inc subs{12:XY}itution on |
+ {12:XY}wo lines |
+ Inc substitution on |
+ two lines |
+ |
+ {11:[No Name] [+] }|
+ |1| Inc subs{12:XY}itution on |
+ |2| {12:XY}wo lines |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :1,2s/t/XY^ |
+ ]])
+
+ feed([[<C-\>e'echo']])
+ -- preview should be unchanged during c_CTRL-\_e editing
+ screen:expect([[
+ Inc subs{12:XY}itution on |
+ {12:XY}wo lines |
+ Inc substitution on |
+ two lines |
+ |
+ {11:[No Name] [+] }|
+ |1| Inc subs{12:XY}itution on |
+ |2| {12:XY}wo lines |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ ={1:'echo'}^ |
+ ]])
+
+ feed('<CR>')
+ -- preview should be cleared if command is changed to a non-previewable one
+ screen:expect([[
+ Inc substitution on |
+ two lines |
+ Inc substitution on |
+ two lines |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :echo^ |
+ ]])
+ end)
+
end)
describe("inccommand=nosplit", function()
diff --git a/test/functional/ui/winbar_spec.lua b/test/functional/ui/winbar_spec.lua
index 982d2d67fd..92a6ab2e84 100644
--- a/test/functional/ui/winbar_spec.lua
+++ b/test/functional/ui/winbar_spec.lua
@@ -26,6 +26,8 @@ describe('winbar', function()
[7] = {background = Screen.colors.LightGrey},
[8] = {background = Screen.colors.LightMagenta},
[9] = {bold = true, foreground = Screen.colors.Blue, background = Screen.colors.LightMagenta},
+ [10] = {background = Screen.colors.LightGrey, underline = true},
+ [11] = {background = Screen.colors.LightGrey, underline = true, bold = true, foreground = Screen.colors.Magenta},
})
meths.set_option('winbar', 'Set Up The Bars')
end)
@@ -245,6 +247,23 @@ describe('winbar', function()
{4:[No Name] }|
|
]])
+ -- Test for issue #18791
+ command('tabnew')
+ screen:expect([[
+ {10: }{11:4}{10: [No Name] }{1: [No Name] }{2: }{10:X}|
+ {1:Set Up The Bars }|
+ ^ |
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {4:[No Name] }|
+ |
+ ]])
end)
it('mouse click and drag work correctly in buffer', function()