You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(cli): render mid-spin log lines flush-left, coordinating spinner and logging
Log records emitted while the TTY spinner was painting rendered with
phantom leading padding (e.g. 19 blank columns after a '[|] set_repo
remove' frame during update/prepare), or -- with colours disabled on a
TTY -- glued straight onto the leftover frame text. ColorFormatter
prepended ESC[2K (erase entire line) to the levelname, which blanks the
frame but leaves the cursor at the frame's end column, so the record
started mid-line; with colours off there was no erase at all.
Move screen management out of the formatter into a shared seam:
* mtui/support/spinner.py: serialize frame painting through a
module-level RLock, register active spinners, and expose
spinner_suspended() -- it erases the visible frame with CR + ESC[K
(homing the cursor to column 0) and pauses repainting while held.
stop() erases under the lock and _spin re-checks the stop flag under
the lock so a frame is never repainted after stop erased it.
* mtui/cli/colors/formatter.py: emit every record from a
SpinnerAwareStreamHandler that wraps super().emit() in
spinner_suspended(), and drop the ESC[2K injections from
ColorFormatter (also fixes the NO_COLOR-on-a-TTY variant and stops
the escape leaking into non-terminal handlers such as the MCP
capture handler).
* mtui/cli/prompter.py: hold spinner_suspended() for the whole stdin
read so the SSH command-timeout prompt is not repainted over by a
live 'run' spinner.
Off a TTY nothing changes: spinners never register, spinner_suspended()
writes nothing, and the handler behaves like a plain StreamHandler.
Worker parallelism is untouched -- only terminal writes serialize.
Regression tests drive the real spinner and the real create_logger
handler against a pty and assert on the raw captured bytes: a record
emitted mid-spin must be preceded by CR + ESC[K and render flush-left;
the non-TTY path is pinned byte-exact.
0 commit comments