diff options
| author | Gabriel Schneider <[email protected]> | 2026-10-01 10:09:54 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 10:36:28 -0300 |
| commit | edad6d960dc0fc1165cbb3b801e0538045b2247f (patch) | |
| tree | 0bedfbb9cd371e5d77cb697438c5198c688653c5 /src/File.zig | |
| parent | 4db57bf5bd788a292fcf2cfbea3b6d8b281510f0 (diff) | |
| download | pardes-edad6d960dc0fc1165cbb3b801e0538045b2247f.tar.gz pardes-edad6d960dc0fc1165cbb3b801e0538045b2247f.zip | |
A +Pager keeps its program's colours: the session parses what /pager is written after its directory with ghostty-vt, SGR becomes spans drawn over the plain text, every other escape is dropped, and PagerColor off pages it plain
Diffstat (limited to 'src/File.zig')
| -rw-r--r-- | src/File.zig | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/src/File.zig b/src/File.zig index 4fac0073..b3c28290 100644 --- a/src/File.zig +++ b/src/File.zig @@ -75,6 +75,11 @@ pub const State = struct { /// A +Pager pane (`pardes -`) whose text is a diff (`git diff`, `show`, /// `log -p`): drawn and looked at as a diff (Pane.colorAlgo). pager_diff: bool = false, + /// A +Pager's colours, as its program printed them (pager.zig): drawn + /// over its text by recolorSyntax, never read over 9P. ponytail: any + /// edit drops them (setContentSpan); shifting them through the splice, + /// as pane.zig's shiftOne moves dot, would keep them. + pager_spans: []pardes.pager.Span = &.{}, /// Seconds of the last content change, for the filesystem's stat; zero until edited. mtime: u32 = 0, /// Non-null for a generated output buffer rather than an on-disk file. @@ -982,6 +987,7 @@ pub fn deinit(p: *Pardes, pane: *Pane, file: *State) void { if (file.mini) |*mini| mini.deinit(p.gpa); if (file.line_starts.len > 0) p.gpa.free(file.line_starts); if (file.highlights.len > 0) p.tree_sitter_gpa.free(file.highlights); + p.gpa.free(file.pager_spans); locations.freeRows(p.gpa, file.location_rows); if (file.context_declarations.len > 0) p.tree_sitter_gpa.free(file.context_declarations); if (file.node_tree) |tree| syntax.freeTree(tree); @@ -1010,6 +1016,8 @@ pub fn setContent(p: *Pardes, f: *State, new: []u8) void { pub fn setContentSpan(p: *Pardes, f: *State, new: []u8, span: ?Span) void { locations.freeRows(p.gpa, f.location_rows); f.location_rows = &.{}; + p.gpa.free(f.pager_spans); + f.pager_spans = &.{}; for (p.panes) |slot| if (slot) |pane| { if (pane.file) |*file| if (file == f) { for (0..pane.sel.len) |button| { @@ -1483,7 +1491,8 @@ fn synStyle(p: *Pardes, sy: syntax.Syn) ?SynStyle { pub fn recolorSyntax(p: *Pardes, s: *Surface, pane: *Pane, f: *State, r: pardes.Rect, tx: u16, tw: u16, body_h: u16) void { const highlights = if (f.mini) |mini| mini.colors else f.highlights; const highlight_start = if (f.mini != null) 0 else f.highlight_start; - if (highlights.len == 0 and f.output == null) return; + const spans = f.pager_spans; + if (highlights.len == 0 and f.output == null and spans.len == 0) return; const prefix_width = gutterWidth(pane); const tz_recolor = tracy.zone(@src(), "synRecolor"); defer tz_recolor.end(); @@ -1526,6 +1535,14 @@ pub fn recolorSyntax(p: *Pardes, s: *Surface, pane: *Pane, f: *State, r: pardes. else null else null; if (tint) |t| if (prefix_width < tw) tintRow(s, tx + @as(u16, @intCast(prefix_width)), body_y + vr, tx + tw, t.bg); + // A +Pager's own colours (pager.zig) on every row but one the diff + // look tints: an added or removed line is drawn as pardes draws a + // diff, and git's red and green on it would only fight the tint. + var span_at = if (tint != null) spans.len else std.sort.partitionPoint(pardes.pager.Span, spans, base + hs, struct { + fn before(at: usize, span: pardes.pager.Span) bool { + return span.end <= at; + } + }.before); var c: usize = 0; var screen_c: usize = 0; while (hs + c < limit and prefix_width + screen_c < tw) { @@ -1562,6 +1579,27 @@ pub fn recolorSyntax(p: *Pardes, s: *Surface, pane: *Pane, f: *State, r: pardes. if (style.bg != .default) cell.style.bg = style.bg; } } + while (span_at < spans.len and spans[span_at].end <= idx) span_at += 1; + if (span_at < spans.len and spans[span_at].start <= idx) { + const st = spans[span_at].style; + var fill: usize = 0; + while (fill < cells and prefix_width + screen_c + fill < tw) : (fill += 1) { + const cell = s.at(tx + @as(u16, @intCast(prefix_width + screen_c + fill)), body_y + vr); + if (cell.default) continue; + // A palette colour through the theme's sixteen, as a + // terminal pane's cell; truecolor as it is. + if (st.fg != .default) cell.style.fg = if (st.fg == .index) terminal.palColor(p, st.fg.index) else st.fg; + if (st.bg != .default) cell.style.bg = if (st.bg == .index) terminal.palColor(p, st.bg.index) else st.bg; + cell.style.bold = cell.style.bold or st.bold; + cell.style.dim = st.dim; + cell.style.italic = st.italic; + cell.style.blink = st.blink; + cell.style.reverse = st.reverse; + cell.style.invisible = st.invisible; + cell.style.strikethrough = st.strikethrough; + if (st.ul != .off) cell.style.ul = st.ul; + } + } screen_c += cells; c = grapheme_end - hs; } |
