Skip to content

Commit 63b9173

Browse files
committed
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)
1 parent af647e7 commit 63b9173

File tree

16 files changed

+90
-36
lines changed

16 files changed

+90
-36
lines changed

runtime/doc/map.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,8 +1580,11 @@ Example: >
15801580
echo 'hello'
15811581
g:calledMyCommand = true
15821582
}
1583-
No nesting is supported, inline functions cannot be used. Using `:normal`
1584-
directly does not work, you can use it indirectly with `:execute`.
1583+
< *E1231*
1584+
There must be white space before the "{". No nesting is supported, inline
1585+
functions cannot be used. Commands where a "|" may appear in the argument,
1586+
such as commands with an expression argument, cannot be followed by a "|" and
1587+
another command.
15851588

15861589
The replacement text {repl} for a user defined command is scanned for special
15871590
escape sequences, using <...> notation. Escape sequences are replaced with

src/errors.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -643,4 +643,6 @@ EXTERN char e_list_dict_or_blob_required_for_argument_nr[]
643643
EXTERN char e_expected_dictionary_for_using_key_str_but_got_str[]
644644
INIT(= N_("E1229: Expected dictionary for using key \"%s\", but got %s"));
645645
EXTERN char e_encryption_sodium_mlock_failed[]
646-
INIT(= N_("E1230: encryption: sodium_mlock() failed"));
646+
INIT(= N_("E1230: Encryption: sodium_mlock() failed"));
647+
EXTERN char e_cannot_use_bar_to_separate_commands_here_str[]
648+
INIT(= N_("E1231: Cannot use a bar to separate commands here: %s"));

src/eval.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2314,7 +2314,7 @@ eval0(
23142314
}
23152315

23162316
if (eap != NULL)
2317-
eap->nextcmd = check_nextcmd(p);
2317+
set_nextcmd(eap, p);
23182318

23192319
return ret;
23202320
}
@@ -6173,7 +6173,7 @@ ex_echo(exarg_T *eap)
61736173
clear_tv(&rettv);
61746174
arg = skipwhite(arg);
61756175
}
6176-
eap->nextcmd = check_nextcmd(arg);
6176+
set_nextcmd(eap, arg);
61776177
clear_evalarg(&evalarg, eap);
61786178

61796179
if (eap->skip)
@@ -6317,7 +6317,7 @@ ex_execute(exarg_T *eap)
63176317
if (eap->skip)
63186318
--emsg_skip;
63196319

6320-
eap->nextcmd = check_nextcmd(arg);
6320+
set_nextcmd(eap, arg);
63216321
}
63226322

63236323
/*

src/evalvars.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,7 @@ ex_let(exarg_T *eap)
812812
list_func_vars(&first);
813813
list_vim_vars(&first);
814814
}
815-
eap->nextcmd = check_nextcmd(arg);
815+
set_nextcmd(eap, arg);
816816
}
817817
else if (expr[0] == '=' && expr[1] == '<' && expr[2] == '<')
818818
{
@@ -1629,7 +1629,7 @@ ex_unletlock(
16291629
arg = skipwhite(name_end);
16301630
} while (!ends_excmd2(name_end, arg));
16311631

1632-
eap->nextcmd = check_nextcmd(arg);
1632+
set_nextcmd(eap, arg);
16331633
}
16341634

16351635
static int

src/ex_cmds.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ ex_sort(exarg_T *eap)
450450
unique = TRUE;
451451
else if (*p == '"') // comment start
452452
break;
453-
else if (check_nextcmd(p) != NULL)
453+
else if (eap->nextcmd == NULL && check_nextcmd(p) != NULL)
454454
{
455455
eap->nextcmd = check_nextcmd(p);
456456
break;
@@ -3930,7 +3930,7 @@ ex_substitute(exarg_T *eap)
39303930
cmd = skipwhite(cmd);
39313931
if (*cmd && *cmd != '"') // if not end-of-line or comment
39323932
{
3933-
eap->nextcmd = check_nextcmd(cmd);
3933+
set_nextcmd(eap, cmd);
39343934
if (eap->nextcmd == NULL)
39353935
{
39363936
semsg(_(e_trailing_arg), cmd);

src/ex_docmd.c

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2314,22 +2314,24 @@ do_one_cmd(
23142314
ea.do_ecmd_cmd = getargcmd(&ea.arg);
23152315

23162316
/*
2317-
* Check for '|' to separate commands and '"' or '#' to start comments.
2318-
* Don't do this for ":read !cmd" and ":write !cmd".
2319-
*/
2320-
if ((ea.argt & EX_TRLBAR) && !ea.usefilter)
2321-
separate_nextcmd(&ea);
2322-
2323-
/*
2324-
* Check for <newline> to end a shell command.
2317+
* For commands that do not use '|' inside their argument: Check for '|' to
2318+
* separate commands and '"' or '#' to start comments.
2319+
*
2320+
* Otherwise: Check for <newline> to end a shell command.
23252321
* Also do this for ":read !cmd", ":write !cmd" and ":global".
2322+
* Also do this inside a { - } block after :command and :autocmd.
23262323
* Any others?
23272324
*/
2325+
if ((ea.argt & EX_TRLBAR) && !ea.usefilter)
2326+
{
2327+
separate_nextcmd(&ea);
2328+
}
23282329
else if (ea.cmdidx == CMD_bang
23292330
|| ea.cmdidx == CMD_terminal
23302331
|| ea.cmdidx == CMD_global
23312332
|| ea.cmdidx == CMD_vglobal
2332-
|| ea.usefilter)
2333+
|| ea.usefilter
2334+
|| inside_block(&ea))
23332335
{
23342336
for (p = ea.arg; *p; ++p)
23352337
{
@@ -5409,6 +5411,21 @@ check_nextcmd(char_u *p)
54095411
return NULL;
54105412
}
54115413

5414+
/*
5415+
* If "eap->nextcmd" is not set, check for a next command at "p".
5416+
*/
5417+
void
5418+
set_nextcmd(exarg_T *eap, char_u *arg)
5419+
{
5420+
char_u *p = check_nextcmd(arg);
5421+
5422+
if (eap->nextcmd == NULL)
5423+
eap->nextcmd = p;
5424+
else if (p != NULL)
5425+
// cannot use "| command" inside a {} block
5426+
semsg(_(e_cannot_use_bar_to_separate_commands_here_str), arg);
5427+
}
5428+
54125429
/*
54135430
* - if there are more files to edit
54145431
* - and this is the last window
@@ -7546,7 +7563,7 @@ ex_wincmd(exarg_T *eap)
75467563
else
75477564
p = eap->arg + 1;
75487565

7549-
eap->nextcmd = check_nextcmd(p);
7566+
set_nextcmd(eap, p);
75507567
p = skipwhite(p);
75517568
if (*p != NUL && *p != (
75527569
#ifdef FEAT_EVAL
@@ -8580,7 +8597,7 @@ ex_findpat(exarg_T *eap)
85808597
if (!ends_excmd2(eap->arg, p))
85818598
eap->errmsg = ex_errmsg(e_trailing_arg, p);
85828599
else
8583-
eap->nextcmd = check_nextcmd(p);
8600+
set_nextcmd(eap, p);
85848601
}
85858602
}
85868603
if (!eap->skip)

src/ex_eval.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,18 @@ ex_endblock(exarg_T *eap)
14611461
leave_block(cstack);
14621462
}
14631463

1464+
int
1465+
inside_block(exarg_T *eap)
1466+
{
1467+
cstack_T *cstack = eap->cstack;
1468+
int i;
1469+
1470+
for (i = 0; i <= cstack->cs_idx; ++i)
1471+
if (cstack->cs_flags[cstack->cs_idx] & CSF_BLOCK)
1472+
return TRUE;
1473+
return FALSE;
1474+
}
1475+
14641476
/*
14651477
* ":throw expr"
14661478
*/

src/proto/ex_docmd.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ int ends_excmd(int c);
3333
int ends_excmd2(char_u *cmd_start, char_u *cmd);
3434
char_u *find_nextcmd(char_u *p);
3535
char_u *check_nextcmd(char_u *p);
36+
void set_nextcmd(exarg_T *eap, char_u *p);
3637
char_u *get_command_name(expand_T *xp, int idx);
3738
void not_exiting(void);
3839
int before_quit_autocmds(win_T *wp, int quit_all, int forceit);

src/proto/ex_eval.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ void ex_break(exarg_T *eap);
2222
void ex_endwhile(exarg_T *eap);
2323
void ex_block(exarg_T *eap);
2424
void ex_endblock(exarg_T *eap);
25+
int inside_block(exarg_T *eap);
2526
void ex_throw(exarg_T *eap);
2627
void do_throw(cstack_T *cstack);
2728
void ex_try(exarg_T *eap);

src/syntax.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3789,7 +3789,7 @@ syn_cmd_enable(exarg_T *eap, int syncing UNUSED)
37893789
static void
37903790
syn_cmd_reset(exarg_T *eap, int syncing UNUSED)
37913791
{
3792-
eap->nextcmd = check_nextcmd(eap->arg);
3792+
set_nextcmd(eap, eap->arg);
37933793
if (!eap->skip)
37943794
{
37953795
set_internal_string_var((char_u *)"syntax_cmd", (char_u *)"reset");
@@ -3821,7 +3821,7 @@ syn_cmd_onoff(exarg_T *eap, char *name)
38213821
{
38223822
char_u buf[100];
38233823

3824-
eap->nextcmd = check_nextcmd(eap->arg);
3824+
set_nextcmd(eap, eap->arg);
38253825
if (!eap->skip)
38263826
{
38273827
STRCPY(buf, "so ");
@@ -3928,7 +3928,7 @@ syn_cmd_list(
39283928
arg = skipwhite(arg_end);
39293929
}
39303930
}
3931-
eap->nextcmd = check_nextcmd(arg);
3931+
set_nextcmd(eap, arg);
39323932
}
39333933

39343934
static void
@@ -4921,7 +4921,7 @@ syn_cmd_keyword(exarg_T *eap, int syncing UNUSED)
49214921
}
49224922

49234923
if (rest != NULL)
4924-
eap->nextcmd = check_nextcmd(rest);
4924+
set_nextcmd(eap, rest);
49254925
else
49264926
semsg(_(e_invarg2), arg);
49274927

@@ -4978,7 +4978,7 @@ syn_cmd_match(
49784978
/*
49794979
* Check for trailing command and illegal trailing arguments.
49804980
*/
4981-
eap->nextcmd = check_nextcmd(rest);
4981+
set_nextcmd(eap, rest);
49824982
if (!ends_excmd2(eap->cmd, rest) || eap->skip)
49834983
rest = NULL;
49844984
else if (ga_grow(&curwin->w_s->b_syn_patterns, 1) != FAIL
@@ -5218,7 +5218,7 @@ syn_cmd_region(
52185218
* Check for trailing garbage or command.
52195219
* If OK, add the item.
52205220
*/
5221-
eap->nextcmd = check_nextcmd(rest);
5221+
set_nextcmd(eap, rest);
52225222
if (!ends_excmd(*rest) || eap->skip)
52235223
rest = NULL;
52245224
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)
58965896
semsg(_("E404: Illegal arguments: %s"), arg_start);
58975897
else if (!finished)
58985898
{
5899-
eap->nextcmd = check_nextcmd(arg_start);
5899+
set_nextcmd(eap, arg_start);
59005900
redraw_curbuf_later(SOME_VALID);
59015901
syn_stack_free_all(curwin->w_s); // Need to recompute all syntax.
59025902
}

0 commit comments

Comments
 (0)