diff options
Diffstat (limited to 'src/output_pane.zig')
| -rw-r--r-- | src/output_pane.zig | 57 |
1 files changed, 46 insertions, 11 deletions
diff --git a/src/output_pane.zig b/src/output_pane.zig index 9021e479..1850fa92 100644 --- a/src/output_pane.zig +++ b/src/output_pane.zig @@ -106,14 +106,22 @@ pub fn traits(o: Origin) Traits { .hover => .{ .name = config.hover_buffer }, // prose: an action list, a diff, a report about the backend .code_action, .format, .status, .explain => .{ .name = config.lsp_buffer }, - // Rename responses are edits consumed before an output can open; - // the exhaustive table still records the otherwise-unused trait. - .rename => .{ .name = config.lsp_buffer }, + // Rename usually resolves to edit records the core consumes before + // any buffer opens; what RENDERS is the multi-file PREVIEW — one + // location row per would-be edit — which n/N step like any list. + .rename => .{ .name = config.search_buffer, .steps = true }, .definition, .declaration, .type_definition, .implementation, .references => .{ .name = config.search_buffer, .steps = true, .jumps = true, }, + // The hierarchy kinds behave like references: a list of places, + // and a lone answer (one caller, one subtype) is a jump. + .incoming_calls, .outgoing_calls, .supertypes, .subtypes => .{ + .name = config.search_buffer, + .steps = true, + .jumps = true, + }, // completion lists WHAT COULD GO HERE, one row per candidate's // definition. It does not jump on a single row where the gotos do: // a goto answers a question whose answer is a place, so landing @@ -397,8 +405,25 @@ fn openStepped(p: *Pardes, id: usize, from: Origin, content: []u8) !void { fn helpContent(gpa: std.mem.Allocator, prefix: []const u8) ![]u8 { const full_header = "pardes builtins, and how to run each:\nSPC and its keys, a chord, a button, the\ntopbar - or the name, executed anywhere.\n\n"; const group_header = "pardes builtins under SPC"; + // The LANGUAGE KEYS are the one part of the keymap Help would otherwise + // never show: they are motions and modes, not words, so no builtin row + // carries them — yet they are the keys a reader comes looking for. Full + // listing only; a mid-chord `SPC l` view stays a pure filter. + const language_footer = + "\nlanguage keys (motions, not words):\n" ++ + "gd gD gy gi gr goto: definition,\n" ++ + " declaration, type-def,\n" ++ + " implementation, refs\n" ++ + "]d [d ]D [D diagnostics: next,\n" ++ + " prev, last, first\n" ++ + "= format (applies, one\n" ++ + " undo step)\n" ++ + "Tab after a . completion, in insert\n" ++ + "C-left-click definition, by mouse\n" ++ + "SPC l ... hover, rename, symbols,\n" ++ + " calls, types: above\n"; var len: usize = if (prefix.len == 0) - full_header.len + full_header.len + language_footer.len else group_header.len + prefix.len * 2 + 2; for (pardes.builtin_rows) |row| { @@ -431,6 +456,10 @@ fn helpContent(gpa: std.mem.Allocator, prefix: []const u8) ![]u8 { content[at] = '\n'; at += 1; } + if (prefix.len == 0) { + @memcpy(content[at..][0..language_footer.len], language_footer); + at += language_footer.len; + } std.debug.assert(at == content.len); return content; } @@ -442,22 +471,28 @@ pub fn openHelp(p: *Pardes, id: usize, prefix: []const u8) !void { return openRead(p, id, .{ .cmd = .Help }, prefix, content); } -test "full Help renders every enabled builtin row" { +test "full Help renders every builtin row, then the language keys" { const content = try helpContent(std.testing.allocator, ""); defer std.testing.allocator.free(content); - const body = content[(std.mem.lastIndexOf(u8, content, "\n\n") orelse + // FIRST blank line: the end of the header (the footer opens with one too) + const body = content[(std.mem.indexOf(u8, content, "\n\n") orelse return error.MissingHelpHeader) + 2 ..]; var lines = std.mem.splitScalar(u8, body, '\n'); for (pardes.builtin_rows) |row| try std.testing.expectEqualStrings(row.line, lines.next() orelse return error.MissingBuiltinHelpRow); - // The renderer terminates every row with a newline, so only split's empty - // trailing field may remain. Any extra non-empty field is an unregistered - // Help row and any missing row already failed in the loop above. + // ...and after the last row, the language-keys section: the one part of + // the keymap no builtin row can carry, closing the page. try std.testing.expectEqualStrings("", lines.next() orelse - return error.MissingHelpTerminator); - try std.testing.expect(lines.next() == null); + return error.MissingLanguageKeys); + try std.testing.expectEqualStrings("language keys (motions, not words):", lines.next() orelse + return error.MissingLanguageKeys); + try std.testing.expect(std.mem.indexOf(u8, body, "\ngd gD gy gi gr goto: definition,\n") != null); + // the group view stays a pure filter: no footer under a prefix + const group = try helpContent(std.testing.allocator, "l"); + defer std.testing.allocator.free(group); + try std.testing.expect(std.mem.indexOf(u8, group, "language keys") == null); } /// The complete live Config report: the generated settings and the host facts |
