From 23f430573efe4f6ef55b0180aa0d742ff4eca1d9 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Mon, 28 Sep 2026 00:01:57 -0300 Subject: Make a pane's tag a Text edited with the body's own keys The tag was a fixed buffer with its own one-line editor, a cursor measured across the path, and a hijack of the body's mode while it was typed into. It is now the pane's second Text: its own characters after the computed prefix (path, dirty marker, PDF page), which is never stored in it, so a rename or a dirty marker never moves its cursor. Normal and insert mode are the body's, undo included; `:` moves the keyboard between body and tag, the tag remembers its cursor and starts on Save, and executing a word from it hands the keyboard back. The mouse still sees the prefix: a sweep selects across it and a click on the path drafts a new name. Co-Authored-By: Claude Opus 5.5 --- test/mode.zig | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'test/mode.zig') diff --git a/test/mode.zig b/test/mode.zig index 19d59699..c429ea72 100644 --- a/test/mode.zig +++ b/test/mode.zig @@ -6,7 +6,7 @@ const Pardes = pardes.Pardes; fn mode(p: *Pardes, id: usize, expected: panes.Text.Mode) !void { try std.testing.expect(p.executeBuiltinLine(id, "Mode")); try std.testing.expectEqual(expected, p.panes[id].?.body.mode); - try std.testing.expect(!p.panes[id].?.tag_edit); + try std.testing.expect(p.panes[id].?.focus == .body); } fn clickModeTag(p: *Pardes) !void { @@ -17,13 +17,12 @@ fn clickModeTag(p: *Pardes) !void { const row = if (p.settings.tag_bottom) rect.y + rect.h - pardes.BOX_H else rect.y; for ([_]pardes.Mouse.Kind{ .press, .release }) |kind| p.update(.{ .mouse = .{ .button = .left, .kind = kind, .col = rect.x + pardes.TAG_TEXT_INSET + @as(u16, @intCast(col)), .row = row } }); - try std.testing.expect(pane.tag_edit); + try std.testing.expect(pane.focus == .tag); } -fn customTag(pane: *pardes.Pane, text: []const u8) void { - @memcpy(pane.tag_tail[0..text.len], text); - pane.tag_tail_len = text.len; - pane.tag_init = true; +fn customTag(pane: *pardes.Pane, text: []const u8) !void { + if (pane.tag.own) |own| pane.gpa.free(own); + pane.tag.own = try pane.gpa.dupe(u8, text); } test "Mode cycles terminal modes and keeps legacy toggle and custom tags" { @@ -37,14 +36,18 @@ test "Mode cycles terminal modes and keeps legacy toggle and custom tags" { try std.testing.expect(std.mem.indexOf(u8, try p.tagText(p.scratch.allocator(), pane), " Mode") != null); try mode(p, 0, .normal); try mode(p, 0, .insert); + // A clicked tag is typed into; its execute key is a normal-mode key, as + // a body's is, and the body keeps its own mode meanwhile. try clickModeTag(p); - try std.testing.expectEqual(panes.Text.Mode.insert, pane.tag_mode); + try std.testing.expectEqual(panes.Text.Mode.insert, pane.tag.mode); + try std.testing.expectEqual(panes.Text.Mode.insert, pane.body.mode); + p.update(.{ .key = .{ .cp = pardes.Key.escape } }); p.update(.{ .key = .{ .cp = pardes.Key.tab } }); try std.testing.expectEqual(panes.Text.Mode.tty, pane.body.mode); - try std.testing.expect(!pane.tag_edit); + try std.testing.expect(pane.focus == .body); while (p.nextEffect()) |effect| try std.testing.expect(effect != .write); - customTag(pane, " Togglettymode Keep"); + try customTag(pane, " Togglettymode Keep"); try mode(p, 0, .normal); try mode(p, 0, .insert); try std.testing.expect(p.executeBuiltinLine(0, "Togglettymode")); @@ -53,7 +56,7 @@ test "Mode cycles terminal modes and keeps legacy toggle and custom tags" { try std.testing.expectEqual(panes.Text.Mode.normal, pane.body.mode); p.update(.{ .key = .{ .cp = 'b', .ctrl = true } }); try std.testing.expectEqual(panes.Text.Mode.tty, pane.body.mode); - try std.testing.expectEqualStrings(" Togglettymode Keep", pane.tag_tail[0..pane.tag_tail_len]); + try std.testing.expectEqualStrings(" Togglettymode Keep", pane.tag.own.?); } test "Mode from actual tag Exec preserves parked file and output insert transactions" { @@ -65,17 +68,17 @@ test "Mode from actual tag Exec preserves parked file and output insert transact const pane = try p.setTestFile("ab\n"); if (output) pane.file.?.output = .{ .from = .search }; try std.testing.expect(std.mem.indexOf(u8, try p.tagText(p.scratch.allocator(), pane), " Mode") == null); - customTag(pane, " Mode"); + try customTag(pane, " Mode"); try mode(p, 0, .insert); p.update(.{ .key = .{ .cp = '界', .text = "界" } }); p.update(.{ .key = .{ .cp = 'x', .text = "x" } }); try std.testing.expectEqualStrings("界xab\n", pane.file.?.content); try clickModeTag(p); - try std.testing.expectEqual(panes.Text.Mode.insert, pane.tag_mode); - if (normal_tag) pane.body.mode = .normal; + try std.testing.expectEqual(panes.Text.Mode.insert, pane.body.mode); + if (normal_tag) pane.tag.mode = .normal else p.update(.{ .key = .{ .cp = pardes.Key.escape } }); p.update(.{ .key = .{ .cp = pardes.Key.tab } }); try std.testing.expectEqual(panes.Text.Mode.normal, pane.body.mode); - try std.testing.expect(!pane.tag_edit); + try std.testing.expect(pane.focus == .body); try std.testing.expect(pane.body.append_at == null); p.update(.{ .key = .{ .cp = 'u' } }); try std.testing.expectEqualStrings("ab\n", pane.file.?.content); -- cgit v1.3