diff options
-rw-r--r-- | runtime/doc/map.txt | 7 | ||||
-rw-r--r-- | src/errors.h | 4 | ||||
-rw-r--r-- | src/eval.c | 6 | ||||
-rw-r--r-- | src/evalvars.c | 4 | ||||
-rw-r--r-- | src/ex_cmds.c | 4 | ||||
-rw-r--r-- | src/ex_docmd.c | 39 | ||||
-rw-r--r-- | src/ex_eval.c | 12 | ||||
-rw-r--r-- | src/proto/ex_docmd.pro | 1 | ||||
-rw-r--r-- | src/proto/ex_eval.pro | 1 | ||||
-rw-r--r-- | src/syntax.c | 14 | ||||
-rw-r--r-- | src/testdir/test_autocmd.vim | 8 | ||||
-rw-r--r-- | src/testdir/test_usercommands.vim | 8 | ||||
-rw-r--r-- | src/userfunc.c | 12 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9compile.c | 2 | ||||
-rw-r--r-- | src/vim9script.c | 2 |
16 files changed, 90 insertions, 36 deletions
diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index a10c85b7a..57239923a 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -1580,8 +1580,11 @@ Example: > echo 'hello' g:calledMyCommand = true } -No nesting is supported, inline functions cannot be used. Using `:normal` -directly does not work, you can use it indirectly with `:execute`. +< *E1231* +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 escape sequences, using <...> notation. Escape sequences are replaced with diff --git a/src/errors.h b/src/errors.h index 942cf658b..24420e43e 100644 --- a/src/errors.h +++ b/src/errors.h @@ -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[] INIT(= N_("E1229: Expected dictionary for using key \"%s\", but got %s")); 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")); diff --git a/src/eval.c b/src/eval.c index 550fe8e2b..a72519dc4 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2314,7 +2314,7 @@ eval0( } if (eap != NULL) - eap->nextcmd = check_nextcmd(p); + set_nextcmd(eap, p); return ret; } @@ -6173,7 +6173,7 @@ ex_echo(exarg_T *eap) clear_tv(&rettv); arg = skipwhite(arg); } - eap->nextcmd = check_nextcmd(arg); + set_nextcmd(eap, arg); clear_evalarg(&evalarg, eap); if (eap->skip) @@ -6317,7 +6317,7 @@ ex_execute(exarg_T *eap) if (eap->skip) --emsg_skip; - eap->nextcmd = check_nextcmd(arg); + set_nextcmd(eap, arg); } /* diff --git a/src/evalvars.c b/src/evalvars.c index dc747f717..721b688d5 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -812,7 +812,7 @@ ex_let(exarg_T *eap) list_func_vars(&first); list_vim_vars(&first); } - eap->nextcmd = check_nextcmd(arg); + set_nextcmd(eap, arg); } else if (expr[0] == '=' && expr[1] == '<' && expr[2] == '<') { @@ -1629,7 +1629,7 @@ ex_unletlock( arg = skipwhite(name_end); } while (!ends_excmd2(name_end, arg)); - eap->nextcmd = check_nextcmd(arg); + set_nextcmd(eap, arg); } static int diff --git a/src/ex_cmds.c b/src/ex_cmds.c index d9ec4a44b..d30db9195 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -450,7 +450,7 @@ ex_sort(exarg_T *eap) unique = TRUE; else if (*p == '"') // comment start break; - else if (check_nextcmd(p) != NULL) + else if (eap->nextcmd == NULL && check_nextcmd(p) != NULL) { eap->nextcmd = check_nextcmd(p); break; @@ -3930,7 +3930,7 @@ ex_substitute(exarg_T *eap) cmd = skipwhite(cmd); if (*cmd && *cmd != '"') // if not end-of-line or comment { - eap->nextcmd = check_nextcmd(cmd); + set_nextcmd(eap, cmd); if (eap->nextcmd == NULL) { semsg(_(e_trailing_arg), cmd); diff --git a/src/ex_docmd.c b/src/ex_docmd.c index fde68be72..a0e8370c2 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -2314,22 +2314,24 @@ do_one_cmd( ea.do_ecmd_cmd = getargcmd(&ea.arg); /* - * Check for '|' to separate commands and '"' or '#' to start comments. - * Don't do this for ":read !cmd" and ":write !cmd". - */ - if ((ea.argt & EX_TRLBAR) && !ea.usefilter) - separate_nextcmd(&ea); - - /* - * Check for <newline> to end a shell command. + * For commands that do not use '|' inside their argument: Check for '|' to + * separate commands and '"' or '#' to start comments. + * + * Otherwise: Check for <newline> to end a shell command. * Also do this for ":read !cmd", ":write !cmd" and ":global". + * Also do this inside a { - } block after :command and :autocmd. * Any others? */ + if ((ea.argt & EX_TRLBAR) && !ea.usefilter) + { + separate_nextcmd(&ea); + } else if (ea.cmdidx == CMD_bang || ea.cmdidx == CMD_terminal || ea.cmdidx == CMD_global || ea.cmdidx == CMD_vglobal - || ea.usefilter) + || ea.usefilter + || inside_block(&ea)) { for (p = ea.arg; *p; ++p) { @@ -5410,6 +5412,21 @@ check_nextcmd(char_u *p) } /* + * 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 * - and this is the last window * - and forceit not used @@ -7546,7 +7563,7 @@ ex_wincmd(exarg_T *eap) else p = eap->arg + 1; - eap->nextcmd = check_nextcmd(p); + set_nextcmd(eap, p); p = skipwhite(p); if (*p != NUL && *p != ( #ifdef FEAT_EVAL @@ -8580,7 +8597,7 @@ ex_findpat(exarg_T *eap) if (!ends_excmd2(eap->arg, p)) eap->errmsg = ex_errmsg(e_trailing_arg, p); else - eap->nextcmd = check_nextcmd(p); + set_nextcmd(eap, p); } } if (!eap->skip) diff --git a/src/ex_eval.c b/src/ex_eval.c index 827f9cdcd..77dceccf0 100644 --- a/src/ex_eval.c +++ b/src/ex_eval.c @@ -1461,6 +1461,18 @@ ex_endblock(exarg_T *eap) 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" */ diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro index 419d00457..ae378d9ed 100644 --- a/src/proto/ex_docmd.pro +++ b/src/proto/ex_docmd.pro @@ -33,6 +33,7 @@ int ends_excmd(int c); int ends_excmd2(char_u *cmd_start, char_u *cmd); char_u *find_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); void not_exiting(void); int before_quit_autocmds(win_T *wp, int quit_all, int forceit); diff --git a/src/proto/ex_eval.pro b/src/proto/ex_eval.pro index f1861612a..f5037c932 100644 --- a/src/proto/ex_eval.pro +++ b/src/proto/ex_eval.pro @@ -22,6 +22,7 @@ void ex_break(exarg_T *eap); void ex_endwhile(exarg_T *eap); void ex_block(exarg_T *eap); void ex_endblock(exarg_T *eap); +int inside_block(exarg_T *eap); void ex_throw(exarg_T *eap); void do_throw(cstack_T *cstack); void ex_try(exarg_T *eap); diff --git a/src/syntax.c b/src/syntax.c index fea317ab3..b3545b37b 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -3789,7 +3789,7 @@ syn_cmd_enable(exarg_T *eap, int syncing UNUSED) static void syn_cmd_reset(exarg_T *eap, int syncing UNUSED) { - eap->nextcmd = check_nextcmd(eap->arg); + set_nextcmd(eap, eap->arg); if (!eap->skip) { 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]; - eap->nextcmd = check_nextcmd(eap->arg); + set_nextcmd(eap, eap->arg); if (!eap->skip) { STRCPY(buf, "so "); @@ -3928,7 +3928,7 @@ syn_cmd_list( arg = skipwhite(arg_end); } } - eap->nextcmd = check_nextcmd(arg); + set_nextcmd(eap, arg); } static void @@ -4921,7 +4921,7 @@ error: } if (rest != NULL) - eap->nextcmd = check_nextcmd(rest); + set_nextcmd(eap, rest); else semsg(_(e_invarg2), arg); @@ -4978,7 +4978,7 @@ syn_cmd_match( /* * 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) rest = NULL; 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. * If OK, add the item. */ - eap->nextcmd = check_nextcmd(rest); + set_nextcmd(eap, rest); if (!ends_excmd(*rest) || eap->skip) rest = NULL; 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); else if (!finished) { - eap->nextcmd = check_nextcmd(arg_start); + set_nextcmd(eap, arg_start); redraw_curbuf_later(SOME_VALID); syn_stack_free_all(curwin->w_s); // Need to recompute all syntax. } diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim index 4a7dd60f6..b2e4952be 100644 --- a/src/testdir/test_autocmd.vim +++ b/src/testdir/test_autocmd.vim @@ -2816,11 +2816,19 @@ func Test_autocmd_with_block() setlocal matchpairs+=<:> /<start } + au CursorHold * { + autocmd BufReadPre * ++once echo 'one' | echo 'two' + g:gotSafeState = 77 + } augroup END let expected = "\n--- Autocommands ---\nblock_testing BufRead\n *.xml {^@ setlocal matchpairs+=<:>^@ /<start^@ }" call assert_equal(expected, execute('au BufReadPost *.xml')) + doautocmd CursorHold + call assert_equal(77, g:gotSafeState) + unlet g:gotSafeState + augroup block_testing au! augroup END diff --git a/src/testdir/test_usercommands.vim b/src/testdir/test_usercommands.vim index 173b23ed2..9cb592e23 100644 --- a/src/testdir/test_usercommands.vim +++ b/src/testdir/test_usercommands.vim @@ -645,6 +645,14 @@ func Test_usercmd_with_block() echo 'hello' END call CheckScriptFailure(lines, 'E1026:') + + let lines =<< trim END + command BarCommand { + echo 'hello' | echo 'there' + } + BarCommand + END + call CheckScriptFailure(lines, 'E1231:') endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/userfunc.c b/src/userfunc.c index 5cb3d92e6..79a6621b2 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -3842,7 +3842,7 @@ define_function(exarg_T *eap, char_u *name_arg) { if (!eap->skip) list_functions(NULL); - eap->nextcmd = check_nextcmd(eap->arg); + set_nextcmd(eap, eap->arg); return NULL; } @@ -3869,7 +3869,7 @@ define_function(exarg_T *eap, char_u *name_arg) } if (*p == '/') ++p; - eap->nextcmd = check_nextcmd(p); + set_nextcmd(eap, p); return NULL; } @@ -3947,7 +3947,7 @@ define_function(exarg_T *eap, char_u *name_arg) semsg(_(e_trailing_arg), p); goto ret_free; } - eap->nextcmd = check_nextcmd(p); + set_nextcmd(eap, p); if (eap->nextcmd != NULL) *p = NUL; if (!eap->skip && !got_int) @@ -4655,7 +4655,7 @@ ex_delfunction(exarg_T *eap) semsg(_(e_trailing_arg), p); return; } - eap->nextcmd = check_nextcmd(p); + set_nextcmd(eap, p); if (eap->nextcmd != NULL) *p = NUL; @@ -4844,7 +4844,7 @@ ex_return(exarg_T *eap) if (returning) eap->nextcmd = NULL; else if (eap->nextcmd == NULL) // no argument - eap->nextcmd = check_nextcmd(arg); + set_nextcmd(eap, arg); if (eap->skip) --emsg_skip; @@ -5004,7 +5004,7 @@ ex_call(exarg_T *eap) } } else - eap->nextcmd = check_nextcmd(arg); + set_nextcmd(eap, arg); } end: diff --git a/src/version.c b/src/version.c index c6852f1e7..48df2c1bd 100644 --- a/src/version.c +++ b/src/version.c @@ -756,6 +756,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3297, +/**/ 3296, /**/ 3295, diff --git a/src/vim9compile.c b/src/vim9compile.c index d2a6f68db..d96724b12 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -5691,7 +5691,7 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx) name_end = skip_regexp(name_start + 1, '/', TRUE); if (*name_end == '/') ++name_end; - eap->nextcmd = check_nextcmd(name_end); + set_nextcmd(eap, name_end); } if (name_end == name_start || *skipwhite(name_end) != '(') { diff --git a/src/vim9script.c b/src/vim9script.c index 40f857fe0..68919e8cc 100644 --- a/src/vim9script.c +++ b/src/vim9script.c @@ -311,7 +311,7 @@ ex_import(exarg_T *eap) cmd_end = handle_import(eap->arg, NULL, current_sctx.sc_sid, &evalarg, NULL); if (cmd_end != NULL) - eap->nextcmd = check_nextcmd(cmd_end); + set_nextcmd(eap, cmd_end); clear_evalarg(&evalarg, eap); } |