summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/File.zig33
-rw-r--r--src/panes.zig2
-rw-r--r--src/pardes.zig1
3 files changed, 35 insertions, 1 deletions
diff --git a/src/File.zig b/src/File.zig
index d16d4fc0..c738ee58 100644
--- a/src/File.zig
+++ b/src/File.zig
@@ -72,6 +72,9 @@ pub const State = struct {
/// Its file was deleted on disk: said once (`deleted`) until it is
/// written or found again.
disk_gone: bool = false,
+ /// 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,
/// 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.
@@ -998,6 +1001,36 @@ pub fn setContentSpan(p: *Pardes, f: *State, new: []u8, span: ?Span) void {
f.highlights = &.{};
f.highlight_start = 0;
f.syntax_dirty = true;
+ if (std.mem.endsWith(u8, f.path, "/+Pager")) f.pager_diff = looksLikeDiff(new[0..@min(new.len, 64 * 1024)]);
+}
+
+/// Whether `head`, a text's first bytes, holds a diff: a `diff` header, or
+/// a unified hunk's `---`, `+++` and `@@` lines.
+pub fn looksLikeDiff(head: []const u8) bool {
+ if (std.mem.startsWith(u8, head, "diff ") or std.mem.indexOf(u8, head, "\ndiff ") != null) return true;
+ const minus = std.mem.indexOf(u8, head, "--- ") orelse return false;
+ const plus = std.mem.indexOfPos(u8, head, minus, "\n+++ ") orelse return false;
+ return std.mem.indexOfPos(u8, head, plus, "\n@@ ") != null;
+}
+
+test "a +Pager pane holding a diff is drawn and looked at as one; holding other text, as text" {
+ const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true });
+ defer p.deinit();
+ const pane = try p.setTestFile("");
+ const f = &pane.file.?;
+ p.gpa.free(f.path);
+ f.path = try p.gpa.dupe(u8, "/tmp/+Pager");
+ setContent(p, f, try p.gpa.dupe(u8, "commit abc\n\ndiff --git a/x b/x\n--- a/x\n+++ b/x\n@@ -1 +1 @@\n-a\n+b\n"));
+ try std.testing.expect(pane.colorAlgo() == .diff);
+ try std.testing.expect(pardes.look.diffLines(p, pane) != null);
+ setContent(p, f, try p.gpa.dupe(u8, "commit abc\n\n a plain log\n"));
+ try std.testing.expect(pane.colorAlgo() != .diff);
+}
+
+test "a pager's text is a diff when it holds a diff header or a unified hunk" {
+ try std.testing.expect(looksLikeDiff("commit abc\nAuthor: x\n\n msg\n\ndiff --git a/f b/f\n"));
+ try std.testing.expect(looksLikeDiff("--- a/f\n+++ b/f\n@@ -1 +1 @@\n-a\n+b\n"));
+ try std.testing.expect(!looksLikeDiff("commit abc\nAuthor: x\n\n plain log\n"));
}
pub fn restoreSnap(pane: *Pane, f: *State, snap: Snapshot) void {
diff --git a/src/panes.zig b/src/panes.zig
index a395d6ed..9d1b7571 100644
--- a/src/panes.zig
+++ b/src/panes.zig
@@ -448,7 +448,7 @@ pub const Pane = struct {
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 (std.mem.endsWith(u8, f.path, ".diff") or std.mem.endsWith(u8, f.path, ".patch") or f.pager_diff) return .diff;
if (f.output != null) {
const tr = Output.fileTraits(f.output);
if (tr.locations) return .locations;
diff --git a/src/pardes.zig b/src/pardes.zig
index 84b891e5..5d0ab7e8 100644
--- a/src/pardes.zig
+++ b/src/pardes.zig
@@ -4640,6 +4640,7 @@ pub const Pardes = struct {
const named = try std.fs.path.join(gpa, &.{ dir, "+Pager" });
gpa.free(shown.file.?.path);
shown.file.?.path = named;
+ shown.file.?.pager_diff = panes.File.looksLikeDiff(content[0..@min(content.len, 64 * 1024)]);
p.oneColumn();
},
.embedded => {