summaryrefslogtreecommitdiff
path: root/docs
Commit message (Collapse)AuthorAge
* addr, dot and limit on a pane with no text are refused `invalid address: ↵Gabriel Schneider32 hours
| | | | | | | | | this pane has no text to address`, which a mount reads as EINVAL, not EIO 9ns maps a refusal back to its errno by its words; "this pane has no text to address" held none it knows. The reference quotes the new words. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* /pager's refusals say invalid, so a mount's shell hears EINVAL: `pager: ↵Gabriel Schneider32 hours
| | | | | | | | | | | invalid directory "relative": must be absolute` 9ns maps a refusal back to an errno by its words, and "the directory must be absolute" and "one directory a write" held none it knows, so a shell through the mount got EIO for both. They now say `invalid`, as every EINVAL here does, and the reference quotes the new words. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Recipes work through a pane of their own, its look and exec, and keep a ↵Gabriel Schneider32 hours
| | | | | | command pane while their open lasts; the docs give cmd panes, the err grep, alt-screen prompts, /pager's refusals, Tty+ on a ctl, --, and theme failures in words Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Recipes read look and exec on the open they wrote, the reference says a ↵Gabriel Schneider33 hours
| | | | | | fresh open reads anyone's last answer, and /pager is documented Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The docs say Grep is a literal search, that a write's own status comes ↵Gabriel Schneider33 hours
| | | | | | before the log's last err, and that Delcol opens no +Unsaved Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The docs take round 32: petscii words in terminal and image tags, open ↵Gabriel Schneider34 hours
| | | | | | records and EMFILE, ThemeFile failures and replays, trailing-colon looks, pty/run after clear, no-text addr refusals, held log reads at Restore, pardes - in one open, and a detached pty in pixels Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Scripting shows a bash event helper that owns two tag words, writes other ↵Gabriel Schneider34 hours
| | | | | | clicks back and lets event go, and warns that cat event | while read swallows the next click Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The docs take round 31: one +Pager per directory and how pardes - cleans its ↵Gabriel Schneider36 hours
| | | | | | text, SYSTEMD_PAGER, a paged diff drawn as one, event reads in pieces, sel, write-back origins, +PdfSections rows, a PDF body by lines, bare :N looks and quoted bad values Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Every scripting and setup recipe runs as written: fmt-here finds the session ↵Gabriel Schneider36 hours
| | | | | | itself, the recipes share one stated preamble, run a command waits for its tag, and setup says man reads MANPAGER first Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A terminal's kitty graphics draw as glyph art where pixels cannot, and by ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | | | | | choice: Petscii on the pane, TermImages for new ones Under an outer terminal without kitty graphics a tty pardes cannot pass a terminal pane's images on, so it draws them itself as an image pane's Petscii does: each row of an image is matched to C64-palette glyph art over the cells it covers (GlyphArt.renderRect, the exact-grid half of GlyphArt.render), cached while it is on screen. yazi is still told the kitty protocol works, so it keeps sending its previews. The same art is a choice anywhere: the Petscii builtin now takes a terminal pane too (PaneKind.picture), flipping its images between pixels and glyphs, and a terminal holding images, or drawing them as glyphs by choice, says petscii:on|off in its tag as an image pane does. TermImages real|petscii (default real) is what a new terminal starts with; it is in DumpConfig, /ctl and the reference. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The docs describe the pager that landed: pardes - and its +Pager pane, a ↵Gabriel Schneider37 hours
| | | | | | terminal's PAGER, command panes' cat, Pager pardes|off, and pty/run no longer waiting in one Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The book and the HTML gain "Setting up your environment" after the guideGabriel Schneider37 hours
| | | | | | | | | chapters lists setup.typ second and #doc takes a setup id. Shell lines (#cmd) follow the density too: roomy in the book and the HTML, with a tint and space around them, tight on the A4 sheet; the book sets code blocks on the same tint. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Setting up your environment: a 9ns mount, pardes as the editor, pager and ↵Gabriel Schneider37 hours
| | | | | | yazi opener, the shells with prompt marks, language servers, fonts and plan9port, each snippet tried Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The docs take the 9P agent's round 30: log stats 0, names escape every ↵Gabriel Schneider37 hours
| | | | | | control byte, $winid and the pager defaults, the one client rule, and Shift-Esc said one way in the guide and the cheatsheet Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The book and the HTML set #pairs tables roomy, the A4 sheet tightGabriel Schneider37 hours
| | | | | | | | | A pairs-density state, set to tight by cheatsheet-a4.typ and roomy otherwise, gives book and HTML tables more row padding and room between the key and the meaning. The book sets its body at 10pt with more space around sections and between paragraphs and list items. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The book and the HTML hold every topic, and #doc links to its chapter or sectionGabriel Schneider37 hours
| | | | | | | | | | | | | chapters now names guide, cheatsheet, scripting, reference, themes and building. #doc takes the chapter ids, keeps the old ones mapped onto them (tags and fs to the guide and the reference, config, keys and detached to their guide sections), and links in the book and the HTML, where a doc-links state says every chapter is there; on the A4 sheet it names the chapter and section. The reference points at the scripting and building chapters by #doc instead of in words, and the guide heading for pardes FILE and --wait keeps its two dashes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs/typ gets book and HTML wrappers over one chapter listGabriel Schneider37 hours
| | | | | | | | | | | style.typ lists the chapters in reading order (guide, cheatsheet, scripting, reference, building), each with its content file or none while unwritten. book.typ sets them as an A4 book with a title page and contents, the tutor read from src/tutor.txt last; html.typ sets them as one HTML page with a nav of anchors. An unwritten chapter shows a placeholder, so both compile before the topics exist. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The cheatsheet draws mouse buttons as a mouse, keys as chips, and pairs as ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | | | | | | | | | tables #btn and #chord draw a mouse (left button, wheel, right button) with the pressed part filled; the wheel is a narrow slot on a paper halo, hollow or filled, so it never reads as a button. A chord is the held button, then for each click the held one and that one down, with arrows between; #btn(.., shift: true) adds a ⇧. HTML gets a span with an aria-label. A key is one soft pill with no border: a combination (Ctrl-w) reads Ctrl + w and a sequence (g g, SPC f c) g › g, separators muted inside it; #keys("h", "j", ...) sets alternatives as separate pills. The drift test reads every key a #keys call names. #pairs sets key | meaning content as a two-column table on alternating tints; split: 2 sets the leader map as two such tables side by side. The mouse chords get their own table: cut, paste, copy (B1-B2 then B1-B3, one B1 hold, as mouse.zig says), 2-1 with an argument, 2-3 cancelling. The A4 page draws its own title and drops the content's level-1 heading. docs/typ/README is the function contract for content files. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Themes become a short Typst topic: choosing one, the native palettes and ↵Gabriel Schneider37 hours
| | | | | | ports, and a theme file's roles Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Building gathers the platforms, options, tests, release gates and how the ↵Gabriel Schneider37 hours
| | | | | | core, threads, detached sessions and 9P fit, from the old design notes checked against the code Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The reference is fs.md's per-file semantics, errors and limits in Typst, ↵Gabriel Schneider37 hours
| | | | | | with the settings table, and says what the pane ctl's Left, Right, Up and Down do Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Scripting over 9P has one chapter, and the served README and the 9P skill ↵Gabriel Schneider37 hours
| | | | | | shrink to a summary, the traps and a pointer to it Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The guide walks a newcomer through pardes day to day, and the cheatsheet ↵Gabriel Schneider37 hours
| | | | | | says what Esc and Shift-Esc really do Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Docs say how a look resolves a relative path: the looking pane's directory, ↵Gabriel Schneider37 hours
| | | | | | | | | | | then each jump-list pane's, most recent first fs.md's look section and tags.md said nothing of where a relative path is looked for, so a look that found a file in a directory visited an hour ago, or not in an open pane never visited, was a surprise. The order is written as look.zig's resolveLookTarget has it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Docs give a look miss's real words, that event is one reader's, the real cap ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | on held reads, Dump's Restore word, a reused command pane's runs, and the one-write trap fs.md's look misses now read as the editor says them (<path>:99 has no line 99, has no page N); event says a second reading open fails file in use; held reads say the 64 state-holding opens are the real cap, under the 128 a connection may park; Dump says it adds a Restore word to the workspace tag; a reused command pane's body is said to keep each run under a % line, with how to take the last. The 9P skill gains the trap that bash's printf to a mounted ctl arrives one write per line. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Edit's w and the other left-out sam commands fail EIO in words, never ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | EOPNOTSUPP, and /os refuses a rename or a chmod as not permitted, EACCES "w is not supported in pardes" read through a mount as EOPNOTSUPP, as if the file system lacked an operation, and a chmod under /os was answered "invalid truncate", EINVAL. An Edit command pardes leaves out now says so in words 9ns reads as EIO, and a rename or mode change of an /os file is "permission denied", EACCES. fs.md's Failure section and /os entry say both. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* name takes any byte a file name can hold, controls, edge blanks and bytes ↵Gabriel Schneider37 hours
| | | | | | | | | | | | not UTF-8 included, so what name reads writes back as it was A pane opened on a file whose name held a tab, a control byte or bytes not UTF-8 read that name from its name file, and the same bytes written back were refused. Only what no file name holds is refused now: a second line and a NUL. The ctl word name still refuses a second blank after the word, as a line's words are split at blanks. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Views generated by each read stat 0, as acme's do: data, xdata, index, ↵Gabriel Schneider37 hours
| | | | | | | | | | | | layout, recent and listeners; fs.md says which files have real lengths A stat of index, layout, recent or listeners built the whole view to count it, and data and xdata reported the body's length though a read answers what addr selects. Those now stat 0, as screen and pane/new already did, and fs.md lists the files whose length is real and says to read the rest to the end. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A shell command from the workspace's or a column's tag runs as a command ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | pane in the session's directory, never typed into the terminal with the keyboard A command clicked in a header tag, or written to /tagexec or a column's exec, was typed into the active terminal when it sat at an empty prompt, so it ran in that pane's directory and left no run or exit record. It now always gets a command pane of its own in the session's directory, as acme's row and column tags have no directory but the session's. tags.md writes the rule down: pane words act on the column's active pane, a column's words on the column, shell commands as their own panes, and over 9P a pane's word is refused. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Release Pardes 0.13Gabriel Schneider37 hours
|\ | | | | | | Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * A one-page A4 cheatsheet, the first file of a Typst docs corpus in docs/typGabriel Schneider37 hours
| | | | | | | | | | | | | | | | | | | | | | | | docs/typ/cheatsheet.typ holds the facts as semantic calls (#key, #btn, #chord, #word, #tag, #addr, #file, #cmd, #doc); docs/typ/style.typ defines those once, drawing them for paged output and emitting HTML elements under --features html; docs/typ/cheatsheet-a4.typ is the page. `zig build cheatsheet` renders it when typst is on PATH. A config.zig test reads every .typ in docs/typ and fails when one names a builtin, key binding or default tag pardes no longer has. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A diff line looks up the path and line it names, as any look doesGabriel Schneider37 hours
|/ | | | | | | | | | | | | | | | | | | | | | | | The look on a diff line was its own resolver: a walk up to .git/.jj from the diff's directory, its own "no such file here" and "deleted by this diff". A review tool's cached patch, in no repository, missed every file though the session's terminals sat in the checkout. Now a diff line only expands and transforms. Its expansion (what the hover shows) is the whole line for a header, a `@@` line, or a hunk line pointed at on its prefix, and its text is the look address the line names (look.diffAddress): `path` for `diff --git`/`---`/`+++`, `path:c` for `@@ -a,b +c,d @@`, `path:N` for a hunk line's new line (a removed line's, the new line now where it was). That text goes through the regular look exactly as if selected by hand: same resolution, placement and errors. A 9P look of a whole diff line takes the same transform. Kept: the line classification, hunk arithmetic, git prefix stripping and timestamp cutting (diff.zig). Gone: the repo-root walk, its messages, Target.old_side and deletesAhead, and the click's row stash (Pardes.diff_look). A test compares a B3 on a cached patch's line with a look of the hand-selected `entry/src/entry.rs:2` in the same session. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Release Pardes 0.12Gabriel Schneider37 hours
|\ | | | | | | Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * Over a program that tracks the mouse, B2 and B3 are pardes's execute and ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | | | | | look, as in any pane, and Shift sends them to the program as its buttons 2 and 3; B1 and the wheel stay the program's, Shift keeping them pardes's The Shift that sends B2 or B3 is left out of their reports and of the drags they hold: it only chose the target. A B2 or B3 sweep of pardes's moves nothing to the program under 1003. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Recent and /recent keep PDFs and images as they keep files, and an open ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | | | | | | | | | file's row is where its dot is now Only text files were recorded, so a PDF read yesterday was not there to find again, and an open file's row showed the place it last closed at, stale by however far it had moved since. A PDF is kept at its page and reopened there from its row; an image by its path; an open one's row reads its pane's place at the time of the listing. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | DumpConfig writes a setting this shell cannot show as a "# Word unsupported" ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | | | | | | | comment, GripWidth among them on the tty, so the whole report writes back to /ctl The report said it could be written back as is, but "Lift unsupported" and the tty's "GripWidth 100" were each refused by the root ctl, and "DumpDir (none)" would have named a directory "(none)". Those lines are now comments, and a test writes every line of the report back. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Docs say what Rename, a look at a missing or unreadable file, Restore, a ↵Gabriel Schneider37 hours
|/ | | | | | | | | | | | | PDF's body and one open's undo step do, and the PDF tag in its order fs.md said Rename lists the places; it says its count and lists none. It now also says a look at no such file is a logged miss while an unreadable one fails the write, that Restore brings no jump list back, that a PDF's body is read-only page text no address reaches, and that one open's writes are one undo step only while nothing else edits the pane between them. tags.md listed the PDF tag's words out of order. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A diff look names a file as the repository does: git's side prefix dropped ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | | | by git's rules, a plain diff's names as written In a git section (one with a `diff --git` line) the one-letter side prefix git writes, `a/`/`b/` or with diff.mnemonicPrefix `c/`, `i/`, `w/`, `o/`, is dropped from its paths only when both paths of that line carry one, different ones: `--no-prefix` writes none, so its `a/x a/x` is a real directory `a` and is kept. A plain `diff -u` never strips: its names are used as written, past the timestamp. `/dev/null` stays itself. The walker does this once (diff.Walk.side, diff.gitHeader), so the path a look resolves, and the one a miss says, are the repository's name: `Look: src/x.zig: no such file here`, `Look: lib/old.zig: deleted by this diff`. The look no longer tries a stripped name beside the written one. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fs.md says a body write to a terminal is typed input, never a bracketed pasteGabriel Schneider37 hours
| | | | | | | | | | | A write to a terminal's body goes to its child as typed keys: no bracketed-paste marks around it, even when the program set 2004, so a newline in it is Enter and a shell runs each line. fs.md did not say which, and a script cannot guess. It does now, and a test writes to a terminal whose program asked for bracketed paste and checks the bytes sent are only the ones written. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Save path logs a save record naming the path it wroteGabriel Schneider37 hours
| | | | | | | | | | | Save of a pane's own file logged `save <serial> <name>`, and so did a scratch's `Save path` (the pane takes that name). A `Save path` that writes a copy of a file pane, or a terminal's scrollback, elsewhere logged nothing, so a follower could not tell the file was written. It now logs `save <serial> <path>` with the path written, once the host has written it (events.noteLogAs). fs.md's log table says so. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* name refuses a directory, EISDIR, when written, not at the Save that could ↵Gabriel Schneider37 hours
| | | | | | | | | | | | only fail `name ~`, `name /` or `name foo/` renamed the pane to a directory, and only its Save failed later. A name ending in `/`, the root, or one naming a directory that is there is now refused at once, with words a mount reads as EISDIR (`name: <path> is a directory, not a file`). The ctl word name and a forwarded `pardes ~` go through the same check. fs.md says so. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fs.md says that in a > to a tag cut into several writes, those taken before ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | a refused one stand A `>` to a tag that a client sends in several writes is checked a write at a time. When a later one is refused, the earlier accepted ones stay in the tag. Buffering the whole open to apply it or none would cost more than it saves, so fs.md now says what happens: each write stands on its own, and only the refused one changes nothing. A test covers a truncation, an accepted write, then a refused one. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* An addr, dot or limit pair out of order or past the text is refused as the ↵Gabriel Schneider37 hours
| | | | | | | | | | | | address form is, not clamped `#5,#2` and `#2,#99` were refused (addresses out of order, address out of range), but the pair form `5 2` became 5..5 and `2 99` became 2..end, silently a different range from the one asked for. A pair is now checked the same way: past the text is out of range, and an end before its start is out of order. fs.md says so. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* An empty range written back to event acts on the word a click there expands ↵Gabriel Schneider37 hours
| | | | | | | | | | | | to, as acme's expand does `ML960 960` or `MX1 1` written back with no text acted on the empty range between the offsets: a look of nothing, an exec of nothing. A click at a point expands to the word or file name under it, and acme's written-back event does the same. It now expands with look.expandedWord, as a no-drag click does, on its line of the body or tag. fs.md says so. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fs.md says a line held to the close reports its failure only as the log's ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | err, and that a script needing the result ends its write with a newline fs.md said an Edit block never ended "fails at the close" with ``unmatched `{'``, which reads as the close failing. The close reports no error (round 24's decision: no clunk-time errors), and the write that sent the block had already succeeded. The failure is only the log's err record. The same holds for the tail of a 4096-multiple write that the close runs. fs.md now says so, gives both err texts, and tells a script that needs a line's result to end its write with a newline. tree.zig's "an Edit block still open when its open closes fails there with an err and changes nothing" is the test. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A 9P look keeps its leading blanks: an indented line, or blanks alone, is ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | looked for as written Every line written to look or exec went through Messages.next, which trimmed blanks from both ends. A look of ` indented` then found the first bare `indented`, and a diff's blank context line ` ` looked at nothing. A look's line is now its text: only its `\r` and newline go. lookAt keeps the blanks for the word search too; it expands `~` only for a look that starts with one, and the path, address and command readings trim for themselves as before. runSearch keeps a pattern's blanks, since a builtin's argument comes trimmed already. An exec line is trimmed as before. fs.md says so. Co-Authored-By: Claude Opus 5.5 <[email protected]>
*-. Release Pardes 0.9Gabriel Schneider37 hours
|\ \ | | | | | | | | | Co-Authored-By: Claude Opus 5.5 <[email protected]>
| | * A program that tracks the mouse gets its clicks, drags and moves over its ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | grid, in the format it chose; Shift keeps pardes's select, execute and look, and chrome is never the program's Presses and releases under 1000, drags with a button down under 1002, every move once per cell under 1003, X10 presses under 9, in raw terminal input only. A press the program took keeps its drag and release, reported clamped to the grid's edge wherever the pointer goes. The press also makes the pane the active one. docs/tags.md says so. Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * | A right click on a diff line opens the place it names: its file, the hunk's ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | new line, the line itself In a diff pane (a .diff/.patch file, or a command pane's diff output), the look's own expansion, which its hover shows, takes a whole line for a `diff --git`, `---`, `+++` or `@@` line wherever the pointer is on it, markers included, and for a hunk line when the pointer is on its `+`, `-` or space. Then the look opens the file (a/ b/ dropped, timestamps cut) at the line from the hunk header and the lines above it: `@@` the hunk's first new line, context and added lines their own, a removed line the new line now where it was. `diff --git` and `+++` open the new file; `---` the old one, unless the `+++` under it names another. On a hunk line's code the expansion is its words, the prefix never one of them, and looks as ever. Other panes are untouched. Paths resolve in the repository (walking up to `.git` or `.jj` from the diff's directory, or a command pane's), then that directory. A file not here opens nothing and says `Look: b/x: no such file here`, or `deleted by this diff`. A 9P look writing a whole line of the diff does the same. Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * | A diff reads as the code it changes: hunks in their file's language, added ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | and removed rows tinted A .diff or .patch pane, and a command pane whose output is a diff (`git diff`, `git show`, `diff -u`; told by a `diff --git` line, or `---`/`+++` with a `@@` under them, in its first rows), colour each hunk's code in the language of the file its section names (`+++ b/<path>`, `--- a/<path>` for a deleted file), with tree-sitter, as highlightLocations does for results. src/diff.zig walks a unified diff by its `@@` counts, so a removed line that reads `--- x` is no header. Each side of a hunk is parsed as one text (context and removed lines the old side, context and added lines the new), so a string or comment across lines colours as it does in the file; a side no line takes its colours from is not parsed. A section's hunks share a parse, in pieces of about 40 lines (a hunk past 80 is cut), only those in view, and each piece's colours are kept by its bytes, so scrolling back and a terminal's every repaint parse nothing again. Added and removed lines carry a flag in their style byte; the painter tints their rows to the pane's edge, a little way from the page toward the theme's ANSI green or red, and draws the prefix in that hue pushed to read on it. A file in no known language keeps the old line colours. A command pane is read once its command has finished: its rows are copied once (File.DiffOutput, dropped when the pane runs again), so no frame dumps the scrollback, and painted over what git printed. A running command is shown as it prints. Co-Authored-By: Claude Opus 5.5 <[email protected]>