mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.2.3297: cannot use all commands inside a {} block
Problem: Cannot use all commands inside a {} block after :command and :autocmd. Solution: Do consider \n to separate commands. (closes #8620)
This commit is contained in:
parent
af647e76ca
commit
63b9173693
@ -1580,8 +1580,11 @@ Example: >
|
|||||||
echo 'hello'
|
echo 'hello'
|
||||||
g:calledMyCommand = true
|
g:calledMyCommand = true
|
||||||
}
|
}
|
||||||
No nesting is supported, inline functions cannot be used. Using `:normal`
|
< *E1231*
|
||||||
directly does not work, you can use it indirectly with `:execute`.
|
There must be white space before the "{". No nesting is supported, inline
|
||||||
|
functions cannot be used. Commands where a "|" may appear in the argument,
|
||||||
|
such as commands with an expression argument, cannot be followed by a "|" and
|
||||||
|
another command.
|
||||||
|
|
||||||
The replacement text {repl} for a user defined command is scanned for special
|
The replacement text {repl} for a user defined command is scanned for special
|
||||||
escape sequences, using <...> notation. Escape sequences are replaced with
|
escape sequences, using <...> notation. Escape sequences are replaced with
|
||||||
|
@ -643,4 +643,6 @@ EXTERN char e_list_dict_or_blob_required_for_argument_nr[]
|
|||||||
EXTERN char e_expected_dictionary_for_using_key_str_but_got_str[]
|
EXTERN char e_expected_dictionary_for_using_key_str_but_got_str[]
|
||||||
INIT(= N_("E1229: Expected dictionary for using key \"%s\", but got %s"));
|
INIT(= N_("E1229: Expected dictionary for using key \"%s\", but got %s"));
|
||||||
EXTERN char e_encryption_sodium_mlock_failed[]
|
EXTERN char e_encryption_sodium_mlock_failed[]
|
||||||
INIT(= N_("E1230: encryption: sodium_mlock() failed"));
|
INIT(= N_("E1230: Encryption: sodium_mlock() failed"));
|
||||||
|
EXTERN char e_cannot_use_bar_to_separate_commands_here_str[]
|
||||||
|
INIT(= N_("E1231: Cannot use a bar to separate commands here: %s"));
|
||||||
|
@ -2314,7 +2314,7 @@ eval0(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (eap != NULL)
|
if (eap != NULL)
|
||||||
eap->nextcmd = check_nextcmd(p);
|
set_nextcmd(eap, p);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -6173,7 +6173,7 @@ ex_echo(exarg_T *eap)
|
|||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
arg = skipwhite(arg);
|
arg = skipwhite(arg);
|
||||||
}
|
}
|
||||||
eap->nextcmd = check_nextcmd(arg);
|
set_nextcmd(eap, arg);
|
||||||
clear_evalarg(&evalarg, eap);
|
clear_evalarg(&evalarg, eap);
|
||||||
|
|
||||||
if (eap->skip)
|
if (eap->skip)
|
||||||
@ -6317,7 +6317,7 @@ ex_execute(exarg_T *eap)
|
|||||||
if (eap->skip)
|
if (eap->skip)
|
||||||
--emsg_skip;
|
--emsg_skip;
|
||||||
|
|
||||||
eap->nextcmd = check_nextcmd(arg);
|
set_nextcmd(eap, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -812,7 +812,7 @@ ex_let(exarg_T *eap)
|
|||||||
list_func_vars(&first);
|
list_func_vars(&first);
|
||||||
list_vim_vars(&first);
|
list_vim_vars(&first);
|
||||||
}
|
}
|
||||||
eap->nextcmd = check_nextcmd(arg);
|
set_nextcmd(eap, arg);
|
||||||
}
|
}
|
||||||
else if (expr[0] == '=' && expr[1] == '<' && expr[2] == '<')
|
else if (expr[0] == '=' && expr[1] == '<' && expr[2] == '<')
|
||||||
{
|
{
|
||||||
@ -1629,7 +1629,7 @@ ex_unletlock(
|
|||||||
arg = skipwhite(name_end);
|
arg = skipwhite(name_end);
|
||||||
} while (!ends_excmd2(name_end, arg));
|
} while (!ends_excmd2(name_end, arg));
|
||||||
|
|
||||||
eap->nextcmd = check_nextcmd(arg);
|
set_nextcmd(eap, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -450,7 +450,7 @@ ex_sort(exarg_T *eap)
|
|||||||
unique = TRUE;
|
unique = TRUE;
|
||||||
else if (*p == '"') // comment start
|
else if (*p == '"') // comment start
|
||||||
break;
|
break;
|
||||||
else if (check_nextcmd(p) != NULL)
|
else if (eap->nextcmd == NULL && check_nextcmd(p) != NULL)
|
||||||
{
|
{
|
||||||
eap->nextcmd = check_nextcmd(p);
|
eap->nextcmd = check_nextcmd(p);
|
||||||
break;
|
break;
|
||||||
@ -3930,7 +3930,7 @@ ex_substitute(exarg_T *eap)
|
|||||||
cmd = skipwhite(cmd);
|
cmd = skipwhite(cmd);
|
||||||
if (*cmd && *cmd != '"') // if not end-of-line or comment
|
if (*cmd && *cmd != '"') // if not end-of-line or comment
|
||||||
{
|
{
|
||||||
eap->nextcmd = check_nextcmd(cmd);
|
set_nextcmd(eap, cmd);
|
||||||
if (eap->nextcmd == NULL)
|
if (eap->nextcmd == NULL)
|
||||||
{
|
{
|
||||||
semsg(_(e_trailing_arg), cmd);
|
semsg(_(e_trailing_arg), cmd);
|
||||||
|
@ -2314,22 +2314,24 @@ do_one_cmd(
|
|||||||
ea.do_ecmd_cmd = getargcmd(&ea.arg);
|
ea.do_ecmd_cmd = getargcmd(&ea.arg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for '|' to separate commands and '"' or '#' to start comments.
|
* For commands that do not use '|' inside their argument: Check for '|' to
|
||||||
* Don't do this for ":read !cmd" and ":write !cmd".
|
* separate commands and '"' or '#' to start comments.
|
||||||
*/
|
*
|
||||||
if ((ea.argt & EX_TRLBAR) && !ea.usefilter)
|
* Otherwise: Check for <newline> to end a shell command.
|
||||||
separate_nextcmd(&ea);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check for <newline> to end a shell command.
|
|
||||||
* Also do this for ":read !cmd", ":write !cmd" and ":global".
|
* Also do this for ":read !cmd", ":write !cmd" and ":global".
|
||||||
|
* Also do this inside a { - } block after :command and :autocmd.
|
||||||
* Any others?
|
* Any others?
|
||||||
*/
|
*/
|
||||||
|
if ((ea.argt & EX_TRLBAR) && !ea.usefilter)
|
||||||
|
{
|
||||||
|
separate_nextcmd(&ea);
|
||||||
|
}
|
||||||
else if (ea.cmdidx == CMD_bang
|
else if (ea.cmdidx == CMD_bang
|
||||||
|| ea.cmdidx == CMD_terminal
|
|| ea.cmdidx == CMD_terminal
|
||||||
|| ea.cmdidx == CMD_global
|
|| ea.cmdidx == CMD_global
|
||||||
|| ea.cmdidx == CMD_vglobal
|
|| ea.cmdidx == CMD_vglobal
|
||||||
|| ea.usefilter)
|
|| ea.usefilter
|
||||||
|
|| inside_block(&ea))
|
||||||
{
|
{
|
||||||
for (p = ea.arg; *p; ++p)
|
for (p = ea.arg; *p; ++p)
|
||||||
{
|
{
|
||||||
@ -5409,6 +5411,21 @@ check_nextcmd(char_u *p)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If "eap->nextcmd" is not set, check for a next command at "p".
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
set_nextcmd(exarg_T *eap, char_u *arg)
|
||||||
|
{
|
||||||
|
char_u *p = check_nextcmd(arg);
|
||||||
|
|
||||||
|
if (eap->nextcmd == NULL)
|
||||||
|
eap->nextcmd = p;
|
||||||
|
else if (p != NULL)
|
||||||
|
// cannot use "| command" inside a {} block
|
||||||
|
semsg(_(e_cannot_use_bar_to_separate_commands_here_str), arg);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* - if there are more files to edit
|
* - if there are more files to edit
|
||||||
* - and this is the last window
|
* - and this is the last window
|
||||||
@ -7546,7 +7563,7 @@ ex_wincmd(exarg_T *eap)
|
|||||||
else
|
else
|
||||||
p = eap->arg + 1;
|
p = eap->arg + 1;
|
||||||
|
|
||||||
eap->nextcmd = check_nextcmd(p);
|
set_nextcmd(eap, p);
|
||||||
p = skipwhite(p);
|
p = skipwhite(p);
|
||||||
if (*p != NUL && *p != (
|
if (*p != NUL && *p != (
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
@ -8580,7 +8597,7 @@ ex_findpat(exarg_T *eap)
|
|||||||
if (!ends_excmd2(eap->arg, p))
|
if (!ends_excmd2(eap->arg, p))
|
||||||
eap->errmsg = ex_errmsg(e_trailing_arg, p);
|
eap->errmsg = ex_errmsg(e_trailing_arg, p);
|
||||||
else
|
else
|
||||||
eap->nextcmd = check_nextcmd(p);
|
set_nextcmd(eap, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!eap->skip)
|
if (!eap->skip)
|
||||||
|
@ -1461,6 +1461,18 @@ ex_endblock(exarg_T *eap)
|
|||||||
leave_block(cstack);
|
leave_block(cstack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
inside_block(exarg_T *eap)
|
||||||
|
{
|
||||||
|
cstack_T *cstack = eap->cstack;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i <= cstack->cs_idx; ++i)
|
||||||
|
if (cstack->cs_flags[cstack->cs_idx] & CSF_BLOCK)
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ":throw expr"
|
* ":throw expr"
|
||||||
*/
|
*/
|
||||||
|
@ -33,6 +33,7 @@ int ends_excmd(int c);
|
|||||||
int ends_excmd2(char_u *cmd_start, char_u *cmd);
|
int ends_excmd2(char_u *cmd_start, char_u *cmd);
|
||||||
char_u *find_nextcmd(char_u *p);
|
char_u *find_nextcmd(char_u *p);
|
||||||
char_u *check_nextcmd(char_u *p);
|
char_u *check_nextcmd(char_u *p);
|
||||||
|
void set_nextcmd(exarg_T *eap, char_u *p);
|
||||||
char_u *get_command_name(expand_T *xp, int idx);
|
char_u *get_command_name(expand_T *xp, int idx);
|
||||||
void not_exiting(void);
|
void not_exiting(void);
|
||||||
int before_quit_autocmds(win_T *wp, int quit_all, int forceit);
|
int before_quit_autocmds(win_T *wp, int quit_all, int forceit);
|
||||||
|
@ -22,6 +22,7 @@ void ex_break(exarg_T *eap);
|
|||||||
void ex_endwhile(exarg_T *eap);
|
void ex_endwhile(exarg_T *eap);
|
||||||
void ex_block(exarg_T *eap);
|
void ex_block(exarg_T *eap);
|
||||||
void ex_endblock(exarg_T *eap);
|
void ex_endblock(exarg_T *eap);
|
||||||
|
int inside_block(exarg_T *eap);
|
||||||
void ex_throw(exarg_T *eap);
|
void ex_throw(exarg_T *eap);
|
||||||
void do_throw(cstack_T *cstack);
|
void do_throw(cstack_T *cstack);
|
||||||
void ex_try(exarg_T *eap);
|
void ex_try(exarg_T *eap);
|
||||||
|
14
src/syntax.c
14
src/syntax.c
@ -3789,7 +3789,7 @@ syn_cmd_enable(exarg_T *eap, int syncing UNUSED)
|
|||||||
static void
|
static void
|
||||||
syn_cmd_reset(exarg_T *eap, int syncing UNUSED)
|
syn_cmd_reset(exarg_T *eap, int syncing UNUSED)
|
||||||
{
|
{
|
||||||
eap->nextcmd = check_nextcmd(eap->arg);
|
set_nextcmd(eap, eap->arg);
|
||||||
if (!eap->skip)
|
if (!eap->skip)
|
||||||
{
|
{
|
||||||
set_internal_string_var((char_u *)"syntax_cmd", (char_u *)"reset");
|
set_internal_string_var((char_u *)"syntax_cmd", (char_u *)"reset");
|
||||||
@ -3821,7 +3821,7 @@ syn_cmd_onoff(exarg_T *eap, char *name)
|
|||||||
{
|
{
|
||||||
char_u buf[100];
|
char_u buf[100];
|
||||||
|
|
||||||
eap->nextcmd = check_nextcmd(eap->arg);
|
set_nextcmd(eap, eap->arg);
|
||||||
if (!eap->skip)
|
if (!eap->skip)
|
||||||
{
|
{
|
||||||
STRCPY(buf, "so ");
|
STRCPY(buf, "so ");
|
||||||
@ -3928,7 +3928,7 @@ syn_cmd_list(
|
|||||||
arg = skipwhite(arg_end);
|
arg = skipwhite(arg_end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
eap->nextcmd = check_nextcmd(arg);
|
set_nextcmd(eap, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -4921,7 +4921,7 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rest != NULL)
|
if (rest != NULL)
|
||||||
eap->nextcmd = check_nextcmd(rest);
|
set_nextcmd(eap, rest);
|
||||||
else
|
else
|
||||||
semsg(_(e_invarg2), arg);
|
semsg(_(e_invarg2), arg);
|
||||||
|
|
||||||
@ -4978,7 +4978,7 @@ syn_cmd_match(
|
|||||||
/*
|
/*
|
||||||
* Check for trailing command and illegal trailing arguments.
|
* Check for trailing command and illegal trailing arguments.
|
||||||
*/
|
*/
|
||||||
eap->nextcmd = check_nextcmd(rest);
|
set_nextcmd(eap, rest);
|
||||||
if (!ends_excmd2(eap->cmd, rest) || eap->skip)
|
if (!ends_excmd2(eap->cmd, rest) || eap->skip)
|
||||||
rest = NULL;
|
rest = NULL;
|
||||||
else if (ga_grow(&curwin->w_s->b_syn_patterns, 1) != FAIL
|
else if (ga_grow(&curwin->w_s->b_syn_patterns, 1) != FAIL
|
||||||
@ -5218,7 +5218,7 @@ syn_cmd_region(
|
|||||||
* Check for trailing garbage or command.
|
* Check for trailing garbage or command.
|
||||||
* If OK, add the item.
|
* If OK, add the item.
|
||||||
*/
|
*/
|
||||||
eap->nextcmd = check_nextcmd(rest);
|
set_nextcmd(eap, rest);
|
||||||
if (!ends_excmd(*rest) || eap->skip)
|
if (!ends_excmd(*rest) || eap->skip)
|
||||||
rest = NULL;
|
rest = NULL;
|
||||||
else if (ga_grow(&(curwin->w_s->b_syn_patterns), pat_count) != FAIL
|
else if (ga_grow(&(curwin->w_s->b_syn_patterns), pat_count) != FAIL
|
||||||
@ -5896,7 +5896,7 @@ syn_cmd_sync(exarg_T *eap, int syncing UNUSED)
|
|||||||
semsg(_("E404: Illegal arguments: %s"), arg_start);
|
semsg(_("E404: Illegal arguments: %s"), arg_start);
|
||||||
else if (!finished)
|
else if (!finished)
|
||||||
{
|
{
|
||||||
eap->nextcmd = check_nextcmd(arg_start);
|
set_nextcmd(eap, arg_start);
|
||||||
redraw_curbuf_later(SOME_VALID);
|
redraw_curbuf_later(SOME_VALID);
|
||||||
syn_stack_free_all(curwin->w_s); // Need to recompute all syntax.
|
syn_stack_free_all(curwin->w_s); // Need to recompute all syntax.
|
||||||
}
|
}
|
||||||
|
@ -2816,11 +2816,19 @@ func Test_autocmd_with_block()
|
|||||||
setlocal matchpairs+=<:>
|
setlocal matchpairs+=<:>
|
||||||
/<start
|
/<start
|
||||||
}
|
}
|
||||||
|
au CursorHold * {
|
||||||
|
autocmd BufReadPre * ++once echo 'one' | echo 'two'
|
||||||
|
g:gotSafeState = 77
|
||||||
|
}
|
||||||
augroup END
|
augroup END
|
||||||
|
|
||||||
let expected = "\n--- Autocommands ---\nblock_testing BufRead\n *.xml {^@ setlocal matchpairs+=<:>^@ /<start^@ }"
|
let expected = "\n--- Autocommands ---\nblock_testing BufRead\n *.xml {^@ setlocal matchpairs+=<:>^@ /<start^@ }"
|
||||||
call assert_equal(expected, execute('au BufReadPost *.xml'))
|
call assert_equal(expected, execute('au BufReadPost *.xml'))
|
||||||
|
|
||||||
|
doautocmd CursorHold
|
||||||
|
call assert_equal(77, g:gotSafeState)
|
||||||
|
unlet g:gotSafeState
|
||||||
|
|
||||||
augroup block_testing
|
augroup block_testing
|
||||||
au!
|
au!
|
||||||
augroup END
|
augroup END
|
||||||
|
@ -645,6 +645,14 @@ func Test_usercmd_with_block()
|
|||||||
echo 'hello'
|
echo 'hello'
|
||||||
END
|
END
|
||||||
call CheckScriptFailure(lines, 'E1026:')
|
call CheckScriptFailure(lines, 'E1026:')
|
||||||
|
|
||||||
|
let lines =<< trim END
|
||||||
|
command BarCommand {
|
||||||
|
echo 'hello' | echo 'there'
|
||||||
|
}
|
||||||
|
BarCommand
|
||||||
|
END
|
||||||
|
call CheckScriptFailure(lines, 'E1231:')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
@ -3842,7 +3842,7 @@ define_function(exarg_T *eap, char_u *name_arg)
|
|||||||
{
|
{
|
||||||
if (!eap->skip)
|
if (!eap->skip)
|
||||||
list_functions(NULL);
|
list_functions(NULL);
|
||||||
eap->nextcmd = check_nextcmd(eap->arg);
|
set_nextcmd(eap, eap->arg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3869,7 +3869,7 @@ define_function(exarg_T *eap, char_u *name_arg)
|
|||||||
}
|
}
|
||||||
if (*p == '/')
|
if (*p == '/')
|
||||||
++p;
|
++p;
|
||||||
eap->nextcmd = check_nextcmd(p);
|
set_nextcmd(eap, p);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3947,7 +3947,7 @@ define_function(exarg_T *eap, char_u *name_arg)
|
|||||||
semsg(_(e_trailing_arg), p);
|
semsg(_(e_trailing_arg), p);
|
||||||
goto ret_free;
|
goto ret_free;
|
||||||
}
|
}
|
||||||
eap->nextcmd = check_nextcmd(p);
|
set_nextcmd(eap, p);
|
||||||
if (eap->nextcmd != NULL)
|
if (eap->nextcmd != NULL)
|
||||||
*p = NUL;
|
*p = NUL;
|
||||||
if (!eap->skip && !got_int)
|
if (!eap->skip && !got_int)
|
||||||
@ -4655,7 +4655,7 @@ ex_delfunction(exarg_T *eap)
|
|||||||
semsg(_(e_trailing_arg), p);
|
semsg(_(e_trailing_arg), p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
eap->nextcmd = check_nextcmd(p);
|
set_nextcmd(eap, p);
|
||||||
if (eap->nextcmd != NULL)
|
if (eap->nextcmd != NULL)
|
||||||
*p = NUL;
|
*p = NUL;
|
||||||
|
|
||||||
@ -4844,7 +4844,7 @@ ex_return(exarg_T *eap)
|
|||||||
if (returning)
|
if (returning)
|
||||||
eap->nextcmd = NULL;
|
eap->nextcmd = NULL;
|
||||||
else if (eap->nextcmd == NULL) // no argument
|
else if (eap->nextcmd == NULL) // no argument
|
||||||
eap->nextcmd = check_nextcmd(arg);
|
set_nextcmd(eap, arg);
|
||||||
|
|
||||||
if (eap->skip)
|
if (eap->skip)
|
||||||
--emsg_skip;
|
--emsg_skip;
|
||||||
@ -5004,7 +5004,7 @@ ex_call(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
eap->nextcmd = check_nextcmd(arg);
|
set_nextcmd(eap, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
@ -755,6 +755,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 */
|
||||||
|
/**/
|
||||||
|
3297,
|
||||||
/**/
|
/**/
|
||||||
3296,
|
3296,
|
||||||
/**/
|
/**/
|
||||||
|
@ -5691,7 +5691,7 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx)
|
|||||||
name_end = skip_regexp(name_start + 1, '/', TRUE);
|
name_end = skip_regexp(name_start + 1, '/', TRUE);
|
||||||
if (*name_end == '/')
|
if (*name_end == '/')
|
||||||
++name_end;
|
++name_end;
|
||||||
eap->nextcmd = check_nextcmd(name_end);
|
set_nextcmd(eap, name_end);
|
||||||
}
|
}
|
||||||
if (name_end == name_start || *skipwhite(name_end) != '(')
|
if (name_end == name_start || *skipwhite(name_end) != '(')
|
||||||
{
|
{
|
||||||
|
@ -311,7 +311,7 @@ ex_import(exarg_T *eap)
|
|||||||
cmd_end = handle_import(eap->arg, NULL, current_sctx.sc_sid,
|
cmd_end = handle_import(eap->arg, NULL, current_sctx.sc_sid,
|
||||||
&evalarg, NULL);
|
&evalarg, NULL);
|
||||||
if (cmd_end != NULL)
|
if (cmd_end != NULL)
|
||||||
eap->nextcmd = check_nextcmd(cmd_end);
|
set_nextcmd(eap, cmd_end);
|
||||||
clear_evalarg(&evalarg, eap);
|
clear_evalarg(&evalarg, eap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user