vim-patch:partial:9.2.0573: Vim9: missing EX_WHOLE on some block keywords (#40071)

Problem:  Several Vim9 keywords lack EX_WHOLE and can be shortened in
          Vim9 script, inconsistent with endif/enddef/endfor/endwhile/
          endtry which already have it.  The error from :endd in a
          nested function also hardcodes "enddef" instead of reporting
          what the user typed.  fullcommand("ho") returns "horizontal"
          even though :ho is below the documented 3-char minimum.
Solution: Add EX_WHOLE to :class, :def, :endclass, :endinterface,
          :endenum, :public and :static.  In get_function_body() pass
          the user-typed command to the error message.  Force :ho to
          CMD_SIZE in find_ex_command() so fullcommand() reflects the
          modifier minimum.  Extend tests and documentation accordingly
          (Peter Kenny).

fixes:  vim/vim#20032
closes: vim/vim#20191

38d9a16eba

Co-authored-by: Peter Kenny <github.com@k1w1.cyou>
This commit is contained in:
zeertzjq
2026-06-01 09:04:30 +08:00
committed by GitHub
parent 71a02e261d
commit edcaf1887a
9 changed files with 93 additions and 20 deletions

View File

@@ -62,17 +62,17 @@ For inserting text see |insert.txt|.
:[range]d[elete] [x] Delete [range] lines (default: current line) [into
register x].
Note these weird abbreviations:
:dl delete and list
:dell idem
:delel idem
:deletl idem
:deletel idem
:dp delete and print
:dep idem
:delp idem
:delep idem
:deletp idem
:deletep idem
:dl delete and list
:dell idem
:delel idem
:deletl idem
:deletel idem
:dp delete and print
:dep idem
:delp idem
:delep idem
:deletp idem
:deletep idem
:[range]d[elete] [x] {count}
Delete {count} lines, starting with [range]

View File

@@ -840,8 +840,8 @@ CTRL-W i Open a new window, with the cursor on the first line
Like `[D` and `]D`, but search in [range] lines
(default: whole file).
See |:search-args| for [/] and [!].
Note that `:dl` works like `:delete` with the "l"
flag, not `:dlist`.
Note: `:dl` works like `:delete` with the "l" flag,
not `:dlist`.
*[_CTRL-D*
[ CTRL-D Jump to the first macro definition that contains the

View File

@@ -119,6 +119,14 @@ Some of the ":" commands are really long. We already mentioned that
":substitute" can be abbreviated to ":s". This is a generic mechanism, all
":" commands can be abbreviated.
The builtin function |fullcommand()| can be used to return an abbreviated
command's full name. For example, the following commands echo "edit", "echo",
and "echomsg":
>vim
:echo fullcommand('e')
:echo fullcommand('ec')
:echo fullcommand('echom')
<
How short can a command get? There are 26 letters, and many more commands.
For example, ":set" also starts with ":s", but ":s" doesn't start a ":set"
command. Instead ":set" can be abbreviated to ":se".

View File

@@ -2901,8 +2901,16 @@ fullcommand({name}) *fullcommand()*
Returns an empty string if a command doesn't exist or if it's
ambiguous (for user-defined commands).
For example `fullcommand('s')`, `fullcommand('sub')`,
`fullcommand(':%substitute')` all return "substitute".
Note: Command validation is not performed. Results depend on
Vim's internal command-specific identification rules.
Examples:
>vim
echo [fullcommand('s')] |" ['substitute']
echo [fullcommand('sub')] |" ['substitute']
echo [fullcommand(': mark word')] |" ['mark']
echo [fullcommand(': markword')] |" ['']
echo [fullcommand('en')] |" ['endif']
<
Parameters: ~
• {name} (`string`)

View File

@@ -2571,8 +2571,16 @@ function vim.fn.foreach(expr1, expr2) end
--- Returns an empty string if a command doesn't exist or if it's
--- ambiguous (for user-defined commands).
---
--- For example `fullcommand('s')`, `fullcommand('sub')`,
--- `fullcommand(':%substitute')` all return "substitute".
--- Note: Command validation is not performed. Results depend on
--- Vim's internal command-specific identification rules.
--- Examples:
--- >vim
--- echo [fullcommand('s')] |" ['substitute']
--- echo [fullcommand('sub')] |" ['substitute']
--- echo [fullcommand(': mark word')] |" ['mark']
--- echo [fullcommand(': markword')] |" ['']
--- echo [fullcommand('en')] |" ['endif']
--- <
---
--- @param name string
--- @return string

View File

@@ -3230,9 +3230,16 @@ M.funcs = {
Returns an empty string if a command doesn't exist or if it's
ambiguous (for user-defined commands).
For example `fullcommand('s')`, `fullcommand('sub')`,
`fullcommand(':%substitute')` all return "substitute".
Note: Command validation is not performed. Results depend on
Vim's internal command-specific identification rules.
Examples:
>vim
echo [fullcommand('s')] |" ['substitute']
echo [fullcommand('sub')] |" ['substitute']
echo [fullcommand(': mark word')] |" ['mark']
echo [fullcommand(': markword')] |" ['']
echo [fullcommand('en')] |" ['endif']
<
]=],
name = 'fullcommand',
params = { { 'name', 'string' } },

View File

@@ -3269,6 +3269,14 @@ char *find_ex_command(exarg_T *eap, int *full)
}
}
// Force ":ho" to be unresolved. Without this, find_ex_command()
// matches it to CMD_horizontal (the only "ho*" entry), which makes
// fullcommand("ho") return "horizontal" even though ":ho" cannot be
// used as the modifier (cmdmods[] requires 3 chars, "hor").
if (eap->cmdidx == CMD_horizontal && p - eap->cmd == 2) {
eap->cmdidx = CMD_SIZE;
}
return p;
}

View File

@@ -253,7 +253,14 @@ func Test_marks_k_cmd()
call setline(1, ['foo', 'bar', 'baz', 'qux'])
1,3kr
call assert_equal([0, 3, 1, 0], getpos("'r"))
" whitespace before mark
4k f
call assert_equal([0, 4, 1, 0], getpos("'f"))
:2 k g
call assert_equal([0, 2, 1, 0], getpos("'g"))
bw!
call assert_fails(':kz7', 'E488: Trailing characters: z7')
call assert_fails(':execute ":k^"', 'E191: Argument must be a letter or forward/backward quote')
endfunc
" Test for file marks (A-Z)

View File

@@ -7620,6 +7620,33 @@ func Test_catch_pattern_trailing_chars()
bw!
endfunc
" Test using fullcommand() {{{1
func Test_builtin_fullcommand()
" :hor is the minimum abbreviation of :horizontal; :ho is invalid
call assert_equal('', fullcommand('ho'))
call assert_equal('horizontal', fullcommand('hor'))
" :k takes one {a-zA-Z'} mark argument and optional whitespace
call assert_equal('k', fullcommand('k'))
call assert_equal('k', fullcommand(':k'))
call assert_equal('k', fullcommand('karrrrrgh!'))
" :dl is "delete and list" in a legacy Vim script scope
call assert_equal('delete', fullcommand('dl'))
" :s two and three letter commands
call assert_equal('substitute', fullcommand('sIr'))
call assert_equal('substitute', fullcommand('sIrarrrrrgh!'))
" :finally
call assert_equal('finally', fullcommand('fina'))
" 'final' - returns 'final', a Vim9 script-exclusive keyword
" - is a valid shortening of :finally in legacy Vim script
"call assert_equal('final', fullcommand('final'))
call assert_equal('finally', fullcommand('finall'))
endfunc
"-------------------------------------------------------------------------------
" Modelines {{{1
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker