control-mode correctness: pane output, hook frames, layout events and attach targets
this release fixes five defects found by auditing gotmuxcc against the tmux source at e880cf63 (next-3.9). nothing had regressed from the tmux upgrade itself — the suite passed against a freshly built next-3.9 before any change — but four of the five were long-standing and one is new with tmux 3.8.
fixes
refresh-client -Aand-rarguments are now quoted when tmux's parser would otherwise read them as a conditional keyword. tmux lexes a%-leading word as a keyword unless every character of it is%or a digit (cmd-parse.y, yylex), sorefresh-client -A %0:onwas a hard parse error andSetPaneOutput,EnablePaneOutput,DisablePaneOutput,PausePaneOutput,ContinuePaneOutput,SetMultiplePaneOutputsandReportPaneColorshad never worked against a real server. broken since tmux 3.0; six unit expectations asserted the unparseable strings, which is why nothing caught it. the quoting mirrors the lexer rule, so bare-t %0targets keep their existing wire format (c5bbfa3).- the router no longer pairs a hook's guard block with a queued request. tmux inserts a command run by a hook into the control client's own queue and guards it like any other, so it arrives as an unrequested
%begin/%endpair carrying a flags field of0; pairing that withpending[0]handed the request the hook's output and put every later reply off by one. blocks the client did not type are now tracked under a sentinel label and their output discarded (f9910fb). %layout-changeis parsed positionally, so lines carrying empty fields are no longer dropped entirely. tmux expands a fixed four-variable template, and#{window_raw_flags}is empty for any window that is not current, last, marked or zoomed and has no activity, bell, silence or modal pane — much the more common case — while both layout fields come back empty for a window whose only panes are floating, which is new with tmux 3.8 and reachable viabreak-pane -W(71034b7).- the control client now attaches by
#{session_id}rather than#{session_name}. tmux allows:and.in names again since166267c8, andattach-session -treads those as the session:window.pane separators, soNewTmuxreturned a client whose transport was already dead and the first call failed with "tmux exit" (1cce29e). Optionspassesshow-options -H, restoring user options registered as hooks that tmux7277712cbegan hiding. the flag exists only on tmux 3.8 and later, so a rejected flag falls back to the flagless call, and that error is the one reported if the fallback also fails (ce54bb1).
additions
- the layouts tmux accepts beyond the four gotmux exposes are available as
WindowLayoutMainHorizontalLayout,WindowLayoutMainVerticalLayout,WindowLayoutMainHorizontalMirrorandWindowLayoutMainVerticalMirror(8ca39b0). - pane and window flag characters are documented including tmux 3.8's
A(float above zoom) andO(modal pane), andSetControlFlagsdocumentsnew-layouts, the any-client flags, and that tmux splits the flag list on commas only (8ca39b0).
tests
- 344 tests and subtests passed with
-race -count=1, including the full tmux integration suite; none were skipped,go vet ./...is clean, and the suite was run against both a next-3.8 binary and a freshly built next-3.9 (8ca39b0). - 222
%begin … 0guard fixtures across 14 files claimed tmux sends0for replies to commands the client had typed, which real tmux never does; they are corrected to1. handshake and initial-attach fixtures, which genuinely carry0, are unchanged (f9910fb).
caveats
WindowLayoutMainVerticaldeliberately keeps its inherited value ofmain-horizontal. gotmux has the same name/value mismatch and gotmuxcc mirrors its public API, so changing the value would silently alter the layout every existing caller gets; useWindowLayoutMainVerticalLayoutformain-vertical(8ca39b0).- the
show-options -Hfallback for servers predating the flag is covered by unit tests only; it was not exercised against a real pre-3.8 server (ce54bb1). quoteArgumentnow quotes arguments such as%0:onthat were previously sent bare. bare pane targets are unaffected, but a caller comparing exact command strings will see the change (c5bbfa3).- the hook mis-pairing regression is covered by unit tests replaying a captured next-3.9 stream. an integration test was written and removed: reproducing it needs another request in flight at the instant the hook block lands, which does not happen reliably against a live server, so the test passed with the fix reverted (f9910fb).
- the minimum go version remains 1.22, and no exported signature was removed or changed.
upgrading
go get github.com/atomicstack/gotmuxcc@v0.4.0