vim-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.
55d4691308
This commit is contained in:
Jan Edmund Lazo
2019-10-30 22:22:23 -04:00
parent 3ccdbc570d
commit 903cd73af1
3 changed files with 52 additions and 11 deletions

View File

@@ -1162,6 +1162,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}.
@@ -1169,7 +1173,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
@@ -1180,8 +1185,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:
@@ -1257,9 +1263,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: >
@@ -1304,8 +1310,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
@@ -1342,7 +1348,8 @@ Possible values are:
-addr=other other kind of range -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:
@@ -1360,7 +1367,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

@@ -5026,8 +5026,13 @@ static int uc_add_command(char_u *name, size_t name_len, char_u *rep,
} }
if (cmp == 0) { if (cmp == 0) {
if (!force) { // Command can be replaced with "command!" and when sourcing the
EMSG(_("E174: Command already exists: add ! to replace it")); // 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)) {
EMSG2(_("E174: Command already exists: add ! to replace it: %s"),
name);
goto fail; goto fail;
} }

View File

@@ -184,6 +184,34 @@ func Test_Ambiguous()
call assert_fails("\x4ei\041", 'E492: Not an editor command: Ni!') call assert_fails("\x4ei\041", 'E492: Not an editor command: Ni!')
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'