diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/ex_cmds.c | 76 | ||||
-rw-r--r-- | src/nvim/testdir/test_global.vim | 9 |
2 files changed, 54 insertions, 31 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 0b30132eb8..115df815c6 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -4176,6 +4176,17 @@ do_sub_msg ( return false; } +static void global_exe_one(char_u *const cmd, const linenr_T lnum) +{ + curwin->w_cursor.lnum = lnum; + curwin->w_cursor.col = 0; + if (*cmd == NUL || *cmd == '\n') { + do_cmdline((char_u *)"p", NULL, NULL, DOCMD_NOWAIT); + } else { + do_cmdline(cmd, NULL, NULL, DOCMD_NOWAIT); + } +} + /* * Execute a global command of the form: * @@ -4205,8 +4216,12 @@ void ex_global(exarg_T *eap) int match; int which_pat; - if (global_busy) { - EMSG(_("E147: Cannot do :global recursive")); /* will increment global_busy */ + // When nesting the command works on one line. This allows for + // ":g/found/v/notfound/command". + if (global_busy && (eap->line1 != 1 + || eap->line2 != curbuf->b_ml.ml_line_count)) { + // will increment global_busy to break out of the loop + EMSG(_("E147: Cannot do :global recursive with a range")); return; } @@ -4255,35 +4270,40 @@ void ex_global(exarg_T *eap) return; } - /* - * pass 1: set marks for each (not) matching line - */ - for (lnum = eap->line1; lnum <= eap->line2 && !got_int; ++lnum) { - /* a match on this line? */ + if (global_busy) { + lnum = curwin->w_cursor.lnum; match = vim_regexec_multi(®match, curwin, curbuf, lnum, - (colnr_T)0, NULL); + (colnr_T)0, NULL); if ((type == 'g' && match) || (type == 'v' && !match)) { - ml_setmarked(lnum); - ndone++; + global_exe_one(cmd, lnum); + } + } else { + // pass 1: set marks for each (not) matching line + for (lnum = eap->line1; lnum <= eap->line2 && !got_int; lnum++) { + // a match on this line? + match = vim_regexec_multi(®match, curwin, curbuf, lnum, + (colnr_T)0, NULL); + if ((type == 'g' && match) || (type == 'v' && !match)) { + ml_setmarked(lnum); + ndone++; + } + line_breakcheck(); } - line_breakcheck(); - } - /* - * pass 2: execute the command for each line that has been marked - */ - if (got_int) - MSG(_(e_interr)); - else if (ndone == 0) { - if (type == 'v') { - smsg(_("Pattern found in every line: %s"), pat); + // pass 2: execute the command for each line that has been marked + if (got_int) { + MSG(_(e_interr)); + } else if (ndone == 0) { + if (type == 'v') { + smsg(_("Pattern found in every line: %s"), pat); + } else { + smsg(_("Pattern not found: %s"), pat); + } } else { - smsg(_("Pattern not found: %s"), pat); + global_exe(cmd); } - } else { - global_exe(cmd); + ml_clearmarked(); // clear rest of the marks } - ml_clearmarked(); /* clear rest of the marks */ vim_regfree(regmatch.regprog); } @@ -4312,13 +4332,7 @@ void global_exe(char_u *cmd) old_lcount = curbuf->b_ml.ml_line_count; while (!got_int && (lnum = ml_firstmarked()) != 0 && global_busy == 1) { - curwin->w_cursor.lnum = lnum; - curwin->w_cursor.col = 0; - if (*cmd == NUL || *cmd == '\n') { - do_cmdline((char_u *)"p", NULL, NULL, DOCMD_NOWAIT); - } else { - do_cmdline(cmd, NULL, NULL, DOCMD_NOWAIT); - } + global_exe_one(cmd, lnum); os_breakcheck(); } diff --git a/src/nvim/testdir/test_global.vim b/src/nvim/testdir/test_global.vim index be8aa69623..bdeaf8e2cf 100644 --- a/src/nvim/testdir/test_global.vim +++ b/src/nvim/testdir/test_global.vim @@ -9,3 +9,12 @@ func Test_yank_put_clipboard() set clipboard& bwipe! endfunc + +func Test_nested_global() + new + call setline(1, ['nothing', 'found', 'found bad', 'bad']) + call assert_fails('g/found/3v/bad/s/^/++/', 'E147') + g/found/v/bad/s/^/++/ + call assert_equal(['nothing', '++found', 'found bad', 'bad'], getline(1, 4)) + bwipe! +endfunc |