From 42748f92b77367db415c8b4d0f2e537a9e1ddde7 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Mon, 28 Sep 2026 00:13:11 -0300 Subject: Make the column and workspace tags Texts with the pane tag's keys The headers had their own one-line editor with its own keys: Enter always executed, h/l and J/K moved between headers and panes, Ctrl-c/x/v cut and pasted, and TagLine refused a newline that 9P accepted. They are now Texts like a pane's tag, with no prefix and a default until edited, so normal and insert mode, undo and the look and execute keys are the body's. Moving between them is the window keys' job: Up from a pane with nothing above it reaches its column's tag and then the workspace's, Down comes back, and Left and Right walk the column tags. Co-Authored-By: Claude Opus 5.5 --- src/Text.zig | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'src/Text.zig') diff --git a/src/Text.zig b/src/Text.zig index 3e48a42e..d4b6d048 100644 --- a/src/Text.zig +++ b/src/Text.zig @@ -1,7 +1,8 @@ //! One editable text, acme's Text (editors/acme/dat.h:171-190, text.c): the //! cursor, the selections and the modal state that edit it, and the undo of -//! an edit buffer. A pane's body is one, its tag is another, and so is the -//! answer typed into a pane's prompt. Where a body's characters come from -- +//! an edit buffer. A pane's body is one, its tag is another, and so are the +//! answer typed into a pane's prompt and the tags of the columns and the +//! workspace. Where a body's characters come from -- //! a file's content, a terminal's edit overlay, a PDF's text -- is the //! window's business (edit.zig's editText and flatSurface), the way acme's //! Text reads its File; every other text owns its characters. Everything @@ -19,7 +20,7 @@ pub const Mode = enum { normal, insert, tty }; /// Which text of its window this is, acme's `what`. It says where the /// characters live and whether moving the cursor scrolls a body. -pub const What = enum { body, tag, input }; +pub const What = enum { body, tag, input, column, workspace }; /// A modal line selection (helix `x`): whole rows [r0, r1], absolute. pub const LineSel = struct { @@ -74,15 +75,25 @@ ed_undo_len: usize = 0, ed_redo: [Terminal.history_max]Terminal.Snapshot = undefined, ed_redo_len: usize = 0, -/// The window this text belongs to (acme's t->w). +/// The window this text belongs to (acme's t->w). A column's or the +/// workspace's tag belongs to no pane; nothing asks it for one. pub fn pane(t: *Text) *Pane { return switch (t.what) { .body => @alignCast(@fieldParentPtr("body", t)), .tag => @alignCast(@fieldParentPtr("tag", t)), .input => @alignCast(@fieldParentPtr("input", t)), + .column, .workspace => unreachable, }; } +/// Free what a text owns: its characters and the buffers its undo keeps. +pub fn deinit(t: *Text, gpa: std.mem.Allocator) void { + if (t.own) |own| gpa.free(own); + for (t.ed_undo[0..t.ed_undo_len]) |item| if (item.ovl) |overlay| gpa.free(overlay.text); + for (t.ed_redo[0..t.ed_redo_len]) |item| if (item.ovl) |overlay| gpa.free(overlay.text); + t.* = .{ .what = t.what }; +} + /// Bring the cursor into view (acme's textshow). Only a body scrolls to it; /// the tagline follows its caret where it is drawn, and a prompt's answer is /// drawn whole. -- cgit v1.3