fix: keep system names whole at 40 columns

The size column took half the line and cut every name to eleven
letters: Game Boy, Game Boy Advance and Game Boy Color read alike. A
system row now carries shorter size forms, and the longest one that
leaves the name whole is shown, none when that is what keeps it.
This commit is contained in:
Abdessamad Derraz committed 2026-10-23 20:53:07 +02:00
1 parent 36f4b338e1
commit ba4db2ab57
4 files changed
+58 -5

No files matched your search

+1 -1
View File
@@ -11,7 +11,7 @@
$ErrorActionPreference = "Stop"
$defaultInstallUrl = "https://raw.githubusercontent.com/Abdess/retrobios/main/install.py"
$defaultInstallSha256 = "3d36f9aaf0bfd17cc2eeff61d0f99d35ff60d7cf967572ec146b166681334e5d"
$defaultInstallSha256 = "eaa912af47dc6f29e4436ec200a1b431b8ddd8006ca08e57c8c73d3a05717818"
$maximumInstallerBytes = 2MB
$installerExit = 0
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
+23 -3
View File
@@ -10178,6 +10178,9 @@ class TuiRow(NamedTuple):
right: str = ""
value: object = None
style: str = ""
# Shorter forms of right, longest first, for a narrow screen: the label
# keeps its room before the right-hand text does.
narrow: tuple = ()
# Screens that scroll text instead of listing rows.
@@ -10358,16 +10361,21 @@ def _system_rows(state: TuiState) -> list[TuiRow]:
need = _needed(row)
count, size = shared.get(row["system"], (0, 0))
own, own_size = need - count, row["bytes_needed"] - size
narrow: tuple = ()
if not need:
right = "in place"
elif not count:
right = f"{_plural(need, 'file')}, {format_size(row['bytes_needed'])}"
narrow = (format_size(row["bytes_needed"]),)
elif not own:
right = f"{_plural(need, 'file')}, {format_size(size)}, all shared"
narrow = (f"{format_size(size)}, shared", format_size(size))
else:
right = f"{_plural(own, 'file')}, {format_size(own_size)} + {count} shared"
narrow = (f"{format_size(own_size)} + {count} shared",
f"{format_size(own_size)} + {count} sh.", format_size(own_size))
rows.append(TuiRow("system", f"{box} {label}", right, row["system"],
"" if need else "dim"))
"" if need else "dim", narrow))
return rows
@@ -11292,8 +11300,20 @@ _ROW_VERBS = {
def _row_line(row: TuiRow, focused: bool, width: int) -> TuiLine:
right = middle(row.right, max(12, width // 2)) if row.right else ""
text = _columns(("> " if focused else " ") + row.label, right, width)
left = ("> " if focused else " ") + row.label
if row.narrow:
# The name first: the longest right-hand form that leaves it whole,
# else none at all when that is what keeps it whole. Nintendo Game
# Boy, Game Boy Advance and Game Boy Color read alike once cut.
whole = width - cell_width(left) - 2
right = next((form for form in (row.right, *row.narrow)
if cell_width(form) <= whole), "")
if not right and cell_width(left) > width:
right = row.narrow[-1]
text = _columns(left, right, width)
else:
right = middle(row.right, max(12, width // 2)) if row.right else ""
text = _columns(left, right, width)
return _styled(text, "focus" if focused else row.style)
+1 -1
View File
@@ -18,7 +18,7 @@ esac
TEMP_INSTALLER=""
TEMP_DIRECTORY=""
DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/install.py"
DEFAULT_INSTALL_SHA256="3d36f9aaf0bfd17cc2eeff61d0f99d35ff60d7cf967572ec146b166681334e5d"
DEFAULT_INSTALL_SHA256="eaa912af47dc6f29e4436ec200a1b431b8ddd8006ca08e57c8c73d3a05717818"
MAX_INSTALLER_BYTES=2097152
cleanup() {
+33
View File
@@ -2578,6 +2578,39 @@ class AuditRoundFour(unittest.TestCase):
self.assertIn(line, install.tui_outcome(state)[1])
class NarrowSystemNames(unittest.TestCase):
"""At 40 columns the size column took half the line: Game Boy, Game Boy
Advance and Game Boy Color all read "Nintendo Gam"."""
def test_the_name_comes_before_the_size(self):
state = checked_state()
names = {"nintendo-gb": "Nintendo Game Boy", "nintendo-gba": "Nintendo Game Boy Advance",
"nintendo-gbc": "Nintendo Game Boy Color",
"videoton-tvc": "Videoton TV Computer"}
state.manifest = {**state.manifest, "system_titles": names}
state.systems = [
{"event": "system", "platform": "retroarch", "system": system, "name": system,
"files": 30, "present": 0, "missing": 30, "wrong_hash": 0,
"bytes_needed": 30 * 1024 * 1024}
for system in names]
state.files = [{"event": "file", "platform": "retroarch", "dest": f"s{n}.bin",
"systems": list(names), "size": 1024, "state": "missing"}
for n in range(27)]
state.ticked = set(names)
state.stack.append("systems")
for cols, rows in ((40, 15), (40, 12), (52, 15)):
with self.subTest(size=f"{cols}x{rows}"):
text = "\n".join(install.tui_view(state, cols, rows))
for name in names.values():
self.assertIn(name, text)
self.assertNotIn("...", text)
for line in text.splitlines():
self.assertLessEqual(install.cell_width(line), cols)
# Wide, the full form stays.
self.assertIn("3 files, 30.0 MB + 27 shared",
"\n".join(install.tui_view(state, 120, 40)))
class Crash(unittest.TestCase):
"""An unexpected error ends on one sentence and a log, never a traceback."""