aboutsummaryrefslogtreecommitdiffstats
path: root/tests/live_input.py (follow)
Commit message (Collapse)AuthorAge
* slosh: rename the project from sl0pptyuser2026-08-18
| | | | | | | | | | | | | | | | | | | | | sl0p + pty was error-prone to type and the zero made it worse; slosh (slop + sh) is one syllable, impossible to typo, and slosh.foo is ours. Mechanical rename everywhere it appears: binary, env vars (SLOSH, SLOSH_SESSION, SLOSH_BIN, SLOSH_CONFIG), socket dir (/tmp/slosh-<uid>, $XDG_RUNTIME_DIR/slosh), config path (~/.config/slosh), header guards, src/sl0ppty.h -> src/slosh.h, contrib/sl0ppty-dev -> contrib/slosh-dev, the driving-slosh skill, docs and tests. The sl0ppi fork references and the sl0p theme stay: one is history, the other is the brand. The rename surfaced a latent bug in test_osc5577: the hello-reply answer always appeared on screen twice (ECHOCTL echo plus cat -v), but a seven-character implementation name happened to wrap the second copy across the 60-column boundary, so counting substrings in wrapped text found one and passed for the wrong reason. A five-character name moved the wrap and exposed it. The loop guard itself is correct -- with echo off before the request there is exactly one reply -- so the test now counts on de-wrapped text and tolerates the pane's own echo.
* sl0ppty: ruff format the Pythonuser2026-08-17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The bumpy one, again. Every `.py` outside `vendor/` plus the three `contrib/` scripts that are Python with no extension: 60 files, 6,714 lines rewritten, no behaviour changed. Nothing here is worth reading -- the next commit adds it to `.git-blame-ignore-revs` so `git blame` walks past it. It is a bigger reformat than the C was, 60% of the lines against 17%, and for a reason worth writing down rather than tuning away: ruff and black break a call that does not fit onto one argument per line, where this code aligned the continuation under the opening paren. The test suite is thousands of `check("some prose", cond, detail)` calls, so nearly every one of them changed shape and the suite grew 3,308 lines. Line length was the one lever that moved it -- 120 columns would have been a 40% reformat and no growth at all -- and it was left at 88, because picking an unusual width to dodge a one-time diff is paying forever to avoid paying once. Import sorting came with it. Two files had `import os, pty, uuid, select, struct, sys, termios, time, fcntl, signal` on one line and now have ten. Verified after, not before, because a formatter that alters behaviour would be worse than none: - `make retest`, 1801 checks green -- and this reformats the suite that does the checking, including `harness.py`, which every one of those files imports. - `make test-live`, the tty tests the fast suite skips. They matter here more than usual: `live_input.py` and `live_m0.py` are two of the files whose comma-imports were split, and nothing in the fast suite would have noticed if that broke them. - All 60 files still compile, `make fmt` twice in a row changes nothing the second time, and `ruff check --select I` has nothing left to say.
* make coverage: a number, cheaplyuser2026-08-15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | `make coverage` builds a second binary with gcc's --coverage into build/cov, runs every suite against it, and prints a per-file table from gcov. About a minute. Nothing installed, nothing about the normal zig build changed. gcc rather than clang because the counters need a gcov that matches the compiler, and gcov is what this machine has -- no llvm-profdata, no llvm-cov, no lcov, no gcovr. The aggregation is forty lines of python reading gcov's own summaries, which is the whole reason this was cheap. The suites drive it through $SL0PPTY_BIN, one line in the harness, so there is no second copy of the test code and no risk of the coverage run testing something else. Two things about the result, both in the report itself: - the C unit tests link the *same* instrumented objects, so input.c, kdl.c, shader.c and expr.c are credited for the tests that exercise them. Built separately, input.c read 54% while having a dedicated decoder test -- a lie about where the tests are rather than about the code. - server.c reads ~8% and is not untested. The session server is a daemonised child ending in _exit(), which is right there and skips the flush gcov needs. The counters are lost, not the tests. Said in the output, because an unexplained low number invites someone to "fix" working code -- and changing correct code to make a tool happier is the wrong trade. Where it lands today: 85.4% of 6298 lines. The gaps that are real rather than mechanical are jsonval.c (58%), screen.c (64%) and pty.c (59%) -- error paths and the parts of the diff emitter that only a resize or a weird terminal reaches.
* sl0ppty: rename from sl0pttyuser2026-08-14
| | | | | | | | | | | | | | | | A pty is a pseudo-terminal, and that is what this multiplexes: the extra t was never standing for anything. Renaming now, while the only users are the people who typed the old name on purpose, is cheaper than renaming later. Mechanical, but not only cosmetic. The name is also the runtime contract, so this moves $SL0PTTY and $SL0PTTY_CONFIG, ~/.config/sl0ptty/config.kdl, the socket directory ($XDG_RUNTIME_DIR/sl0ptty, /tmp/sl0ptty-<uid>), and the identity string a program gets back from an OSC 5577 hello. A session left running under the old binary keeps its old socket directory and is invisible to the new one; there is no migration and it does not seem worth writing one. The sl0ppi fork keeps its name: it is a different thing, and D1 still points at it.
* sl0ptty: M7 — layout files and suspended panessl0p2026-08-13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A session can be a file: layout { tab name="api" purpose="project:api.a1b2c3" cwd="~/dev/api" { pane purpose="agent:main" command="pi" pane split="rows" { pane purpose="service:web" command="npm run dev" suspended=true pane purpose="shell:scratch" } } } built by --layout at startup or applied to a running session with {"cmd":"apply-layout", path|kdl, replace?}. Idempotency stays with the caller, which is where sl0ppi's CLI design already puts it: diff list-tabs against the projects on disk, then apply what is missing. close-tab completes that loop. Purposes a layout declares are locked, so identity comes from the file rather than from whatever the program inside prints — tested by having a pane try to take one in-band and be refused. Suspended panes: a pane that exists, is laid out, and has run nothing, showing what it would run and starting on its first keystroke (which is consumed, not forwarded). This is sl0ppi's D6 — a root with twelve projects must not become twelve running servers — and it is the reason can be cheap. Also fixes a test-isolation bug latent since M2: the live tests attached to the session called "main", which is whatever happens to exist on the box rather than one they created. They now use a unique session per run, which is how a run that had somebody else's htop in it became reproducible. 284 checks green (257 headless + 27 live).
* sl0ptty: M1 — layout tree, splits, focus, frames, and the hit list in usesl0p2026-08-13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | app_t owns the tree, focus, the prefix and what a key means; the interactive client and the headless driver are now both thin front ends over it, so there is exactly one implementation of every command. Layout is the pure function D6 promised: layout(tree, rect) recomputed every frame, remainder spread across children so nothing drifts, and splitting in a direction that already exists grows that split rather than nesting — three splits give three equal columns, not 1/2 + 1/4 + 1/4. Chrome: rounded frames, aspect-corrected gap, centred titles. The split button is budgeted BEFORE the title and hit-tested from the rect it was drawn in, which is the fix the fork needed four attempts to land. Every painted element registers (rect, action) as it is painted; a click is a lookup. Mouse into a pane is translated to pane-local coordinates. Three bugs the harness caught, none of which unit tests would have: - one click on the split button split twice: press *and* release both fired. Chrome now acts on press; forwarding to a pane still gets every event. - callbacks were registered as &fn, but the option is pointer-typed, so the stored 'callback' was a stack address. Any OSC 2 or DSR jumped into a dead frame. Now a hard segfault turned into two regression tests. - a keystroke that changed nothing still emitted a cursor hide/show pair. The cursor is hidden lazily now, so an idle frame costs zero bytes. 96 checks green in 6s (40 unit, 23 screen, 33 layout), plus 9 live.
* sl0ptty: M0.5 — the headless driver and the harness everything rests onsl0p2026-08-13
| | | | | | | | | | | | | | | | | | | | | | | | | --script runs the whole compositor with no tty: commands in (send, raw, settle, resize, snapshot, alive), composited screen out as JSON — rows of text, style runs, cursor, and the hit list. Styles are emitted as runs rather than per-cell objects, because a test wants 'columns 0..5 of row 0 are bold red', not 1920 objects. The hit list is empty until M1 paints something clickable, but the type, the JSON, and hit_test() exist now: one geometry, established before there is anything to get wrong. Also fixes two host-policy defaults found by the cursor never appearing. lib-vt is a VT library, not a terminal, so it starts with DECTCEM (mode 25) off and grapheme clustering (2027) off. Both are now set via MODE_DEFAULT, so they survive RIS. tests/harness.py + tests/test_screen.py: 19 checks over composition, styling, wide chars/clusters, scrollback, resize and the full input round trip — including the kitty/legacy re-encoding matrix, which no longer needs a pty. make test is now 2.4s for 59 checks; make test-live keeps the four that genuinely need a tty.
* sl0ptty: input decoder + per-pane re-encodesl0p2026-08-13
The half libghostty-vt does not do: decode what the outer terminal sends us into semantic events, then re-encode each event for the target pane against that pane's own negotiated modes. Decoder (src/input.c): legacy keys and modifiers, SS3, tilde keys, the kitty keyboard protocol (CSI u, shifted/base layout sub-params, press/repeat/release, associated text), SGR mouse incl. drag and wheel, bracketed paste, focus events, alt-prefix, UTF-8, and partial sequences retained across reads. Re-encoding (pane_send_key/mouse/paste) drives lib-vt's key and mouse encoders via setopt_from_terminal, so a pane gets exactly what it negotiated. The mouse encoder wants surface pixels; we declare a 1x1 pixel cell so cell coordinates are exact rather than approximated. The prefix key is handled on decoded events, not bytes, so it cannot be confused by a byte that merely looks like C-a inside a UTF-8 or escape sequence. Tests: 40 table-driven decoder cases (tests/input_test.c) + a live check that drives the same client into a legacy pane and a kitty/mouse pane and asserts each receives its own encoding (tests/live_input.py). 59 checks, all green.