Skip to content

Commit 4d6f32c

Browse files
committed
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)
1 parent f1f0792 commit 4d6f32c

File tree

6 files changed

+393
-28
lines changed

6 files changed

+393
-28
lines changed

runtime/doc/cmdline.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,11 +409,19 @@ CTRL-D List names that match the pattern in front of the cursor.
409409
*c_CTRL-N*
410410
CTRL-N After using 'wildchar' which got multiple matches, go to next
411411
match. Otherwise recall more recent command-line from history.
412+
*/_CTRL-N*
413+
When 'incsearch' is set, entering a search pattern for "/" or
414+
"?" and the current match is displayed then CTRL-N will move
415+
to the next match (does not take |search-offset| into account)
412416
<S-Tab> *c_CTRL-P* *c_<S-Tab>*
413417
CTRL-P After using 'wildchar' which got multiple matches, go to
414418
previous match. Otherwise recall older command-line from
415419
history. <S-Tab> only works with the GUI, on the Amiga and
416420
with MS-DOS.
421+
*/_CTRL-P*
422+
When 'incsearch' is set, entering a search pattern for "/" or
423+
"?" and the current match is displayed then CTRL-P will move
424+
to the previous match (does not take |search-offset| into account).
417425
*c_CTRL-A*
418426
CTRL-A All names that match the pattern in front of the cursor are
419427
inserted.
@@ -423,6 +431,7 @@ CTRL-L A match is done on the pattern in front of the cursor. If
423431
If there are multiple matches the longest common part is
424432
inserted in place of the pattern. If the result is shorter
425433
than the pattern, no completion is done.
434+
*/_CTRL-L*
426435
When 'incsearch' is set, entering a search pattern for "/" or
427436
"?" and the current match is displayed then CTRL-L will add
428437
one character from the end of the current match. If

src/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2110,6 +2110,7 @@ test_arglist \
21102110
test_regexp_utf8 \
21112111
test_reltime \
21122112
test_ruby \
2113+
test_search \
21132114
test_searchpos \
21142115
test_set \
21152116
test_signs \

src/ex_getln.c

Lines changed: 138 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@ _RTLENTRYF
137137
#endif
138138
sort_func_compare(const void *s1, const void *s2);
139139
#endif
140+
#ifdef FEAT_SEARCH_EXTRA
141+
static void set_search_match(pos_T *t);
142+
#endif
140143

141144
/*
142145
* getcmdline() - accept a command line starting with firstc.
@@ -178,6 +181,9 @@ getcmdline(
178181
colnr_T old_curswant;
179182
colnr_T old_leftcol;
180183
linenr_T old_topline;
184+
pos_T cursor_start;
185+
pos_T match_start = curwin->w_cursor;
186+
pos_T match_end;
181187
# ifdef FEAT_DIFF
182188
int old_topfill;
183189
# endif
@@ -223,7 +229,9 @@ getcmdline(
223229

224230
ccline.overstrike = FALSE; /* always start in insert mode */
225231
#ifdef FEAT_SEARCH_EXTRA
232+
clearpos(&match_end);
226233
old_cursor = curwin->w_cursor; /* needs to be restored later */
234+
cursor_start = old_cursor;
227235
old_curswant = curwin->w_curswant;
228236
old_leftcol = curwin->w_leftcol;
229237
old_topline = curwin->w_topline;
@@ -996,6 +1004,15 @@ getcmdline(
9961004

9971005
/* Truncate at the end, required for multi-byte chars. */
9981006
ccline.cmdbuff[ccline.cmdlen] = NUL;
1007+
#ifdef FEAT_SEARCH_EXTRA
1008+
if (ccline.cmdlen == 0)
1009+
old_cursor = cursor_start;
1010+
else
1011+
{
1012+
old_cursor = match_start;
1013+
decl(&old_cursor);
1014+
}
1015+
#endif
9991016
redrawcmd();
10001017
}
10011018
else if (ccline.cmdlen == 0 && c != Ctrl_W
@@ -1021,6 +1038,10 @@ getcmdline(
10211038
msg_col = 0;
10221039
msg_putchar(' '); /* delete ':' */
10231040
}
1041+
#ifdef FEAT_SEARCH_EXTRA
1042+
if (ccline.cmdlen == 0)
1043+
old_cursor = cursor_start;
1044+
#endif
10241045
redraw_cmdline = TRUE;
10251046
goto returncmd; /* back to cmd mode */
10261047
}
@@ -1104,6 +1125,10 @@ getcmdline(
11041125
ccline.cmdbuff[i++] = ccline.cmdbuff[j++];
11051126
/* Truncate at the end, required for multi-byte chars. */
11061127
ccline.cmdbuff[ccline.cmdlen] = NUL;
1128+
#ifdef FEAT_SEARCH_EXTRA
1129+
if (ccline.cmdlen == 0)
1130+
old_cursor = cursor_start;
1131+
#endif
11071132
redrawcmd();
11081133
goto cmdline_changed;
11091134

@@ -1440,26 +1465,31 @@ getcmdline(
14401465
if (p_is && !cmd_silent && (firstc == '/' || firstc == '?'))
14411466
{
14421467
/* Add a character from under the cursor for 'incsearch' */
1443-
if (did_incsearch
1444-
&& !equalpos(curwin->w_cursor, old_cursor))
1468+
if (did_incsearch)
14451469
{
1446-
c = gchar_cursor();
1447-
/* If 'ignorecase' and 'smartcase' are set and the
1448-
* command line has no uppercase characters, convert
1449-
* the character to lowercase */
1450-
if (p_ic && p_scs && !pat_has_uppercase(ccline.cmdbuff))
1451-
c = MB_TOLOWER(c);
1452-
if (c != NUL)
1470+
curwin->w_cursor = match_end;
1471+
if (!equalpos(curwin->w_cursor, old_cursor))
14531472
{
1454-
if (c == firstc || vim_strchr((char_u *)(
1455-
p_magic ? "\\^$.*[" : "\\^$"), c)
1456-
!= NULL)
1473+
c = gchar_cursor();
1474+
/* If 'ignorecase' and 'smartcase' are set and the
1475+
* command line has no uppercase characters, convert
1476+
* the character to lowercase */
1477+
if (p_ic && p_scs
1478+
&& !pat_has_uppercase(ccline.cmdbuff))
1479+
c = MB_TOLOWER(c);
1480+
if (c != NUL)
14571481
{
1458-
/* put a backslash before special characters */
1459-
stuffcharReadbuff(c);
1460-
c = '\\';
1482+
if (c == firstc || vim_strchr((char_u *)(
1483+
p_magic ? "\\^$.*[" : "\\^$"), c)
1484+
!= NULL)
1485+
{
1486+
/* put a backslash before special
1487+
* characters */
1488+
stuffcharReadbuff(c);
1489+
c = '\\';
1490+
}
1491+
break;
14611492
}
1462-
break;
14631493
}
14641494
}
14651495
goto cmdline_not_changed;
@@ -1473,7 +1503,75 @@ getcmdline(
14731503

14741504
case Ctrl_N: /* next match */
14751505
case Ctrl_P: /* previous match */
1476-
if (xpc.xp_numfiles > 0)
1506+
#ifdef FEAT_SEARCH_EXTRA
1507+
if (p_is && !cmd_silent && (firstc == '/' || firstc == '?'))
1508+
{
1509+
pos_T t;
1510+
int search_flags = SEARCH_KEEP + SEARCH_NOOF
1511+
+ SEARCH_PEEK;
1512+
1513+
if (char_avail())
1514+
continue;
1515+
cursor_off();
1516+
out_flush();
1517+
if (c == Ctrl_N)
1518+
{
1519+
t = match_end;
1520+
search_flags += SEARCH_COL;
1521+
}
1522+
else
1523+
t = match_start;
1524+
++emsg_off;
1525+
i = searchit(curwin, curbuf, &t,
1526+
c == Ctrl_N ? FORWARD : BACKWARD,
1527+
ccline.cmdbuff, count, search_flags,
1528+
RE_SEARCH, 0, NULL);
1529+
--emsg_off;
1530+
if (i)
1531+
{
1532+
old_cursor = match_start;
1533+
match_end = t;
1534+
match_start = t;
1535+
if (c == Ctrl_P && firstc == '/')
1536+
{
1537+
/* move just before the current match, so that
1538+
* when nv_search finishes the cursor will be
1539+
* put back on the match */
1540+
old_cursor = t;
1541+
(void)decl(&old_cursor);
1542+
}
1543+
if (lt(t, old_cursor) && c == Ctrl_N)
1544+
{
1545+
/* wrap around */
1546+
old_cursor = t;
1547+
if (firstc == '?')
1548+
(void)incl(&old_cursor);
1549+
else
1550+
(void)decl(&old_cursor);
1551+
}
1552+
1553+
set_search_match(&match_end);
1554+
curwin->w_cursor = match_start;
1555+
changed_cline_bef_curs();
1556+
update_topline();
1557+
validate_cursor();
1558+
highlight_match = TRUE;
1559+
old_curswant = curwin->w_curswant;
1560+
old_leftcol = curwin->w_leftcol;
1561+
old_topline = curwin->w_topline;
1562+
# ifdef FEAT_DIFF
1563+
old_topfill = curwin->w_topfill;
1564+
# endif
1565+
old_botline = curwin->w_botline;
1566+
update_screen(NOT_VALID);
1567+
redrawcmdline();
1568+
}
1569+
else
1570+
vim_beep(BO_ERROR);
1571+
goto cmdline_not_changed;
1572+
}
1573+
#endif
1574+
else if (xpc.xp_numfiles > 0)
14771575
{
14781576
if (nextwild(&xpc, (c == Ctrl_P) ? WILD_PREV : WILD_NEXT,
14791577
0, firstc != '@') == FAIL)
@@ -1821,19 +1919,11 @@ getcmdline(
18211919
{
18221920
pos_T save_pos = curwin->w_cursor;
18231921

1824-
/*
1825-
* First move cursor to end of match, then to the start. This
1826-
* moves the whole match onto the screen when 'nowrap' is set.
1827-
*/
1828-
curwin->w_cursor.lnum += search_match_lines;
1829-
curwin->w_cursor.col = search_match_endcol;
1830-
if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
1831-
{
1832-
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
1833-
coladvance((colnr_T)MAXCOL);
1834-
}
1922+
match_start = curwin->w_cursor;
1923+
set_search_match(&curwin->w_cursor);
18351924
validate_cursor();
18361925
end_pos = curwin->w_cursor;
1926+
match_end = end_pos;
18371927
curwin->w_cursor = save_pos;
18381928
}
18391929
else
@@ -1894,6 +1984,8 @@ getcmdline(
18941984
if (did_incsearch)
18951985
{
18961986
curwin->w_cursor = old_cursor;
1987+
if (gotesc)
1988+
curwin->w_cursor = cursor_start;
18971989
curwin->w_curswant = old_curswant;
18981990
curwin->w_leftcol = old_leftcol;
18991991
curwin->w_topline = old_topline;
@@ -6983,3 +7075,21 @@ script_get(exarg_T *eap, char_u *cmd)
69837075

69847076
return (char_u *)ga.ga_data;
69857077
}
7078+
7079+
#ifdef FEAT_SEARCH_EXTRA
7080+
static void
7081+
set_search_match(pos_T *t)
7082+
{
7083+
/*
7084+
* First move cursor to end of match, then to the start. This
7085+
* moves the whole match onto the screen when 'nowrap' is set.
7086+
*/
7087+
t->lnum += search_match_lines;
7088+
t->col = search_match_endcol;
7089+
if (t->lnum > curbuf->b_ml.ml_line_count)
7090+
{
7091+
t->lnum = curbuf->b_ml.ml_line_count;
7092+
coladvance((colnr_T)MAXCOL);
7093+
}
7094+
}
7095+
#endif

src/testdir/Make_all.mak

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ NEW_TESTS = test_arglist.res \
181181
test_perl.res \
182182
test_quickfix.res \
183183
test_ruby.res \
184+
test_search.res \
184185
test_signs.res \
185186
test_startup.res \
186187
test_startup_utf8.res \

0 commit comments

Comments
 (0)