summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-07-06 20:58:04 -0300
committerGabriel Schneider <[email protected]>2026-08-01 15:02:07 -0300
commit49f8c696ea208d2653521699d77d7e8f48cac183 (patch)
tree522a74735b2507399c2fc913a8bdc4287584f98f /src
parent513938c1cfb216a3bc4a3559cf7731b8e44a952f (diff)
downloadpardes-49f8c696ea208d2653521699d77d7e8f48cac183.tar.gz
pardes-49f8c696ea208d2653521699d77d7e8f48cac183.zip
rework tty n/N: a pure token MOTION (normal mode only) — select the next/prev whitespace-separated token that look.resolve can open (several per line: the greet ls row hops big.txt -> plain.txt -> sub), park the cursor at the token start, open NOTHING. Enter's existing normal-mode handler does the look on the selection (dir -> shell+ls there, file -> pane), so navigation continues with n/N+Return inside whatever opened. Wraps when nothing lies in the motion direction (first n out of tty mode starts at the prompt row and lands on the first token — lookStep pins the cursor first). vsel anchors the token end, cursor at its start (vselText is end-inclusive). File-pane search n/N untouched. ttylook.snap rewritten for the new semantics: token hops with selection styling, insert-mode n still types, Return-opens-dir, empty-dir no-op, cursor-word Enter opens a file. 29/29.
Diffstat (limited to 'src')
-rw-r--r--src/pardes.zig50
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 };