summaryrefslogtreecommitdiff
path: root/src/Text.zig
Commit message (Collapse)AuthorAge
*-. Trial merge: 9P + helix + renderGabriel Schneider39 hours
|\ \
| | * No panic from a notice wider than its band, or from the rest of its classGabriel Schneider39 hours
| |/ |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The showcase GUI died in joinNotice on a long shader-error notice: with the tagline narrower than the body, the band hides more columns (skip) than a long message has padding (pad), and `skip..@min(pad, ..)` ran backwards. An audit of draw.zig, Layer.zig, Presentation.zig and animation.zig found the same class elsewhere, all fixed: - a multi-row pane tag or header scrolled for its caret's line sliced a shorter row past its end (paintPaneTag, renderHeaderLayer); - a zero-width column tag kept an earlier frame's viewport, and a column move's clip took it below zero (now saturating, and the early return resets the viewport and caret); - a tag line past 65535 columns overflowed tag_scroll's u16; - a hover left over from a bigger window dashed past the grid; - a border drag over a column that went away, a move preview past a shrunken grid, a column-move rail at zero columns; - Layer.pointAt cast a host's unchecked float metrics (web) to u16; - Text.insertVerticalCursor read past its lines for a cursor whose text changed under it. Regressions: a test of a notice wider than its band through Msg and through setMessage (the Post.zig compile-error path), which panics without the fix; and a monkey over the core at a gui's metrics (random resizes to a cell, long notices, prompts, multi-row tags, clicks, keys), 400 steps in the suite, PARDES_FUZZ_SEED/STEPS for longer runs; 60 seeds x 3000 steps clean. Shared files touched: none of the list (draw.zig, Layer.zig, Text.zig).
| * A selection's other ranges live out of line, made at the second range and ↵Gabriel Schneider39 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | freed at one The ranges beside the primary were an inline array in every Text, which at 1024 grew each pane by about 60 KiB. They are now allocated when a second range appears (Text.reserveSels) and given back when the selection is one range again (Text.dropSels); a column's or the workspace's tag allocates from Text.gpa, any other text from its pane's. A refused tag edit restores them by copy. The Pane size budget is back to 128 KiB, and a test holds that a single cursor allocates nothing for them. Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * g. goes to where the last edit endedGabriel Schneider39 hours
| | | | | | | | | | | | | | | | | | | | helix goto_last_modification: every range moves to the end of the last change (the start of a deletion, the end of an insertion), extending in select mode. The position is kept on the Text in surface rows, set where setEditText hands a body its new text, so a terminal's typed text has one too and moves with its scrollback. Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * K and Alt-K keep or drop the ranges a regex matches in; Alt-: turns every ↵Gabriel Schneider39 hours
| | | | | | | | | | | | | | | | | | | | | | range forward K and Alt-K share the s/S prompt, which now carries a mode rather than a split flag: a range stays when a match starts inside it (K) or when none does (Alt-K), the primary becomes the first, and keeping none leaves the selection as it was (helix keep_or_remove_matches). Alt-: is ensure_selections_forward. Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * A selection holds up to 1024 ranges on the desktop, 64 on the boardGabriel Schneider39 hours
| | | | | | | | | | | | | | | | | | | | | | The limit was 64 everywhere, which helix-golf's enumerate_and_align outgrows (%s |\d+ makes 121 ranges). It is now memory.limits.selections, per platform, and the counts that hold it are u16. The ranges stay inline in each Text, so a pane grows by about 80 KiB on the desktop (three texts and the regex prompt's snapshot); the Pane size budget in Terminal.zig moves from 128 to 160 KiB and says why. Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * Every range lives through insert mode, carried through each editGabriel Schneider39 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Insert mode dropped the selection on the first key and restored only the primary's appended-over span on Esc. Now each insert-mode edit is made at the bare cursor as before, and the range is then carried through it with helix's Range::map rules: typing slides an i range and stretches an a range, Enter (which now also drops the blanks before the cursor, as helix does) slides or stretches by what the cursor moved, and an arrow collapses. The replay gives every other range the same. Esc after a pulls each range's end back by one (helix restore_cursor), which replaces Text.append_at. The wiX-edit-drops-sel and msel-append waivers are gone. Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * Registers hold a value per range, and "<reg> names oneGabriel Schneider39 hours
|/ | | | | | | | | | | | | Registers.zig replaces the one yank buffer: every register keeps a value per range, y fills them in document order, and p, P, R and insert Ctrl-r put value i at range i, repeating the last (helix paste_impl). "<reg> names the register for the next command; _ swallows, # numbers the ranges, . is each range's text, % the file's name, / the last s/S pattern, and + and * are the system clipboard through the ClipYank and ClipPaste paths. SPC y now writes + alone, as helix's does. The acme chords and a paste into a terminal take the default register joined by newlines. The msel-yank-paste waiver is gone. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Let the keyboard reach a tag's path, read-onlyGabriel Schneider39 hours
| | | | | | | | | | | | | | The tag's computed path, dirty marker and page were out of the keyboard's reach: its cursor lived in the text after them. It now lives in the tag as shown, as in acme where the name is ordinary text at the start of the tag, so `0` goes to the line's start and motions select and yank the path. The path stays read-only: an edit that would change it is refused and leaves the cursor where it was, and typing into a file's path drafts a new name as a click on it does. Sync moves the tag's positions when the prefix changes length, so a rename or the dirty marker still never moves the cursor off the text after it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Have Text.pane return nothing for a header instead of trappingGabriel Schneider39 hours
| | | | | | | | | A column's or the workspace's tag has no pane, and asking one for it hit unreachable; every caller guarded against that by checking `what` first. An optional makes each caller say what it does without a pane, so a forgotten guard no longer compiles into a crash. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Make the column and workspace tags Texts with the pane tag's keysGabriel Schneider39 hours
| | | | | | | | | | | | | 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 <[email protected]>
* Make a pane's tag a Text edited with the body's own keysGabriel Schneider39 hours
| | | | | | | | | | | | | | 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 <[email protected]>
* Give prompts their own line to type into instead of the tag's tailGabriel Schneider39 hours
| | | | | | | | | | | A search, pipe or Save prompt wrote its marker and answer onto the end of the tag, so the tag's cursor, its selection, its 9P writes and a prompt abandoned by a click all shared one buffer: the abandoned text stayed in the tag and a 9P write landed inside the prompt. The answer is now its own Text on the pane, typed in insert mode and shown on the notice band where it was already drawn, and the tag never holds any of it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Give a pane's body its own Text holding the cursor, selections, mode and undoGabriel Schneider39 hours
acme keeps what edits a text in its Text (dat.h:171-190) and the window holds a body and a tag of that type. The cursor, the selections, the modal state and the edit-buffer undo move off Pane into Text.zig, Pane holds them as its body, and the edit and normal-mode operations take the Text they edit. Nothing changes in behaviour; this is the step that lets the tag become a second Text. Co-Authored-By: Claude Opus 5.5 <[email protected]>