10 Commits
Author SHA1 Message Date
Jean-Pierre MartineauandClaude Opus 5.5 11b5274b31 Docstrings and comments of the tests are in ASD-STE100
Each test docstring states the behaviour that the test proves, in the
simple present. No assertion message, test id, or other string literal
changed. Four statements now agree with the code: the Trace highlight
stays on the last row, a menu count, and two others.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-06 21:36:50 -04:00
Jean-Pierre MartineauandClaude Opus 5.5 7bcb1db360 The battery shows its last digit on Linux and macOS
A full T1000-E read 9 or 10% in the header on Ubuntu, while the radio
reported 4.21 V. The battery was never the fault. A full pack's "100"
lost its last zero, and 99% lost its 9 to the % sign that followed it.

MeshTerm adds one column to the width the terminal reports, because
prompt_toolkit's Windows console output reports one column fewer than
the window has, on purpose. That was done on every desktop, but a Linux
or macOS terminal reports its width exactly. There the extra column fell
off the screen. prompt_toolkit draws with autowrap off, so each row's
last character landed on top of the one before it, and whatever sat
flush right lost its end. The battery gauge sits flush right.

The column is now added only where the terminal hid one, which is the
Windows console. The full_width preference and MESHTERM_FULL_WIDTH still
override either way. Driven into an exact 80-column terminal under
--mock, the header now ends "100" at 4.21 V and "98%" at 4.18 V, where
it ended "10" and "9%". In a real Windows console the reported 119
columns still widen to 120.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 04:21:38 -04:00
Jean-Pierre MartineauandClaude Opus 5.5 b6e7cd5c16 The handhelds are named for their variant: picocalc-lyra and cardputer-zero
M5Stack makes three Cardputers and only the Zero runs Linux; the PicoCalc
takes several cores and only the Luckfox Lyra runs MeshTerm. So the bare
names were ambiguous, and every reference to the two devices now carries
the variant: the --platform values and MESHTERM_PLATFORM, the Platform
constants (PICOCALC_LYRA, CARDPUTER_ZERO), their lane decks and every
screen's picocalc_lyra_lane / cardputer_zero_lane, the font inventories,
the lane chips' theme styles, the scripts/ folders, the two chrome test
files, and the docs and CLAUDE.md that name them.

There is no alias: --platform picocalc is refused with the three real
choices listed, rather than falling back to the desktop layout. The
PicoCalc is auto-detected from its device tree, so it needs nothing.
What names hardware or a user's data keeps its name: the PicoCalc
keyboard's input-device name, its battery's sysfs supply, and the serial
profile the Lyra setup script writes. .gitignore follows the firmware's
folder, and the changelog keeps the words each release used.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-04 11:52:41 -04:00
Jean-Pierre MartineauandClaude Opus 5 6f7b24e790 A dialog's glyphs land where prompt_toolkit measured them, too
The rows the fast renderer writes were already pinned. Anything
prompt_toolkit lays out itself — a floating dialog, and the backdrop it
repaints — still went out through its differential renderer, which steps a
cursor of its own by each glyph's measured width and moves relatively from
there, so one glyph drawn at another width threw off every move after it.

That renderer never knows a column absolutely, so the pin is spelled
relative to the glyph instead: save the cursor, draw the glyph, restore,
step forward exactly the width the renderer is about to add. The terminal's
cursor is back in step after every glyph, and nothing is tracked that could
drift from the renderer's own bookkeeping. PinnedOutput wraps the real
terminal; the width reclaim stays outermost.

A flag's two indicators are now merged into one cell before layout, like a
ZWJ sequence, so the pair is written as one glyph rather than with a cursor
move between its halves.

Nothing is pinned on a platform that draws no emoji: the PicoCalc only ever
draws glyphs its own font has verified.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 20:07:45 -04:00
Jean-Pierre MartineauandClaude Fable 5.1 c9f5a71ce7 Every Python file names its licence with an SPDX identifier
Apache-2.0 does not require per-file headers, but a file lifted out of the tree carried no marking at all. One comment line, first (or right after a shebang), on every .py under meshterm/, tests/, packaging/ and scripts/, plus the extensionless SPI bridge; tests/test_spdx.py keeps a new file from landing without one.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-13 13:09:18 -04:00
Jean-Pierre MartineauandClaude Opus 5 92d31a3191 Every file is spelled the way the formatter spells it
`ruff format .` across the repo: 153 files, no behaviour change. This is the
second gate CONTRIBUTING.md promises, and until now it reported 154 files needing
reformat — so a first contributor ran the command the guide told them to run and
could not tell their own diff from the background.

Landed on its own, with nothing else in it, because a whole-repo reformat is only
safe to skip past in blame if it is provably nothing but layout. It was checked
that way rather than assumed: every changed file was formatted in memory and
compared by full `ast.dump()`, and 152 of 153 come out structurally identical
(the one exception was a docstring opening on a quote character, fixed in the
commit before this one). The string and comment token streams were diffed
separately, so a quote flip or an edited comment could not hide inside a
re-layout — five quote-style normalisations and sixteen implicit-concatenation
joins, all value-identical, and one commented-out line gaining the space after
its `#`. `meshterm specimen` is byte-identical on both platforms, and the suite
is 1888 green, gallery gate and `test_theme16` included.

What actually changed, in order of how much of the diff it is: wrapped calls and
signatures rejoin onto one line where they fit inside the hundred columns; the
magic trailing comma expands what it is there to expand; complex slices gain
their spaces (`[len(noise) :]`); a few redundant parens go. The tables that are
laid out to be read were fenced in the previous commit and are untouched here.

The aligned trailing-comment column is gone from about ninety lanes that were not
fenced — including the `heat.*` ladder in `MESH_THEME`, which cannot be fenced
where it sits. Every comment stays on the entry it describes, so nothing there
reads wrong; it just no longer lines up.

Add this commit to `.git-blame-ignore-revs`, which follows immediately.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 01:07:19 -04:00
Jean-Pierre MartineauandClaude Sonnet 5 8f1fba135e Platform seam: meshterm/platforms.py, --platform flag, dual-platform gallery
One frozen Platform spec (REGULAR/PICOCALC), resolved once at boot
(--platform flag > MESHTERM_PLATFORM env > /proc/device-tree/model
auto-detect > REGULAR) and read via get_platform()/set_platform() -
never a stale `from platforms import PLATFORM`, which the module
docstring calls out. `meshterm platform` reports the resolution and
everything it looked at.

Wires the two correctness bindings that matter before any flavour
work lands: width_reclaim off on PicoCalc's exact-width console
(session._reclaim_last_column, env override still wins), and the
emoji-width calibration probe skipped outright when a platform never
draws emoji.

tests/test_gallery.py renders all 16 screens the interactive menu
opens against REGULAR (72x24) and PICOCALC (53x26 live floor, 53x40
lux case), asserting no line overflows its platform - 35 passing
cases, 13 xfailed as a real P6 worklist (contacts, map, walk,
livefeed, remote_cli, path_composer). Also caught and left alone: the
map screen's footer hint already overflowed the *existing* 72-col
standard before this seam existed, unrelated to picocalc - xfailed
rather than fixed as a drive-by. tests/test_platforms.py unit-tests
the module directly; conftest.py gained an autouse fixture resetting
the platform between tests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 02:18:22 -04:00
Jean-Pierre Martineau 966900a9dc Revert "Drop the +1 last-column width reclaim"
This reverts commit 62422c176426be11f356d92d4d081bd65eb1961e.
2026-07-16 23:28:37 -04:00
Jean-Pierre MartineauandClaude Opus 4.8 ee047f1212 Drop the +1 last-column width reclaim
The MESHTERM_FULL_WIDTH reclaim reported the terminal one column wider than
probed, to draw a final column some terminals under-report. With the emoji
width now aligned to the terminal, that extra column pushes the frame past the
real screen edge and tears the layout. Remove it: the size probe is used as-is
again (_WidthExtendedOutput, _RECLAIM_LAST_COLUMN, _resolve_output, and the
MESHTERM_FULL_WIDTH gate all gone), and the app renders to prompt_toolkit's
default output. Drops tests/test_session_width.py with the feature.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 23:26:02 -04:00
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