comparison 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
comparison
equal deleted inserted replaced
11493:bc5afe585f0d 11494:8e5ec22db3d8
5901 return TRUE; 5901 return TRUE;
5902 } 5902 }
5903 return FALSE; 5903 return FALSE;
5904 } 5904 }
5905 5905
5906 static void
5907 global_exe_one(char_u *cmd, linenr_T lnum)
5908 {
5909 curwin->w_cursor.lnum = lnum;
5910 curwin->w_cursor.col = 0;
5911 if (*cmd == NUL || *cmd == '\n')
5912 do_cmdline((char_u *)"p", NULL, NULL, DOCMD_NOWAIT);
5913 else
5914 do_cmdline(cmd, NULL, NULL, DOCMD_NOWAIT);
5915 }
5916
5906 /* 5917 /*
5907 * Execute a global command of the form: 5918 * Execute a global command of the form:
5908 * 5919 *
5909 * g/pattern/X : execute X on all lines where pattern matches 5920 * g/pattern/X : execute X on all lines where pattern matches
5910 * v/pattern/X : execute X on all lines where pattern does not match 5921 * v/pattern/X : execute X on all lines where pattern does not match
5931 char_u *pat; 5942 char_u *pat;
5932 regmmatch_T regmatch; 5943 regmmatch_T regmatch;
5933 int match; 5944 int match;
5934 int which_pat; 5945 int which_pat;
5935 5946
5936 if (global_busy) 5947 /* When nesting the command works on one line. This allows for
5937 { 5948 * ":g/found/v/notfound/command". */
5938 EMSG(_("E147: Cannot do :global recursive")); /* will increment global_busy */ 5949 if (global_busy && (eap->line1 != 1
5950 || eap->line2 != curbuf->b_ml.ml_line_count))
5951 {
5952 /* will increment global_busy to break out of the loop */
5953 EMSG(_("E147: Cannot do :global recursive with a range"));
5939 return; 5954 return;
5940 } 5955 }
5941 5956
5942 if (eap->forceit) /* ":global!" is like ":vglobal" */ 5957 if (eap->forceit) /* ":global!" is like ":vglobal" */
5943 type = 'v'; 5958 type = 'v';
5991 { 6006 {
5992 EMSG(_(e_invcmd)); 6007 EMSG(_(e_invcmd));
5993 return; 6008 return;
5994 } 6009 }
5995 6010
5996 /* 6011 if (global_busy)
5997 * pass 1: set marks for each (not) matching line 6012 {
5998 */ 6013 lnum = curwin->w_cursor.lnum;
5999 for (lnum = eap->line1; lnum <= eap->line2 && !got_int; ++lnum)
6000 {
6001 /* a match on this line? */
6002 match = vim_regexec_multi(&regmatch, curwin, curbuf, lnum, 6014 match = vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
6003 (colnr_T)0, NULL); 6015 (colnr_T)0, NULL);
6004 if ((type == 'g' && match) || (type == 'v' && !match)) 6016 if ((type == 'g' && match) || (type == 'v' && !match))
6005 { 6017 global_exe_one(cmd, lnum);
6006 ml_setmarked(lnum); 6018 }
6007 ndone++; 6019 else
6008 } 6020 {
6009 line_breakcheck(); 6021 /*
6010 } 6022 * pass 1: set marks for each (not) matching line
6011 6023 */
6012 /* 6024 for (lnum = eap->line1; lnum <= eap->line2 && !got_int; ++lnum)
6013 * pass 2: execute the command for each line that has been marked 6025 {
6014 */ 6026 /* a match on this line? */
6015 if (got_int) 6027 match = vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
6016 MSG(_(e_interr)); 6028 (colnr_T)0, NULL);
6017 else if (ndone == 0) 6029 if ((type == 'g' && match) || (type == 'v' && !match))
6018 { 6030 {
6019 if (type == 'v') 6031 ml_setmarked(lnum);
6020 smsg((char_u *)_("Pattern found in every line: %s"), pat); 6032 ndone++;
6033 }
6034 line_breakcheck();
6035 }
6036
6037 /*
6038 * pass 2: execute the command for each line that has been marked
6039 */
6040 if (got_int)
6041 MSG(_(e_interr));
6042 else if (ndone == 0)
6043 {
6044 if (type == 'v')
6045 smsg((char_u *)_("Pattern found in every line: %s"), pat);
6046 else
6047 smsg((char_u *)_("Pattern not found: %s"), pat);
6048 }
6021 else 6049 else
6022 smsg((char_u *)_("Pattern not found: %s"), pat); 6050 {
6023 }
6024 else
6025 {
6026 #ifdef FEAT_CLIPBOARD 6051 #ifdef FEAT_CLIPBOARD
6027 start_global_changes(); 6052 start_global_changes();
6028 #endif 6053 #endif
6029 global_exe(cmd); 6054 global_exe(cmd);
6030 #ifdef FEAT_CLIPBOARD 6055 #ifdef FEAT_CLIPBOARD
6031 end_global_changes(); 6056 end_global_changes();
6032 #endif 6057 #endif
6033 } 6058 }
6034 6059
6035 ml_clearmarked(); /* clear rest of the marks */ 6060 ml_clearmarked(); /* clear rest of the marks */
6061 }
6062
6036 vim_regfree(regmatch.regprog); 6063 vim_regfree(regmatch.regprog);
6037 } 6064 }
6038 6065
6039 /* 6066 /*
6040 * Execute "cmd" on lines marked with ml_setmarked(). 6067 * Execute "cmd" on lines marked with ml_setmarked().
6061 global_need_beginline = FALSE; 6088 global_need_beginline = FALSE;
6062 global_busy = 1; 6089 global_busy = 1;
6063 old_lcount = curbuf->b_ml.ml_line_count; 6090 old_lcount = curbuf->b_ml.ml_line_count;
6064 while (!got_int && (lnum = ml_firstmarked()) != 0 && global_busy == 1) 6091 while (!got_int && (lnum = ml_firstmarked()) != 0 && global_busy == 1)
6065 { 6092 {
6066 curwin->w_cursor.lnum = lnum; 6093 global_exe_one(cmd, lnum);
6067 curwin->w_cursor.col = 0;
6068 if (*cmd == NUL || *cmd == '\n')
6069 do_cmdline((char_u *)"p", NULL, NULL, DOCMD_NOWAIT);
6070 else
6071 do_cmdline(cmd, NULL, NULL, DOCMD_NOWAIT);
6072 ui_breakcheck(); 6094 ui_breakcheck();
6073 } 6095 }
6074 6096
6075 global_busy = 0; 6097 global_busy = 0;
6076 if (global_need_beginline) 6098 if (global_need_beginline)
8512 } 8534 }
8513 # endif 8535 # endif
8514 } 8536 }
8515 } 8537 }
8516 #endif 8538 #endif
8517