diff options
Diffstat (limited to 'src/pardes.zig')
| -rw-r--r-- | src/pardes.zig | 50 |
1 files changed, 38 insertions, 12 deletions
diff --git a/src/pardes.zig b/src/pardes.zig index a2cfe1c6..ebc54426 100644 --- a/src/pardes.zig +++ b/src/pardes.zig @@ -1708,28 +1708,54 @@ pub const Pardes = struct { /// chosen row gets the real look. The modal cursor is the position, so /// the walk continues from wherever j/k left it. The look may focus what /// it opened; focus comes back here so the next n keeps stepping. + /// n/N on a terminal pane: a MOTION over lookable tokens. Select the + /// next/prev whitespace-separated token that look.resolve can turn into a + /// file/dir (several per line: an ls row hops big.txt -> plain.txt), park + /// the cursor at its start, open NOTHING — Enter's normal-mode handler + /// looks the selection. Wraps around when nothing lies in the direction + /// (fresh out of tty mode the cursor sits below the output, so the first + /// n lands on the first token). fn lookStep(p: *Pardes, pane: *Pane, pl: PaneLines, delta: i32) void { - const id = p.active; + _ = p; // a pure motion now: Enter's normal-mode handler does the look + pane.pinCursor(); // fresh out of tty mode the cursor still tracks the shell const nrows: i32 = @intCast(pl.lines.len); + if (nrows == 0) return; var realbuf: [4096]u8 = undefined; - var r = pane.cur_row + delta; - while (r >= 0 and r < nrows) : (r += delta) { + var k: i32 = 0; + while (k < nrows) : (k += 1) { + const r = @mod(pane.cur_row + delta * k, nrows); const ln = pl.lines[@intCast(r)]; - var hi: usize = 0; - while (hi < ln.len and look.isFileChar(ln[hi])) hi += 1; - if (hi == 0 or look.resolve(ln[0..hi], pane.cwdSlice(), &realbuf) == .none) continue; - pane.msel = .{ .active = true, .r0 = r, .r1 = r }; - pane.vsel.active = false; + var hit_t0: usize = 0; + var hit_t1: usize = 0; + var i: usize = 0; + while (i < ln.len) { + while (i < ln.len and (ln[i] == ' ' or ln[i] == '\t')) i += 1; + const t0 = i; + while (i < ln.len and ln[i] != ' ' and ln[i] != '\t') i += 1; + if (i == t0) break; + // on the cursor's own row (no wrap yet) only tokens strictly + // past the cursor count, in the motion's direction + if (k == 0) { + if (delta > 0 and @as(i32, @intCast(t0)) <= pane.cur_col) continue; + if (delta < 0 and @as(i32, @intCast(t0)) >= pane.cur_col) continue; + } + if (look.resolve(ln[t0..i], pane.cwdSlice(), &realbuf) == .none) continue; + hit_t0 = t0; + hit_t1 = i; + if (delta > 0) break; // first token forward; keep the last one backward + } + if (hit_t1 == 0) continue; + // anchor the selection at the token's end, cursor at its START + pane.vsel = .{ .active = true, .row = r, .col = @intCast(hit_t1 - 1) }; + pane.msel.active = false; pane.cur_row = r; - pane.cur_col = 0; + pane.cur_col = @intCast(hit_t0); pane.cur_off = 0; pane.cur_pinned = true; pane.ensureCursorVisible(); - p.actOnSelection(.right, id, ln[0..hi], null); - p.active = id; return; } - // nothing lookable that way: stay put + // nothing lookable anywhere: stay put } const InsertAt = enum { at, append, line_start, line_end, open_below, open_above }; |
