// lesson: search
Search
A file you can't search is a file you can only scroll. The good news after the last few lessons: search is easy โ plain C string work, no escape codes, no state machines. The design still deserves five minutes, because search UX has sharp conventions.
Find-next semantics
The operation that matters is not "find" but find next: given where I am, where is the following match? Repeat-invocations then walk match to match. Two conventions define it:
- Start searching at a given position (inclusive), and let the caller pass "cursor + one column" for repeat-search โ else pressing find-next while standing on a match finds the same match forever. Keeping the +1 out of the search function keeps the function honest and the policy visible at the call site.
- Wrap around. Hitting the last match then searching again jumps back to the first (vim flashes "search hit BOTTOM, continuing at TOP"). Implement by scanning position โ end of buffer, then start of buffer โ position.
Within a line, strstr(3) does the byte work โ find the first
occurrence of a needle in a haystack. The only wrinkle: starting
mid-line means searching the line's suffix (strstr(line + col, q)), then reporting the match's column relative to the whole line
(add the offset back โ a classic pointer-arithmetic fencepost).
Real editors layer niceties on this core โ case folding, highlight-all, incremental search that jumps as you type, regex. All of them sit on exactly this function; incremental search, for instance, is just re-running find-next from the search's origin on every keystroke of the query.
โบ Find in Buffer
20 ptsImplement:
int editor_find_next(const struct editor *e, const char *query,
int from_row, int from_col,
int *match_row, int *match_col);
- Search forward from (
from_row,from_col) inclusive, wrapping past the end of the buffer, over all lines โ including the part of the starting line beforefrom_col*on the wrapped pass (a match just left of the cursor must be reachable). - On a hit: store its position, return 1. No match anywhere (or empty/NULL query, or an out-of-range start): return 0.
- Matches are byte-exact and case-sensitive.
Log in to submit a solution and earn points.