Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Search backward

The process is very similar, but in reverse. This time we use the std.mem.lastIndexOf function, that finds the relative position of a slice in another slice before a certain index, or returns null if the slice isn't contained in the other slice.

Following steps are followed unless a match is returned.

search a slice of the current row [0..col]
search the previous lines
start of file, no wrapscan? return null
restart from the end of the file
if you reach the initial line, only search [col..]

If a match is found, pos.lnr is updated, because the callback will need the line where it was found.

Editor.zig
/// Start a search backwards.
fn findBackward(e: *Editor, query: []const u8, pos: *t.Pos) ?[]const u8 {
    // first line, search up to col
    const row = e.rowAt(pos.lnr);
    const col = pos.col;
    var rowchars = row.chars.items;
    var i: usize = undefined;

    if (lastIndexOf(u8, rowchars[0..col], query)) |m| {
        return rowchars[m .. m + query.len];
    }
    else if (pos.lnr > 0) {
        // previous lines, search full line
        i = pos.lnr - 1;
        while (true) : (i -= 1) {
            rowchars = e.rowAt(i).chars.items;

            if (lastIndexOf(u8, rowchars, query)) |m| {
                pos.lnr = i;
                return rowchars[m .. m + query.len];
            }
            if (i == 0) break;
        }
    }

    if (!opt.wrapscan) {
        return null;
    }

    i = e.buffer.rows.items.len - 1;
    while (i > pos.lnr) : (i -= 1) {
        rowchars = e.rowAt(i).chars.items;

        if (lastIndexOf(u8, rowchars, query)) |m| {
            pos.lnr = i;
            return rowchars[m .. m + query.len];
        }
    }

    // check again the starting line, this time in the part after the offset
    rowchars = e.rowAt(pos.lnr).chars.items;

    if (lastIndexOf(u8, rowchars[col..], query)) |m| {
        // m is the index in the substring starting from `col`, therefore we
        // must add `col` to get the real index in the row
        return rowchars[m + col .. m + col + query.len];
    }
    return null;
}