Skip to content

Commit 27e2643

Browse files
authored
Add wrap-around search modifier. (#82)
Co-authored-by: numirias <numirias@users.noreply.github.com>
1 parent fb2016a commit 27e2643

4 files changed

Lines changed: 54 additions & 2 deletions

File tree

command.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ mca_search(VOID_PARAM)
168168
cmd_putstr("Keep-pos ");
169169
if (search_type & SRCH_NO_REGEX)
170170
cmd_putstr("Regex-off ");
171+
if (search_type & SRCH_WRAP_AROUND)
172+
cmd_putstr("Wrap-around ");
171173

172174
#if HILITE_SEARCH
173175
if (search_type & SRCH_FILTER)
@@ -534,6 +536,10 @@ mca_search_char(c)
534536
if (mca != A_FILTER)
535537
flag = SRCH_NO_MOVE;
536538
break;
539+
case CONTROL('W'): /* WRAP around */
540+
if (mca != A_FILTER)
541+
flag = SRCH_WRAP_AROUND;
542+
break;
537543
case CONTROL('R'): /* Don't use REGULAR EXPRESSIONS */
538544
flag = SRCH_NO_REGEX;
539545
break;
@@ -545,7 +551,8 @@ mca_search_char(c)
545551

546552
if (flag != 0)
547553
{
548-
search_type ^= flag;
554+
/* Toggle flag, but keep PAST_EOF and WRAP_AROUND mutually exclusive. */
555+
search_type ^= flag | (search_type & (SRCH_PAST_EOF|SRCH_WRAP_AROUND));
549556
mca_search();
550557
return (MCA_MORE);
551558
}

less.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ struct wchar_range_table
355355
#define SRCH_NO_REGEX (1 << 12) /* Don't use regular expressions */
356356
#define SRCH_FILTER (1 << 13) /* Search is for '&' (filter) command */
357357
#define SRCH_AFTER_TARGET (1 << 14) /* Start search after the target line */
358+
#define SRCH_WRAP_AROUND (1 << 15) /* Wrap-around search (continue at BOF/EOF) */
358359

359360
#define SRCH_REVERSE(t) (((t) & SRCH_FORW) ? \
360361
(((t) & ~SRCH_FORW) | SRCH_BACK) : \

less.nro.VER

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,11 @@ but don't move to the first match (KEEP current position).
226226
.IP "^R"
227227
Don't interpret regular expression metacharacters;
228228
that is, do a simple textual comparison.
229+
.IP "^W"
230+
WRAP around the current file.
231+
That is, if the search reaches the end of the current file
232+
without finding a match, the search continues from the first line of the
233+
current file up to the line where it started.
229234
.RE
230235
.IP ?pattern
231236
Search backward in the file for the N-th line containing the pattern.
@@ -250,6 +255,11 @@ or the settings of the \-a or \-j options.
250255
As in forward searches.
251256
.IP "^R"
252257
As in forward searches.
258+
.IP "^W"
259+
WRAP around the current file.
260+
That is, if the search reaches the beginning of the current file
261+
without finding a match, the search continues from the last line of the
262+
current file up to the line where it started.
253263
.RE
254264
.IP "ESC-/pattern"
255265
Same as "/*".

search.c

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1179,6 +1179,9 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos)
11791179

11801180
linenum = find_linenum(pos);
11811181
oldpos = pos;
1182+
/* When the search wraps around, end at starting position. */
1183+
if ((search_type & SRCH_WRAP_AROUND) && endpos == NULL_POSITION)
1184+
endpos = pos;
11821185
for (;;)
11831186
{
11841187
/*
@@ -1194,7 +1197,9 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos)
11941197
return (-1);
11951198
}
11961199

1197-
if ((endpos != NULL_POSITION && pos >= endpos) || maxlines == 0)
1200+
if ((endpos != NULL_POSITION && !(search_type & SRCH_WRAP_AROUND) &&
1201+
(((search_type & SRCH_FORW) && pos >= endpos) ||
1202+
((search_type & SRCH_BACK) && pos <= endpos))) || maxlines == 0)
11981203
{
11991204
/*
12001205
* Reached end position without a match.
@@ -1233,6 +1238,35 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos)
12331238
/*
12341239
* Reached EOF/BOF without a match.
12351240
*/
1241+
if (search_type & SRCH_WRAP_AROUND)
1242+
{
1243+
/*
1244+
* The search wraps around the current file, so
1245+
* try to continue at BOF/EOF.
1246+
*/
1247+
if (search_type & SRCH_FORW)
1248+
{
1249+
pos = ch_zero();
1250+
} else
1251+
{
1252+
pos = ch_length();
1253+
if (pos == NULL_POSITION)
1254+
{
1255+
(void) ch_end_seek();
1256+
pos = ch_length();
1257+
}
1258+
}
1259+
if (pos != NULL_POSITION) {
1260+
/*
1261+
* Wrap-around was successful. Clear
1262+
* the flag so we don't wrap again, and
1263+
* continue the search at new pos.
1264+
*/
1265+
search_type &= ~SRCH_WRAP_AROUND;
1266+
linenum = find_linenum(pos);
1267+
continue;
1268+
}
1269+
}
12361270
if (pendpos != NULL)
12371271
*pendpos = oldpos;
12381272
return (matches);

0 commit comments

Comments
 (0)