summaryrefslogtreecommitdiff
path: root/src/look.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/look.zig')
-rw-r--r--src/look.zig76
1 files changed, 64 insertions, 12 deletions
diff --git a/src/look.zig b/src/look.zig
index e22f5705..afb5b760 100644
--- a/src/look.zig
+++ b/src/look.zig
@@ -1527,9 +1527,11 @@ const DiffLook = union(enum) { none, done, at: []const u8 };
/// line names (diff.targetAt): the new file at a `@@` line's first new
/// line, at a context or added line's own line, and at a removed line's
/// place, the new line now standing where it was. `---`/`+++` open their
-/// file. The path is the repository's (walking up from the diff's
-/// directory to a `.git` or `.jj`), `a/` and `b/` dropped, else the
-/// directory's own. A file that is not there opens nothing and says so.
+/// file. The path is the repository's name (diff.Walk.side: git's side
+/// prefixes dropped by git's rules, a plain diff's names as written),
+/// found from the repository root (walking up from the diff's directory to
+/// a `.git` or `.jj`), else the directory. A file that is not there opens
+/// nothing and says so, by that name.
///
/// Which line: the one a click just gave (`clicked`: exec.pointerOperand
/// expanded to it and kept its row), else, for a look written over 9P, a
@@ -1573,8 +1575,7 @@ fn diffLook(p: *Pardes, id: usize, pane: *Pane, operand: []const u8, clicked: bo
}
/// The file a diff names, from `base` (the diff's directory): tried in the
-/// repository `base` is in, then in `base`, as git writes it (`b/x`, the
-/// repository's `x`) and as written.
+/// repository `base` is in, then in `base`.
fn diffFile(base: []const u8, path: []const u8, out: *[4096]u8) ?[]const u8 {
if (comptime !platform_has_fs) return null;
if (path.len == 0) return null;
@@ -1593,11 +1594,9 @@ fn diffFile(base: []const u8, path: []const u8, out: *[4096]u8) ?[]const u8 {
} else null;
for ([_]?[]const u8{ root, base }) |maybe| {
const at = maybe orelse continue;
- for ([_][]const u8{ diff.stripSide(path), path }) |name| {
- var joined: [4096]u8 = undefined;
- const full = std.fmt.bufPrint(&joined, "{s}/{s}", .{ at, name }) catch continue;
- if (fs.resolveOs(full, out)) |found| if (!found.dir) return found.path;
- }
+ var joined: [4096]u8 = undefined;
+ const full = std.fmt.bufPrint(&joined, "{s}/{s}", .{ at, path }) catch continue;
+ if (fs.resolveOs(full, out)) |found| if (!found.dir) return found.path;
}
return null;
}
@@ -2175,10 +2174,10 @@ test "Look on a diff line of a file that is not here says so and opens nothing"
var after: usize = 0;
for (p.panes) |slot| after += @intFromBool(slot != null);
try std.testing.expectEqual(before, after);
- try std.testing.expectEqualStrings("Look: b/src/elsewhere.zig: no such file here", pane.msg[0..pane.msg_len]);
+ try std.testing.expectEqualStrings("Look: src/elsewhere.zig: no such file here", pane.msg[0..pane.msg_len]);
DiffFixture.click(p, pane, 11);
try std.testing.expect(p.look_missed);
- try std.testing.expectEqualStrings("Look: a/old.zig: deleted by this diff", pane.msg[0..pane.msg_len]);
+ try std.testing.expectEqualStrings("Look: old.zig: deleted by this diff", pane.msg[0..pane.msg_len]);
}
test "Look on plain diff -u output: names as written, timestamps cut, next to the diff" {
@@ -2303,3 +2302,56 @@ test "Look outside a diff pane expands and looks as ever" {
const operand = exec.pointerOperand(p, pane, pointed.sel);
try std.testing.expect(operand.text == null or !std.mem.eql(u8, operand.text.?, "+const a = 1;"));
}
+
+test "Look on a diff under each git prefix opens the repository's file, and a real a/ directory under --no-prefix" {
+ if (!platform_has_fs) return;
+ const Case = struct { text: []const u8, file: []const u8 };
+ const cases = [_]Case{
+ .{ .text = "diff --git a/src/x.zig b/src/x.zig\n--- a/src/x.zig\n+++ b/src/x.zig\n@@ -1,2 +1,2 @@\n-one\n+uno\n two\n", .file = "/src/x.zig" },
+ .{ .text = "diff --git c/src/x.zig w/src/x.zig\n--- c/src/x.zig\n+++ w/src/x.zig\n@@ -1,2 +1,2 @@\n-one\n+uno\n two\n", .file = "/src/x.zig" },
+ .{ .text = "diff --git i/src/x.zig w/src/x.zig\n--- i/src/x.zig\n+++ w/src/x.zig\n@@ -1,2 +1,2 @@\n-one\n+uno\n two\n", .file = "/src/x.zig" },
+ // --no-prefix: `a/x.zig` is the file x.zig in the directory a, and
+ // a `x.zig` at the top is never taken for it.
+ .{ .text = "diff --git a/x.zig a/x.zig\n--- a/x.zig\n+++ a/x.zig\n@@ -1,2 +1,2 @@\n-one\n+uno\n two\n", .file = "/a/x.zig" },
+ };
+ for (cases) |c| {
+ var fx: DiffFixture = undefined;
+ try fx.init(true, &.{ .{ "src/x.zig", "uno\ntwo\n" }, .{ "a/x.zig", "uno\ntwo\n" }, .{ "x.zig", "top\n" } }, c.text);
+ defer fx.tmp.cleanup();
+ const p = try Pardes.init(std.testing.allocator, .{ .cols = 100, .rows = 30 });
+ defer p.deinit();
+ const pane = try fx.open(p, c.text);
+ DiffFixture.click(p, pane, 6); // `two`, a context line: new line 2
+ try std.testing.expect(!p.look_missed);
+ try expectAt(p, c.file, 2);
+ DiffFixture.click(p, pane, 1); // `---`
+ try std.testing.expect(!p.look_missed);
+ try std.testing.expect(std.mem.endsWith(u8, p.panes[p.active].?.file.?.path, c.file));
+ }
+}
+
+test "Look on a diff says a missing or deleted file by its repository name, a plain diff's as written" {
+ if (!platform_has_fs) return;
+ const git_text = "diff --git c/src/gone.zig w/src/gone.zig\n--- c/src/gone.zig\n+++ w/src/gone.zig\n@@ -1 +1 @@\n-a\n+b\n" ++
+ "diff --git a/lib/old.zig b/lib/old.zig\ndeleted file mode 100644\n--- a/lib/old.zig\n+++ /dev/null\n@@ -1 +0,0 @@\n-a\n";
+ const plain_text = "--- a/x.zig\t2026-09-30 10:00:00 +0000\n+++ b/x.zig\t2026-09-30 11:00:00 +0000\n@@ -1 +1 @@\n-a\n+b\n";
+ var fx: DiffFixture = undefined;
+ try fx.init(true, &.{.{ "x.zig", "b\n" }}, git_text);
+ defer fx.tmp.cleanup();
+ const p = try Pardes.init(std.testing.allocator, .{ .cols = 100, .rows = 30 });
+ defer p.deinit();
+ var pane = try fx.open(p, git_text);
+ DiffFixture.click(p, pane, 5);
+ try std.testing.expect(p.look_missed);
+ try std.testing.expectEqualStrings("Look: src/gone.zig: no such file here", pane.msg[0..pane.msg_len]);
+ DiffFixture.click(p, pane, 11);
+ try std.testing.expectEqualStrings("Look: lib/old.zig: deleted by this diff", pane.msg[0..pane.msg_len]);
+ DiffFixture.click(p, pane, 6); // `diff --git` of the deleted file
+ try std.testing.expectEqualStrings("Look: lib/old.zig: deleted by this diff", pane.msg[0..pane.msg_len]);
+ // A plain diff's `b/x.zig` is a path as written: there is no b/ here,
+ // and the x.zig at the top is not it.
+ pane = try fx.open(p, plain_text);
+ DiffFixture.click(p, pane, 4);
+ try std.testing.expect(p.look_missed);
+ try std.testing.expectEqualStrings("Look: b/x.zig: no such file here", pane.msg[0..pane.msg_len]);
+}