diff options
author | KillTheMule <KillTheMule@users.noreply.github.com> | 2017-09-09 11:38:19 +0200 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2017-09-12 22:44:11 +0200 |
commit | 6d0f87a0bd9c683f21c20e29145f375ca77c2792 (patch) | |
tree | 93afedbfa49c9b2553a644a6a5582ef962199bd5 | |
parent | d2cbc311855114b7736919a344a82e303d4a8164 (diff) | |
download | rneovim-6d0f87a0bd9c683f21c20e29145f375ca77c2792.tar.gz rneovim-6d0f87a0bd9c683f21c20e29145f375ca77c2792.tar.bz2 rneovim-6d0f87a0bd9c683f21c20e29145f375ca77c2792.zip |
'inccommand': fix 'gdefault' lockup #7261
closes #7244
ref #7249
-rw-r--r-- | src/nvim/ex_cmds.c | 38 | ||||
-rw-r--r-- | test/functional/ui/inccommand_spec.lua | 27 |
2 files changed, 57 insertions, 8 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 4b3e02e5fd..99bf07c3fb 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -3665,9 +3665,38 @@ 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; + } + // 3. Substitute the string. During 'inccommand' preview only do this if // there is a replace pattern. - if (!preview || has_second_delim) { + if (preview && !has_second_delim) { + // 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; + } + } else if (!preview || has_second_delim) { if (subflags.do_count) { // prevent accidentally changing the buffer by a function save_ma = curbuf->b_p_ma; @@ -3691,13 +3720,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 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) |