A ladder is a hue walk, not a brightness walk, so painting the hot end backwards put the dim colour at the corner. Sort the ramp by stock brightness and follow the pane height for the bottom-left glow.
120 lines
3.6 KiB
Python
120 lines
3.6 KiB
Python
"""The colour palettes everything in the UI draws from.
|
|
|
|
Every colour in Beefy Player is a stock ANSI palette *name*, never RGB, so the
|
|
TUI adopts whatever colours the terminal is configured with. A palette here is
|
|
therefore a short ladder of those names — the "gradient" is a quantised walk
|
|
from the quiet end to the hot end, not an interpolation.
|
|
|
|
The active palette drives the spectrum analyser, the album-art mosaic, the
|
|
provider wordmarks and the pane corners; `c` cycles through them and the
|
|
choice is remembered in the config file.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
#: Dark → hot ladders of ANSI names. Sixteen of them: seven hue gradients, a
|
|
#: few near-monochromes, and the original spectrum.
|
|
PALETTES: dict[str, tuple[str, ...]] = {
|
|
"spectrum": (
|
|
"cyan",
|
|
"blue",
|
|
"magenta",
|
|
"bright_magenta",
|
|
"yellow",
|
|
"bright_yellow",
|
|
"red",
|
|
),
|
|
"rainbow": (
|
|
"red",
|
|
"bright_yellow",
|
|
"bright_green",
|
|
"bright_cyan",
|
|
"bright_blue",
|
|
"bright_magenta",
|
|
),
|
|
"ocean": (
|
|
"bright_black",
|
|
"blue",
|
|
"bright_blue",
|
|
"cyan",
|
|
"bright_cyan",
|
|
"bright_white",
|
|
),
|
|
"ember": (
|
|
"bright_black",
|
|
"red",
|
|
"bright_red",
|
|
"yellow",
|
|
"bright_yellow",
|
|
"bright_white",
|
|
),
|
|
"mint": (
|
|
"bright_black",
|
|
"green",
|
|
"bright_green",
|
|
"cyan",
|
|
"bright_cyan",
|
|
"bright_white",
|
|
),
|
|
"sunset": ("magenta", "bright_magenta", "red", "bright_red", "yellow"),
|
|
"violet": ("blue", "bright_blue", "magenta", "bright_magenta", "bright_white"),
|
|
"acid": ("bright_black", "green", "bright_green", "yellow", "bright_yellow"),
|
|
"neon": (
|
|
"bright_magenta",
|
|
"bright_red",
|
|
"bright_yellow",
|
|
"bright_green",
|
|
"bright_cyan",
|
|
),
|
|
"sand": ("bright_black", "yellow", "bright_yellow", "white", "bright_white"),
|
|
"blood": ("bright_black", "red", "bright_red", "bright_magenta"),
|
|
"forest": ("bright_black", "green", "bright_green", "yellow", "bright_white"),
|
|
"ice": ("bright_white", "bright_cyan", "cyan", "bright_blue", "blue"),
|
|
"steel": ("bright_black", "white", "bright_white", "bright_cyan"),
|
|
"candy": ("magenta", "bright_magenta", "bright_cyan", "bright_yellow"),
|
|
"mono": ("bright_black", "white", "bright_white"),
|
|
}
|
|
|
|
#: The stock names from dark to bright. These are xterm's default values in
|
|
#: Rec. 601 luma order — the closest thing to a stock answer. A theme may
|
|
#: disagree about the exact numbers, but the ordering is what the frame fades
|
|
#: need: a ladder is a *hue* walk, so where it ends says nothing about which
|
|
#: end is brighter.
|
|
BRIGHTNESS: tuple[str, ...] = (
|
|
"black",
|
|
"blue",
|
|
"red",
|
|
"bright_red",
|
|
"magenta",
|
|
"bright_magenta",
|
|
"bright_blue",
|
|
"green",
|
|
"bright_black",
|
|
"cyan",
|
|
"bright_green",
|
|
"bright_cyan",
|
|
"yellow",
|
|
"white",
|
|
"bright_yellow",
|
|
"bright_white",
|
|
)
|
|
|
|
_RANK = {name: rank for rank, name in enumerate(BRIGHTNESS)}
|
|
|
|
#: Cycle order for the palette key.
|
|
PALETTE_ORDER: tuple[str, ...] = tuple(PALETTES)
|
|
|
|
#: What you get until you press `c`.
|
|
DEFAULT_PALETTE = "spectrum"
|
|
|
|
|
|
def palette_stops(name: str | None) -> tuple[str, ...]:
|
|
"""The ladder for ``name``, falling back to the default palette."""
|
|
key = (name or "").strip().lower()
|
|
return PALETTES.get(key, PALETTES[DEFAULT_PALETTE])
|
|
|
|
|
|
def brightness(colour: str) -> int:
|
|
"""How bright a stock name is: 0 (black) to 15 (bright white)."""
|
|
return _RANK.get(colour.strip().lower(), 0)
|