From a25dbeee10756a8f457d4632e8fda0c1cb509d61 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 16 Aug 2024 08:32:53 +0800 Subject: [PATCH] vim-patch:9.1.0677: :keepp does not retain the substitute pattern Problem: :keeppatterns does not retain the substitute pattern for a :s command Solution: preserve the last substitute pattern when used with the :keeppatterns command modifier (Gregory Anders) closes: vim/vim#15497 https://github.com/vim/vim/commit/3b59be4ed8a145d3188934f1a5cd85432bd2433d Co-authored-by: Gregory Anders --- runtime/doc/cmdline.txt | 2 +- src/nvim/ex_cmds.c | 10 ++++++---- test/old/testdir/test_substitute.vim | 15 ++++++++++----- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt index f306067a9c..fa68d69371 100644 --- a/runtime/doc/cmdline.txt +++ b/runtime/doc/cmdline.txt @@ -348,7 +348,7 @@ terminals) :keepp[atterns] {command} *:keepp* *:keeppatterns* Execute {command}, without adding anything to the search - history + history or modifying the last substitute pattern. ============================================================================== 2. Command-line completion *cmdline-completion* diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 8c536d4838..5e87936be1 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -3085,7 +3085,7 @@ void sub_set_replacement(SubReplacementString sub) /// /// @returns true if :substitute can be replaced with a join command static bool sub_joining_lines(exarg_T *eap, char *pat, size_t patlen, const char *sub, - const char *cmd, bool save) + const char *cmd, bool save, bool keeppatterns) FUNC_ATTR_NONNULL_ARG(1, 4, 5) { // TODO(vim): find a generic solution to make line-joining operations more @@ -3123,7 +3123,7 @@ static bool sub_joining_lines(exarg_T *eap, char *pat, size_t patlen, const char } if (save) { - if ((cmdmod.cmod_flags & CMOD_KEEPPATTERNS) == 0) { + if (!keeppatterns) { save_re_pat(RE_SUBST, pat, patlen, magic_isset()); } // put pattern in history @@ -3331,6 +3331,7 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_n linenr_T old_line_count = curbuf->b_ml.ml_line_count; char *sub_firstline; // allocated copy of first sub line bool endcolumn = false; // cursor in last column when done + const bool keeppatterns = cmdmod.cmod_flags & CMOD_KEEPPATTERNS; PreviewLines preview_lines = { KV_INITIAL_VALUE, 0 }; static int pre_hl_id = 0; pos_T old_cursor = curwin->w_cursor; @@ -3391,7 +3392,7 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_n cmd = skip_substitute(cmd, delimiter); sub = xstrdup(p); - if (!eap->skip && cmdpreview_ns <= 0) { + if (!eap->skip && !keeppatterns && cmdpreview_ns <= 0) { sub_set_replacement((SubReplacementString) { .sub = xstrdup(sub), .timestamp = os_time(), @@ -3412,7 +3413,8 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_n endcolumn = (curwin->w_curswant == MAXCOL); } - if (sub != NULL && sub_joining_lines(eap, pat, patlen, sub, cmd, cmdpreview_ns <= 0)) { + if (sub != NULL && sub_joining_lines(eap, pat, patlen, sub, cmd, cmdpreview_ns <= 0, + keeppatterns)) { xfree(sub); return 0; } diff --git a/test/old/testdir/test_substitute.vim b/test/old/testdir/test_substitute.vim index f0a25b2804..90c46abe8b 100644 --- a/test/old/testdir/test_substitute.vim +++ b/test/old/testdir/test_substitute.vim @@ -806,7 +806,7 @@ func Test_replace_keeppatterns() a foobar -substitute foo asdf +substitute foo asdf foo one two . @@ -815,21 +815,26 @@ one two /^substitute s/foo/bar/ call assert_equal('foo', @/) - call assert_equal('substitute bar asdf', getline('.')) + call assert_equal('substitute bar asdf foo', getline('.')) /^substitute keeppatterns s/asdf/xyz/ call assert_equal('^substitute', @/) - call assert_equal('substitute bar xyz', getline('.')) + call assert_equal('substitute bar xyz foo', getline('.')) + + /^substitute + & + call assert_equal('^substitute', @/) + call assert_equal('substitute bar xyz bar', getline('.')) exe "normal /bar /e\" call assert_equal(15, col('.')) normal - keeppatterns /xyz call assert_equal('bar ', @/) - call assert_equal('substitute bar xyz', getline('.')) + call assert_equal('substitute bar xyz bar', getline('.')) exe "normal 0dn" - call assert_equal('xyz', getline('.')) + call assert_equal('xyz bar', getline('.')) close! endfunc