diff options
| author | Gabriel Schneider <[email protected]> | 2026-07-06 17:36:07 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-08-01 15:02:07 -0300 |
| commit | ffa636a284b3ccc9aa4f31dff7f148780d2cd00b (patch) | |
| tree | aba9014d031f4f2b63c55fd06167c1398f7085d9 /src | |
| parent | 65bffe2c7b7fcdbd82cc112315e64e1bca8dd150 (diff) | |
| download | pardes-ffa636a284b3ccc9aa4f31dff7f148780d2cd00b.tar.gz pardes-ffa636a284b3ccc9aa4f31dff7f148780d2cd00b.zip | |
tty look motion: n/N on a terminal pane (normal mode only) walk the pane's own output rows — paneCursorLines, prompt/echo rows already blanked by the OSC 133 marks — for the next/prev row whose leading file-ish word resolves through look.resolve (realpath-only, side-effect-free; only the chosen row gets the real look), msel-select it, scroll it into view, and look it via actOnSelection. The modal cursor is the position (no new Pane state), so the walk resumes wherever j/k left it; focus returns to the terminal after the look so n keeps stepping; no wrap; no hit = no-op. Insert mode still splices, tty mode still forwards to the pty. The file-pane search stepper stays separate (different row predicate: the searched file's path prefix vs general resolvability). New snap script ttylook.snap + golden; all 19 baseline goldens untouched and green (20/20).
Diffstat (limited to 'src')
| -rw-r--r-- | src/pardes.zig | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/src/pardes.zig b/src/pardes.zig index 88b10374..ac543aeb 100644 --- a/src/pardes.zig +++ b/src/pardes.zig @@ -1545,6 +1545,9 @@ pub const Pardes = struct { if (pane.file != null and is(key, '/')) return p.startSearch(pane); if (pane.file != null and is(key, 'n')) return p.searchStep(pane, 1); if (pane.file != null and is(key, 'N')) return p.searchStep(pane, -1); + // terminal n/N: look the next/previous output row that looks somewhere + if (pane.isTerminal() and is(key, 'n')) return p.lookStep(pane, pl, 1); + if (pane.isTerminal() and is(key, 'N')) return p.lookStep(pane, pl, -1); } // ---- file search (`/` + n/N): grep into a shell pane, look the results ---- @@ -1632,6 +1635,37 @@ pub const Pardes = struct { // no result that way (or none at all): nowhere to go, stay put } + /// n/N on a terminal pane (normal mode): select the next/previous output + /// row whose leading file-ish word looks somewhere — resolves to a + /// file/dir/path:NNN exactly as a right click would — and look it. The + /// scan only resolves (realpath, no pane opens, no scrolls); the one + /// 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. + fn lookStep(p: *Pardes, pane: *Pane, pl: PaneLines, delta: i32) void { + const id = p.active; + const nrows: i32 = @intCast(pl.lines.len); + var realbuf: [4096]u8 = undefined; + var r = pane.cur_row + delta; + while (r >= 0 and r < nrows) : (r += delta) { + 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; + pane.cur_row = r; + pane.cur_col = 0; + 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 + } + const InsertAt = enum { at, append, line_start, line_end, open_below, open_above }; fn enterInsert(p: *Pardes, pane: *Pane, where: InsertAt) void { |
