Files
MeshTerm/tests/test_session_width.py
T
Jean-Pierre MartineauandClaude Opus 4.8 bdd4650133 Full width: reclaim the terminal's under-reported last column
On some terminals prompt_toolkit's size probe reports the window one column
narrower than it really is, so the frame draws to columns-1 and the true
last column sits unused (selectable to the right of the border). Wrap the
real terminal output in _WidthExtendedOutput, which reports columns+1 from
get_size(); since the renderer and the frame compositor both key off that,
the final column now gets drawn.

Gated behind _RECLAIM_LAST_COLUMN (env MESHTERM_FULL_WIDTH=0 to disable) so
it can be turned off on a terminal whose probe is already correct — there
the extra column would fall off-screen and wrap — and eventually promoted
to a user setting. Test-supplied outputs are never wrapped, so headless
rendering keeps its exact size.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 18:47:08 -04:00

53 lines
2.3 KiB
Python

"""Session width tests: reclaiming the terminal's final column.
Some terminals (and prompt_toolkit's size probe on them) report the window one column
narrower than it really is, so the frame's right border lands one short and the true last
column sits unused. The session can report one extra column to close that gap. The wrapping
output is pure and the resolver is a small branch, so both are assertable without a terminal.
"""
from __future__ import annotations
from types import SimpleNamespace
from prompt_toolkit.data_structures import Size
import meshterm.ui.tui.session as session_mod
from meshterm.ui.tui.session import TuiSession, _WidthExtendedOutput
def test_width_extended_output_reports_one_more_column() -> None:
"""get_size() gains a column; every other attribute forwards to the wrapped output."""
inner = SimpleNamespace(
get_size=lambda: Size(rows=24, columns=80),
write=lambda s: f"wrote:{s}",
encoding="utf-8",
)
out = _WidthExtendedOutput(inner)
assert out.get_size() == Size(rows=24, columns=81) # the reclaimed column
assert out.write("x") == "wrote:x" # forwarded method
assert out.encoding == "utf-8" # forwarded attribute
def test_session_leaves_a_supplied_output_untouched() -> None:
"""A test-supplied output is never wrapped — headless sizes stay exactly as set."""
dummy = SimpleNamespace(get_size=lambda: Size(rows=10, columns=40))
session = TuiSession(output=dummy)
assert session._resolve_output() is dummy
def test_session_wraps_the_real_terminal_when_enabled(monkeypatch) -> None:
"""No supplied output + gate on → the real terminal output is width-extended."""
fake = SimpleNamespace(get_size=lambda: Size(rows=30, columns=100))
monkeypatch.setattr("prompt_toolkit.output.defaults.create_output", lambda: fake)
monkeypatch.setattr(session_mod, "_RECLAIM_LAST_COLUMN", True)
out = TuiSession()._resolve_output()
assert isinstance(out, _WidthExtendedOutput)
assert out.get_size() == Size(rows=30, columns=101)
def test_session_gate_off_uses_the_bare_terminal(monkeypatch) -> None:
"""Gate off → the real terminal output is used untouched (pt builds its own)."""
monkeypatch.setattr(session_mod, "_RECLAIM_LAST_COLUMN", False)
assert TuiSession()._resolve_output() is None