Let the map brightness reach the map, and put the options in groups
The map brightness setting could not make the map visible on a vector theme, which is the one place it was needed. Those themes want the ground well out of the way -- a tinted photograph of a county behind the vectors is the one thing that stops a vector display looking like one -- and that was done by multiplying the setting by about a quarter. A multiplier is a ceiling: turned the whole way up, the setting still gave a map at a tenth the brightness the default theme gives, which is to say invisible, and no amount of turning it up did anything about that. It is a curve now rather than a ceiling. The theme raises the setting to a power, so the middle of the range is still quiet -- seventy per cent lands where the old quarter did, which is the look these themes are for -- and the top of the range is a full-brightness map on every theme there is. On the green phosphor the setting now spans a luminance of six to seventy where it used to stop at twenty-one. And the options are in six groups rather than one list: receiver, listening, aircraft, animation, the map, labels. Thirty-three of them on one screen is a wall rather than a menu. A number opens a group and a number inside it changes an option, with the numbers still being each option's place in the whole list so that the same number means the same option wherever it is typed -- which meant reordering the list so that every group is contiguous, and there is a test that says so. A group menu makes a known option harder to reach than a flat list did, so the name works too: typing "map brightness" at the top goes straight to it, and part of a name lists everything it could mean. A name that matches exactly wins outright, so "speed" reaches the setting called speed rather than that one and every other whose description happens to mention the word. One thing to know: a bare number at the top of the menu now opens a group where it used to edit the option of that number. The tests that drove the menu that way would have gone on silently editing whatever option shared the number, so they ask by name now, and one of them checks that a group number changes nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016PsWPTweCT6pwxKngvVxcg
This commit is contained in:
parent
2da1d1f245
commit
6d2436cde1
10 changed files with 540 additions and 250 deletions
|
|
@ -722,9 +722,7 @@ def aircraft_menu(console: Console, cfg: ScanConfig) -> None:
|
|||
_rule(console, "aircraft (ADS-B)")
|
||||
console.print(Panel(Text.from_markup(_AIRCRAFT_INTRO),
|
||||
border_style="blue", padding=(0, 1)))
|
||||
_options_table(console, options, "Listening")
|
||||
console.print()
|
||||
_options_table(console, options, "Drawing")
|
||||
_option_groups(console, options)
|
||||
logs = air.logs_in(cfg.output_dir)
|
||||
kept = "no logs yet" if not logs else \
|
||||
f"{len(logs)} log{'s' if len(logs) != 1 else ''}"
|
||||
|
|
@ -738,8 +736,8 @@ def aircraft_menu(console: Console, cfg: ScanConfig) -> None:
|
|||
f"[/grey62]\n"
|
||||
f" [cyan]m[/cyan] Draw a map from a log [grey62]{kept} in "
|
||||
f"{cfg.output_dir}[/grey62]\n"
|
||||
f" [cyan]N[/cyan] change option N "
|
||||
f"[grey62]and [cyan]?N[/cyan] says what option N does[/grey62]\n"
|
||||
f" [cyan]N[/cyan] open group N "
|
||||
f"[grey62]or type part of an option's name to find it[/grey62]\n"
|
||||
f" [cyan]s[/cyan] Save these as default "
|
||||
f"[grey62]kept in {air.options_path()}[/grey62]\n"
|
||||
f" [cyan]d[/cyan] Reset them\n"
|
||||
|
|
@ -765,11 +763,124 @@ def aircraft_menu(console: Console, cfg: ScanConfig) -> None:
|
|||
if _confirm(" reset every aircraft option"):
|
||||
options = air.AircraftOptions()
|
||||
console.print(" [green]reset[/green]")
|
||||
elif answer.isdigit() and 1 <= int(answer) <= len(air.OPTION_GROUPS):
|
||||
_option_group_menu(console, options,
|
||||
air.OPTION_GROUPS[int(answer) - 1])
|
||||
elif answer.lstrip("?").strip().isdigit():
|
||||
_edit_option(console, options, answer)
|
||||
elif answer:
|
||||
found = _find_options(answer)
|
||||
if not found:
|
||||
console.print(f" [yellow]nothing matches {answer!r} \u2014 "
|
||||
f"enter a group number, or p, r, m, s, d or b"
|
||||
f"[/yellow]")
|
||||
elif len(found) == 1:
|
||||
_edit_option(console, options,
|
||||
str(air.OPTIONS.index(found[0]) + 1))
|
||||
else:
|
||||
_option_list(console, options, found, f"matching {answer!r}")
|
||||
_pick_option(console, options)
|
||||
|
||||
|
||||
def _option_groups(console: Console, options) -> None:
|
||||
"""The groups, and how many of each has been changed from the default.
|
||||
|
||||
A list of six lines rather than a table of thirty-three: the options
|
||||
are all still there, and this is the way in to them.
|
||||
"""
|
||||
from . import aircraft as air
|
||||
|
||||
default = air.AircraftOptions()
|
||||
t = Table(box=None, header_style="bold", pad_edge=False,
|
||||
title="[bold]options[/bold]", title_justify="left")
|
||||
t.add_column("#", style="grey62", width=3, justify="right")
|
||||
t.add_column("group", width=20)
|
||||
t.add_column("", width=16, style="grey62")
|
||||
t.add_column("what is in it", style="grey62", overflow="fold")
|
||||
for i, group in enumerate(air.OPTION_GROUPS, 1):
|
||||
items = air.in_group(group)
|
||||
changed = sum(1 for o in items
|
||||
if getattr(options, o.key) != getattr(default, o.key))
|
||||
count = f"{len(items)} option{'s' if len(items) != 1 else ''}"
|
||||
if changed:
|
||||
count += f", {changed} changed"
|
||||
t.add_row(str(i), group.lower(),
|
||||
Text(count, style="bold cyan" if changed else "grey62"),
|
||||
", ".join(o.label.lower() for o in items))
|
||||
console.print(t)
|
||||
|
||||
|
||||
def _find_options(text: str) -> list:
|
||||
"""Every option this could mean, nearest match first.
|
||||
|
||||
An exact name wins outright. Typing "seconds" should reach the setting
|
||||
called seconds, not that one and every other whose description happens
|
||||
to mention the word -- so a name that matches exactly is the answer, and
|
||||
the wider search is only what happens when nothing does.
|
||||
"""
|
||||
from . import aircraft as air
|
||||
|
||||
wanted = text.strip().lower()
|
||||
if not wanted:
|
||||
return []
|
||||
exact = [o for o in air.OPTIONS
|
||||
if wanted in (o.key.lower(), o.label.lower())]
|
||||
if exact:
|
||||
return exact
|
||||
return [o for o in air.OPTIONS
|
||||
if wanted in o.key.lower() or wanted in o.label.lower()
|
||||
or wanted in o.help.lower()]
|
||||
|
||||
|
||||
def _option_list(console: Console, options, items, title: str) -> None:
|
||||
"""One table of whichever options were asked for."""
|
||||
from . import aircraft as air
|
||||
|
||||
default = air.AircraftOptions()
|
||||
t = Table(box=None, header_style="bold", pad_edge=False,
|
||||
title=f"[bold]{title}[/bold]", title_justify="left")
|
||||
t.add_column("#", style="grey62", width=3, justify="right")
|
||||
t.add_column("option", width=20)
|
||||
t.add_column("value", width=16)
|
||||
t.add_column("what it does", style="grey62", overflow="fold")
|
||||
for o in items:
|
||||
value = air.format_option(o, getattr(options, o.key))
|
||||
changed = getattr(options, o.key) != getattr(default, o.key)
|
||||
t.add_row(str(air.OPTIONS.index(o) + 1), o.label + (" *" if changed else ""),
|
||||
Text(value, style="bold cyan" if changed else "white"),
|
||||
o.help)
|
||||
console.print(t)
|
||||
|
||||
|
||||
def _pick_option(console: Console, options) -> None:
|
||||
"""Ask which of the options just listed to change, and change it."""
|
||||
console.print("[grey62]Enter an option number to change it, "
|
||||
"[cyan]?N[/cyan] for what it does, or blank to go back."
|
||||
"[/grey62]")
|
||||
answer = _ask(console, " option").strip().lower()
|
||||
if answer and answer.lstrip("?").strip().isdigit():
|
||||
_edit_option(console, options, answer)
|
||||
|
||||
|
||||
def _option_group_menu(console: Console, options, group: str) -> None:
|
||||
"""One group of options, on a screen of its own."""
|
||||
from . import aircraft as air
|
||||
|
||||
while True:
|
||||
_rule(console, group.lower())
|
||||
items = air.in_group(group)
|
||||
_option_list(console, options, items, group.lower())
|
||||
console.print("\n[grey62]Enter an option number to change it, "
|
||||
"[cyan]?N[/cyan] for what it does, or [cyan]b[/cyan] "
|
||||
"to go back.[/grey62]")
|
||||
answer = _ask(console, " option", "b").strip().lower()
|
||||
if not answer or answer in _BACK:
|
||||
return
|
||||
if answer.lstrip("?").strip().isdigit():
|
||||
_edit_option(console, options, answer)
|
||||
else:
|
||||
console.print(" [yellow]enter a number from the lists, or "
|
||||
"p, r, m, s, d or b[/yellow]")
|
||||
console.print(" [yellow]enter a number from the list, "
|
||||
"or b[/yellow]")
|
||||
|
||||
|
||||
def _edit_option(console: Console, options, answer: str) -> None:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue