patch 8.1.0573: cannot redefine user command without ! in same script

Problem:    Cannot redefine user command without ! in same script
Solution:   Allow redefining user command without ! in same script, like with
            functions.
This commit is contained in:
Bram Moolenaar
2018-12-08 16:03:28 +01:00
parent 76ab4fd619
commit 55d4691308
4 changed files with 59 additions and 13 deletions

View File

@ -1223,6 +1223,10 @@ See |:verbose-cmd| for more information.
attributes (see below) are {attr}. If the command attributes (see below) are {attr}. If the command
already exists, an error is reported, unless a ! is already exists, an error is reported, unless a ! is
specified, in which case the command is redefined. specified, in which case the command is redefined.
There is one exception: When sourcing a script again,
a command that was previously defined in that script
will be silently replaced.
:delc[ommand] {cmd} *:delc* *:delcommand* *E184* :delc[ommand] {cmd} *:delc* *:delcommand* *E184*
Delete the user-defined command {cmd}. Delete the user-defined command {cmd}.
@ -1230,7 +1234,8 @@ See |:verbose-cmd| for more information.
:comc[lear] *:comc* *:comclear* :comc[lear] *:comc* *:comclear*
Delete all user-defined commands. Delete all user-defined commands.
Command attributes
Command attributes ~
User-defined commands are treated by Vim just like any other Ex commands. They User-defined commands are treated by Vim just like any other Ex commands. They
can have arguments, or have a range specified. Arguments are subject to can have arguments, or have a range specified. Arguments are subject to
@ -1241,8 +1246,9 @@ There are a number of attributes, split into four categories: argument
handling, completion behavior, range handling, and special cases. The handling, completion behavior, range handling, and special cases. The
attributes are described below, by category. attributes are described below, by category.
Argument handling *E175* *E176* *:command-nargs*
Argument handling ~
*E175* *E176* *:command-nargs*
By default, a user defined command will take no arguments (and an error is By default, a user defined command will take no arguments (and an error is
reported if any are supplied). However, it is possible to specify that the reported if any are supplied). However, it is possible to specify that the
command can take arguments, using the -nargs attribute. Valid cases are: command can take arguments, using the -nargs attribute. Valid cases are:
@ -1271,8 +1277,10 @@ defined, not where it is invoked! Example:
Executing script2.vim will result in "None" being echoed. Not what you Executing script2.vim will result in "None" being echoed. Not what you
intended! Calling a function may be an alternative. intended! Calling a function may be an alternative.
Completion behavior *:command-completion* *E179*
*E180* *E181* *:command-complete* Completion behavior ~
*:command-completion* *E179* *E180* *E181*
*:command-complete*
By default, the arguments of user defined commands do not undergo completion. By default, the arguments of user defined commands do not undergo completion.
However, by specifying one or the other of the following attributes, argument However, by specifying one or the other of the following attributes, argument
completion can be enabled: completion can be enabled:
@ -1317,9 +1325,9 @@ completion can be enabled:
Note: That some completion methods might expand environment variables. Note: That some completion methods might expand environment variables.
Custom completion *:command-completion-custom* Custom completion ~
*:command-completion-customlist* *:command-completion-custom*
*E467* *E468* *:command-completion-customlist* *E467* *E468*
It is possible to define customized completion schemes via the "custom,{func}" It is possible to define customized completion schemes via the "custom,{func}"
or the "customlist,{func}" completion argument. The {func} part should be a or the "customlist,{func}" completion argument. The {func} part should be a
function with the following signature: > function with the following signature: >
@ -1364,8 +1372,8 @@ the 'path' option: >
This example does not work for file names with spaces! This example does not work for file names with spaces!
Range handling *E177* *E178* *:command-range* Range handling ~
*:command-count* *E177* *E178* *:command-range* *:command-count*
By default, user-defined commands do not accept a line number range. However, By default, user-defined commands do not accept a line number range. However,
it is possible to specify that the command does take a range (the -range it is possible to specify that the command does take a range (the -range
attribute), or that it takes an arbitrary count value, either in the line attribute), or that it takes an arbitrary count value, either in the line
@ -1399,8 +1407,11 @@ Possible values are:
-addr=loaded_buffers Range for loaded buffers -addr=loaded_buffers Range for loaded buffers
-addr=windows Range for windows -addr=windows Range for windows
-addr=tabs Range for tab pages -addr=tabs Range for tab pages
-addr=other other kind of range
Special cases *:command-bang* *:command-bar*
Special cases ~
*:command-bang* *:command-bar*
*:command-register* *:command-buffer* *:command-register* *:command-buffer*
There are some special cases as well: There are some special cases as well:
@ -1418,7 +1429,8 @@ replacement text separately.
Note that these arguments can be abbreviated, but that is a deprecated Note that these arguments can be abbreviated, but that is a deprecated
feature. Use the full name for new scripts. feature. Use the full name for new scripts.
Replacement text
Replacement text ~
The replacement text for a user defined command is scanned for special escape The replacement text for a user defined command is scanned for special escape
sequences, using <...> notation. Escape sequences are replaced with values sequences, using <...> notation. Escape sequences are replaced with values

View File

@ -5869,9 +5869,13 @@ uc_add_command(
if (cmp == 0) if (cmp == 0)
{ {
if (!force) // Command can be replaced with "command!" and when sourcing the
// same script again, but only once.
if (!force && (cmd->uc_script_ctx.sc_sid != current_sctx.sc_sid
|| cmd->uc_script_ctx.sc_seq == current_sctx.sc_seq))
{ {
EMSG(_("E174: Command already exists: add ! to replace it")); EMSG2(_("E174: Command already exists: add ! to replace it: %s"),
name);
goto fail; goto fail;
} }

View File

@ -90,6 +90,34 @@ func Test_Ambiguous()
delcommand Dothat delcommand Dothat
endfunc endfunc
func Test_redefine_on_reload()
call writefile(['command ExistingCommand echo "yes"'], 'Xcommandexists')
call assert_equal(0, exists(':ExistingCommand'))
source Xcommandexists
call assert_equal(2, exists(':ExistingCommand'))
" Redefining a command when reloading a script is OK.
source Xcommandexists
call assert_equal(2, exists(':ExistingCommand'))
" But redefining in another script is not OK.
call writefile(['command ExistingCommand echo "yes"'], 'Xcommandexists2')
call assert_fails('source Xcommandexists2', 'E174:')
call delete('Xcommandexists2')
" And defining twice in one script is not OK.
delcommand ExistingCommand
call assert_equal(0, exists(':ExistingCommand'))
call writefile([
\ 'command ExistingCommand echo "yes"',
\ 'command ExistingCommand echo "no"',
\ ], 'Xcommandexists')
call assert_fails('source Xcommandexists', 'E174:')
call assert_equal(2, exists(':ExistingCommand'))
call delete('Xcommandexists')
delcommand ExistingCommand
endfunc
func Test_CmdUndefined() func Test_CmdUndefined()
call assert_fails('Doit', 'E492:') call assert_fails('Doit', 'E492:')
au CmdUndefined Doit :command Doit let g:didit = 'yes' au CmdUndefined Doit :command Doit let g:didit = 'yes'

View File

@ -792,6 +792,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
573,
/**/ /**/
572, 572,
/**/ /**/