Mercurial > vim
diff src/ex_cmds.c @ 11494:8e5ec22db3d8 v8.0.0630
patch 8.0.0630: it is not easy to work on lines without a match
commit https://github.com/vim/vim/commit/f84b122a99da75741ae686fabb6f81b8b4755998
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Jun 10 14:29:52 2017 +0200
patch 8.0.0630: it is not easy to work on lines without a match
Problem: The :global command does not work recursively, which makes it
difficult to execute a command on a line where one pattern matches
and another does not match. (Miles Cranmer)
Solution: Allow for recursion if it is for only one line. (closes #1760)
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sat, 10 Jun 2017 14:30:03 +0200 |
parents | c45fb081391c |
children | 578df034735d |
line wrap: on
line diff
--- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -5903,6 +5903,17 @@ do_sub_msg( return FALSE; } + static void +global_exe_one(char_u *cmd, 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: * @@ -5933,9 +5944,13 @@ 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; } @@ -5993,46 +6008,58 @@ 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++; - } - 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((char_u *)_("Pattern found in every line: %s"), pat); - else - smsg((char_u *)_("Pattern not found: %s"), pat); + global_exe_one(cmd, lnum); } else { -#ifdef FEAT_CLIPBOARD - start_global_changes(); -#endif - global_exe(cmd); + /* + * 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(); + } + + /* + * 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((char_u *)_("Pattern found in every line: %s"), pat); + else + smsg((char_u *)_("Pattern not found: %s"), pat); + } + else + { #ifdef FEAT_CLIPBOARD - end_global_changes(); -#endif - } - - ml_clearmarked(); /* clear rest of the marks */ + start_global_changes(); +#endif + global_exe(cmd); +#ifdef FEAT_CLIPBOARD + end_global_changes(); +#endif + } + + ml_clearmarked(); /* clear rest of the marks */ + } + vim_regfree(regmatch.regprog); } @@ -6063,12 +6090,7 @@ 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); ui_breakcheck(); } @@ -8514,4 +8536,3 @@ ex_oldfiles(exarg_T *eap UNUSED) } } #endif -