Add theme customizer.
This commit is contained in:
@@ -123,9 +123,11 @@ Session.zig libghostty-vt Terminal + parser, fed by the PTY
|
||||
Pty.zig openpt/fork/exec, controlling terminal setup
|
||||
script.zig runs a command for `$(...)` in a layout's directory
|
||||
key.zig GDK keyval -> libghostty-vt key mapping
|
||||
theme.zig colors libghostty-vt has no opinion about, per scheme
|
||||
Settings.zig preferences: theme and startup tabs, JSON on disk
|
||||
palette.zig every colour by name, its default per scheme, and the CSS for it
|
||||
theme.zig the palette resolved for the terminal renderer, which reads numbers
|
||||
Settings.zig preferences: theme, palette overrides, startup tabs, JSON on disk
|
||||
SettingsDialog.zig the settings page, including the startup list editor
|
||||
PaletteEditor.zig the colour editor inside it: a swatch per palette entry
|
||||
TabSettingsDialog.zig one tab's own settings, and the emoji picker
|
||||
emoji.zig generated: every emoji the picker offers, and the search over them
|
||||
```
|
||||
@@ -392,6 +394,11 @@ in principle, but a terminal grid is small.
|
||||
- **Light and dark schemes**, following the desktop by default and pinnable
|
||||
from the settings page, applying to open tabs immediately — terminal palette
|
||||
included. See [Theme](#theme)
|
||||
- **Every colour in the palette editable**, per scheme, from **Settings →
|
||||
Appearance → Customise**: the surfaces, the text on them, the accents, the
|
||||
status colours, and the terminal's own background, cursor, selection and 16
|
||||
ANSI colours. Each change repaints as you make it. See
|
||||
[Customising the palette](#customising-the-palette)
|
||||
|
||||
### Shortcuts
|
||||
|
||||
@@ -669,6 +676,9 @@ light and a dark scheme. `Ctrl+,` or the gear at the foot of the sidebar opens
|
||||
**Settings**, whose Appearance section holds the choice: light, dark, or
|
||||
**system**, which is the default and follows the desktop.
|
||||
|
||||
Every colour it resolves to can be changed — see
|
||||
[Customising the palette](#customising-the-palette).
|
||||
|
||||
The preference lives in `~/.config/playpen/settings.json` (or
|
||||
`$XDG_CONFIG_HOME`), beside `layouts.json`, alongside the
|
||||
[startup tabs](#startup-tabs):
|
||||
@@ -677,6 +687,7 @@ The preference lives in `~/.config/playpen/settings.json` (or
|
||||
{
|
||||
"version": 1,
|
||||
"theme": "system",
|
||||
"colors": {},
|
||||
"startup": []
|
||||
}
|
||||
```
|
||||
@@ -691,15 +702,18 @@ Three separate colour systems have to agree for that to be true, which is what
|
||||
dialog chrome. It is told to force a scheme, or left on `default` to follow
|
||||
the desktop.
|
||||
- **`style.css`** colours everything the app draws itself. It is written
|
||||
entirely against named colours, with one palette file per scheme
|
||||
(`palette-dark.css`, `palette-light.css`); the matching palette is prepended
|
||||
and the pair loaded as a single `GtkCssProvider`. No rule in `style.css` may
|
||||
hardcode a colour — a literal hex is a rule that looks right in whichever
|
||||
scheme you happened to be testing in.
|
||||
entirely against named colours; `palette.zig` writes the `@define-color`
|
||||
block that defines them for the scheme in force, and the two are loaded as a
|
||||
single `GtkCssProvider`. No rule in `style.css` may hardcode a colour — a
|
||||
literal hex is a rule that looks right in whichever scheme you happened to be
|
||||
testing in, and one the colour editor cannot reach.
|
||||
- **`theme.zig`** holds what Cairo draws the terminal grid from: the default
|
||||
background, foreground and cursor, plus the 16 ANSI colours. The style tree
|
||||
is never consulted there, so a CSS reload alone would leave every terminal
|
||||
painted in the scheme it started in.
|
||||
painted in the scheme it started in. It resolves the same table `style.css`
|
||||
is fed from, and caches the result — the renderer asks for the background
|
||||
once a frame and for the palette once a cell, and neither should be going
|
||||
through the settings for an answer.
|
||||
|
||||
The ANSI palette is the part that is easy to skip and shouldn't be. The
|
||||
standard xterm yellow is `#cdcd00`, which on a white background is close to
|
||||
@@ -718,6 +732,59 @@ its `dark` property rather than the stored preference, and the preference only
|
||||
decides what the style manager is told. A desktop that switches at sunset takes
|
||||
this app with it, with no extra machinery and no second source of truth.
|
||||
|
||||
### Customising the palette
|
||||
|
||||
**Settings → Appearance → Customise** opens the palette itself: a swatch for
|
||||
every colour named above, in sections — surfaces, text, tab rows, accent,
|
||||
status, then the terminal's own background, foreground, cursor and selection,
|
||||
and the 16 ANSI colours as a strip. Beside each row is the hex it currently
|
||||
resolves to, so a palette can be read off as text rather than only picked at,
|
||||
and a button that puts that one colour back. Each section heading has the same
|
||||
button for the section, and the foot of the list has one for the whole scheme.
|
||||
|
||||
Three things about how it behaves, all following from the same decision — that
|
||||
the editor edits **the palette you can see**:
|
||||
|
||||
- **A change applies as you make it.** Every colour in the list paints something
|
||||
behind the dialog, so the swatch is its own preview; there is no OK button
|
||||
because there is nothing pending to confirm.
|
||||
- **It edits the scheme in force.** Which is why the way to edit the other one is
|
||||
the theme picker directly above: switch to light, and the section switches with
|
||||
it. Both palettes are kept, so an afternoon spent pinned to light doesn't cost
|
||||
you the dark palette you built.
|
||||
- **The terminal follows the window.** Left alone, the terminal's background *is*
|
||||
the pane surface, its foreground *is* the body text, and its selection *is* the
|
||||
muted accent — so recolouring the app recolours the terminal drawn inside it,
|
||||
and the frame around a terminal keeps matching its contents. Setting one of
|
||||
those explicitly breaks the link for that colour and only that colour.
|
||||
|
||||
Only what has been changed is stored, per scheme, under `colors` in
|
||||
`settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"theme": "dark",
|
||||
"colors": {
|
||||
"dark": { "accent": "#ff8800", "sidebar": "#3a0d0d" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
That is a deliberate choice over writing whole palettes out. It keeps the file
|
||||
short and hand-editable, it is what lets a row know whether it has been changed,
|
||||
and it means the shipped defaults can be retuned in a later version and still
|
||||
reach everyone who never touched them — rather than only the people who had
|
||||
never opened the editor. A name this build doesn't know, or a value that isn't
|
||||
`#rrggbb`, costs that one colour and is logged; the rest of the file is read
|
||||
normally.
|
||||
|
||||
`palette.zig` is where the names, the defaults and the grouping live, which is
|
||||
why there is no longer a `palette-dark.css`. An editor needs to know what the
|
||||
colours are called, what they started as, and which ones belong together, and
|
||||
none of that can be read back out of a stylesheet without parsing it — so the
|
||||
table answers all of it and the CSS is generated from the table.
|
||||
|
||||
## Not implemented
|
||||
|
||||
This is a proof of concept, and the following are deliberately absent:
|
||||
|
||||
Reference in New Issue
Block a user