summaryrefslogtreecommitdiff
path: root/src/ex_cmds.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2005-02-26 23:04:13 +0000
committerBram Moolenaar <Bram@vim.org>2005-02-26 23:04:13 +0000
commit05159a0c6a27a030c8497c5cf836977090f9e75d (patch)
tree9ccc167cf3e830e5d01aff4555f99d854cbb623b /src/ex_cmds.c
parent5313dcb75ac76501f23d21ac94efdbeeabc860bc (diff)
downloadvim-05159a0c6a27a030c8497c5cf836977090f9e75d.zip
updated for version 7.0052
Diffstat (limited to 'src/ex_cmds.c')
-rw-r--r--src/ex_cmds.c80
1 files changed, 67 insertions, 13 deletions
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index 9ebf39cfb..419c1981d 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -30,7 +30,7 @@ static int check_readonly __ARGS((int *forceit, buf_T *buf));
#ifdef FEAT_AUTOCMD
static void delbuf_msg __ARGS((char_u *name));
#endif
-static int do_sub_msg __ARGS((void));
+static int do_sub_msg __ARGS((int count_only));
static int
#ifdef __BORLANDC__
_RTLENTRYF
@@ -3661,6 +3661,7 @@ do_sub(eap)
regmmatch_T regmatch;
static int do_all = FALSE; /* do multiple substitutions per line */
static int do_ask = FALSE; /* ask for confirmation */
+ static int do_count = FALSE; /* count only */
static int do_error = TRUE; /* if false, ignore errors */
static int do_print = FALSE; /* print last line with subs. */
static int do_list = FALSE; /* list last line with subs. */
@@ -3684,6 +3685,7 @@ do_sub(eap)
linenr_T sub_firstlnum; /* nr of first sub line */
char_u *sub_firstline; /* allocated copy of first sub line */
int endcolumn = FALSE; /* cursor in last column when done */
+ pos_T old_cursor = curwin->w_cursor;
cmd = eap->arg;
if (!global_busy)
@@ -3822,6 +3824,8 @@ do_sub(eap)
do_all = !do_all;
else if (*cmd == 'c')
do_ask = !do_ask;
+ else if (*cmd == 'n')
+ do_count = TRUE;
else if (*cmd == 'e')
do_error = !do_error;
else if (*cmd == 'r') /* use last used regexp */
@@ -3846,6 +3850,8 @@ do_sub(eap)
break;
++cmd;
}
+ if (do_count)
+ do_ask = FALSE;
/*
* check for a trailing count
@@ -4030,8 +4036,25 @@ do_sub(eap)
prev_matchcol = matchcol;
/*
- * 2. If do_ask is set, ask for confirmation.
+ * 2. If do_count is set only increase the counter.
+ * If do_ask is set, ask for confirmation.
*/
+ if (do_count)
+ {
+ /* For a multi-line match, put matchcol at the NUL at
+ * the end of the line and set nmatch to one, so that
+ * we continue looking for a match on the next line.
+ * Avoids that ":s/\nB\@=//gc" get stuck. */
+ if (nmatch > 1)
+ {
+ matchcol = STRLEN(sub_firstline);
+ nmatch = 1;
+ }
+ sub_nsubs++;
+ did_sub = TRUE;
+ goto skip;
+ }
+
if (do_ask)
{
/* change State to CONFIRM, so that the mouse works
@@ -4064,9 +4087,9 @@ do_sub(eap)
curwin->w_cursor.col = regmatch.endpos[0].col - 1;
getvcol(curwin, &curwin->w_cursor, NULL, NULL, &ec);
msg_start();
- for (i = 0; i < sc; ++i)
+ for (i = 0; i < (long)sc; ++i)
msg_putchar(' ');
- for ( ; i <= ec; ++i)
+ for ( ; i <= (long)ec; ++i)
msg_putchar('^');
resp = getexmodeline('?', NULL, 0);
@@ -4458,6 +4481,11 @@ skip:
outofmem:
vim_free(sub_firstline); /* may have to free allocated copy of the line */
+
+ /* ":s/pat//n" doesn't move the cursor */
+ if (do_count)
+ curwin->w_cursor = old_cursor;
+
if (sub_nsubs)
{
/* Set the '[ and '] marks. */
@@ -4471,7 +4499,7 @@ outofmem:
coladvance((colnr_T)MAXCOL);
else
beginline(BL_WHITE | BL_FIX);
- if (!do_sub_msg() && do_ask)
+ if (!do_sub_msg(do_count) && do_ask)
MSG("");
}
else
@@ -4498,7 +4526,8 @@ outofmem:
* Return TRUE if a message was given.
*/
static int
-do_sub_msg()
+do_sub_msg(count_only)
+ int count_only; /* used 'n' flag for ":s" */
{
/*
* Only report substitutions when:
@@ -4506,8 +4535,8 @@ do_sub_msg()
* - command was typed by user, or number of changed lines > 'report'
* - giving messages is not disabled by 'lazyredraw'
*/
- if (sub_nsubs > p_report
- && (KeyTyped || sub_nlines > 1 || p_report < 1)
+ if (((sub_nsubs > p_report && (KeyTyped || sub_nlines > 1 || p_report < 1))
+ || count_only)
&& messaging())
{
if (got_int)
@@ -4515,9 +4544,10 @@ do_sub_msg()
else
msg_buf[0] = NUL;
if (sub_nsubs == 1)
- STRCAT(msg_buf, _("1 substitution"));
+ STRCAT(msg_buf, count_only ? _("1 match") : _("1 substitution"));
else
- sprintf((char *)msg_buf + STRLEN(msg_buf), _("%ld substitutions"),
+ sprintf((char *)msg_buf + STRLEN(msg_buf),
+ count_only ? _("%ld matches") : _("%ld substitutions"),
sub_nsubs);
if (sub_nlines == 1)
STRCAT(msg_buf, _(" on 1 line"));
@@ -4561,7 +4591,7 @@ ex_global(eap)
exarg_T *eap;
{
linenr_T lnum; /* line number according to old situation */
- int ndone;
+ int ndone = 0;
int type; /* first char of cmd: 'v' or 'g' */
char_u *cmd; /* command argument */
@@ -4633,10 +4663,29 @@ ex_global(eap)
return;
}
+#ifdef HAVE_SETJMP_H
+ /*
+ * Matching with a regexp may cause a very deep recursive call of
+ * regmatch(). Vim will crash when running out of stack space.
+ * Catch this here if the system supports it.
+ * It's a bit slow, thus do it outside of the loop.
+ */
+ mch_startjmp();
+ if (SETJMP(lc_jump_env) != 0)
+ {
+ mch_didjmp();
+# ifdef SIGHASARG
+ if (lc_signal != SIGINT)
+# endif
+ EMSG(_(e_complex));
+ got_int = TRUE;
+ goto jumpend;
+ }
+#endif
+
/*
* pass 1: set marks for each (not) matching line
*/
- ndone = 0;
for (lnum = eap->line1; lnum <= eap->line2 && !got_int; ++lnum)
{
/* a match on this line? */
@@ -4649,6 +4698,11 @@ ex_global(eap)
line_breakcheck();
}
+#ifdef HAVE_SETJMP_H
+jumpend:
+ mch_endjmp();
+#endif
+
/*
* pass 2: execute the command for each line that has been marked
*/
@@ -4719,7 +4773,7 @@ global_exe(cmd)
/* If subsitutes done, report number of substitues, otherwise report
* number of extra or deleted lines. */
- if (!do_sub_msg())
+ if (!do_sub_msg(FALSE))
msgmore(curbuf->b_ml.ml_line_count - old_lcount);
}