neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit e7dfbf13439fd8b2c91df02607a0581fa7795cc0
parent 798cb0f19a3b1bbd9003418f8d5645b7cb3141ec
Author: zeertzjq <zeertzjq@outlook.com>
Date:   Fri,  8 Aug 2025 21:58:55 +0800

vim-patch:9.1.1607: :apple command detected as :append (#35237)

Problem:  :apple command detected as :append (dai475694450)
Solution: Disallow to define a custom command with lower-case letter,
          correctly detect :insert/:change/:append ex commands
          (Hirohito Higashi).

fixes: vim/vim#17893
closes: vim/vim#17930

https://github.com/vim/vim/commit/efd83d441ba14eaadf5df4c7c29fddebb2a24780

Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Diffstat:
Msrc/nvim/eval/userfunc.c | 19+++++++------------
Mtest/old/testdir/test_vimscript.vim | 46++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 53 insertions(+), 12 deletions(-)

diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c @@ -2500,19 +2500,14 @@ static int get_function_body(exarg_T *eap, garray_T *newlines, char *line_arg_in } // Check for ":append", ":change", ":insert". - p = skip_range(p, NULL); - if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p')) - || (p[0] == 'c' - && (!ASCII_ISALPHA(p[1]) - || (p[1] == 'h' && (!ASCII_ISALPHA(p[2]) - || (p[2] == 'a' - && (strncmp(&p[3], "nge", 3) != 0 - || !ASCII_ISALPHA(p[6]))))))) - || (p[0] == 'i' - && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n' - && (!ASCII_ISALPHA(p[2]) - || (p[2] == 's')))))) { + char *const tp = p = skip_range(p, NULL); + if ((checkforcmd(&p, "append", 1) + || checkforcmd(&p, "change", 1) + || checkforcmd(&p, "insert", 1)) + && (*p == '!' || *p == '|' || ascii_iswhite_nl_or_nul(*p))) { skip_until = xmemdupz(".", 1); + } else { + p = tp; } // heredoc: Check for ":python <<EOF", ":lua <<EOF", etc. diff --git a/test/old/testdir/test_vimscript.vim b/test/old/testdir/test_vimscript.vim @@ -6813,6 +6813,52 @@ func Test_script_lines() catch call assert_exception('Vim(function):E1145: Missing heredoc end marker: .') endtry + + " More test for :append, :change, :insert + let cmds = ["append", "change", "insert"] + let suffixes = ["", "!", "|", "|xyz", " "] + + for c in cmds + " Single character (with some accepted trailing characters) + for s in suffixes + let cmd = c[:0] .. s + let line = ["func LinesCheck()", cmd, "", "endfunc", "call LinesCheck()"] + call writefile(line, 'Xfunc', 'D') + call assert_fails('source Xfunc', 'E1145: Missing heredoc end marker: .', $'"{cmd}"') + endfor + + " Unnecessary arguments + let cmd = c[:2] .. " end" + let line[1] = cmd + call writefile(line, 'Xfunc', 'D') + call assert_fails('source Xfunc', 'E488: Trailing characters: end:', $'"{cmd}"') + + " Extra characters at the end (i.e., other commands) + let cmd = c .. "x" + let line[1] = cmd + call writefile(line, 'Xfunc', 'D') + call assert_fails('source Xfunc', 'E492: Not an editor command:', $'"{cmd}"') + endfor + + let line =<< trim END + func AppendCheck() + apple + endfunc + call AppendCheck() + END + call writefile(line, 'Xfunc', 'D') + call assert_fails('source Xfunc', 'E492: Not an editor command: apple') + + let line =<< trim END + func AppendCheck() + command! apple :echo "hello apple" + apple + endfunc + call AppendCheck() + END + call writefile(line, 'Xfunc', 'D') + call assert_fails('source Xfunc', 'E183: User defined commands must start with an uppercase letter') + endfunc "-------------------------------------------------------------------------------