diff options
-rw-r--r-- | runtime/autoload/rustfmt.vim | 7 | ||||
-rw-r--r-- | runtime/doc/builtin.txt | 34 | ||||
-rw-r--r-- | runtime/ftplugin/rust.vim | 16 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/builtin_types.lua | 4 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/vimfn.lua | 42 | ||||
-rw-r--r-- | src/nvim/drawline.c | 3 | ||||
-rw-r--r-- | src/nvim/eval.lua | 42 | ||||
-rw-r--r-- | src/nvim/mapping.c | 56 | ||||
-rw-r--r-- | src/nvim/move.c | 10 | ||||
-rw-r--r-- | src/nvim/window.c | 2 | ||||
-rw-r--r-- | test/functional/api/keymap_spec.lua | 20 | ||||
-rw-r--r-- | test/functional/ui/decorations_spec.lua | 34 | ||||
-rw-r--r-- | test/functional/ui/winbar_spec.lua | 9 | ||||
-rw-r--r-- | test/old/testdir/test_ins_complete.vim | 29 |
14 files changed, 226 insertions, 82 deletions
diff --git a/runtime/autoload/rustfmt.vim b/runtime/autoload/rustfmt.vim index 8fd3858178..f325df2fda 100644 --- a/runtime/autoload/rustfmt.vim +++ b/runtime/autoload/rustfmt.vim @@ -1,5 +1,6 @@ " Author: Stephen Sugden <stephen@stephensugden.com> " Last Modified: 2023-09-11 +" Last Change: 2025 Mar 31 by Vim project (rename s:RustfmtConfigOptions()) " " Adapted from https://github.com/fatih/vim-go " For bugs, patches and license go to https://github.com/rust-lang/rust.vim @@ -61,7 +62,7 @@ function! s:RustfmtWriteMode() endif endfunction -function! s:RustfmtConfigOptions() +function! rustfmt#RustfmtConfigOptions() let l:rustfmt_toml = findfile('rustfmt.toml', expand('%:p:h') . ';') if l:rustfmt_toml !=# '' return '--config-path '.shellescape(fnamemodify(l:rustfmt_toml, ":p")) @@ -84,7 +85,7 @@ function! s:RustfmtCommandRange(filename, line1, line2) let l:arg = {"file": shellescape(a:filename), "range": [a:line1, a:line2]} let l:write_mode = s:RustfmtWriteMode() - let l:rustfmt_config = s:RustfmtConfigOptions() + let l:rustfmt_config = rustfmt#RustfmtConfigOptions() " FIXME: When --file-lines gets to be stable, add version range checking " accordingly. @@ -99,7 +100,7 @@ endfunction function! s:RustfmtCommand() let write_mode = g:rustfmt_emit_files ? '--emit=stdout' : '--write-mode=display' - let config = s:RustfmtConfigOptions() + let config = rustfmt#RustfmtConfigOptions() return join([g:rustfmt_command, write_mode, config, g:rustfmt_options]) endfunction diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 3ad5d83ac2..a4061e7228 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -110,7 +110,7 @@ append({lnum}, {text}) *append()* < Parameters: ~ - • {lnum} (`integer`) + • {lnum} (`integer|string`) • {text} (`string|string[]`) Return: ~ @@ -1047,7 +1047,7 @@ cindent({lnum}) *cindent()* To get or set indent of lines in a string, see |vim.text.indent()|. Parameters: ~ - • {lnum} (`integer`) + • {lnum} (`integer|string`) Return: ~ (`integer`) @@ -1637,7 +1637,7 @@ diff_filler({lnum}) *diff_filler()* Returns 0 if the current window is not in diff mode. Parameters: ~ - • {lnum} (`integer`) + • {lnum} (`integer|string`) Return: ~ (`integer`) @@ -1654,7 +1654,7 @@ diff_hlID({lnum}, {col}) *diff_hlID()* syntax information about the highlighting. Parameters: ~ - • {lnum} (`integer`) + • {lnum} (`integer|string`) • {col} (`integer`) Return: ~ @@ -2563,7 +2563,7 @@ foldclosed({lnum}) *foldclosed()* line, "'m" mark m, etc. Parameters: ~ - • {lnum} (`integer`) + • {lnum} (`integer|string`) Return: ~ (`integer`) @@ -2576,7 +2576,7 @@ foldclosedend({lnum}) *foldclosedend()* line, "'m" mark m, etc. Parameters: ~ - • {lnum} (`integer`) + • {lnum} (`integer|string`) Return: ~ (`integer`) @@ -2594,7 +2594,7 @@ foldlevel({lnum}) *foldlevel()* line, "'m" mark m, etc. Parameters: ~ - • {lnum} (`integer`) + • {lnum} (`integer|string`) Return: ~ (`integer`) @@ -2629,7 +2629,7 @@ foldtextresult({lnum}) *foldtextresult()* Useful when exporting folded text, e.g., to HTML. Parameters: ~ - • {lnum} (`integer`) + • {lnum} (`integer|string`) Return: ~ (`string`) @@ -5706,7 +5706,7 @@ line2byte({lnum}) *line2byte()* Also see |byte2line()|, |go| and |:goto|. Parameters: ~ - • {lnum} (`integer`) + • {lnum} (`integer|string`) Return: ~ (`integer`) @@ -5719,7 +5719,7 @@ lispindent({lnum}) *lispindent()* When {lnum} is invalid, -1 is returned. Parameters: ~ - • {lnum} (`integer`) + • {lnum} (`integer|string`) Return: ~ (`integer`) @@ -6090,7 +6090,7 @@ mapset({dict}) < Parameters: ~ - • {dict} (`boolean`) + • {dict} (`table<string,any>`) Return: ~ (`any`) @@ -6993,7 +6993,7 @@ nextnonblank({lnum}) *nextnonblank()* See also |prevnonblank()|. Parameters: ~ - • {lnum} (`integer`) + • {lnum} (`integer|string`) Return: ~ (`integer`) @@ -7127,7 +7127,7 @@ prevnonblank({lnum}) *prevnonblank()* Also see |nextnonblank()|. Parameters: ~ - • {lnum} (`integer`) + • {lnum} (`integer|string`) Return: ~ (`integer`) @@ -8940,7 +8940,7 @@ setline({lnum}, {text}) *setline()* < Note: The '[ and '] marks are not set. Parameters: ~ - • {lnum} (`integer`) + • {lnum} (`integer|string`) • {text} (`any`) Return: ~ @@ -10854,7 +10854,7 @@ synID({lnum}, {col}, {trans}) *synID()* < Parameters: ~ - • {lnum} (`integer`) + • {lnum} (`integer|string`) • {col} (`integer`) • {trans} (`0|1`) @@ -10959,7 +10959,7 @@ synconcealed({lnum}, {col}) *synconcealed()* mechanisms |syntax-vs-match|. Parameters: ~ - • {lnum} (`integer`) + • {lnum} (`integer|string`) • {col} (`integer`) Return: ~ @@ -10985,7 +10985,7 @@ synstack({lnum}, {col}) *synstack()* valid positions. Parameters: ~ - • {lnum} (`integer`) + • {lnum} (`integer|string`) • {col} (`integer`) Return: ~ diff --git a/runtime/ftplugin/rust.vim b/runtime/ftplugin/rust.vim index 3e2741f919..53f7f83363 100644 --- a/runtime/ftplugin/rust.vim +++ b/runtime/ftplugin/rust.vim @@ -3,6 +3,7 @@ " Maintainer: Chris Morgan <me@chrismorgan.info> " Last Change: 2024 Mar 17 " 2024 May 23 by Riley Bruins <ribru17@gmail.com ('commentstring') +" 2025 Mar 31 by Vim project (set 'formatprg' option) " For bugs, patches and license go to https://github.com/rust-lang/rust.vim if exists("b:did_ftplugin") @@ -57,6 +58,19 @@ setlocal includeexpr=rust#IncludeExpr(v:fname) setlocal suffixesadd=.rs +if executable(get(g:, 'rustfmt_command', 'rustfmt')) + if get(g:, "rustfmt_fail_silently", 0) + augroup rust.vim.FailSilently + autocmd! * <buffer> + autocmd ShellFilterPost <buffer> if v:shell_error | execute 'echom "shell filter returned error " . v:shell_error . ", undoing changes"' | undo | endif + augroup END + endif + + let &l:formatprg = get(g:, 'rustfmt_command', 'rustfmt') . ' ' . + \ get(g:, 'rustfmt_options', '') . ' ' . + \ rustfmt#RustfmtConfigOptions() +endif + if exists("g:ftplugin_rust_source_path") let &l:path=g:ftplugin_rust_source_path . ',' . &l:path endif @@ -149,7 +163,7 @@ endif let b:undo_ftplugin = " \ compiler make | - \ setlocal formatoptions< comments< commentstring< include< includeexpr< suffixesadd< + \ setlocal formatoptions< comments< commentstring< include< includeexpr< suffixesadd< formatprg< \|if exists('b:rust_set_style') \|setlocal tabstop< shiftwidth< softtabstop< expandtab< textwidth< \|endif diff --git a/runtime/lua/vim/_meta/builtin_types.lua b/runtime/lua/vim/_meta/builtin_types.lua index 9dd0374486..763153f38d 100644 --- a/runtime/lua/vim/_meta/builtin_types.lua +++ b/runtime/lua/vim/_meta/builtin_types.lua @@ -184,14 +184,14 @@ --- @field signs vim.fn.sign[] --- @class vim.fn.sign_place.dict ---- @field lnum? integer +--- @field lnum? integer|string --- @field priority? integer --- @class vim.fn.sign_placelist.list.item --- @field buffer integer|string --- @field group? string --- @field id? integer ---- @field lnum integer +--- @field lnum? integer|string --- @field name string --- @field priority? integer diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 813a89898e..157799f36e 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -85,7 +85,7 @@ function vim.fn.api_info() end --- let failed = append(0, ["Chapter 1", "the beginning"]) --- < --- ---- @param lnum integer +--- @param lnum integer|string --- @param text string|string[] --- @return 0|1 function vim.fn.append(lnum, text) end @@ -907,7 +907,7 @@ function vim.fn.chdir(dir) end --- --- To get or set indent of lines in a string, see |vim.text.indent()|. --- ---- @param lnum integer +--- @param lnum integer|string --- @return integer function vim.fn.cindent(lnum) end @@ -1244,7 +1244,7 @@ function vim.fn.ctxset(context, index) end --- @return any function vim.fn.ctxsize() end ---- @param lnum integer +--- @param lnum integer|string --- @param col? integer --- @param off? integer --- @return any @@ -1441,7 +1441,7 @@ function vim.fn.did_filetype() end --- line, "'m" mark m, etc. --- Returns 0 if the current window is not in diff mode. --- ---- @param lnum integer +--- @param lnum integer|string --- @return integer function vim.fn.diff_filler(lnum) end @@ -1455,7 +1455,7 @@ function vim.fn.diff_filler(lnum) end --- The highlight ID can be used with |synIDattr()| to obtain --- syntax information about the highlighting. --- ---- @param lnum integer +--- @param lnum integer|string --- @param col integer --- @return any function vim.fn.diff_hlID(lnum, col) end @@ -2282,7 +2282,7 @@ function vim.fn.fnamemodify(fname, mods) end --- {lnum} is used like with |getline()|. Thus "." is the current --- line, "'m" mark m, etc. --- ---- @param lnum integer +--- @param lnum integer|string --- @return integer function vim.fn.foldclosed(lnum) end @@ -2292,7 +2292,7 @@ function vim.fn.foldclosed(lnum) end --- {lnum} is used like with |getline()|. Thus "." is the current --- line, "'m" mark m, etc. --- ---- @param lnum integer +--- @param lnum integer|string --- @return integer function vim.fn.foldclosedend(lnum) end @@ -2307,7 +2307,7 @@ function vim.fn.foldclosedend(lnum) end --- {lnum} is used like with |getline()|. Thus "." is the current --- line, "'m" mark m, etc. --- ---- @param lnum integer +--- @param lnum integer|string --- @return integer function vim.fn.foldlevel(lnum) end @@ -2338,7 +2338,7 @@ function vim.fn.foldtext() end --- line, "'m" mark m, etc. --- Useful when exporting folded text, e.g., to HTML. --- ---- @param lnum integer +--- @param lnum integer|string --- @return string function vim.fn.foldtextresult(lnum) end @@ -3284,7 +3284,7 @@ function vim.fn.getjumplist(winnr, tabnr) end --- @return string function vim.fn.getline(lnum, end_) end ---- @param lnum integer +--- @param lnum integer|string --- @param end_ true|number|string|table --- @return string|string[] function vim.fn.getline(lnum, end_) end @@ -5170,7 +5170,7 @@ function vim.fn.line(expr, winid) end --- |getline()|. When {lnum} is invalid -1 is returned. --- Also see |byte2line()|, |go| and |:goto|. --- ---- @param lnum integer +--- @param lnum integer|string --- @return integer function vim.fn.line2byte(lnum) end @@ -5180,7 +5180,7 @@ function vim.fn.line2byte(lnum) end --- relevant. {lnum} is used just like in |getline()|. --- When {lnum} is invalid, -1 is returned. --- ---- @param lnum integer +--- @param lnum integer|string --- @return integer function vim.fn.lispindent(lnum) end @@ -5479,7 +5479,7 @@ function vim.fn.mapnew(expr1, expr2) end --- @param mode string --- @param abbr? boolean ---- @param dict? boolean +--- @param dict? table<string,any> --- @return any function vim.fn.mapset(mode, abbr, dict) end @@ -5519,7 +5519,7 @@ function vim.fn.mapset(mode, abbr, dict) end --- endfor --- < --- ---- @param dict boolean +--- @param dict table<string,any> --- @return any function vim.fn.mapset(dict) end @@ -6355,7 +6355,7 @@ function vim.fn.msgpackparse(data) end --- {lnum} is used like with |getline()|. --- See also |prevnonblank()|. --- ---- @param lnum integer +--- @param lnum integer|string --- @return integer function vim.fn.nextnonblank(lnum) end @@ -6454,7 +6454,7 @@ function vim.fn.pow(x, y) end --- {lnum} is used like with |getline()|. --- Also see |nextnonblank()|. --- ---- @param lnum integer +--- @param lnum integer|string --- @return integer function vim.fn.prevnonblank(lnum) end @@ -8063,7 +8063,7 @@ function vim.fn.setcmdline(str, pos) end --- @return any function vim.fn.setcmdpos(pos) end ---- @param lnum integer +--- @param lnum integer|string --- @param col? integer --- @param off? integer --- @return any @@ -8142,7 +8142,7 @@ function vim.fn.setfperm(fname, mode) end --- --- <Note: The '[ and '] marks are not set. --- ---- @param lnum integer +--- @param lnum integer|string --- @param text any --- @return any function vim.fn.setline(lnum, text) end @@ -9898,7 +9898,7 @@ function vim.fn.swapname(buf) end --- echo synIDattr(synID(line("."), col("."), 1), "name") --- < --- ---- @param lnum integer +--- @param lnum integer|string --- @param col integer --- @param trans 0|1 --- @return integer @@ -9994,7 +9994,7 @@ function vim.fn.synIDtrans(synID) end --- since syntax and matching highlighting are two different --- mechanisms |syntax-vs-match|. --- ---- @param lnum integer +--- @param lnum integer|string --- @param col integer --- @return [integer, string, integer] function vim.fn.synconcealed(lnum, col) end @@ -10017,7 +10017,7 @@ function vim.fn.synconcealed(lnum, col) end --- character in a line and the first column in an empty line are --- valid positions. --- ---- @param lnum integer +--- @param lnum integer|string --- @param col integer --- @return integer[] function vim.fn.synstack(lnum, col) end diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 43d9f67b5c..79cfc1ab2f 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -1163,7 +1163,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, b } } - decor_providers_invoke_line(wp, lnum - 1); + decor_providers_invoke_line(wp, lnum - 1); // may invalidate wp->w_virtcol + validate_virtcol(wp); has_decor = decor_redraw_line(wp, lnum - 1, &decor_state); diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index ffdbacb2b4..9f662c6457 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -153,7 +153,7 @@ M.funcs = { ]=], name = 'append', - params = { { 'lnum', 'integer' }, { 'text', 'string|string[]' } }, + params = { { 'lnum', 'integer|string' }, { 'text', 'string|string[]' } }, returns = '0|1', signature = 'append({lnum}, {text})', }, @@ -1235,7 +1235,7 @@ M.funcs = { ]=], name = 'cindent', - params = { { 'lnum', 'integer' } }, + params = { { 'lnum', 'integer|string' } }, returns = 'integer', signature = 'cindent({lnum})', }, @@ -1663,7 +1663,7 @@ M.funcs = { args = { 1, 3 }, base = 1, name = 'cursor', - params = { { 'lnum', 'integer' }, { 'col', 'integer' }, { 'off', 'integer' } }, + params = { { 'lnum', 'integer|string' }, { 'col', 'integer' }, { 'off', 'integer' } }, signature = 'cursor({lnum}, {col} [, {off}])', }, cursor__1 = { @@ -1898,7 +1898,7 @@ M.funcs = { ]=], name = 'diff_filler', - params = { { 'lnum', 'integer' } }, + params = { { 'lnum', 'integer|string' } }, returns = 'integer', signature = 'diff_filler({lnum})', }, @@ -1918,7 +1918,7 @@ M.funcs = { ]=], name = 'diff_hlID', - params = { { 'lnum', 'integer' }, { 'col', 'integer' } }, + params = { { 'lnum', 'integer|string' }, { 'col', 'integer' } }, signature = 'diff_hlID({lnum}, {col})', }, digraph_get = { @@ -2915,7 +2915,7 @@ M.funcs = { ]=], name = 'foldclosed', - params = { { 'lnum', 'integer' } }, + params = { { 'lnum', 'integer|string' } }, returns = 'integer', signature = 'foldclosed({lnum})', }, @@ -2931,7 +2931,7 @@ M.funcs = { ]=], name = 'foldclosedend', - params = { { 'lnum', 'integer' } }, + params = { { 'lnum', 'integer|string' } }, returns = 'integer', signature = 'foldclosedend({lnum})', }, @@ -2952,7 +2952,7 @@ M.funcs = { ]=], name = 'foldlevel', - params = { { 'lnum', 'integer' } }, + params = { { 'lnum', 'integer|string' } }, returns = 'integer', signature = 'foldlevel({lnum})', }, @@ -2993,7 +2993,7 @@ M.funcs = { ]=], name = 'foldtextresult', - params = { { 'lnum', 'integer' } }, + params = { { 'lnum', 'integer|string' } }, returns = 'string', signature = 'foldtextresult({lnum})', }, @@ -4126,7 +4126,7 @@ M.funcs = { args = { 2 }, base = 1, name = 'getline', - params = { { 'lnum', 'integer' }, { 'end', 'true|number|string|table' } }, + params = { { 'lnum', 'integer|string' }, { 'end', 'true|number|string|table' } }, returns = 'string|string[]', }, getloclist = { @@ -6374,7 +6374,7 @@ M.funcs = { ]=], name = 'line2byte', - params = { { 'lnum', 'integer' } }, + params = { { 'lnum', 'integer|string' } }, returns = 'integer', signature = 'line2byte({lnum})', }, @@ -6390,7 +6390,7 @@ M.funcs = { ]=], name = 'lispindent', - params = { { 'lnum', 'integer' } }, + params = { { 'lnum', 'integer|string' } }, returns = 'integer', signature = 'lispindent({lnum})', }, @@ -6762,7 +6762,7 @@ M.funcs = { args = { 1, 3 }, base = 1, name = 'mapset', - params = { { 'mode', 'string' }, { 'abbr', 'boolean' }, { 'dict', 'boolean' } }, + params = { { 'mode', 'string' }, { 'abbr', 'boolean' }, { 'dict', 'table<string,any>' } }, signature = 'mapset({mode}, {abbr}, {dict})', }, mapset__1 = { @@ -6806,7 +6806,7 @@ M.funcs = { < ]=], name = 'mapset', - params = { { 'dict', 'boolean' } }, + params = { { 'dict', 'table<string,any>' } }, signature = 'mapset({dict})', }, match = { @@ -7751,7 +7751,7 @@ M.funcs = { ]=], name = 'nextnonblank', - params = { { 'lnum', 'integer' } }, + params = { { 'lnum', 'integer|string' } }, returns = 'integer', signature = 'nextnonblank({lnum})', }, @@ -7899,7 +7899,7 @@ M.funcs = { ]=], name = 'prevnonblank', - params = { { 'lnum', 'integer' } }, + params = { { 'lnum', 'integer|string' } }, returns = 'integer', signature = 'prevnonblank({lnum})', }, @@ -9775,7 +9775,7 @@ M.funcs = { args = { 1, 3 }, base = 1, name = 'setcursorcharpos', - params = { { 'lnum', 'integer' }, { 'col', 'integer' }, { 'off', 'integer' } }, + params = { { 'lnum', 'integer|string' }, { 'col', 'integer' }, { 'off', 'integer' } }, signature = 'setcursorcharpos({lnum}, {col} [, {off}])', }, setcursorcharpos__1 = { @@ -9870,7 +9870,7 @@ M.funcs = { ]=], name = 'setline', - params = { { 'lnum', 'integer' }, { 'text', 'any' } }, + params = { { 'lnum', 'integer|string' }, { 'text', 'any' } }, signature = 'setline({lnum}, {text})', }, setloclist = { @@ -11939,7 +11939,7 @@ M.funcs = { < ]=], name = 'synID', - params = { { 'lnum', 'integer' }, { 'col', 'integer' }, { 'trans', '0|1' } }, + params = { { 'lnum', 'integer|string' }, { 'col', 'integer' }, { 'trans', '0|1' } }, returns = 'integer', signature = 'synID({lnum}, {col}, {trans})', }, @@ -12046,7 +12046,7 @@ M.funcs = { mechanisms |syntax-vs-match|. ]=], name = 'synconcealed', - params = { { 'lnum', 'integer' }, { 'col', 'integer' } }, + params = { { 'lnum', 'integer|string' }, { 'col', 'integer' } }, returns = '[integer, string, integer]', signature = 'synconcealed({lnum}, {col})', }, @@ -12072,7 +12072,7 @@ M.funcs = { valid positions. ]=], name = 'synstack', - params = { { 'lnum', 'integer' }, { 'col', 'integer' } }, + params = { { 'lnum', 'integer|string' }, { 'col', 'integer' } }, returns = 'integer[]', signature = 'synstack({lnum}, {col})', }, diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index 3dc66f7dba..36369e1e57 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -681,12 +681,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, if ((mp->m_mode & mode) != 0 && mp->m_keylen == len && strncmp(mp->m_keys, lhs, (size_t)len) == 0) { - if (is_abbrev) { - semsg(_(e_global_abbreviation_already_exists_for_str), mp->m_keys); - } else { - semsg(_(e_global_mapping_already_exists_for_str), mp->m_keys); - } - retval = 5; + retval = 6; goto theend; } } @@ -799,11 +794,6 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, did_it = true; break; } else if (args->unique) { - if (is_abbrev) { - semsg(_(e_abbreviation_already_exists_for_str), p); - } else { - semsg(_(e_mapping_already_exists_for_str), p); - } retval = 5; goto theend; } else { @@ -962,6 +952,7 @@ theend: /// - 2 for no match /// - 4 for out of mem (deprecated, WON'T HAPPEN) /// - 5 for entry not unique +/// - 6 for buflocal unique entry conflicts with global entry /// int do_map(int maptype, char *arg, int mode, bool is_abbrev) { @@ -2637,16 +2628,47 @@ static void do_exmap(exarg_T *eap, int isabbrev) char *cmdp = eap->cmd; int mode = get_map_mode(&cmdp, eap->forceit || isabbrev); - switch (do_map((*cmdp == 'n') ? MAPTYPE_NOREMAP - : (*cmdp == 'u') ? MAPTYPE_UNMAP : MAPTYPE_MAP, - eap->arg, mode, isabbrev)) { + int maptype; + if (*cmdp == 'n') { + maptype = MAPTYPE_NOREMAP; + } else if (*cmdp == 'u') { + maptype = MAPTYPE_UNMAP; + } else { + maptype = MAPTYPE_MAP; + } + MapArguments parsed_args; + int result = str_to_mapargs(eap->arg, maptype == MAPTYPE_UNMAP, &parsed_args); + switch (result) { + case 0: + break; + case 1: + emsg(_(e_invarg)); + goto free_rhs; + break; + default: + assert(false && "Unknown return code from str_to_mapargs!"); + goto free_rhs; + } + switch (buf_do_map(maptype, &parsed_args, mode, isabbrev, curbuf)) { case 1: emsg(_(e_invarg)); break; case 2: emsg(isabbrev ? _(e_noabbr) : _(e_nomap)); break; + case 5: + semsg(isabbrev ? _(e_abbreviation_already_exists_for_str) + : _(e_mapping_already_exists_for_str), + parsed_args.lhs); + break; + case 6: + semsg(isabbrev ? _(e_global_abbreviation_already_exists_for_str) + : _(e_global_mapping_already_exists_for_str), + parsed_args.lhs); } +free_rhs: + xfree(parsed_args.rhs); + xfree(parsed_args.orig_rhs); } /// ":abbreviate" and friends. @@ -2808,6 +2830,12 @@ void modify_keymap(uint64_t channel_id, Buffer buffer, bool is_unmap, String mod is_abbrev ? e_abbreviation_already_exists_for_str : e_mapping_already_exists_for_str, lhs.data); goto fail_and_free; + break; + case 6: + api_set_error(err, kErrorTypeException, + is_abbrev ? e_global_abbreviation_already_exists_for_str + : e_global_mapping_already_exists_for_str, lhs.data); + goto fail_and_free; default: assert(false && "Unrecognized return code!"); goto fail_and_free; diff --git a/src/nvim/move.c b/src/nvim/move.c index 89d2b69f51..55e724f38d 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -1363,8 +1363,9 @@ bool scrolldown(win_T *wp, linenr_T line_count, int byfold) } wp->w_botline -= wp->w_topline - first; wp->w_topline = first; + } else if (decor_conceal_line(wp, wp->w_topline - 1, false)) { + todo++; } else { - todo += decor_conceal_line(wp, wp->w_topline - 1, false); if (do_sms) { int size = linetabsize_eol(wp, wp->w_topline); if (size > width1) { @@ -1386,6 +1387,13 @@ bool scrolldown(win_T *wp, linenr_T line_count, int byfold) wp->w_botline--; // approximate w_botline invalidate_botline(wp); } + + // Adjust for concealed lines above w_topline + while (wp->w_topline > 1 && decor_conceal_line(wp, wp->w_topline - 2, false)) { + wp->w_topline--; + hasFolding(wp, wp->w_topline, &wp->w_topline, NULL); + } + wp->w_wrow += done; // keep w_wrow updated wp->w_cline_row += done; // keep w_cline_row updated diff --git a/src/nvim/window.c b/src/nvim/window.c index 916c193469..3022dccb1c 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6634,7 +6634,7 @@ void win_set_inner_size(win_T *wp, bool valid_cursor) int prev_height = wp->w_height_inner; int height = wp->w_height_request; if (height == 0) { - height = wp->w_height - wp->w_winbar_height; + height = MAX(0, wp->w_height - wp->w_winbar_height); } if (height != prev_height) { diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua index acaccee4e5..2c44905274 100644 --- a/test/functional/api/keymap_spec.lua +++ b/test/functional/api/keymap_spec.lua @@ -1465,4 +1465,24 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() eq(1, exec_lua [[return GlobalCount]]) eq('\nNo mapping found', n.exec_capture('nmap <C-I>')) end) + + it('does not overwrite in <unique> mappings', function() + api.nvim_buf_set_keymap(0, 'i', 'lhs', 'rhs', {}) + eq( + 'E227: Mapping already exists for lhs', + pcall_err(api.nvim_buf_set_keymap, 0, 'i', 'lhs', 'rhs', { unique = true }) + ) + + api.nvim_buf_set_keymap(0, 'ia', 'lhs2', 'rhs2', {}) + eq( + 'E226: Abbreviation already exists for lhs2', + pcall_err(api.nvim_buf_set_keymap, 0, 'ia', 'lhs2', 'rhs2', { unique = true }) + ) + + api.nvim_set_keymap('n', 'lhs', 'rhs', {}) + eq( + 'E225: Global mapping already exists for lhs', + pcall_err(api.nvim_buf_set_keymap, 0, 'n', 'lhs', 'rhs', { unique = true }) + ) + end) end) diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua index 5ef1ef54bb..307f750175 100644 --- a/test/functional/ui/decorations_spec.lua +++ b/test/functional/ui/decorations_spec.lua @@ -811,6 +811,33 @@ describe('decorations providers', function() | ]]) end) + + it('inline virt_text does not result in wrong cursor column #33153', function() + insert("line1 with a lot of text\nline2 with a lot of text") + setup_provider([[ + _G.do_win = false + vim.keymap.set('n', 'f', function() + _G.do_win = true + vim.cmd('redraw!') + end) + vim.o.concealcursor = 'n' + function on_do(event) + if event == 'win' and _G.do_win then + vim.api.nvim_buf_set_extmark(0, ns1, 1, 0, { + virt_text = { { 'virt_text ' } }, + virt_text_pos = 'inline' + }) + end + end + ]]) + feed('f') + screen:expect([[ + line1 with a lot of text | + virt_text line2 with a lot of tex^t | + {1:~ }|*5 + | + ]]) + end) end) describe('decoration_providers', function() @@ -2978,6 +3005,13 @@ describe('extmark decorations', function() {1:~ }| | ]]) + -- No asymmetric topline for <C-E><C-Y> #33182 + feed('4<C-E>') + exec('set concealcursor=n') + api.nvim_buf_set_extmark(0, ns, 4, 0, { conceal_lines = "" }) + eq(5, n.fn.line('w0')) + feed('<C-E><C-Y>') + eq(5, n.fn.line('w0')) end) end) diff --git a/test/functional/ui/winbar_spec.lua b/test/functional/ui/winbar_spec.lua index d1fd273dc1..09338eb7d2 100644 --- a/test/functional/ui/winbar_spec.lua +++ b/test/functional/ui/winbar_spec.lua @@ -540,6 +540,15 @@ describe('winbar', function() ]]) eq('Vim(set):E36: Not enough room', pcall_err(command, 'set winbar=test')) end) + + it('does not crash due to negative grid height #33176', function() + screen:try_resize(screen._width, 20) + command('botright split | belowright vsplit | 2wincmd w') + api.nvim_set_option_value('winfixheight', true, { scope = 'local', win = 0 }) + api.nvim_win_set_height(0, 8) + feed('q:') + n.assert_alive() + end) end) describe('local winbar with tabs', function() diff --git a/test/old/testdir/test_ins_complete.vim b/test/old/testdir/test_ins_complete.vim index 4bb537c081..0e4f051f5a 100644 --- a/test/old/testdir/test_ins_complete.vim +++ b/test/old/testdir/test_ins_complete.vim @@ -3420,4 +3420,33 @@ func Test_complete_multiline_marks() delfunc Omni_test endfunc +func Test_complete_append_selected_match_default() + " when typing a normal character during completion, + " completion is ended, see + " :h popupmenu-completion ("There are three states:") + func PrintMenuWords() + let info = complete_info(["selected", "matches"]) + call map(info.matches, {_, v -> v.word}) + return info + endfunc + + new + call setline(1, ["fo", "foo", "foobar", "fobarbaz"]) + exe "normal! Gof\<c-n>\<c-r>=PrintMenuWords()\<cr>" + call assert_equal('fo{''matches'': [''fo'', ''foo'', ''foobar'', ''fobarbaz''], ''selected'': 0}', getline(5)) + %d + call setline(1, ["fo", "foo", "foobar", "fobarbaz"]) + exe "normal! Gof\<c-n>o\<c-r>=PrintMenuWords()\<cr>" + call assert_equal('foo{''matches'': [], ''selected'': -1}', getline(5)) + %d + set completeopt=menu,noselect + call setline(1, ["fo", "foo", "foobar", "fobarbaz"]) + exe "normal! Gof\<c-n>\<c-n>o\<c-r>=PrintMenuWords()\<cr>" + call assert_equal('foo{''matches'': [], ''selected'': -1}', getline(5)) + bw! + + set completeopt& + delfunc PrintMenuWords +endfunc + " vim: shiftwidth=2 sts=2 expandtab nofoldenable |