summaryrefslogtreecommitdiff
path: root/src
Commit message (Collapse)AuthorAge
* Under pardes's placement a pane whose neighbour is in no column goes at a ↵Gabriel Schneider34 hours
| | | | | | | | column's foot, not nowhere After Delcol took the last column's panes, pane/new under Placement made a scratch that no column held, since a scratch was placed only under the asking pane, which was gone; a look from it then unwrapped the missing parent in belowParent and panicked (the 9P monkey's crash-e1873f34). Both now fall back to the foot of the active column, else the last. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The grapheme width test expects two cells for two invalid bytes, as qsltkuom ↵Gabriel Schneider34 hours
| | | | | | | | draws them Its reference list compared \xe4\xb8 with vaxis's own gwidth, which counts the pair one cell; since qsltkuom each invalid byte is a cell, one U+FFFD each, as surface.zig draws it, so the pair is two. The unit suite failed on it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* An invalid byte in a grapheme is one cell, and never reaches vaxis's widthGabriel Schneider34 hours
| | | | | | uucode joins a stray lead byte (as U+FFFD) to a following e and combining mark into one grapheme; vaxis's gwidth then counts back the replacement rune's three bytes over the one byte it stood for and overflows (gwidth.zig:62), panicking the next frame after a write of \xee e \xcc\x81 to xdata (the 9P monkey's crash-b2417c49). graphemeDisplayWidth now gives each invalid byte one cell, as surface.zig draws it, and measures the valid runs between alone. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Writes held before the shell's clock is first seen no longer overflow its ↵Gabriel Schneider34 hours
| | | | | | | | first step A 9P write served before a detached host's first pump holds its batch stamped at time 0, so nextWake said to wake at 20 ms while advance, seeing the clock for the first time, set stepped_ns days later and counted due - stepped_ns back past zero: an integer-overflow panic. It was what the 64 KiB msize trial hit in fs-test (restore detached space, the connection closing at the first write's clunk), a race any msize can lose. A batch's wake is now never before the next frame. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A class with non-ASCII runes matches them: [éa-z] is taken as (é|[a-z]), a ↵Gabriel Schneider34 hours
| | | | | | | | range up to 256 runes spelled out mvzr's classes hold bytes, and it refused a multibyte member as a bad expression. Rewriting the class before compiling, as ^a|^b already is, needs no mvzr patch; runes that differ only in their last byte go as one alternative (\xc3[\xa0-\xbf] for [à-ÿ]) so a 256-rune range fits the 512-operation limit, which counts the pattern as rewritten. A wider range and [^é] are refused, naming why. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A search whose pattern opens with a literal jumps to where that literal is, ↵Gabriel Schneider34 hours
| | | | | | | | not through every line Finding /line 049999/ in 1171 KB took 175.5 ms (Debug), each line run through mvzr's matcher in turn. The literal prefix (none when the pattern has a | anywhere) is found with indexOfPos first and matching starts on its line: 4.44 ms. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A write to addr, limit or mark asks for no frame, so its close is not held ↵Gabriel Schneider34 hours
| | | | | | | | behind one Every write that changes a pane set needs_frame, an addr write too, so the editor drew a whole frame after each and the clunk that followed waited for the turn while it did: 0.5 ms (Debug) to 1.2 ms a clunk, what made addr and event write-back 4-10x acme's. An address, a limit and the mark flag are nothing drawn; their writes no longer ask for a frame. Clunk after an addr write: 0.518 -> 0.015 ms (Debug tty, fs.py client). Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A pane's ctl reads acme's fields in acme's order, the undo and redo flags ↵Gabriel Schneider34 hours
| | | | | | | | included, then pardes's own Where plan9port's line has whether Undo and Redo have a step, pardes's had current, so a client reading acme's fields by position read a word for a flag. The two flags now follow the tab width, as in plan9port's winctlprint, and current|notcurrent and a REPL's id come after them. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A pane's ctl takes acme's ctl words, done by the files that replace themGabriel Schneider34 hours
| | | | | | name, put, clean, dirty, del, delete, dot=addr, addr=dot, limit=addr, mark, nomark, show and cleartag were unknown control messages. Each is now done by the file or builtin that replaces it (name, Save, dirty, Del, a Del that does not ask, dot and addr and limit, mark, the tag), checked with the rest of the write before any runs; dump, dumpdir, font, menu and nomenu are refused, EINVAL, saying where pardes does it or that it has no such thing. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* acme's words run as pardes's or are refused, never as shell commands: Put savesGabriel Schneider34 hours
| | | | | | Put, Get, Delete, Snarf, Cut, Paste, Zerox, Sort, Putall, Load, ID and Send written to exec or tagexec each ran as a shell command that exited 127, the write answering 0 -- a Put that looked like a save. Put now runs Save and Delete a Del that does not ask; the rest are refused, EINVAL, invalid: acme's X is not a pardes builtin (with where pardes does it, where it does), in exec and ctl alike. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A look that misses file:/re/ names the file and is logged as that file's pane'sGabriel Schneider34 hours
| | | | | | A miss said only look: no match for regexp, against the pane the look came from. It now says look: <file>: no match for regexp, on the pane of the file it searched. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A refused Delcol changes nothing: no +Unsaved opens, no focus movesGabriel Schneider34 hours
| | | | | | Delcol's refusal opened +Unsaved, placing a pane in the layout it was refusing to change. Its unsaved records and notice say which panes; the list pane is left to the refusals of the other words. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A tag write past the limit is refused whole, naming itGabriel Schneider34 hours
| | | | | | A write to tag longer than the room left was cut and applied in part. It now changes nothing and fails ENOSPC, tag: over 4096 bytes; the docs give the limit. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A repeated log record is counted only when its whole text repeats, not just ↵Gabriel Schneider34 hours
| | | | | | | | what was cut to fit (xN) compared records after msg and err cut long texts to fit, so two different long failures that agreed in their first 200-odd bytes were counted as one. The whole text of the newest counted record is now hashed, and a repeat needs it too. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Mini with no argument is wrong #args, EINVAL; Find, Grep and Mini say their ↵Gabriel Schneider34 hours
| | | | | | | | names capitalised Mini needs a file but did not say so, so a bare Mini ran and failed EIO. It now requires its argument, refused wrong #args (EINVAL) as every such word is. Its failures, Find's and Grep's start with the builtin's own name (Mini:, Find:, Grep:), as the others' do. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A bad command inside an Edit block written whole is named, not the } after itGabriel Schneider34 hours
| | | | | | A command in a { block that failed to parse ended the block there, so its } was taken as a control message of its own and the write failed unknown control message "}". A { block not yet closed now runs to its } whatever fails to parse in it, and the error names the command (Edit: unknown command z), as the line-by-line path does. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* pty/run takes one line a run, its answer read before the nextGabriel Schneider34 hours
| | | | | | Two lines -- in one write, or as bash writes them, a line at a time on one open -- each ran, and the first's answer was lost under the second's. A write with more than one line, or a next line before the last answer is read, is now refused, EINVAL. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* pty/ctl exec on a command pane is refused: a command pane does not restartGabriel Schneider34 hours
| | | | | | exec on a finished command pane ran its line again, silently, with no header, footer or records. It is now refused, EINVAL, invalid exec: a command pane does not restart. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A failure said while a 9P write waits on it posts no msg, only the write's errGabriel Schneider34 hours
| | | | | | A failure the editor said as it performed a write's work (a Save's disk write, a shell, a language server) was posted as a msg and taken back out when the write's err was logged, which it cannot be once a log follower has read it: a follower saw both. Such a failure is now posted without a msg in the first place (fs.write_waits), and nothing is taken back. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* An open's writes in a row to one place go in as one edit: a 10 MB body write ↵Gabriel Schneider34 hours
| | | | | | | | is linear Each body or data write copied and hashed the whole buffer, so a write the mount cut in 8 KB pieces was quadratic: 10 MB took 50 s and a 1 MB insert into 10 MB 11 s, holding the editor's turn. An open's appends to body, or inserts going on at data's address, are now held and put in as one splice (one copy, one undo step, one line-starts pass) before any other request, the close, or the editor's step once the writes pause 20 ms. fs.py-driven: 2 MB 2.19 -> 0.16 s, 10 MB 50.17 -> 0.78 s, 1 MB data into 10 MB 11.49 -> 0.26 s. A body-2m case (2 MB in 256 KB writes on one open) joins the perf gate: 84023 -> 15785 us; baselines re-recorded. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* An Edit x gives each of its searches the step budget, and a search that ↵Gabriel Schneider34 hours
| | | | | | | | spends it says it took too much time The budget was the compiled pattern's, spent over every search an x made: Edit ,x/x+/c/z/ over 100k lines ran out and failed, blamed on backtracking. Each search now starts with the whole budget, and one that spends it says regular expression search took too much time, gave up. (Not "too long": 9ns reads those words as ENAMETOOLONG.) Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A pattern up to 512 characters compiles; a longer one is refused naming the ↵Gabriel Schneider34 hours
| | | | | | | | limit mvzr's Regex holds 64 operations, so a pattern much past 64 bytes was refused as bad regular expression. pardes now compiles into mvzr's SizedRegex(512, 64), and a pattern that is too long (told apart from a malformed one by compiling it with room) says it is longer than mvzr's 512 operations. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A ctl or exec line with no newline runs with its write and fails it, unless ↵Gabriel Schneider34 hours
| | | | | | | | it needs more A last line with no newline was held to the close, so printf bogus > ctl answered 0 and failed only in the log, Edit ,s/zzz/y/ too. A write shorter than its Twrite is the whole of what was written (acme takes each write whole): its tail runs then and a failure is the write's. It is held only when the parser says it needs more -- an open { block, an a/c/i text -- or when the write filled its Twrite and may go on (the listener tells the core the room, msize less its header). Co-Authored-By: Claude Opus 5.5 <[email protected]>
*-. Merge: 9P round 23 + perf fixes + input garbage fixes + Crt docGabriel Schneider34 hours
|\ \
| | * Function keys, Insert and the keypad reach a terminal pane as their terminal ↵Gabriel Schneider34 hours
| | | | | | | | | | | | sequences
| | * A modifier or function key alone types nothing into a terminal paneGabriel Schneider34 hours
| | |
| | * A lone ESC that ends a read waits for the rest of its sequenceGabriel Schneider34 hours
| | |
| | * Terminal replies and malformed escape sequences never become typed textGabriel Schneider34 hours
| |/
* | Every catch unreachable, orelse unreachable and syscall assert outside tests ↵Gabriel Schneider34 hours
| | | | | | | | | | | | | | | | is a real refusal or says why it cannot fire A sweep for round 23's crash: a run's answer (pty/run) was bufPrint'd into 48 bytes with catch unreachable, so a foreground program's long name (macOS gives up to 32 bytes) panicked; it now cuts at the room, keeping its newline, in 96 bytes. The rest were numbers into buffers sized for them, a braille codepoint, pthread calls on the queue's own mutex, and pdf_view's resolved outline entries: each now carries a one-line comment saying why it cannot fire. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Delcol on the last column leaves the window, empty but for its workspace ↵Gabriel Schneider34 hours
| | | | | | | | | | | | | | | | tag, as acme's does The last column's Delcol ended the session. The window now stays, with only the workspace tag; Newcol, and New (which makes the column it goes in), start it again. A word run with no pane at all runs with a stand-in that is no pane, the root ctl takes session words, and pane/new makes its scratch in the session's directory. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Back at the oldest place says nothing further back, and Forward at the ↵Gabriel Schneider34 hours
| | | | | | | | | | | | | | | | newest nothing further on A step past either end of the jumplist did nothing, silently. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A name refused for a leading blank says a blank at its startGabriel Schneider34 hours
| | | | | | | | | | | | Both ends said a blank at its end. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Lspinfo lists pardes's own dependency imports only for a file in pardes's treeGabriel Schneider34 hours
| | | | | | | | | | | | The in-process ZLS's report listed the module map of the build pardes came from (vaxis, ghostty and the rest) for any .zig file, a project that has none of them included. It now lists them only for a file in that tree (project_root, a build option), and says there are none for any other. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Not-found failures say it once, in plain words: grep: pattern not found, ↵Gabriel Schneider34 hours
| | | | | | | | | | | | | | | | callers not found The ENOENT that 9ns reads from a failure's words came from a tacked-on suffix, grep: no match, not found, definition: nothing found, not found, no shell "x", not found. They now say it once: grep: pattern not found, find: name not found, Callers: callers not found, definition: not found, shell "x" not found (...). Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A language with no server to start says language server for .py not found, ↵Gabriel Schneider34 hours
| | | | | | | | | | | | | | | | not that it did not answer A question about a file whose language server is not there came back as no answer at all, which the core said as the language server did not answer. The client now answers @none language server for <ext> not found, ENOENT by its words. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A Recent or Jumplist row for a file that shrank lands on its last line, the ↵Gabriel Schneider34 hours
| | | | | | | | | | | | | | | | same by either route, and says so A +Recent row clamped silently and a Jumplist row missed (has no line N). Both are remembered places now: the look clamps to the file as it is, closed or open, and the message row says <file> has N lines now: at its last. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A new file, once saved, shows in /recent, openGabriel Schneider34 hours
| | | | | | | | | | | | A pane named for a file not yet on disk is not kept in Recent (round 22), and its Save did not add it, so the file stayed out of /recent while open. A Save that puts a file on disk now records it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A PDF that cannot be read fails its look with its path and whyGabriel Schneider34 hours
| | | | | | | | | | | | A truncated PDF said only look: <error>, with no path, where an image that cannot be read names both. It now says look: <path>: not a PDF pardes can read: <why>. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A Tty started by a shell's path keeps the path in its Tty+ wordGabriel Schneider34 hours
| | | | | | | | | | | | The tag said Tty+<basename>, so a click on it looked the bare name up on the usual paths and found nothing, or another program. A shell given as a path now keeps the path in the word. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Two Dumps in one second get names of their ownGabriel Schneider34 hours
| | | | | | | | | | | | A dump is named by the second it was written in, so a second Dump within it overwrote the first. A clash now takes -2, -3 and on. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A second line written to name is refused EINVAL, in one write or on the same ↵Gabriel Schneider34 hours
| | | | | | | | | | | | | | | | open bash writes printf 'a\nb\n' a line at a time, so each line arrived as a whole name on the held open and renamed the pane twice. An open that has named its pane now refuses a further line, as a two-line write already was. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A ThemeFile that cannot be read or is no theme fails its write, and a bad ↵Gabriel Schneider34 hours
| | | | | | | | | | | | | | | | path says why The theme is read when the host performs the request, after the write had been answered, so a missing file or a bad theme only showed a message; and a path not ending .zon said only invalid theme path. Load failures are now the waiting write's (late, as a Save's), and the path refusal says a theme file is a .zon. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A ^ after | anchors its branch: ^def|^ finds lines starting either wayGabriel Schneider34 hours
| | | | | | | | | | | | mvzr takes ^ only at its pattern's start, so in ^def|^ the second branch never matched mid-text. An alternation whose every top-level branch starts with ^ is now compiled as ^(def| ); a mix of anchored and unanchored branches is refused rather than silently wrong. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A buffer whose file was deleted on disk is dirty, and Del asks firstGabriel Schneider34 hours
| | | | | | | | | | | | A file deleted under an open buffer left dirty 0 and let Del, Exit and the rest throw the only copy of its text away unasked. It now counts as dirty, as acme's does, and the refusals ask about it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Every child starts with its signals at their defaults and none blockedGabriel Schneider34 hours
| | | | | | | | | | | | Shells, command panes, language servers, the link opener and the v9fs mount inherited the editor's signal mask (the tty's blocked SIGWINCH) and anything it ignored (a SIGHUP nohup ignored), since only handlers reset at exec. Each fork now resets every disposition and clears the mask before its exec (resetChildSignals); std's spawn for selection pipes runs with the mask cleared across it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A path with a part over 255 bytes is refused, never a panicGabriel Schneider34 hours
| | | | | | | | | | | | std's statFile takes the kernel's ENAMETOOLONG for a bug (errnoBug), so a name, look, DumpDir or Save path with a part over 255 bytes panicked the editor (exec.kindOf via writeName, recentKeeps, dumpFailed). Every non-test statFile now goes through fs.statPath, which refuses such a name as NameTooLong first; fs.py drives long, looping, not-a-directory and not-ours paths through name, look, DumpDir, Dump and Save. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | The GUI's idle wakeup copies no 20 KB message batchGabriel Schneider34 hours
| | | | | | | | | | | | Queue.take built its batch (queue capacity plus room, some 20 KB) and returned it by value on every wakeup, a memset and a memcpy of it though the queue was empty; it led the idle profile. drainQueue now fills a batch the Shell keeps, and an empty queue leaves it untouched. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Typing tells g. where its edit ended, so no edit scans the whole file twice ↵Gabriel Schneider34 hours
|/ | | | | | | | to find it setEditText found the last edit's end by comparing the old and new texts from both ends and counting rows to it, twice over the file on every keystroke: edit-char grew with the file (+135% at 300k lines). Typing, deleting, Enter and Tab now pass the end they know (setEditTextEnd); the comparison stays for the edits that do not say (paste, pipes, s). perf edit-char: 50k lines 16661 -> 15286 us, 300k lines 30507 -> 22291 us (render alone ~13.6 ms of each, the render agent's). Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The theme's chrome is worked out once, not per grapheme; still post passes ↵Gabriel Schneider34 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | let the GUI rest; a perf gate somtrmsz's contrast floors made ChromeTheme.fromTheme run its focus-tint and separator searches (pow calls each), and Output's RowDecoration.styleAt called it for every grapheme of every highlighted row: the 50k-line file's render went from 0.11 ms to 13 ms. Pardes.bodyChrome now keeps the theme's chrome, worked out again only when the theme differs; recolorSyntax asks for it once a decorated row, and a plain row (nearly every row of a file) never asks. ReleaseFast, medium fixture, median us, before -> after (main): render 13150 -> 76 (111), key-down 14658 -> 79 (110), wheel 13589 -> 76 (109), open 14891 -> 2095 (2055), edit-char 16703 -> 3006 (1251; the rest of that gap is editing and tree-sitter, not this). Post.animating asked for frames whenever the window had focus and any pass was ready, so a still pass kept the GUI drawing at the display's rate (Bloom: 49% of a core idle, in a hidden test window). A pass now says whether it moves on its own: the CRT (its hum and dither) and a Shadertoy file whose source reads iTime, iFrame or iDate (shader_build.readsTime; the flag rides the wire's post message); Bloom, Vignette and Grain are still. Bloom idle: 49% -> 1.2%, as with no pass. zig build perf-gate: the 50k-line file's gestures, each's fastest sample within 3x of the recorded baseline's (test/perf-baseline-<platform>- <optimize>.json, recorded from this build), run with every unit-test. On the regressed code it fails at 180x for render.
* A listing freezes at its open, so a read in several chunks never splices two ↵Gabriel Schneider34 hours
| | | | | | | | moments /index and the other listings were rendered afresh for each read, so a client reading one in chunks while panes changed got rows from two moments spliced together (the fs-test flake). /index, /layout, /recent, /commands, /status, /listeners and a ctl opened only to read now freeze at the open, as /screen does. Co-Authored-By: Claude Opus 5.5 <[email protected]>