From e729ce294f9756165020ad86e3b98b4112e1a6ab Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 6 Jun 2021 21:38:09 +0200 Subject: patch 8.2.2955: Vim9: using filter in compiled command does not work Problem: Vim9: using filter in compiled command does not work. Solution: Generate EXEC including the command modifier. --- src/ex_cmds.c | 24 ++++++++++++++++++++++++ src/ex_docmd.c | 10 ++++++++-- src/proto/ex_cmds.pro | 1 + src/testdir/test_vim9_cmd.vim | 8 ++++++++ src/version.c | 2 ++ src/vim9compile.c | 23 ++++++++++++++++++++--- 6 files changed, 63 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/ex_cmds.c b/src/ex_cmds.c index e1497a5a4a..614d41d69f 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -5277,6 +5277,16 @@ ex_drop(exarg_T *eap) */ char_u * skip_vimgrep_pat(char_u *p, char_u **s, int *flags) +{ + return skip_vimgrep_pat_ext(p, s, flags, NULL, NULL); +} + +/* + * As skip_vimgrep_pat() and store the character overwritten by NUL in "cp" + * and the pointer to it in "nulp". + */ + char_u * +skip_vimgrep_pat_ext(char_u *p, char_u **s, int *flags, char_u **nulp, int *cp) { int c; @@ -5287,7 +5297,14 @@ skip_vimgrep_pat(char_u *p, char_u **s, int *flags) *s = p; p = skiptowhite(p); if (s != NULL && *p != NUL) + { + if (nulp != NULL) + { + *nulp = p; + *cp = *p; + } *p++ = NUL; + } } else { @@ -5301,7 +5318,14 @@ skip_vimgrep_pat(char_u *p, char_u **s, int *flags) // Truncate the pattern. if (s != NULL) + { + if (nulp != NULL) + { + *nulp = p; + *cp = *p; + } *p = NUL; + } ++p; // Find the flags diff --git a/src/ex_docmd.c b/src/ex_docmd.c index fbf2c7d0dd..4aaccb593f 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -2881,7 +2881,9 @@ parse_command_modifiers( case 'f': // only accept ":filter {pat} cmd" { - char_u *reg_pat; + char_u *reg_pat; + char_u *nulp = NULL; + int c = 0; if (!checkforcmd_noparen(&p, "filter", 4) || *p == NUL || ends_excmd(*p)) @@ -2902,7 +2904,8 @@ parse_command_modifiers( p = skip_vimgrep_pat(p, NULL, NULL); else // NOTE: This puts a NUL after the pattern. - p = skip_vimgrep_pat(p, ®_pat, NULL); + p = skip_vimgrep_pat_ext(p, ®_pat, NULL, + &nulp, &c); if (p == NULL || *p == NUL) break; if (!skip_only) @@ -2911,6 +2914,9 @@ parse_command_modifiers( vim_regcomp(reg_pat, RE_MAGIC); if (cmod->cmod_filter_regmatch.regprog == NULL) break; + // restore the character overwritten by NUL + if (nulp != NULL) + *nulp = c; } eap->cmd = p; continue; diff --git a/src/proto/ex_cmds.pro b/src/proto/ex_cmds.pro index 1711af4537..c083cec5cc 100644 --- a/src/proto/ex_cmds.pro +++ b/src/proto/ex_cmds.pro @@ -39,5 +39,6 @@ int prepare_tagpreview(int undo_sync, int use_previewpopup, use_popup_T use_popu void ex_smile(exarg_T *eap); void ex_drop(exarg_T *eap); char_u *skip_vimgrep_pat(char_u *p, char_u **s, int *flags); +char_u *skip_vimgrep_pat_ext(char_u *p, char_u **s, int *flags, char_u **nulp, int *cp); void ex_oldfiles(exarg_T *eap); /* vim: set ft=c : */ diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim index 8481ecc595..23c5cfacf6 100644 --- a/src/testdir/test_vim9_cmd.vim +++ b/src/testdir/test_vim9_cmd.vim @@ -534,6 +534,14 @@ def Test_command_modifier_filter() assert_equal(execute('filter /piyo/ registers abc'), expected) END CheckDefAndScriptSuccess(lines) + + # also do this compiled + lines =<< trim END + @a = 'very specific z3d37dh234 string' + filter z3d37dh234 registers + assert_match('very specific z3d37dh234 string', Screenline(&lines)) + END + CheckDefAndScriptSuccess(lines) enddef def Test_win_command_modifiers() diff --git a/src/version.c b/src/version.c index f9529abc1d..4dc6bd523b 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2955, /**/ 2954, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 0c73433d5f..1256bfaac4 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -8536,13 +8536,30 @@ compile_put(char_u *arg, exarg_T *eap, cctx_T *cctx) static char_u * compile_exec(char_u *line, exarg_T *eap, cctx_T *cctx) { - char_u *p; - int has_expr = FALSE; - char_u *nextcmd = (char_u *)""; + char_u *p; + int has_expr = FALSE; + char_u *nextcmd = (char_u *)""; if (cctx->ctx_skip == SKIP_YES) goto theend; + // If there was a prececing command modifier, drop it and include it in the + // EXEC command. + if (cctx->ctx_has_cmdmod) + { + garray_T *instr = &cctx->ctx_instr; + isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1; + + if (isn->isn_type == ISN_CMDMOD) + { + vim_regfree(isn->isn_arg.cmdmod.cf_cmdmod + ->cmod_filter_regmatch.regprog); + vim_free(isn->isn_arg.cmdmod.cf_cmdmod); + --instr->ga_len; + cctx->ctx_has_cmdmod = FALSE; + } + } + if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE) { long argt = eap->argt; -- cgit v1.2.3