fix: centre the mark on the usage screen, measure the art rather than assume it #11

Merged
marcos-mendez merged 3 commits from fix/mark-centred-size-agnostic into master 2026-09-27 16:57:47 -03:00
marcos-mendez commented 2026-09-27 15:06:54 -03:00 (Migrated from github.com)

The problem

Two defects in keelbanner.py, the module that puts the Keel mark above the
confconsole usage screen.

  1. The mark was not centred. In the maintainer's screenshot it sits off centre,
    against the left edge of the dialog.
  2. The module and its tests stated how big the art is: the docstring said the
    marks were "(38 by 19)" and "(23 by 11)", and two tests asserted exactly
    those sizes. The art is drawn in the keel-core overlay and is about to be
    redrawn, so any size stated here is a defect whatever the art turns out to
    be.

The diagnosis

above() prepended the block exactly as it was read and nothing ever shifted
it, so the mark inherited the dialog's left margin. The size assumptions were
documentation and test fixtures only: mark_size, fits and choose already
measured from the string, which is why the screen keeps working whatever is
installed, but the fixtures were copies of today's art with the row and column
numbers hardcoded around them, so the redraw would have failed the suite for no
good reason.

The fix

keelbanner.center(mark, width) shifts the whole block right by one indent,
the same for every line, computed from the mark's widest line. Centring each
line on its own would have destroyed the mark's internal alignment. A mark as
wide as the width, or wider, gets no indent and is never truncated; no line of
the block carries trailing whitespace; a blank line inside the mark stays
blank rather than becoming a line of spaces. Only the mark is centred: the
usage text keeps its own left margin and is otherwise untouched.

The width is inner_width(cols), the columns the box leaves inside its frame,
now the single definition that fits() also measures against, so the width a
mark is admitted on and the width it is centred on cannot disagree. usage()
derives it once from min(cols, self.width) and uses it for both.

The docstring no longer names a size: it says the size is whatever the
installed files carry, that the module measures the file it reads and that the
mark is centred. The fixtures in tests/test_keelbanner.py and
tests/test_confconsole_usage.py are now synthetic blocks of an arbitrary
size, not copies of the shipped art, and every expectation (which mark a
terminal admits, the blank line between mark and text, the indent the screen
gives, the rows the box grows by) is derived from the size the fixture itself
measures.

Tests

419 tests, up from 379 (the mark's own files: 60 in tests/test_keelbanner.py,
up from 22, and 8 in TestUsageMark). New: the centring function directly (odd and even
leftover so the rounding is pinned, a mark wider than the width, a mark exactly
the width, a blank line, a line of spaces, trailing whitespace in the art, the
row count unchanged, one indent for every line); through the usage screen, that
the mark arrives centred and that the text below it is byte for byte the screen
the appliance shows without a mark; mark_size over blocks of several shapes,
ragged and empty included, in place of the two size assertions; and the
fallback ladder, full mark to small mark to none on a shrinking screen, in one
place.

Coverage

100 percent, lines and branches, 0 missed and 0 partial, for the gate's package
list (keelbanner.py: 52 statements, 16 branches):

PYTHONPATH=. python3 -m coverage run --branch \
  --source=ifutil,keelbanner,keelcli,dbscreen,plugins.d/Instance \
  -m pytest -q tests
python3 -m coverage report --show-missing

Master's database mode change is merged into this branch: its 2.2.3+keel3
entry stands and the entry here is 2.2.3+keel4.

Two tests that hold this open

The suite already used a fixture of its own rather than the shipped art.
Two tests now prove the properties that matter when the art changes under
it.

The block stands in the middle of the width. It reads the blank columns
off each side of the centred block and requires them equal, or the one odd
column left on the right, at seven widths from one column wider than the
mark to far wider. It measures the block instead of recomputing the indent,
so it fails on a block pushed to either side rather than agreeing with
whatever center produced. Its fixture has its widest line neither first
nor last, and one line indented in the art itself.

TestAnUnanticipatedSize. Marks of 1 by 1, 2 by 3, 7 by 24, 12 by 38, 31
by 71 and 44 by 7, none of them a size the art has had, including the two
the new budget allows. Each is measured to the size it was drawn at,
centred inside the dialog frame, and costs the box its own rows and the
blank line under it and nothing more; and for each, one row or one column
less drops the mark rather than the usage text.

Three mutations fail them: right aligning the block, centring on an assumed
width of 38, and hard coding the mark at 19 rows.

Notes

No ASCII art is created, edited or moved by this pull request. The art stays in
the keel-core overlay and is being redrawn separately by the maintainer against
the documented row budget (full mark at most 12 rows by 38 columns, small mark
at most 7 rows); nothing here has to change when it lands.

Worth knowing before drawing it: the usage box is 65 columns wide and the frame
takes 4, so the mark is centred on 61 columns and a mark wider than 61 is
dropped on any terminal. With the usage box at 25 rows, a mark of N rows needs
a terminal of 26 + N rows, so at the new budget the full mark appears from 38
rows and the small mark from 33; below that, and on any terminal under 24 rows,
the screen is exactly what it was.

## The problem Two defects in `keelbanner.py`, the module that puts the Keel mark above the confconsole usage screen. 1. The mark was not centred. In the maintainer's screenshot it sits off centre, against the left edge of the dialog. 2. The module and its tests stated how big the art is: the docstring said the marks were "(38 by 19)" and "(23 by 11)", and two tests asserted exactly those sizes. The art is drawn in the keel-core overlay and is about to be redrawn, so any size stated here is a defect whatever the art turns out to be. ## The diagnosis `above()` prepended the block exactly as it was read and nothing ever shifted it, so the mark inherited the dialog's left margin. The size assumptions were documentation and test fixtures only: `mark_size`, `fits` and `choose` already measured from the string, which is why the screen keeps working whatever is installed, but the fixtures were copies of today's art with the row and column numbers hardcoded around them, so the redraw would have failed the suite for no good reason. ## The fix `keelbanner.center(mark, width)` shifts the whole block right by one indent, the same for every line, computed from the mark's widest line. Centring each line on its own would have destroyed the mark's internal alignment. A mark as wide as the width, or wider, gets no indent and is never truncated; no line of the block carries trailing whitespace; a blank line inside the mark stays blank rather than becoming a line of spaces. Only the mark is centred: the usage text keeps its own left margin and is otherwise untouched. The width is `inner_width(cols)`, the columns the box leaves inside its frame, now the single definition that `fits()` also measures against, so the width a mark is admitted on and the width it is centred on cannot disagree. `usage()` derives it once from `min(cols, self.width)` and uses it for both. The docstring no longer names a size: it says the size is whatever the installed files carry, that the module measures the file it reads and that the mark is centred. The fixtures in `tests/test_keelbanner.py` and `tests/test_confconsole_usage.py` are now synthetic blocks of an arbitrary size, not copies of the shipped art, and every expectation (which mark a terminal admits, the blank line between mark and text, the indent the screen gives, the rows the box grows by) is derived from the size the fixture itself measures. ## Tests 419 tests, up from 379 (the mark's own files: 60 in tests/test_keelbanner.py, up from 22, and 8 in `TestUsageMark`). New: the centring function directly (odd and even leftover so the rounding is pinned, a mark wider than the width, a mark exactly the width, a blank line, a line of spaces, trailing whitespace in the art, the row count unchanged, one indent for every line); through the usage screen, that the mark arrives centred and that the text below it is byte for byte the screen the appliance shows without a mark; `mark_size` over blocks of several shapes, ragged and empty included, in place of the two size assertions; and the fallback ladder, full mark to small mark to none on a shrinking screen, in one place. ## Coverage 100 percent, lines and branches, 0 missed and 0 partial, for the gate's package list (`keelbanner.py`: 52 statements, 16 branches): ``` PYTHONPATH=. python3 -m coverage run --branch \ --source=ifutil,keelbanner,keelcli,dbscreen,plugins.d/Instance \ -m pytest -q tests python3 -m coverage report --show-missing ``` Master's database mode change is merged into this branch: its 2.2.3+keel3 entry stands and the entry here is 2.2.3+keel4. ## Two tests that hold this open The suite already used a fixture of its own rather than the shipped art. Two tests now prove the properties that matter when the art changes under it. *The block stands in the middle of the width.* It reads the blank columns off each side of the centred block and requires them equal, or the one odd column left on the right, at seven widths from one column wider than the mark to far wider. It measures the block instead of recomputing the indent, so it fails on a block pushed to either side rather than agreeing with whatever `center` produced. Its fixture has its widest line neither first nor last, and one line indented in the art itself. *`TestAnUnanticipatedSize`.* Marks of 1 by 1, 2 by 3, 7 by 24, 12 by 38, 31 by 71 and 44 by 7, none of them a size the art has had, including the two the new budget allows. Each is measured to the size it was drawn at, centred inside the dialog frame, and costs the box its own rows and the blank line under it and nothing more; and for each, one row or one column less drops the mark rather than the usage text. Three mutations fail them: right aligning the block, centring on an assumed width of 38, and hard coding the mark at 19 rows. ## Notes No ASCII art is created, edited or moved by this pull request. The art stays in the keel-core overlay and is being redrawn separately by the maintainer against the documented row budget (full mark at most 12 rows by 38 columns, small mark at most 7 rows); nothing here has to change when it lands. Worth knowing before drawing it: the usage box is 65 columns wide and the frame takes 4, so the mark is centred on 61 columns and a mark wider than 61 is dropped on any terminal. With the usage box at 25 rows, a mark of N rows needs a terminal of 26 + N rows, so at the new budget the full mark appears from 38 rows and the small mark from 33; below that, and on any terminal under 24 rows, the screen is exactly what it was.
Sign in to join this conversation.
No description provided.