diff options
Diffstat (limited to 'src/output_pane.zig')
| -rw-r--r-- | src/output_pane.zig | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/src/output_pane.zig b/src/output_pane.zig index a0583506..9c004dff 100644 --- a/src/output_pane.zig +++ b/src/output_pane.zig @@ -123,6 +123,14 @@ pub fn traits(o: Origin) Traits { // rows are `location text`, so n/N walk them .search => .{ .name = config.search_buffer, .steps = true }, .cmd => |b| switch (b) { + // The builtin index. Neither steppable nor executable, and that is + // a decision rather than an omission: its rows are not locations + // (a look on `SPC` would go looking for a file called SPC), and + // `executes` — which is exactly what makes ThemeSel a picker — + // would mean walking the list runs Kill, Del and Delcol in turn. + // Wearing a theme is free; wearing Kill ends the session. The + // names in it are still live text, so middle-clicking the ONE you + // want does the picking, which is all a picker was for. .Help => .{ .name = config.help_buffer }, // the focus history, one location per row: not a search, but the // same kind of list, so n/N walk it and a row is a look target @@ -303,24 +311,36 @@ fn openStepped(p: *Pardes, id: usize, from: Origin, text: []const u8) void { pane.search_row = null; } -/// The Help builtin: every builtin reachable from `prefix` (empty = all -/// of them) with the keys that run it, written into an output buffer -/// (acme's +Errors) — ordinary text, so the names in it are LIVE: middle- -/// click `Tutor` there and the tutor opens. Reuses the open +Help buffer -/// instead of piling panes up, and focus follows: you asked to read it. +/// The Help builtin: THE INDEX of builtins — every one of them, and every way +/// to run it — filtered to what `prefix` can still reach, written into an +/// output buffer (acme's +Errors). Ordinary text, so the names in it are LIVE: +/// middle-click `Tutor` there and the tutor opens. Reuses the open +Help +/// buffer instead of piling panes up, and focus follows: you asked to read it. +/// +/// ONE builtin and not two. The complete index and the mid-chord "what can +/// `SPC h` still reach" are the same array (pardes.builtin_rows) read with a +/// different prefix — the empty one matches every row, including the builtins +/// SPC cannot reach at all, so the reference page IS the filter's degenerate +/// case. A second builtin would have been a second renderer over a superset of +/// these rows, and the two would have drifted the first time a column moved. pub fn openHelp(p: *Pardes, id: usize, prefix: []const u8) void { const pane = p.panes[id] orelse return; const arena = p.scratch.allocator(); var out: std.ArrayList(u8) = .empty; if (prefix.len == 0) { - out.appendSlice(arena, "pardes builtins - SPC then the keys,\nor execute the name anywhere\n\n") catch return; + // the header names the four KINDS of shortcut a row's columns can + // hold, because a blank column is only readable once you know what + // would have been in it + out.appendSlice(arena, "pardes builtins, and how to run each:\nSPC and its keys, a chord, a button, the\ntopbar - or the name, executed anywhere.\n\n") catch return; } else { out.appendSlice(arena, "pardes builtins under SPC") catch return; for (prefix) |c| out.appendSlice(arena, &[_]u8{ ' ', c }) catch return; out.appendSlice(arena, "\n\n") catch return; } - for (pardes.leader_rows) |row| { - if (!std.mem.startsWith(u8, row.path, prefix)) continue; + for (pardes.builtin_rows) |row| { + // a path-less builtin filters as the empty path: in the full listing + // (which starts with nothing) and out of every group + if (!std.mem.startsWith(u8, row.path orelse "", prefix)) continue; out.appendSlice(arena, row.line) catch return; out.append(arena, '\n') catch return; } |
