summaryrefslogtreecommitdiff
path: root/src/exec.zig
Commit message (Collapse)AuthorAge
* A build that runs no commands refuses a word that is not a builtin, and says soGabriel Schneider42 hours
| | | | | | Board and web have no spawn. An unknown word there used to fall through to the command path and do nothing visible; now it answers with a failure the caller sees. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Text sent to a REPL is plain lines, sent whole or not at allGabriel Schneider42 hours
| | | | | | | | | | | | A CRLF became two line ends, the blank line ending a Python block; an ESC in the text, ESC[201~ above all, could end a bracketed paste early; and on the board, whose writes are 128 effects of 64 bytes with nothing pending, a send past 8 KB was cut and lost its closing ESC[201~ and Enter, leaving the REPL in a paste. Lines now end in LF alone, ESC and every control byte but tab and newline are dropped, and a send larger than can be written at once (Pardes.writeRoom) is refused with a message instead of cut. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A command's exit is told once its output is in, by the pty's state, not a timerGabriel Schneider42 hours
| | | | | | | | | | | | | | | | | | The watcher woke the host a second time 60 ms after the exit by its own clock while the grace was counted from the reap: a host busy for 10 ms missed it, and the tag said running for ever and Kill did nothing; and under load exit 0 could land before the last output. As decided, no timer: the exit is told once it is reaped and the pty says nothing is left (poll: no POLLIN, and no POLLHUP, which means the end of file is on its way behind the output), else at that end of file, checked after each chunk of output. The tty host checks inside its step so the frame shows it. The four hosts' copies are one host_io.takeExits/commandEof, which close a told command's pty at its end of file (the fd and the GUI's reader leaked when the exit came first). A finished command pane whose pty a job it left still holds is not reused, so that job is not hung up; and the reset before a reuse is SGR 0, not DECSTR, which ghostty's stream does not implement. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Whether an exec came from a body travels with it, so every selection goes to ↵Gabriel Schneider42 hours
| | | | | | | | | | | | | the REPL The execute key and the middle click marked a global flag that the first execute cleared, so of several selections executed at once only the first reached a bound REPL and the rest ran as commands. Where an exec came from now goes with it, as acme's execute() asks of its Text (exec.c:122,169): builtins.Ctx carries from_body, runBuiltinFrom and executeFrom take it, the gestures set it, and chordEachSel sets it for each selection. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A REPL takes text only while its program has the terminalGabriel Schneider42 hours
| | | | | | | | | | | | | A binding outlived its program: a command pane reused kept the REPL of the command before, a done command pane could be bound, a document pane (a terminal with no emulator) was accepted, and after Ctrl-D in python3 the text went to the shell, which ran import os as ImageMagick's. A command pane's binding now ends with its command and a done one is refused, a pane with no emulator is refused, and an interactive terminal's REPL is live only while a program other than its shell holds the tty (the host's tty_taken); when none of the language's REPLs is, nothing is sent or run and the pane says so. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Tty with a shell that is not there says so, and never sets the caller's shellGabriel Schneider42 hours
| | | | | | | | | | | | | Tty /nonexistent or Tty fsh started the host's fallback shell without a word, and when spawnTty made no pane, the argument became the calling pane's shell. Tty now looks the shell up first and fails 'Tty: no shell "fsh"' when it is neither a name on the usual paths nor a path to one; spawnTty answers the pane it made, the one given the shell, and says why when it made none. The lookup (host_io Shell.find) gives the turn up around its access() calls, since a typed path may be under a mount this editor serves, and forkShell copies the pane's shell before looking it up and checks the pane is still its own after. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The log's run record carries the whole command line, after the new record of ↵Gabriel Schneider42 hours
| | | | | | | | | | | its pane run logged the line's first word only, and before the new record of the pane it ran in, since panes are announced at the end of a step. It now carries the whole line as msg carries its text (control characters, newlines too, as spaces), and announces the new pane first. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A command pane echoes its first command as it does the later onesGabriel Schneider42 hours
| | | | | | | | | Only a reused pane showed '% line' above its command, so the first command's output stood with nothing saying what made it. Every command is echoed now, the first too. The goldens of chordcut, cmdexit, cmdword and layout-open gain that line and the rows below it move down one. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A command of several lines keeps its pane's tag to one row, and the tag ↵Gabriel Schneider42 hours
| | | | | | | | | | | | | | never panics on a longer prefix A two-line exec made a command pane whose tag prefix held the line's newline, so the tag ran to a second row and tagTintRange sliced its first row past its end: panic. acme runs a multi-line selection as one command, and so does pardes; the tag now shows the line's first row, cut at a character's start, and '...', tagTintRange stays inside the row it is given, and the '% line' echo turns the line's newlines into the terminal's, so it does not staircase. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A terminal bound as a language's REPL takes the execs made on that ↵Gabriel Schneider42 hours
| | | | | | | | | | | | | | | | | | | | | | language's files Repl python in a terminal's tag or on its ctl binds it (Repl - unbinds, Repl bare says the binding, the same word again changes nothing), with an id, python-a, python-b, in its tag. An exec made by a gesture on the body of a file in that language -- a middle click or the execute key, on any text, a single word too -- or on the REPL's own body is typed into it, bracketed if its program asked for that, else line by line with a once-said warning for Python's blank lines, then Enter; the message row says -> python-a in the tag's name tint, the log send <from> <to> <id>. Several bound for the language: the pane asks which on its notice band, as Del asks, one key answering, Esc none, nothing remembered. The gesture is known where it is dispatched (mouse.zig, the execute key), so the tag's words, Exec <text> run by name and a command word @`cmd` stay commands, and a 9P exec is never sent. A finished command pane is no REPL; bindings are not dumped. The docs spell out the escapes, the pdb and input() caveat and the no-bracketed-paste papercut. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A reused command pane leaves the last program's screen modes before the next ↵Gabriel Schneider42 hours
| | | | | | | | | | | | | command A program that crashed out of a full screen left the command pane's emulator in the alternate screen with mouse reports, bracketed paste or a hidden cursor on, and the next command ran in that. Before the '% line' separator the pane now leaves the alternate screen, turns those modes off and soft-resets (DECSTR). The docs add that a command which clears the screen and its scrollback erases the pane's history above it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Only Tty reads Word+arg as its argumentGabriel Schneider42 hours
| | | | | | | | Every builtin that takes an argument split a word at its first +, so Dump+2024.zon ran Dump with 2024.zon. A builtin now opts in with plus_arg, read by the registry, and only Tty does. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A spawn names the pane it was made for, so a pane closed and its slot ↵Gabriel Schneider42 hours
| | | | | | | | | | | | | | retaken spawns nothing The spawn effect carried only a slot, and the host read the command and shell off whatever pane held the slot as it forked: a command pane closed and its slot taken by the next one before the effects ran forked the new pane's command twice. The effect now carries the pane's serial and is dropped when the slot holds another; forkShell checks it again after giving up the turn for its directory's stat, the one moment a 9P client can change the panes under it. Every front end performs spawns with the turn, from its step. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A terminal's Tty word names its shell, Tty+fish, and a click on it opens anotherGabriel Schneider42 hours
| | | | | | | | | | | | | | | A terminal's tag said Tty whatever shell it ran. The host's acknowledgement of the shell it forked now sets the word to Tty+<shell>, tinted like the tag's name. Word+arg is taken as Word arg, one word a tag can hold and a click can take whole (+ is a word character), so Tty+fish opens a terminal on fish, as Tty fish does; Tty takes the shell as its argument, which the host forks for that pane instead of the configured one. Every snapshot whose screen shows a terminal's tag changes: 69 goldens, re-recorded by name, whose 297 changed lines are all Tty becoming Tty+bash (the harness runs bash), the cursor columns and style spans that moved with it, or that text cut at a pane's width. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A command line runs as its own command pane unless it is clicked at a ↵Gabriel Schneider42 hours
| | | | | | | | | | | | | | | | | | | | | | | shell's prompt A middle click, an exec write or a tag word that no builtin knows was typed into some terminal for the pane's directory, sharing whatever state that shell was in and answering nothing, so a misspelling vanished into a shell. Now only a line clicked at an interactive terminal's prompt is typed there. From anywhere else it runs as a command pane: a terminal whose child is $SHELL -c the line in the pane's directory, full emulation, which shows its output and then exit N from the host's reaping of the child, and stays. A finished command pane is the next command's for its directory, which runs below what it showed after a '% line' line (acme appends to +Errors and never clears it, util.c:213); a running one gets a second pane. Kill ends a command pane's whole process group, the log records run and exit, exec reads back the command pane's serial, and a line is at most 1 KB, read off the pane as the host forks rather than carried in every spawn effect. ttyForDir's search for a free shell is gone. The goldens of chordcut, cmdword and layout-open change where a file's exec now opens a command pane, and ttytaken is rewritten to exec from the terminal itself; docs/open-questions.md records the decision. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Joincol with no column to the right and Theme with no such theme say soGabriel Schneider42 hours
| | | | | | | | | | | Both did nothing without a word, from a click or a ctl write alike, and a script could not tell a no-op from success. Joincol in the rightmost column now fails 'Joincol: no column to the right'. A Theme name that is none says so and names the themes sharing its first letter, since all of them (ThemeSel lists them) are too many for a message or a refused write; a startup config line still fails quietly, as its other bad lines do. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Exit quits and Kill stops commands, as in acmeGabriel Schneider42 hours
| | | | | | | | | | | | | | | | Kill quit the editor, which in acme is Exit; acme's Kill stops the commands it started. Exit now quits as acme's does (exec.c, rowclean): it refuses once, naming each pane with unsaved text, and quits when asked again with nothing edited since (a small scratch is not asked about). Kill, bare or with names, stops the commands pardes typed into a terminal (an exec, a middle click, a pty/run) while their shell's marks say they run, by SIGTERM to the terminal's foreground job, never to the shell (acme posts the kill note, which terminates). Both are session builtins; the topbar's Kill becomes Exit, same width, and every golden's topbar row changed by exactly that word (checked line by line); the builtins script scrolls one more row for the index's new line. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A switch setting clicked with a selection held flips again, unless the ↵Gabriel Schneider42 hours
| | | | | | | | | | | | | | | selection is on or off Giving panel and scene effects on/off made every switch a word that takes an argument, so a middle click on Verbose or PanelSlide with other text selected passed that text as its value and failed. The click path now passes a held selection to a switch only when it says on or off, and the word flips as it did bare; a ctl write is still checked strictly. The topbarexec golden had been recorded with that failure (Debug clicked with a sweep opening nothing, the very thing the script says it guards); it now shows the overlay again. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* File the tag code into tagline.zig and draw tags beside bodiesGabriel Schneider42 hours
| | | | | | | | | | | With tags reduced to Texts, what is left of them is the computed prefix, the default and saved tails, entering and leaving a tag and the headers: that goes to tagline.zig, as acme keeps the tag half of a window in wind.c. Tag and header drawing moves next to body drawing in body_layer.zig, and the tag hit helpers go to tag_layer.zig with the Hit they read, where sameCell now also tells the lines of a taller tag apart. The docs describe the tag as a Text. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Let a pane's tag take a row for each line it holdsGabriel Schneider42 hours
| | | | | | | | | | | A tag that is a text can hold a newline, and the tagline, the body under it and the pointer all assumed one row. The pane's tag now takes a row per line (up to eight, and never the body's last row); the body starts below it, the rows a pointer counts start the body after the tag's lines, a click on any line puts the tag's cursor there, and a pixel shell gets a tag layer per line. A tag of one line draws exactly as before. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Make a pane's tag a Text edited with the body's own keysGabriel Schneider42 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 Schneider42 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 Schneider42 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]>
* Move exec out of pardes.zig into exec.zigGabriel Schneider42 hours
Pure move, no behaviour change (acme keeps this in exec.c): execute, commandText, max_exec_depth, executeBuiltinLine, applyStartupConfig, runBuiltin and applySettingBuiltin; the getarg-style operand code (withArg, PointerOperand, pointerOperand, heldSelection, chordEachSel); takesCommandLine and the terminals commands run in (spawnTty, spawnV9fsTty, spawnTtyWithMount, evictLonePristineTty, replaceStillborn, ttyForDir); placeDoc; and the save path (submitSave, saveFile, saveTo, askWrite), with the acme-chords test, go verbatim to exec.zig. The methods become free functions taking `p: *Pardes`. executeBuiltinLine is called from ~170 places as `p.executeBuiltinLine(..)`, so Pardes keeps one declaration alias for it and those call sites stay; the other 104 calls change from `p.execute(..)` to `exec.execute(p, ..)`. ninep/ctl.zig has a local named exec, so it writes `pardes.exec.execute` instead of importing the file. Co-Authored-By: Claude Opus 5.5 <[email protected]>