diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2017-09-15 00:04:42 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-15 00:04:42 +0200 |
commit | 1551f7132152aa17d59902fcab2722e9068f9618 (patch) | |
tree | cf34cb4727837071e1ecf1c3950bcf06bbeae551 | |
parent | d2cbc311855114b7736919a344a82e303d4a8164 (diff) | |
parent | 2736f0cb5631dec43064c77f504a7bc160aaeeb1 (diff) | |
download | rneovim-1551f7132152aa17d59902fcab2722e9068f9618.tar.gz rneovim-1551f7132152aa17d59902fcab2722e9068f9618.tar.bz2 rneovim-1551f7132152aa17d59902fcab2722e9068f9618.zip |
Merge #7262 'inccommand': fix 'gdefault' lockup
-rw-r--r-- | src/nvim/ex_cmds.c | 66 | ||||
-rw-r--r-- | test/functional/ui/inccommand_spec.lua | 27 |
2 files changed, 65 insertions, 28 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 4b3e02e5fd..918e7a0c91 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -3665,6 +3665,42 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout) * use "\=col("."). */ curwin->w_cursor.col = regmatch.startpos[0].col; + // When the match included the "$" of the last line it may + // go beyond the last line of the buffer. + if (nmatch > curbuf->b_ml.ml_line_count - sub_firstlnum + 1) { + nmatch = curbuf->b_ml.ml_line_count - sub_firstlnum + 1; + skip_match = true; + } + +#define ADJUST_SUB_FIRSTLNUM() \ + do { \ + /* For a multi-line match, make a copy of the last matched */ \ + /* line and continue in that one. */ \ + if (nmatch > 1) { \ + sub_firstlnum += nmatch - 1; \ + xfree(sub_firstline); \ + sub_firstline = vim_strsave(ml_get(sub_firstlnum)); \ + /* When going beyond the last line, stop substituting. */ \ + if (sub_firstlnum <= line2) { \ + do_again = true; \ + } else { \ + subflags.do_all = false; \ + } \ + } \ + if (skip_match) { \ + /* Already hit end of the buffer, sub_firstlnum is one */ \ + /* less than what it ought to be. */ \ + xfree(sub_firstline); \ + sub_firstline = vim_strsave((char_u *)""); \ + copycol = 0; \ + } \ + } while (0) + + if (preview && !has_second_delim) { + ADJUST_SUB_FIRSTLNUM(); + goto skip; + } + // 3. Substitute the string. During 'inccommand' preview only do this if // there is a replace pattern. if (!preview || has_second_delim) { @@ -3691,13 +3727,6 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout) goto skip; } - // When the match included the "$" of the last line it may - // go beyond the last line of the buffer. - if (nmatch > curbuf->b_ml.ml_line_count - sub_firstlnum + 1) { - nmatch = curbuf->b_ml.ml_line_count - sub_firstlnum + 1; - skip_match = true; - } - // Need room for: // - result so far in new_start (not for first sub in line) // - original text up to match @@ -3728,30 +3757,10 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout) // is beyond the end of the line after the substitution. curwin->w_cursor.col = 0; - // For a multi-line match, make a copy of the last matched - // line and continue in that one. - if (nmatch > 1) { - sub_firstlnum += nmatch - 1; - xfree(sub_firstline); - sub_firstline = vim_strsave(ml_get(sub_firstlnum)); - // When going beyond the last line, stop substituting. - if (sub_firstlnum <= line2) { - do_again = true; - } else { - subflags.do_all = false; - } - } - // Remember next character to be copied. copycol = regmatch.endpos[0].col; - if (skip_match) { - // Already hit end of the buffer, sub_firstlnum is one - // less than what it ought to be. - xfree(sub_firstline); - sub_firstline = vim_strsave((char_u *)""); - copycol = 0; - } + ADJUST_SUB_FIRSTLNUM(); // Now the trick is to replace CTRL-M chars with a real line // break. This would make it impossible to insert a CTRL-M in @@ -4008,6 +4017,7 @@ skip: kv_destroy(matched_lines); return preview_buf; +#undef ADJUST_SUB_FIRSTLNUM } // NOLINT(readability/fn_size) /* diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua index e83bd72ad3..c8fa2888d1 100644 --- a/test/functional/ui/inccommand_spec.lua +++ b/test/functional/ui/inccommand_spec.lua @@ -14,6 +14,7 @@ local neq = helpers.neq local ok = helpers.ok local source = helpers.source local wait = helpers.wait +local nvim = helpers.nvim local default_text = [[ Inc substitution on @@ -1647,3 +1648,29 @@ describe("'inccommand' split windows", function() end) end) + +describe("'inccommand' with 'gdefault'", function() + before_each(function() + clear() + end) + + it("does not lock up #7244", function() + common_setup(nil, "nosplit", "{") + command("set gdefault") + feed(":s/{\\n") + eq({mode='c', blocking=false}, nvim("get_mode")) + feed("/A<Enter>") + expect("A") + eq({mode='n', blocking=false}, nvim("get_mode")) + end) + + it("with multiline text and range, does not lock up #7244", function() + common_setup(nil, "nosplit", "{\n\n{") + command("set gdefault") + feed(":%s/{\\n") + eq({mode='c', blocking=false}, nvim("get_mode")) + feed("/A<Enter>") + expect("A\nA") + eq({mode='n', blocking=false}, nvim("get_mode")) + end) +end) |