Mercurial > vim
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(®match, curwin, curbuf, lnum, | 6014 match = vim_regexec_multi(®match, 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(®match, 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 |