summaryrefslogtreecommitdiff
path: root/src/edit.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 19:36:58 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:15 -0300
commit1df6bd12fafbf97062f7844a23de208add75a843 (patch)
tree78b61cfebeb12c40b679d053b457d2e28f232784 /src/edit.zig
parent1f8de151e382755c1ce597f166ea4552e7f7e8d1 (diff)
downloadpardes-1df6bd12fafbf97062f7844a23de208add75a843.tar.gz
pardes-1df6bd12fafbf97062f7844a23de208add75a843.zip
A pane tag wraps onto rows and can collapse to one, as acme's does
acme's frame wraps a tag at its right edge and the window grows to show every row (wind.c wintaglines); Tagup/Tagdown shrink it to one row and back. Pane tags used to be one row, scrolled sideways to the caret. Now a tag's lines wrap at its width (one cell kept for the caret past a full row) and it starts expanded; insert-mode Up on the first row collapses it, Down on the last row expands it, and Alt-Up/Alt-Down do so in either mode. A word the wrap breaks across rows is still one word to a click and a selection. Column and workspace tags keep scrolling sideways. Tests read body rows relative to the body's first row; the 41 snapshot goldens that moved were re-recorded by name after a programmatic check that each differs only by body rows shifting under the taller tags, and twelve scripts whose clicks targeted fixed rows now click the same text. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/edit.zig')
-rw-r--r--src/edit.zig24
1 files changed, 22 insertions, 2 deletions
diff --git a/src/edit.zig b/src/edit.zig
index 1e480785..a194ef48 100644
--- a/src/edit.zig
+++ b/src/edit.zig
@@ -202,7 +202,7 @@ pub fn clipYank(p: *Pardes, pane: *Pane, main_only: bool) void {
/// (the tag's lines first, the ones it shows)
pub fn paneText(p: *Pardes, pane: *Pane) ![]u8 {
const arena = p.scratch.allocator();
- const tag = try tagline.tagText(p, arena, pane);
+ const tag = (try tagline.shownTag(p, arena, pane)).text;
const from = modal.lineStartOffset(tag, pane.tag_top);
const cut = modal.lineStartOffset(tag, pane.tag_top + pane.tag_rows);
const shown = if (cut < tag.len) tag[from .. cut - 1] else tag[from..];
@@ -299,13 +299,20 @@ pub fn selectionText(p: *Pardes, pane: *Pane, sl: Pane.Sel) ![]const u8 {
return result;
}
const text = try paneText(p, pane);
+ const shown = try tagline.shownTag(p, arena, pane);
var out: std.ArrayList(u8) = .empty;
var it = std.mem.splitAny(u8, text, "\n");
var v: i32 = 0;
var first = true;
while (it.next()) |line| : (v += 1) {
const cols = sweepCols(sl, v) orelse continue;
- if (!first) try out.append(arena, '\n');
+ // A row the tag's wrapping began carries on its text: no newline.
+ const soft = v > 0 and v < pane.tag_rows and std.mem.indexOfScalar(
+ usize,
+ shown.soft,
+ modal.lineStartOffset(shown.text, @as(usize, @intCast(v)) + pane.tag_top) -| 1,
+ ) != null;
+ if (!first and !soft) try out.append(arena, '\n');
first = false;
// Past the first row a body row starts after its line numbers.
const gutter: i32 = if (pane.file != null and v >= pane.tag_rows) panes.File.gutterWidth(pane) else 0;
@@ -750,6 +757,19 @@ fn insertEdit(p: *Pardes, t: *Text, key: Key) void {
Key.left, Key.right, Key.up, Key.down => {
const lines = paneCursorLines(p, t) catch return;
const cur0 = t.toModalCursor();
+ // In a pane's tag, Up on its first line collapses it and Down
+ // on its last expands it, where they would move nothing; acme's
+ // arrows in a tag always do (plan9port text.c:776, Tagdown/Tagup).
+ if (t.what == .tag) if (t.pane()) |pane| {
+ if (key.cp == Key.up and cur0.row == 0) {
+ pane.tag_expanded = false;
+ return;
+ }
+ if (key.cp == Key.down and cur0.row + 1 >= lines.len) {
+ pane.tag_expanded = true;
+ return;
+ }
+ };
const nc = switch (key.cp) {
Key.left => modal.charLeft(lines, cur0),
Key.right => modal.charRight(lines, cur0),