summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/look.zig55
1 files changed, 54 insertions, 1 deletions
diff --git a/src/look.zig b/src/look.zig
index 030aa432..41cfdc0c 100644
--- a/src/look.zig
+++ b/src/look.zig
@@ -792,10 +792,16 @@ fn lookStand(pane: *Pane) LookFrom {
fn lookWalkPanes(p: *Pardes, out: *[MAX_PANES]usize) []const usize {
var n: usize = 0;
+ // A command pane walked from (`make`'s errors): its own places first.
+ if (commandPaneActive(p)) {
+ out[0] = p.active;
+ n = 1;
+ }
var i = p.n_look_src;
while (i > 0) {
i -= 1;
const id = p.paneBySerial(p.look_src[i]) orelse continue;
+ if (n > 0 and out[0] == id) continue;
out[n] = id;
n += 1;
}
@@ -890,11 +896,18 @@ fn lookSpanIn(p: *Pardes, pane: *Pane, from: LookFrom, delta: i32, budget: *usiz
return null;
}
+/// A command pane has the keyboard: `n` there walks its own output.
+fn commandPaneActive(p: *Pardes) bool {
+ const pane = p.panes[p.active] orelse return false;
+ return pane.command != null and pane.file == null and !p.header_focus;
+}
+
pub fn lookWalk(p: *Pardes, delta: i32) void {
var buf: [MAX_PANES]usize = undefined;
const order = lookWalkPanes(p, &buf);
if (order.len == 0) return;
- const owner = if (p.look_walk_owner) |serial| p.paneBySerial(serial) else null;
+ // From a command pane the walk starts there, whoever walked last.
+ const owner = if (commandPaneActive(p)) p.active else if (p.look_walk_owner) |serial| p.paneBySerial(serial) else null;
const active_at = std.mem.indexOfScalar(usize, order, p.active) orelse 0;
const at = if (owner) |wanted|
std.mem.indexOfScalar(usize, order, wanted) orelse active_at
@@ -2643,6 +2656,46 @@ test "Incl's directories find a name found nowhere else, <name> too; bare Incl l
try std.testing.expectEqual(@as(usize, 0), p.incl.items.len);
}
+test "n in a command pane walks its own file:line places, whoever walked last" {
+ if (!platform_has_fs) return;
+ var tmp = std.testing.tmpDir(.{});
+ defer tmp.cleanup();
+ try tmp.dir.writeFile(std.testing.io, .{ .sub_path = "x.c", .data = "a\nb\nc\n" });
+ try tmp.dir.writeFile(std.testing.io, .{ .sub_path = "y.c", .data = "a\nb\n" });
+ var dir_buf: [4096]u8 = undefined;
+ const dir = dir_buf[0..try tmp.dir.realPath(std.testing.io, &dir_buf)];
+ const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 100, .rows = 30 });
+ defer p.deinit();
+ const doc = try p.setTestFile("x\n");
+ p.gpa.free(doc.file.?.path);
+ doc.file.?.path = try std.fs.path.join(p.gpa, &.{ dir, "main.c" });
+ while (p.nextEffect()) |_| {}
+ const dst = exec.execute(p, 0, "make") orelse return error.NoCommandPane;
+ while (p.nextEffect()) |_| {}
+ p.update(.{ .output = .{ .pane = @intCast(dst), .bytes = "x.c:3:1: error: bad\r\ny.c:2:1: warning: odd\r\n" } });
+ p.update(.{ .exited = .{ .pane = @intCast(dst), .status = 2 } });
+ p.update(.{ .eof = .{ .pane = @intCast(dst) } });
+ const cmd = p.panes[dst].?;
+ // A walk last made elsewhere, and another pane with places in it.
+ try std.testing.expect(p.executeBuiltinLine(0, "New"));
+ const scratch = p.panes[p.active].?;
+ _ = pardes.ctlfs.pane.spliceBody(p, scratch, 0, 0, "x.c:1:1 elsewhere\n") orelse return error.NoScratch;
+ p.look_walk_owner = scratch.serial;
+ p.active = dst;
+ cmd.focus = .body;
+ cmd.body.mode = .normal;
+ for ([_]u21{ 'g', 'g' }) |cp| p.update(.{ .key = .{ .cp = cp } });
+ p.update(.{ .key = .{ .cp = 'n' } });
+ try std.testing.expectEqual(dst, p.active);
+ const first = cmd.look_at orelse return error.NoSpot;
+ const lines = try edit.paneCursorLines(p, &cmd.body);
+ try std.testing.expect(std.mem.startsWith(u8, lines[@intCast(first.row)][@intCast(first.col0)..], "x.c:3:1"));
+ p.update(.{ .key = .{ .cp = 'n' } });
+ try std.testing.expectEqual(dst, p.active);
+ const second = cmd.look_at orelse return error.NoSpot;
+ try std.testing.expect(std.mem.startsWith(u8, lines[@intCast(second.row)][@intCast(second.col0)..], "y.c:2:1"));
+}
+
test "Look outside a diff pane expands and looks as ever" {
const p = try Pardes.init(std.testing.allocator, .{ .cols = 100, .rows = 30 });
defer p.deinit();