summaryrefslogtreecommitdiff
path: root/src/ex_getln.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-08-26 19:13:46 +0200
committerBram Moolenaar <Bram@vim.org>2016-08-26 19:13:46 +0200
commit4d6f32cbfbaf324ac4a25c0206a5db0e9f7a48f7 (patch)
tree1f99127dcddcda19da0a408a32612bc33f968fa5 /src/ex_getln.c
parentf1f0792e55e72cdc7c833b30f565a9b02f18bb1e (diff)
downloadvim-4d6f32cbfbaf324ac4a25c0206a5db0e9f7a48f7.zip
patch 7.4.2259
Problem: With 'incsearch' can only see the next match. Solution: Make CTRL-N/CTRL-P move to the previous/next match. (Christian Brabandt)
Diffstat (limited to 'src/ex_getln.c')
-rw-r--r--src/ex_getln.c166
1 files changed, 138 insertions, 28 deletions
diff --git a/src/ex_getln.c b/src/ex_getln.c
index 642e09010..925e2f490 100644
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -137,6 +137,9 @@ _RTLENTRYF
#endif
sort_func_compare(const void *s1, const void *s2);
#endif
+#ifdef FEAT_SEARCH_EXTRA
+static void set_search_match(pos_T *t);
+#endif
/*
* getcmdline() - accept a command line starting with firstc.
@@ -178,6 +181,9 @@ getcmdline(
colnr_T old_curswant;
colnr_T old_leftcol;
linenr_T old_topline;
+ pos_T cursor_start;
+ pos_T match_start = curwin->w_cursor;
+ pos_T match_end;
# ifdef FEAT_DIFF
int old_topfill;
# endif
@@ -223,7 +229,9 @@ getcmdline(
ccline.overstrike = FALSE; /* always start in insert mode */
#ifdef FEAT_SEARCH_EXTRA
+ clearpos(&match_end);
old_cursor = curwin->w_cursor; /* needs to be restored later */
+ cursor_start = old_cursor;
old_curswant = curwin->w_curswant;
old_leftcol = curwin->w_leftcol;
old_topline = curwin->w_topline;
@@ -996,6 +1004,15 @@ getcmdline(
/* Truncate at the end, required for multi-byte chars. */
ccline.cmdbuff[ccline.cmdlen] = NUL;
+#ifdef FEAT_SEARCH_EXTRA
+ if (ccline.cmdlen == 0)
+ old_cursor = cursor_start;
+ else
+ {
+ old_cursor = match_start;
+ decl(&old_cursor);
+ }
+#endif
redrawcmd();
}
else if (ccline.cmdlen == 0 && c != Ctrl_W
@@ -1021,6 +1038,10 @@ getcmdline(
msg_col = 0;
msg_putchar(' '); /* delete ':' */
}
+#ifdef FEAT_SEARCH_EXTRA
+ if (ccline.cmdlen == 0)
+ old_cursor = cursor_start;
+#endif
redraw_cmdline = TRUE;
goto returncmd; /* back to cmd mode */
}
@@ -1104,6 +1125,10 @@ getcmdline(
ccline.cmdbuff[i++] = ccline.cmdbuff[j++];
/* Truncate at the end, required for multi-byte chars. */
ccline.cmdbuff[ccline.cmdlen] = NUL;
+#ifdef FEAT_SEARCH_EXTRA
+ if (ccline.cmdlen == 0)
+ old_cursor = cursor_start;
+#endif
redrawcmd();
goto cmdline_changed;
@@ -1440,26 +1465,31 @@ getcmdline(
if (p_is && !cmd_silent && (firstc == '/' || firstc == '?'))
{
/* Add a character from under the cursor for 'incsearch' */
- if (did_incsearch
- && !equalpos(curwin->w_cursor, old_cursor))
+ if (did_incsearch)
{
- c = gchar_cursor();
- /* If 'ignorecase' and 'smartcase' are set and the
- * command line has no uppercase characters, convert
- * the character to lowercase */
- if (p_ic && p_scs && !pat_has_uppercase(ccline.cmdbuff))
- c = MB_TOLOWER(c);
- if (c != NUL)
+ curwin->w_cursor = match_end;
+ if (!equalpos(curwin->w_cursor, old_cursor))
{
- if (c == firstc || vim_strchr((char_u *)(
- p_magic ? "\\^$.*[" : "\\^$"), c)
- != NULL)
+ c = gchar_cursor();
+ /* If 'ignorecase' and 'smartcase' are set and the
+ * command line has no uppercase characters, convert
+ * the character to lowercase */
+ if (p_ic && p_scs
+ && !pat_has_uppercase(ccline.cmdbuff))
+ c = MB_TOLOWER(c);
+ if (c != NUL)
{
- /* put a backslash before special characters */
- stuffcharReadbuff(c);
- c = '\\';
+ if (c == firstc || vim_strchr((char_u *)(
+ p_magic ? "\\^$.*[" : "\\^$"), c)
+ != NULL)
+ {
+ /* put a backslash before special
+ * characters */
+ stuffcharReadbuff(c);
+ c = '\\';
+ }
+ break;
}
- break;
}
}
goto cmdline_not_changed;
@@ -1473,7 +1503,75 @@ getcmdline(
case Ctrl_N: /* next match */
case Ctrl_P: /* previous match */
- if (xpc.xp_numfiles > 0)
+#ifdef FEAT_SEARCH_EXTRA
+ if (p_is && !cmd_silent && (firstc == '/' || firstc == '?'))
+ {
+ pos_T t;
+ int search_flags = SEARCH_KEEP + SEARCH_NOOF
+ + SEARCH_PEEK;
+
+ if (char_avail())
+ continue;
+ cursor_off();
+ out_flush();
+ if (c == Ctrl_N)
+ {
+ t = match_end;
+ search_flags += SEARCH_COL;
+ }
+ else
+ t = match_start;
+ ++emsg_off;
+ i = searchit(curwin, curbuf, &t,
+ c == Ctrl_N ? FORWARD : BACKWARD,
+ ccline.cmdbuff, count, search_flags,
+ RE_SEARCH, 0, NULL);
+ --emsg_off;
+ if (i)
+ {
+ old_cursor = match_start;
+ match_end = t;
+ match_start = t;
+ if (c == Ctrl_P && firstc == '/')
+ {
+ /* move just before the current match, so that
+ * when nv_search finishes the cursor will be
+ * put back on the match */
+ old_cursor = t;
+ (void)decl(&old_cursor);
+ }
+ if (lt(t, old_cursor) && c == Ctrl_N)
+ {
+ /* wrap around */
+ old_cursor = t;
+ if (firstc == '?')
+ (void)incl(&old_cursor);
+ else
+ (void)decl(&old_cursor);
+ }
+
+ set_search_match(&match_end);
+ curwin->w_cursor = match_start;
+ changed_cline_bef_curs();
+ update_topline();
+ validate_cursor();
+ highlight_match = TRUE;
+ old_curswant = curwin->w_curswant;
+ old_leftcol = curwin->w_leftcol;
+ old_topline = curwin->w_topline;
+# ifdef FEAT_DIFF
+ old_topfill = curwin->w_topfill;
+# endif
+ old_botline = curwin->w_botline;
+ update_screen(NOT_VALID);
+ redrawcmdline();
+ }
+ else
+ vim_beep(BO_ERROR);
+ goto cmdline_not_changed;
+ }
+#endif
+ else if (xpc.xp_numfiles > 0)
{
if (nextwild(&xpc, (c == Ctrl_P) ? WILD_PREV : WILD_NEXT,
0, firstc != '@') == FAIL)
@@ -1821,19 +1919,11 @@ cmdline_changed:
{
pos_T save_pos = curwin->w_cursor;
- /*
- * First move cursor to end of match, then to the start. This
- * moves the whole match onto the screen when 'nowrap' is set.
- */
- curwin->w_cursor.lnum += search_match_lines;
- curwin->w_cursor.col = search_match_endcol;
- if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
- {
- curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- coladvance((colnr_T)MAXCOL);
- }
+ match_start = curwin->w_cursor;
+ set_search_match(&curwin->w_cursor);
validate_cursor();
end_pos = curwin->w_cursor;
+ match_end = end_pos;
curwin->w_cursor = save_pos;
}
else
@@ -1894,6 +1984,8 @@ returncmd:
if (did_incsearch)
{
curwin->w_cursor = old_cursor;
+ if (gotesc)
+ curwin->w_cursor = cursor_start;
curwin->w_curswant = old_curswant;
curwin->w_leftcol = old_leftcol;
curwin->w_topline = old_topline;
@@ -6983,3 +7075,21 @@ script_get(exarg_T *eap, char_u *cmd)
return (char_u *)ga.ga_data;
}
+
+#ifdef FEAT_SEARCH_EXTRA
+ static void
+set_search_match(pos_T *t)
+{
+ /*
+ * First move cursor to end of match, then to the start. This
+ * moves the whole match onto the screen when 'nowrap' is set.
+ */
+ t->lnum += search_match_lines;
+ t->col = search_match_endcol;
+ if (t->lnum > curbuf->b_ml.ml_line_count)
+ {
+ t->lnum = curbuf->b_ml.ml_line_count;
+ coladvance((colnr_T)MAXCOL);
+ }
+}
+#endif