summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-15 16:44:18 -0300
committerGabriel Schneider <[email protected]>2026-09-15 17:24:42 -0300
commit96725011b43d7bf56ac02e710ea4ef4a76f05351 (patch)
tree3fb1dd233337a6023fe11a8e1ad777d6f44accec /src
parent89b3c352378eb0284b521722a13c4245cab41b0c (diff)
downloadpardes-96725011b43d7bf56ac02e710ea4ef4a76f05351.tar.gz
pardes-96725011b43d7bf56ac02e710ea4ef4a76f05351.zip
Make location highlighting an explicit output producer choice
Diffstat (limited to 'src')
-rw-r--r--src/builtins.zig8
-rw-r--r--src/panes.zig30
-rw-r--r--src/pardes.zig19
3 files changed, 39 insertions, 18 deletions
diff --git a/src/builtins.zig b/src/builtins.zig
index 18ea0198..765fa93c 100644
--- a/src/builtins.zig
+++ b/src/builtins.zig
@@ -95,6 +95,8 @@ pub const OutputTraits = struct {
name: []const u8,
steps: bool = false,
jumps: bool = false,
+ // This producer emits location rows whose labels and source excerpts may be styled.
+ locations: bool = false,
commands: bool = false,
doc: bool = false,
// Saving promotes this scratch buffer into an ordinary file.
@@ -357,7 +359,7 @@ pub const PdfTint = struct {
};
pub const PdfSections = struct {
- pub const output: OutputTraits = .{ .name = config.pdf_sections_buffer, .steps = true };
+ pub const output: OutputTraits = .{ .name = config.pdf_sections_buffer, .steps = true, .locations = true };
pub const enabled = pardes.pdf_enabled;
pub fn run(c: Ctx) void {
if (comptime enabled) apply(c) else unreachable;
@@ -618,7 +620,7 @@ pub const Find = struct {
/// matches file CONTENTS under every pane's directory at once.
pub const Grep = struct {
pub const takes_arg = true;
- pub const output: OutputTraits = .{ .name = config.search_buffer, .steps = true };
+ pub const output: OutputTraits = .{ .name = config.search_buffer, .steps = true, .locations = true };
pub fn run(c: Ctx) void {
const pat = std.mem.trim(u8, c.arg orelse "", " \t\r\n");
if (pat.len > 0) return c.p.runSearch(c.id, pat, .grep, .top) catch |err|
@@ -682,7 +684,7 @@ pub const Last = struct {
};
pub const Jumplist = struct {
- pub const output: OutputTraits = .{ .name = config.jumps_buffer, .steps = true };
+ pub const output: OutputTraits = .{ .name = config.jumps_buffer, .steps = true, .locations = true };
pub fn run(c: Ctx) void {
panes.Output.openJumps(c.p, c.id) catch |err| c.p.reportError(c.id, "jumplist", err);
}
diff --git a/src/panes.zig b/src/panes.zig
index 886d4b28..315b0b0f 100644
--- a/src/panes.zig
+++ b/src/panes.zig
@@ -271,8 +271,13 @@ pub const Pane = struct {
pub fn colorAlgo(pane: *const Pane) ColorAlgo {
if (pane.isTerminal()) return .tty;
if (pane.file) |f| {
+ if (f.mini != null) return .source;
if (std.mem.endsWith(u8, f.path, ".diff") or std.mem.endsWith(u8, f.path, ".patch")) return .diff;
- if (f.output != null and !Output.fileTraits(f.output).saves) return .locations;
+ if (f.output != null) {
+ const tr = Output.fileTraits(f.output);
+ if (tr.locations) return .locations;
+ if (!tr.saves) return .none;
+ }
return .source;
}
return .none;
@@ -1811,6 +1816,7 @@ pub const File = struct {
else
@max(start, lineStart(p.gpa, f, f.scroll + pane.rows + SYNTAX_CONTEXT_AFTER_ROWS + slack));
const new_highlights = (switch (pane.colorAlgo()) {
+ .none => @as([]u8, &.{}),
.diff => syntax.highlightDiff(p.tree_sitter_gpa, f.content, start, end),
.locations => if (f.location_rows.len > 0)
syntax.highlightLocationRows(p.tree_sitter_gpa, f.content, f.location_rows)
@@ -2187,6 +2193,7 @@ pub const Output = struct {
fn decorateRow(output: ?State, line: []const u8, metadata: ?locations.Row) RowDecoration {
const origin = (output orelse return .{}).from;
+ if (!traits(origin).locations) return .{};
const target = locations.parse(line);
const spot = if (metadata) |m| m.at else target.at;
if (spot.line == 0) return .{};
@@ -2238,6 +2245,18 @@ pub const Output = struct {
try std.testing.expect(malformed.mark_end <= "src/a.rs:3:99999999999999999999-99999999999999999999 text".len);
}
+ test "plain output does not opt into location decoration" {
+ const report = rowDecoration(.{ .from = .{ .cmd = .LocationsConfig } }, "LocationsConfig context:5 tscontext:on");
+ try std.testing.expectEqualDeep(RowDecoration{}, report);
+ const prose = rowDecoration(.{ .from = .{ .query = .hover } }, "src/a.rs:3:5-7 error: prose");
+ try std.testing.expectEqualDeep(RowDecoration{}, prose);
+ const errors = rowDecoration(.{ .from = .errors }, "src/a.rs:3:5-7 error: prose");
+ try std.testing.expectEqualDeep(RowDecoration{}, errors);
+ try std.testing.expect(!traits(.{ .cmd = .Find }).locations);
+ try std.testing.expect(traits(.{ .cmd = .Grep }).locations);
+ try std.testing.expect(traits(.{ .query = .completion }).locations);
+ }
+
pub fn setArg(o: *State, text: []const u8) error{ArgumentTooLong}!void {
if (text.len > max_arg) return error.ArgumentTooLong;
o.arg_len = @intCast(text.len);
@@ -2251,18 +2270,19 @@ pub const Output = struct {
pub fn traits(o: Origin) Traits {
return switch (o) {
// rows are `location text`, so n/N walk them
- .search => .{ .name = config.search_buffer, .steps = true },
+ .search => .{ .name = config.search_buffer, .steps = true, .locations = true },
.errors => .{ .name = config.errors_buffer, .doc = true },
- .pdf_links => .{ .name = config.pdf_links_buffer, .steps = true },
+ .pdf_links => .{ .name = config.pdf_links_buffer, .steps = true, .locations = true },
.cmd => |b| builtins.registry.outputTraits(b) orelse unreachable,
.query => |k| switch (k) {
.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 => .{ .name = config.search_buffer, .steps = true },
+ .rename => .{ .name = config.search_buffer, .steps = true, .locations = true },
.definition, .declaration, .type_definition, .implementation, .references => .{
.name = config.search_buffer,
.steps = true,
+ .locations = true,
.jumps = true,
},
// The hierarchy kinds behave like references: a list of places,
@@ -2270,11 +2290,13 @@ pub const Output = struct {
.incoming_calls, .outgoing_calls, .supertypes, .subtypes => .{
.name = config.search_buffer,
.steps = true,
+ .locations = true,
.jumps = true,
},
.document_symbols, .workspace_symbols, .diagnostics, .workspace_diagnostics, .select_refs, .completion => .{
.name = config.search_buffer,
.steps = true,
+ .locations = true,
},
},
};
diff --git a/src/pardes.zig b/src/pardes.zig
index 56f95040..25f4e18e 100644
--- a/src/pardes.zig
+++ b/src/pardes.zig
@@ -13827,17 +13827,14 @@ pub const Pardes = struct {
}
const tz_color = tracy.zone(@src(), "paneRecolor");
- switch (pane.colorAlgo()) {
- .tty => if (p.settings.colors) panes.Terminal.recolorAnsi(p, pane, r, tx, tw, body_h, body),
- // `.locations` joins them because it feeds the same `f.highlights`
- // — only the pass that FILLED it differs (refreshHighlights).
- .source, .diff, .locations => {
- const f = &pane.file.?;
- panes.File.drawGutter(p, pane, r, tx, tw, body_h, active);
- if (p.settings.colors) panes.File.recolorSyntax(p, pane, f, r, tx, tw, body_h);
- panes.File.drawWrapMarkers(p, pane, r, tx, tw, body_h, pane_bg);
- },
- .none => {},
+ // File layout is independent of whether its producer requests colors.
+ if (pane.file) |*f| {
+ panes.File.drawGutter(p, pane, r, tx, tw, body_h, active);
+ if (p.settings.colors and pane.colorAlgo() != .none)
+ panes.File.recolorSyntax(p, pane, f, r, tx, tw, body_h);
+ panes.File.drawWrapMarkers(p, pane, r, tx, tw, body_h, pane_bg);
+ } else if (pane.isTerminal() and p.settings.colors) {
+ panes.Terminal.recolorAnsi(p, pane, r, tx, tw, body_h, body);
}
tz_color.end();