@kecan0406/ttheme 1.0.36 → 1.0.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -616
- package/bin/ttheme.js +2 -2
- package/bin/ttheme.js.map +1 -1
- package/dist/manifest.json +1 -1
- package/package.json +1 -1
- package/shell/launch-tab.zsh +3 -1
- package/shell/ttheme.zsh +7 -4
package/README.md
CHANGED
|
@@ -1,646 +1,129 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Character terminal palettes —
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
<h1 align="center">ttheme</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center"><em>Character terminal palettes — readable by rule, switched live, one tab at a time.</em></p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://www.npmjs.com/package/@kecan0406/ttheme"><img src="https://img.shields.io/npm/v/@kecan0406/ttheme?style=flat-square" alt="npm version"></a>
|
|
7
|
+
<a href="https://github.com/kecan0406/ttheme/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/kecan0406/ttheme/ci.yml?branch=main&style=flat-square&label=ci" alt="CI status"></a>
|
|
8
|
+
<a href="https://kecan0406.github.io/ttheme/"><img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fkecan0406.github.io%2Fttheme%2Fmanifest.json&query=%24.palettes.length&label=palettes&style=flat-square&color=c796c8" alt="palettes in the catalog"></a>
|
|
9
|
+
<a href="LICENSE"><img src="https://img.shields.io/npm/l/@kecan0406/ttheme?style=flat-square" alt="MIT license"></a>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="https://kecan0406.github.io/ttheme/">Site</a> ·
|
|
14
|
+
<a href="#palettes">Palettes</a> ·
|
|
15
|
+
<a href="docs/usage.md">Usage</a> ·
|
|
16
|
+
<a href="docs/terminals.md">Terminals</a> ·
|
|
17
|
+
<a href="CONTRIBUTING.md">Contributing</a>
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
<p align="center">
|
|
21
|
+
<img src="docs/demo.gif" alt="ttheme preview: typing nichi filters to the Nichijou palettes, each one repaints the tab as the cursor lands on it, then rei is picked and applied" width="860">
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
## Why ttheme
|
|
25
|
+
|
|
26
|
+
- **Colors from the character.** Every palette keeps the three colors that
|
|
27
|
+
identify its character and borrows its ANSI ramp from an established scheme,
|
|
28
|
+
harmonized so the whole catalog reads alike.
|
|
15
29
|
- **Every palette passes an accessibility gate.** Body text at 7:1 against the
|
|
16
|
-
background (WCAG AAA), every meaningful ANSI color at 3:1
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
30
|
+
background (WCAG AAA), every meaningful ANSI color at 3:1, and each accent stays
|
|
31
|
+
in its role — red reads as an error, green as success. The build fails if a
|
|
32
|
+
palette regresses.
|
|
33
|
+
- **Switched live, per tab.** Tabs in one window can wear different palettes,
|
|
34
|
+
any tab can be repainted at any time, a directory can pin its own, and a new
|
|
35
|
+
tab can take the next character.
|
|
20
36
|
|
|
21
|
-
##
|
|
22
|
-
|
|
23
|
-
Nothing is emulated — a terminal that cannot express something simply does not
|
|
24
|
-
get it.
|
|
25
|
-
|
|
26
|
-
| Feature | Ghostty | iTerm2 | kitty | Alacritty | WezTerm | Windows Terminal | Warp | Terminal.app | Other |
|
|
27
|
-
|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|
|
28
|
-
| **Setup with `init`** | ![Done][done] | ![Done][done] | ![Done][done] | ![Done][done] | ![Done][done] | ![Done][done] | ![Done][done] | ![No][no] | ![No][no] |
|
|
29
|
-
| **Palette files** | ![Done][done] | ![Done][done] | ![Done][done] | ![Done][done] | ![Done][done] | ![Done][done] | ![Done][done] | ![No][no] | ![No][no] |
|
|
30
|
-
| **Runtime repaint** | ![Done][done] | ![Done][done] | ![Done][done] | ![Done][done] | ![Done][done] | ![Done][done] | ![No][no] | ![Done][done] | ![Partial][partial] |
|
|
31
|
-
| **Background pictures** | ![Done][done] | ![Done][done] | ![Done][done] | ![No][no] | ![Partial][partial] | ![No][no] | ![No][no] | ![No][no] | ![No][no] |
|
|
32
|
-
|
|
33
|
-
- **Setup with `init`** — iTerm2 is offered on macOS only, Windows Terminal
|
|
34
|
-
from WSL (or a native Windows zsh), where init writes a settings fragment on
|
|
35
|
-
the Windows side. Warp gets its themes, and the default palette through its
|
|
36
|
-
`settings.toml` (the Warp builds that have one).
|
|
37
|
-
- **Palette files** — iTerm2 gets one dynamic profile per palette, plus
|
|
38
|
-
`.itermcolors` in the archive; Windows Terminal gets one fragment carrying
|
|
39
|
-
every installed scheme.
|
|
40
|
-
- **Runtime repaint** — OSC escape sequences everywhere, per pane in kitty,
|
|
41
|
-
WezTerm and Windows Terminal, one color per sequence (Alacritty drops an OSC 4
|
|
42
|
-
carrying more than seven). kitty and Windows Terminal reset every OSC color
|
|
43
|
-
when their config reloads, so a changed default would undo the palettes open
|
|
44
|
-
tabs wear: kitty's watcher puts each window's palette back as the reload ends,
|
|
45
|
-
and a Windows Terminal tab repaints itself at its next prompt or focus.
|
|
46
|
-
Terminal.app takes every OSC color but no OSC reset, so ttheme reads its
|
|
47
|
-
colors when the shell starts and puts them back itself. Warp answers OSC
|
|
48
|
-
color queries but paints one theme app-wide and never the background an OSC
|
|
49
|
-
sets, so the shell layer stays off there and `ttheme use <palette>` points you at
|
|
50
|
-
`ttheme default <palette>`, which puts the palette on every Warp window; any other terminal that speaks OSC 4/10/11 (foot, Konsole,
|
|
51
|
-
VTE-based terminals…) gets repainting and nothing else.
|
|
52
|
-
- **Colors only** — ttheme sets no font, font size or shader anywhere; those
|
|
53
|
-
stay what you configured in your terminal.
|
|
54
|
-
- **Background pictures** — `find`, `ttheme image` and `preview`'s live
|
|
55
|
-
backdrop. Ghostty shows one picture app-wide, following the focused tab;
|
|
56
|
-
iTerm2 (3.7 or newer) shows one per tab and kitty one per window (a split
|
|
57
|
-
pane included), both with the same preview, tuning and find. WezTerm shows the
|
|
58
|
-
picture of the active tab per window and switches it as `preview` moves, but
|
|
59
|
-
has no in-terminal preview or tuning — find and tune from Ghostty, iTerm2 or
|
|
60
|
-
kitty. Alacritty has no graphics at all. Cut-outs and baked crops need macOS.
|
|
61
|
-
|
|
62
|
-
[done]: https://img.shields.io/badge/Done-2ea44f?style=flat-square
|
|
63
|
-
[partial]: https://img.shields.io/badge/Partial-e3b341?style=flat-square
|
|
64
|
-
[no]: https://img.shields.io/badge/Not%20supported-d0d7de?style=flat-square
|
|
65
|
-
|
|
66
|
-
## Palettes
|
|
67
|
-
|
|
68
|
-
| Group | Palettes |
|
|
69
|
-
|---|---|
|
|
70
|
-
| Vocaloid | `miku` `kumori` `rin` `len` `luka` `kaito` `meiko` |
|
|
71
|
-
| Evangelion — エヴァンゲリオン | `asuka` `rei` `kaworu` `misato` `eva01` `magi` |
|
|
72
|
-
| Madoka Magica — 魔法少女まどか☆マギカ | `madoka` `homura` `sayaka` `kyoko` `mami` `nagisa` `kyubey` |
|
|
73
|
-
| Steins;Gate — シュタインズ・ゲート | `kurisu` `mayuri` `suzuha` |
|
|
74
|
-
| Lucky☆Star — らき☆すた | `konata` `kagami` `tsukasa` `miyuki` |
|
|
75
|
-
| Bocchi the Rock! — ぼっち・ざ・ろっく! | `bocchi` `nijika` `ryo` `kita` |
|
|
76
|
-
| Monogatari — 〈物語〉シリーズ | `hitagi` `shinobu` `tsubasa` `nadeko` |
|
|
77
|
-
| Sailor Moon — 美少女戦士セーラームーン | `moon` `mercury` `mars` `jupiter` `venus` |
|
|
78
|
-
| Lain — serial experiments lain | `lain` |
|
|
79
|
-
| VA-11 Hall-A — Cyberpunk Bartender Action | `jill` `dorothy` `alma` `stella` `sei` `valhalla` |
|
|
80
|
-
| Persona 5 — ペルソナ5 | `joker` `skull` `panther` `fox` `queen` `oracle` `velvet` |
|
|
81
|
-
| Undertale | `toriel` `sans` `papyrus` `undyne` `mettaton` `determination` |
|
|
82
|
-
| Call of the Night — よふかしのうた | `nazuna` `kou` `seri` `anko` `yofukashi` |
|
|
83
|
-
| Higurashi — ひぐらしのなく頃に | `rena` `mion` `rika` `satoko` `hinamizawa` |
|
|
84
|
-
| Doki Doki Literature Club | `sayori` `natsuki` `yuri` `monika` `glitch` |
|
|
85
|
-
| Umineko — うみねこのなく頃に | `battler` `beatrice` `bernkastel` `lambdadelta` `rokkenjima` |
|
|
86
|
-
| K-On! — けいおん! | `yui` `ritsu` `mio` `mugi` `azusa` |
|
|
87
|
-
| Cyberpunk: Edgerunners — サイバーパンク エッジランナーズ | `david` `lucy` `rebecca` `nightcity` |
|
|
88
|
-
| Touhou Project — 東方Project | `reimu` `marisa` `cirno` `youmu` `patchouli` `flandre` |
|
|
89
|
-
| Chuunibyou — 中二病でも恋がしたい! | `rikka` `yuuta` `shinka` `dekomori` `kumin` |
|
|
90
|
-
| Jujutsu Kaisen — 呪術廻戦 | `gojo` `yuji` `megumi` `nobara` `nanami` `geto` `sukuna` |
|
|
91
|
-
| — | `neutral` (default) |
|
|
92
|
-
|
|
93
|
-
`neutral` sits out of the rotation and the listings — it is the pre-shell
|
|
94
|
-
default, still applyable as `ttheme neutral`.
|
|
95
|
-
|
|
96
|
-
Backgrounds and cursors are hand-tuned; the 16 ANSI colors are borrowed from
|
|
97
|
-
established themes (Nvim Dark, Nightfox, Oxocarbon, Selenized, Monokai Pro,
|
|
98
|
-
Duotone, Gruvbox, Rose Pine, TokyoNight, Everforest, IR Black…) or from
|
|
99
|
-
published character themes, picked to match each character's
|
|
100
|
-
tones while passing the contrast gate. Each palette records where its ANSI set
|
|
101
|
-
came from — `ttheme` prints it, and it is in the theme's TOML.
|
|
102
|
-
|
|
103
|
-
## Install
|
|
104
|
-
|
|
105
|
-
**Ghostty, kitty, Alacritty, WezTerm, iTerm2, Windows Terminal or Warp** — one command, no clone:
|
|
37
|
+
## Quick start
|
|
106
38
|
|
|
107
39
|
```sh
|
|
108
40
|
npx @kecan0406/ttheme@latest init
|
|
109
41
|
```
|
|
110
42
|
|
|
111
|
-
It asks which terminals to wire and which series to install
|
|
112
|
-
|
|
113
|
-
should wear them: `default` (preselected) puts one palette on every tab,
|
|
114
|
-
`rotate` gives every new tab the next palette, `keep` leaves your terminal colors
|
|
115
|
-
alone and only installs. Then it shows what it is about to change and writes it all at once,
|
|
116
|
-
so cancelling before that touches nothing. It places the zsh layer under
|
|
117
|
-
`~/.config/ttheme` and edits your terminal config and `~/.zshrc` between
|
|
118
|
-
`# ttheme begin` / `# ttheme end` markers — everything outside the markers is
|
|
119
|
-
left alone, and what goes in is colors only. Before its first edit of a file it
|
|
120
|
-
keeps a copy beside it, `<file>.ttheme.bak`, and it writes through symlinks, so a
|
|
121
|
-
dotfiles repo keeps its links. A key you set yourself stays yours: a Ghostty
|
|
122
|
-
`command` or `shell-integration`, kitty's `window_logo_scale` and
|
|
123
|
-
`window_logo_alpha`. Every file it adds to a terminal's own folders is named
|
|
124
|
-
`ttheme-<palette>`, so a theme of yours is never overwritten. Alacritty lets its
|
|
125
|
-
own config win over an import, so colors set in `alacritty.toml` hide the
|
|
126
|
-
default palette — init says so when it finds them. iTerm2 has no config file to edit, so it gets one profile per
|
|
127
|
-
installed palette instead — `ttheme · miku` and so on, in
|
|
128
|
-
`~/Library/Application Support/iTerm2/DynamicProfiles/ttheme.json`, which
|
|
129
|
-
iTerm2 reloads by itself whenever `ttheme browse` adds or drops one. One more,
|
|
130
|
-
`ttheme · default`, always wears your default palette (none under `keep`), and
|
|
131
|
-
init makes it iTerm2's default profile, so new tabs and windows open wearing the
|
|
132
|
-
palette and its picture from their first frame and follow `ttheme default` from
|
|
133
|
-
then on. iTerm2 reads its default profile only when it starts, so quit and
|
|
134
|
-
reopen it once after init. The profile it replaces stays the parent of every
|
|
135
|
-
ttheme profile, so your font and keys carry over, and `keep` gives it back.
|
|
136
|
-
WezTerm's config is Lua, so init puts a two-line block that runs
|
|
137
|
-
`~/.config/ttheme/wezterm.lua` just before your config's `return config` (or
|
|
138
|
-
writes a small `wezterm.lua` when there is none); WezTerm reloads it by itself.
|
|
139
|
-
Windows Terminal gets a fragment,
|
|
140
|
-
`%LOCALAPPDATA%\Microsoft\Windows Terminal\Fragments\ttheme\ttheme.json`,
|
|
141
|
-
with every installed scheme and the default palette on the profile init ran in —
|
|
142
|
-
`settings.json` is never edited, only touched so the terminal reloads. Warp gets
|
|
143
|
-
a theme per palette, `~/.warp/themes/ttheme-<palette>.yaml`, and the default
|
|
144
|
-
palette as the one `theme` key of `[appearance.themes]` in `~/.warp/settings.toml`
|
|
145
|
-
— Warp applies it within a few seconds, and `keep` puts back the theme you had.
|
|
146
|
-
It ends with a receipt, paints the first palette onto the tab you
|
|
147
|
-
ran it in (not under `keep`) and lists what to do next (`exec zsh` for the
|
|
148
|
-
`ttheme` command here, a terminal restart for new tabs).
|
|
149
|
-
Running it again updates in place; `--yes` (`-y`) skips every prompt and installs no
|
|
150
|
-
palettes, and init refuses to run without a terminal unless it is given —
|
|
151
|
-
`ttheme browse` opens the full catalog any time, to add or drop single palettes.
|
|
43
|
+
It asks which terminals to wire and which series to install, shows every file it
|
|
44
|
+
is about to change, and writes nothing until you confirm. Then:
|
|
152
45
|
|
|
153
46
|
```sh
|
|
154
|
-
|
|
47
|
+
exec zsh # the ttheme command in this tab
|
|
48
|
+
ttheme preview # browse live — the tab repaints as the cursor moves
|
|
155
49
|
```
|
|
156
50
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
and the `ttheme-*` theme files, `~/.config/ttheme` (installed pictures
|
|
160
|
-
included), the cache and the iTerm2 and Windows Terminal files are deleted. A
|
|
161
|
-
config you did not touch since ttheme first edited it comes back byte for byte
|
|
162
|
-
and its backup goes; one you edited since keeps `<file>.ttheme.bak`. Open shells
|
|
163
|
-
drop the layer at their next prompt.
|
|
51
|
+
<details>
|
|
52
|
+
<summary><b>What init changes</b></summary>
|
|
164
53
|
|
|
165
|
-
|
|
166
|
-
|
|
54
|
+
- Your terminal config and `~/.zshrc` get a block between `# ttheme begin` /
|
|
55
|
+
`# ttheme end`; everything outside it is left alone, and what goes in is
|
|
56
|
+
colors only — no font, font size or shader.
|
|
57
|
+
- Each file is backed up once to `<file>.ttheme.bak` before the first edit, and
|
|
58
|
+
written through symlinks, so a dotfiles repo keeps its links.
|
|
59
|
+
- A key you set yourself stays yours, and every file ttheme adds to a terminal's
|
|
60
|
+
folders is named `ttheme-<palette>`.
|
|
61
|
+
- `npx @kecan0406/ttheme@latest uninstall` lists and then reverses all of it.
|
|
167
62
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
# kitty
|
|
172
|
-
curl -L $REL/ttheme-kitty.tar.gz | tar xz
|
|
173
|
-
cp kitty/themes/ttheme-miku.conf ~/.config/kitty/themes/
|
|
174
|
-
# kitty.conf: include themes/ttheme-miku.conf
|
|
175
|
-
|
|
176
|
-
# alacritty
|
|
177
|
-
curl -L $REL/ttheme-alacritty.tar.gz | tar xz
|
|
178
|
-
cp alacritty/themes/ttheme-miku.toml ~/.config/alacritty/themes/
|
|
179
|
-
# alacritty.toml: [general]
|
|
180
|
-
# import = ["~/.config/alacritty/themes/ttheme-miku.toml"]
|
|
181
|
-
|
|
182
|
-
# wezterm
|
|
183
|
-
curl -L $REL/ttheme-wezterm.tar.gz | tar xz
|
|
184
|
-
cp wezterm/colors/ttheme-miku.toml ~/.config/wezterm/colors/
|
|
185
|
-
# wezterm.lua: config.color_scheme = "ttheme-miku"
|
|
186
|
-
|
|
187
|
-
# iTerm2 — open a .itermcolors to add it to Settings > Profiles > Colors presets
|
|
188
|
-
curl -L $REL/ttheme-iterm2.tar.gz | tar xz
|
|
189
|
-
|
|
190
|
-
# windows terminal — every scheme in one fragment
|
|
191
|
-
curl -L $REL/ttheme-windows-terminal.tar.gz | tar xz
|
|
192
|
-
# copy windows-terminal/ttheme.json into
|
|
193
|
-
# %LOCALAPPDATA%\Microsoft\Windows Terminal\Fragments\ttheme\
|
|
194
|
-
|
|
195
|
-
# warp
|
|
196
|
-
curl -L $REL/ttheme-warp.tar.gz | tar xz
|
|
197
|
-
cp warp/themes/ttheme-miku.yaml ~/.warp/themes/
|
|
198
|
-
```
|
|
63
|
+
Per-terminal details, manual install from the release archives and building from
|
|
64
|
+
a checkout are in [docs/install.md](docs/install.md).
|
|
199
65
|
|
|
200
|
-
|
|
201
|
-
palette.
|
|
66
|
+
</details>
|
|
202
67
|
|
|
203
|
-
|
|
204
|
-
build` writes the same tree to `dist/`, `mise run sandbox` tries it in a
|
|
205
|
-
throwaway home, and `mise run bin:build && node bin/ttheme.js init` installs
|
|
206
|
-
it for real.
|
|
207
|
-
|
|
208
|
-
## Use
|
|
68
|
+
## Palettes
|
|
209
69
|
|
|
210
|
-
|
|
211
|
-
ttheme
|
|
212
|
-
|
|
213
|
-
ttheme preview browse live — focus repaints the tab, enter keeps it (this tab or default)
|
|
214
|
-
ttheme next advance this tab to the next palette
|
|
215
|
-
ttheme default make a palette the one new tabs open with
|
|
216
|
-
ttheme on wear the default palette in new tabs again
|
|
217
|
-
ttheme off take the palette and picture off every tab — the terminal's own colors until ttheme on
|
|
218
|
-
ttheme pin pick a palette for this directory — cd into it repaints, cd out restores
|
|
219
|
-
ttheme unpin drop the palette pinned to this directory
|
|
220
|
-
ttheme config edit settings in $EDITOR — they apply in new tabs
|
|
221
|
-
ttheme help the list above, in your terminal
|
|
222
|
-
|
|
223
|
-
ttheme browse pick palettes from the catalog in a live picker
|
|
224
|
-
ttheme list the catalog, ● installed and ○ not (a query filters it, --json prints it as JSON)
|
|
225
|
-
ttheme add install palettes from the catalog
|
|
226
|
-
ttheme remove uninstall palettes
|
|
227
|
-
ttheme update refresh the catalog from the registry
|
|
228
|
-
```
|
|
70
|
+
<p align="center">
|
|
71
|
+
<a href="https://kecan0406.github.io/ttheme/"><img src="https://kecan0406.github.io/ttheme/readme/series.svg" alt="One card per series, drawn in its lead palette" width="856"></a>
|
|
72
|
+
</p>
|
|
229
73
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
keeps the order they were added), groups start folded with the cursor on the
|
|
236
|
-
current palette;
|
|
237
|
-
`↑`/`↓` move (the tab repaints as the focus lands on a palette), `←`/`→` fold
|
|
238
|
-
and unfold (so do enter and space on a series), page up/down and home/end
|
|
239
|
-
jump, typing filters by substring and underlines the match (ctrl-u clears it),
|
|
240
|
-
enter applies, and esc steps back — first out of the filter, then out of the
|
|
241
|
-
preview with the original colors restored. Each palette row carries its 16
|
|
242
|
-
colors, normal over bright. The last line lists only the keys that work right
|
|
243
|
-
there, names the mode when it is not plain browsing (`FILTER`, `TUNE`, `CONFIG`,
|
|
244
|
-
`APPLY`, `KEYS`) and pins where esc goes to the right; `?` shows all of them.
|
|
245
|
-
alt-c opens the settings below in place — `↑`/`↓` pick one, `←`/`→` change it
|
|
246
|
-
(the sort and the search hint animation change live), enter writes the changed
|
|
247
|
-
lines to `config.zsh`, esc puts every value back. From 76
|
|
248
|
-
columns on, a sample session sits against the right edge of the window — the
|
|
249
|
-
16 colors, a prompt, git and test output, a selection — in the palette under
|
|
250
|
-
the cursor. The list and the sample widen with the window (the sample up to 64
|
|
251
|
-
columns) and the gap between them takes the rest; the tuning panel takes the
|
|
252
|
-
sample's place while open, and so does the key list once the sample is 48
|
|
253
|
-
columns wide.
|
|
254
|
-
Under Ghostty or iTerm2 with `TTHEME_TAB_PALETTE=off` (the default), enter asks **this tab** or
|
|
255
|
-
**default**: default records the palette as your default palette (so a later
|
|
256
|
-
`add` or `remove` keeps it), rewrites `theme =` in the `# ttheme begin` block of
|
|
257
|
-
your Ghostty config and sends `SIGUSR2` to the Ghostty that owns the tab, and
|
|
258
|
-
rewrites iTerm2's `ttheme · default` profile, which iTerm2 reloads by itself — so new tabs, and open tabs you have not
|
|
259
|
-
painted by hand, take the palette without a restart. Painting is per surface
|
|
260
|
-
otherwise: a new tab starts from the configured theme, not from what the last
|
|
261
|
-
tab was painted.
|
|
262
|
-
|
|
263
|
-
A palette can also bring a Ghostty background image. The block `init` writes
|
|
264
|
-
includes `~/.config/ttheme/backgrounds/shown.conf` with an optional
|
|
265
|
-
`config-file = ?…`, and that one line names the palette whose picture is up.
|
|
266
|
-
Putting a palette on — `ttheme use <name>`, enter in `preview`, `ttheme next`,
|
|
267
|
-
`ttheme default`, cd into a pinned directory — rewrites the line and sends
|
|
268
|
-
`SIGUSR2`, so whatever Ghostty settings you put in `<palette>.conf` arrive with
|
|
269
|
-
the palette, and palettes without a file show no image:
|
|
74
|
+
<details>
|
|
75
|
+
<summary><b>Every palette</b></summary>
|
|
76
|
+
<br>
|
|
77
|
+
<img src="https://kecan0406.github.io/ttheme/readme/palettes.svg" alt="Every palette in the catalog, grouped by series" width="856">
|
|
78
|
+
</details>
|
|
270
79
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
background-image-opacity = 0.2
|
|
276
|
-
```
|
|
80
|
+
Both images are drawn from the live catalog, so they always match what
|
|
81
|
+
`ttheme browse` offers. `init` installs the series you pick; `ttheme browse`
|
|
82
|
+
adds or drops single palettes any time, and a merged palette reaches everyone
|
|
83
|
+
through `ttheme update` without waiting for a release.
|
|
277
84
|
|
|
278
|
-
|
|
279
|
-
config, not an escape sequence, and Ghostty keeps one background for the whole
|
|
280
|
-
app, so one picture is up at a time, in every window. Moving to another tab
|
|
281
|
-
brings its own: while a tab sits at its prompt it asks for focus events, and
|
|
282
|
-
taking focus puts that tab's picture up — or clears it, when its palette has
|
|
283
|
-
none. A tab busy with a command catches up at its next prompt, focus reporting
|
|
284
|
-
is off while that command runs, and a tab whose colors are not a ttheme palette
|
|
285
|
-
leaves the picture where it is.
|
|
286
|
-
|
|
287
|
-
iTerm2 keeps a picture per tab. There the picture lives in the palette's own
|
|
288
|
-
profile — `ttheme · kagami` carries the file, its opacity as Blend and cover or
|
|
289
|
-
contain as the image mode, rewritten whenever the picture or its tuning
|
|
290
|
-
changes — and putting a palette with a picture on, or taking one off, moves the
|
|
291
|
-
tab to that palette's profile with `OSC 1337 SetProfile`. The first time,
|
|
292
|
-
iTerm2 asks at the top of the tab whether a control sequence may change the
|
|
293
|
-
profile: Always Allow lets every later switch through — put the palette on once
|
|
294
|
-
more for the one that asked — and a tab it refuses still wears the palette's
|
|
295
|
-
colors, only without the picture. iTerm2 has no
|
|
296
|
-
position setting, so a tuned picture that is not centered is baked onto a canvas
|
|
297
|
-
the size of the window, as the sizes above 100% are.
|
|
298
|
-
|
|
299
|
-
A palette with no background yet can find one: on it in `preview`, tab opens
|
|
300
|
-
**find**, which searches a booru for the palette's character tag
|
|
301
|
-
(`meta.booru`) and lays the results out as a grid of thumbnails. It starts on
|
|
302
|
-
danbooru; tab moves to konachan, then yande.re, then back — they share one tag
|
|
303
|
-
vocabulary, so the same tag works on each. danbooru and yande.re carry every
|
|
304
|
-
rating and `TTHEME_FIND_RATING` picks which come through; konachan is
|
|
305
|
-
`konachan.net`, the mirror that carries safe posts only, since `konachan.com`
|
|
306
|
-
answers with a Cloudflare challenge. When a site's connection is cut off — the
|
|
307
|
-
way a network that blocks boorus by name drops danbooru — find asks whether to
|
|
308
|
-
turn on the unblock proxy (`TTHEME_FIND_UNBLOCK`); `y` saves the setting and
|
|
309
|
-
opens find again through it, `n` leaves it off. The
|
|
310
|
-
sites sit in a strip of tabs under the query, the one you are on lit in its own
|
|
311
|
-
color, and it comes again as a badge at the start of the line above a picture
|
|
312
|
-
you try on, next to the site the artwork itself came from when the post records
|
|
313
|
-
one (`pixiv.net`, `deviantart.com`). The grid starts
|
|
314
|
-
with every post of the character; `c` narrows it to **cutouts** — posts carrying
|
|
315
|
-
the site's transparency tags (`transparent_background` on danbooru,
|
|
316
|
-
`transparent` or `vector` on konachan, `transparent_png` on yande.re) whose PNG header says they have
|
|
317
|
-
an alpha channel; yande.re's `transparent_png` already means exactly that, so
|
|
318
|
-
its posts skip the header check, which its slow file server would drag out —
|
|
319
|
-
and the counter reads shown out of checked, `13/33`. find checks only as far as
|
|
320
|
-
the grid reaches and checks more as you scroll; each answer is remembered, so
|
|
321
|
-
coming back to a site or a palette never asks its file server again, and a site
|
|
322
|
-
you have already seen comes back the moment you tab to it. Newer series carry
|
|
323
|
-
few of those tags, so `TTHEME_FIND_CUTOUTS` names the ones to look for, site by
|
|
324
|
-
site.
|
|
325
|
-
|
|
326
|
-
Under each thumbnail is its post id and size, and under that whoever made it:
|
|
327
|
-
the artist, which every site names through its tag types at no extra
|
|
328
|
-
request, and the uploader as `@name` where a post has no artist tag. A score follows as
|
|
329
|
-
`★22` on the sites that keep one. When the same hand uploads the same picture at
|
|
330
|
-
the same size over and over, find folds that run into one tile marked `×9`,
|
|
331
|
-
wherever the order puts its pictures, and folds in the same way a picture
|
|
332
|
-
another site holds too — re-encoded at the same shape, cut from the post its
|
|
333
|
-
source names, or hung under the same parent; space unfolds it and folds it
|
|
334
|
-
again. Pictures by the uploader of the backgrounds
|
|
335
|
-
you already have in the same series come first and carry `≈`, so a series keeps
|
|
336
|
-
one hand; anything under 1600 px on its long edge shows its size in yellow.
|
|
337
|
-
|
|
338
|
-
`s` opens the settings — the ratings to list, the nudity and underwear tags to
|
|
339
|
-
block, cutouts or all, newest or score, and whether runs fold — with ↑↓ on the
|
|
340
|
-
setting, enter to save them to `config.zsh` and esc to put them back. ←→ change
|
|
341
|
-
a value; on the two rows of checkboxes (rating and block) they move between the
|
|
342
|
-
boxes and space ticks one, so `safe` and `explicit` can be listed without
|
|
343
|
-
`questionable`, or underwear let through while nudity stays blocked. At least
|
|
344
|
-
one rating stays ticked. Whatever is not the default shows next to the query, so
|
|
345
|
-
the screen never hides what it is filtering by.
|
|
346
|
-
|
|
347
|
-
`/` opens the query for editing — type a tag to search for something else, or paste a post url or id
|
|
348
|
-
(`https://yande.re/post/show/214705`, `konachan:244200`, `7159377`) to go
|
|
349
|
-
straight to that one picture. While you type, danbooru's tag completion lists
|
|
350
|
-
up to eight tags that start like the last word, each with its post count — the
|
|
351
|
-
way to find a costume variant such as `amane_suzuha_(beta)` or a tag you only
|
|
352
|
-
half remember; `↑`/`↓` pick one and enter searches it. A palette with no `meta.booru` tag at all opens
|
|
353
|
-
find on that empty query, so it can have a background too. `o` opens the post's
|
|
354
|
-
page in a browser.
|
|
355
|
-
|
|
356
|
-
A picture of your own goes in the same way. Drop an image file on the window
|
|
357
|
-
while find is open, or paste it — a file copied in Finder, its path, or a link
|
|
358
|
-
to the image — and find tries it on as if it were a post. `ctrl+v` (or `v`
|
|
359
|
-
outside the search field, `alt+v` on Windows) reads the clipboard itself, which
|
|
360
|
-
is how a screenshot or a browser's "Copy Image" gets in, since no terminal
|
|
361
|
-
pastes picture data as text — on macOS ctrl+shift+cmd+4 takes a screenshot
|
|
362
|
-
straight to the clipboard. When the window comes back into focus with a picture
|
|
363
|
-
on the clipboard, find says so for a few seconds; text on the clipboard that is
|
|
364
|
-
neither a file nor a link goes into the search field instead. Every terminal hands a dropped
|
|
365
|
-
file over as its path, each quoted its own way, and find reads them all; kitty
|
|
366
|
-
and iTerm2 3.7 also deliver the dropped picture itself through kitty's
|
|
367
|
-
drag-and-drop protocol, so a picture dragged out of a browser works there too,
|
|
368
|
-
and kitty's clipboard protocol makes Cmd+V with a picture on the clipboard work
|
|
369
|
-
directly, over ssh as well. PNG and JPEG work everywhere; macOS converts any
|
|
370
|
-
other picture (HEIC, WebP, GIF, TIFF…) and shrinks one over 25 megapixels. The
|
|
371
|
-
installed picture is named `local` in the conf's `# from` line, with the file or
|
|
372
|
-
link it came from, and keeps its original under `backgrounds/originals/` like a
|
|
373
|
-
booru post. Over ssh `ctrl+v` can only reach the clipboard through kitty's protocol,
|
|
374
|
-
since the clipboard is on your own machine.
|
|
375
|
-
|
|
376
|
-
Enter tries the picture on: ttheme downloads the original and paints the whole
|
|
377
|
-
window with it the way the installed background will look — tinted with the
|
|
378
|
-
palette, cropped with headroom above the face, at the opacity the contrast gate
|
|
379
|
-
allows — over a sample of shell output, with the share of transparent pixels
|
|
380
|
-
next to its size (`opaque` when there are none). On macOS an opaque picture is
|
|
381
|
-
cut out first: ttheme asks the system's own Vision framework (macOS 14 or newer,
|
|
382
|
-
through `osascript` — nothing is installed or uploaded) for the character alone,
|
|
383
|
-
marks the picture `cut out`, and `x` switches between the cut-out and the picture
|
|
384
|
-
as it is. When Vision finds no character, or would leave almost nothing or
|
|
385
|
-
remove almost nothing, the picture stays opaque; elsewhere it always does. A post over 25 megapixels is
|
|
386
|
-
fetched as the site's own smaller copy instead — up to 3500 px on yande.re and
|
|
387
|
-
konachan, 850 px on danbooru — and its size carries `↓`; those
|
|
388
|
-
copies are JPEGs, so a cutout tried on that way comes out opaque. `←`/`→` try
|
|
389
|
-
the neighbours, which find fetches ahead of you two at a time, and enter installs
|
|
390
|
-
and returns to the grid with the tile marked `✓`, the tab, search and scroll as
|
|
391
|
-
you left them; esc then hands the last one installed to the preview, which
|
|
392
|
-
carries on straight into the tuning panel below. `c` switches
|
|
393
|
-
between every post and the cutouts, esc goes back. Unless the settings say otherwise,
|
|
394
|
-
only `safe` and `general` posts are shown, and none tagged with nudity or
|
|
395
|
-
underwear (`nude`, `panties` and each site's own spelling of them) — with only
|
|
396
|
-
`safe` ticked yande.re and konachan are asked for `rating:s`, whatever else is
|
|
397
|
-
searched; ticking more ratings or unticking a block in the `s` panel widen it. danbooru takes only two tags from a
|
|
398
|
-
signed-out search, so on it a cutout search leaves the score order out and says
|
|
399
|
-
so. Thumbnails and header checks stay in
|
|
400
|
-
`~/.cache/ttheme/<site>/`; the pictures you try on last only while find is open.
|
|
401
|
-
When a site asks ttheme to slow down, find waits as long as it names, up to a
|
|
402
|
-
minute, with a countdown at the bottom. ttheme keeps no
|
|
403
|
-
list of images — the tag is all it knows about a character.
|
|
404
|
-
|
|
405
|
-
An install writes `<palette>.<hash>.png` (the tinted figure),
|
|
406
|
-
`<palette>.<hash>@fill-<focus>.png` (the picture made at the shape of the window
|
|
407
|
-
find ran in: a cut-out stands whole from its head down against the right edge, a
|
|
408
|
-
little taller than the window, and a wallpaper covers it from its top) — the hash is of
|
|
409
|
-
their content, because Ghostty and iTerm2 reload a background only when its path
|
|
410
|
-
changes, so no two pictures may share a name — `<palette>.conf` and the untouched original under
|
|
411
|
-
`backgrounds/originals/`, and starts it untuned — the picture it replaces moves
|
|
412
|
-
to the shelf with the tuning it had. The
|
|
413
|
-
conf opens with where the picture came from —
|
|
414
|
-
`# from yande.re 214705 https://yande.re/post/show/214705` — and the tuning
|
|
415
|
-
panel shows it next to the palette's name.
|
|
416
|
-
|
|
417
|
-
`preview` shows the background of the palette under the cursor while you
|
|
418
|
-
browse: through the kitty graphics protocol (Ghostty, kitty, and iTerm2 3.7 or newer)
|
|
419
|
-
it draws that palette's `background-image` where Ghostty would place it, faded by
|
|
420
|
-
`background-image-opacity`, behind the list — or just its plain background when
|
|
421
|
-
it has no file. Only PNG images preview.
|
|
422
|
-
|
|
423
|
-
On a palette with a background, tab opens a panel that tunes it in place:
|
|
424
|
-
`↑`/`↓` pick size, position or opacity, and `←`/`→` change it (with shift, ten
|
|
425
|
-
steps at a time). Size walks 1% at a time, shown large in the middle of the
|
|
426
|
-
screen as it changes: 100% is the whole image fitted into the window
|
|
427
|
-
(`contain`), below that it shrinks to 20%, above it the image grows around the
|
|
428
|
-
face until it covers the window, and the top step is **fill** (`cover`). Fill
|
|
429
|
-
uses `<palette>.<hash>@fill-<focus>.png` when it sits beside the image — a crop made
|
|
430
|
-
to fill the window, whose name carries the height of the figure at the window's middle, which
|
|
431
|
-
the sizes above 100% zoom around — and the image itself otherwise. Position
|
|
432
|
-
steps through the nine `background-image-position` anchors, or `1`–`9` jump to
|
|
433
|
-
one in reading order; opacity moves by 0.01. Space turns the palette's
|
|
434
|
-
background off and on, `=` returns it to its defaults, enter keeps the change
|
|
435
|
-
and esc puts back what the panel opened with. `f` in the panel opens find again
|
|
436
|
-
to replace the picture.
|
|
437
|
-
|
|
438
|
-
A palette holds every picture installed on it: an install shelves the one on
|
|
439
|
-
screen rather than dropping it, `,` and `.` walk the saved pictures, and `D`
|
|
440
|
-
removes the one shown. Each picture carries its own settings — size, position,
|
|
441
|
-
opacity, the off switch and the baked crops travel with it under
|
|
442
|
-
`backgrounds/shelf/<palette>/<post>/`, so walking back to a picture puts it
|
|
443
|
-
back the way you left it, and tuning you have not confirmed is written to the
|
|
444
|
-
picture before `,` or `.` moves off it.
|
|
445
|
-
|
|
446
|
-
The palette's `.conf` holds those defaults; the preview only appends two
|
|
447
|
-
optional includes to it and keeps everything else in `<palette>.tune.conf` (the
|
|
448
|
-
tuning) and `<palette>.off.conf` (the off switch), which Ghostty loads after
|
|
449
|
-
the conf. Kept changes are written when the preview closes, by whichever key,
|
|
450
|
-
and reach both terminals from whichever one ran the preview: Ghostty reloads
|
|
451
|
-
when it is showing that palette, and iTerm2's profiles are rewritten. Ghostty has no scale setting,
|
|
452
|
-
so every size but 100% and fill is baked into a copy beside the image and the
|
|
453
|
-
tuning points at it: below 100% onto a transparent canvas of the image's own
|
|
454
|
-
size (`kagami.1a2b3c4d@60-bottom-right.png`, fitted with `contain`), above it onto
|
|
455
|
-
one of the window's size at the time (`kagami.1a2b3c4d@130-center-2880x1800.png`,
|
|
456
|
-
with `cover`). With iTerm2 wired, a size of 100% or less that is not centered
|
|
457
|
-
goes onto the window-sized canvas too, since iTerm2 cannot place an image.
|
|
458
|
-
Baking runs `sips`, so those sizes are offered on macOS only.
|
|
459
|
-
|
|
460
|
-
The preview draws inside the cell grid, and Ghostty's `window-padding` around
|
|
461
|
-
it keeps showing the configured background. While the cursor rests on the
|
|
462
|
-
configured palette and nothing has been tuned, the preview draws nothing and
|
|
463
|
-
lets that background show through whole. Once Ghostty supports kitty's relative
|
|
464
|
-
placements (merged after 1.3.1), the preview notices when it opens and hangs
|
|
465
|
-
its layers out over the padding instead, so every palette reaches the window
|
|
466
|
-
edge.
|
|
467
|
-
|
|
468
|
-
`pin` opens the same browser and, on enter, asks **this directory** or **and
|
|
469
|
-
below**; the answer lands in `~/.config/ttheme/pins`, one `path palette` per
|
|
470
|
-
line, where `path/**` covers everything below it (`~` works, and the file is
|
|
471
|
-
yours to edit). From then on a tab that `cd`s into a pinned path takes its
|
|
472
|
-
palette — symlinks resolve to the pinned directory — and `cd`ing out restores
|
|
473
|
-
what the tab had before, unless you painted it by hand in between, in which
|
|
474
|
-
case your pick stays. The nearest pinned ancestor wins, so a project can pin
|
|
475
|
-
one palette and a subfolder another. Open tabs pick up a changed pins file on
|
|
476
|
-
their next `cd`; `unpin` drops the pin on the current directory.
|
|
477
|
-
|
|
478
|
-
`preview`, `next`, `default`, `pin`, `unpin`, `config` and `help` match exactly; every other first argument is read
|
|
479
|
-
as a palette name, where a unique prefix is enough. Mistyped names get a "did
|
|
480
|
-
you mean" suggestion instead of a wall of output. Piped output drops color and
|
|
481
|
-
turns tab-separated, and `NO_COLOR` is respected.
|
|
482
|
-
|
|
483
|
-
With `TTHEME_TAB_PALETTE=seq`, new tabs take the next palette in group order, with the counter shared across
|
|
484
|
-
tabs — so opening four tabs walks you through four different characters rather
|
|
485
|
-
than rolling the same one twice.
|
|
486
|
-
|
|
487
|
-
Settings live in `~/.config/ttheme/config.zsh` — `init` seeds it with every
|
|
488
|
-
setting at its default on a commented line, so a default a later version changes
|
|
489
|
-
reaches you, and never overwrites a line you changed — bar `TTHEME_TAB_PALETTE`, which its
|
|
490
|
-
default/rotate/keep question sets — `ttheme config` opens it in `$EDITOR` and alt-c in `preview` edits it in place. Only a value that differs from the default
|
|
491
|
-
is left uncommented; setting one back comments it out again. Each line is a plain zsh
|
|
492
|
-
`: ${VAR:=value}` assignment, so a variable exported before the layer loads
|
|
493
|
-
still wins:
|
|
494
|
-
|
|
495
|
-
| Setting | Default | |
|
|
496
|
-
|---|---|---|
|
|
497
|
-
| `TTHEME_TAB_PALETTE` | `off` | `off` keeps new tabs on the terminal's configured theme (`preview` → default changes it); `seq` gives every new tab the next palette. `init` writes `seq` for rotate and `off` for default and keep |
|
|
498
|
-
| `TTHEME_ANNOUNCE` | `1` | `0` silences the one-line notice under "Last login:" |
|
|
499
|
-
| `TTHEME_FX` | `typewriter` | search hint animation — `typewriter`, `decode` or `glitch` |
|
|
500
|
-
| `TTHEME_SORT` | `abc` | `series` lists series and palettes in the order they were added instead of by name — in `ttheme`, `preview` and, once exported, the `init` picker |
|
|
501
|
-
| `TTHEME_FIND_RATING` | `safe` | the ratings `find` lists, any of `safe`, `questionable` and `explicit` separated by spaces (`"safe explicit"`). Each site is read in its own vocabulary, so danbooru's `s` (sensitive) is not mistaken for yande.re's `s` (safe). The set shows next to the query whenever it is not just `safe` |
|
|
502
|
-
| `TTHEME_FIND_BLOCK` | `nudity underwear` | the posts `find` drops by tag: `nudity` (`nude`, `naked`, `topless`…), `underwear` (`panties`, `bra`, `lingerie`… — each with the site's own spelling), both, or `none` to keep every post. What is let through shows next to the query as `allows …` |
|
|
503
|
-
| `TTHEME_FIND_POSTS` | `all` | what `find` opens on — every post of the character, or only the transparent cutouts (`cutouts`) |
|
|
504
|
-
| `TTHEME_FIND_CUTOUTS` | — | the tags `find` calls a transparent cutout, as `key=tag,tag` pairs separated by spaces, keyed by `danbooru`, `konachan` or `yande` (`konachan=transparent,vector yande=transparent_png`). A site with several tags matches any of them; `danbooru=` names none, so its cutouts are the posts whose PNG header has an alpha channel. A site named here loses yande.re's shortcut of skipping that header check. Sites left out keep the built-in tags |
|
|
505
|
-
| `TTHEME_FIND_SOLO` | `on` | `on` keeps only the posts tagged `solo` — the character alone, which is what a backdrop needs. konachan and yande.re do not tag how many people a picture shows, so their posts borrow the tags danbooru holds for the same file, one request per page; a post danbooru does not have is left alone. The query line says `solo` while it is on |
|
|
506
|
-
| `TTHEME_FIND_ORDER` | `fit` | the order `find` lists posts in — `fit` ranks each page it fetches by how well a post makes a backdrop (solo, resolution against the window, a cutout or an aspect close to the window's, score within the page, the palette's colors in its preview; comics, monochrome, sketches and landscapes sink) and appends it below what is already shown, so nothing moves under you; `newest`; or `score` |
|
|
507
|
-
| `TTHEME_FIND_SETS` | `fold` | a run of the same picture at the same size from one uploader, and a picture another site holds too: `fold` shows it as one tile marked `×N`, `show` lists every one |
|
|
508
|
-
| `TTHEME_FIND_REMOVE_BG` | `on` | on macOS, `on` cuts the character out of an opaque picture `find` tries on, with the system's Vision framework; `off` leaves it as it is. The row is in the `s` panel as `remove bg` |
|
|
509
|
-
| `TTHEME_FIND_UNBLOCK` | `0` | find offers to turn it on when a site's connection is cut off. `1` sends `find`'s requests to danbooru through a proxy it runs on `127.0.0.1`, which splits the TLS handshake across two records so a network that blocks it by hostname cannot read the name; konachan and yande.re, which no network is known to block, still go direct. It is not a VPN: the address you reach is unchanged and nothing else on the machine is affected. Needs node 22.21 or newer, and the query line says `unblock` while it is on |
|
|
510
|
-
| `TTHEME_FIND_HOSTS` | — | send a `find` site somewhere else, as `key=https://host` pairs (`danbooru=https://safebooru.donmai.us`, the general-rated mirror, reachable where danbooru is blocked). The tab keeps its name and carries `*` |
|
|
511
|
-
|
|
512
|
-
## The catalog
|
|
513
|
-
|
|
514
|
-
The catalog is not installed wholesale: `init` installs the series you pick, and
|
|
515
|
-
`init --yes` none at all. `ttheme browse` opens the catalog as a live picker —
|
|
516
|
-
groups fold and unfold, typing filters (a query has no spaces, `space` is the
|
|
517
|
-
pick key), the tab repaints as the cursor lands on a palette, `space` marks one
|
|
518
|
-
(a series from its header, everything shown from `select all`), and enter
|
|
519
|
-
installs exactly what is marked and removes what is not:
|
|
85
|
+
## Usage
|
|
520
86
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
87
|
+
| Command | |
|
|
88
|
+
|---|---|
|
|
89
|
+
| `ttheme preview` | browse live — the tab repaints as the cursor moves, enter applies it to this tab or makes it the default |
|
|
90
|
+
| `ttheme use <palette>` | paint this tab (a unique prefix works) |
|
|
91
|
+
| `ttheme next` | advance this tab to the next palette |
|
|
92
|
+
| `ttheme default <palette>` | the palette new tabs open with |
|
|
93
|
+
| `ttheme pin` / `unpin` | a palette for this directory — `cd` in repaints, `cd` out restores |
|
|
94
|
+
| `ttheme browse` | pick palettes from the catalog |
|
|
95
|
+
| `ttheme on` / `off` | wear the default again / give the terminal its own colors back |
|
|
96
|
+
| `ttheme config` | settings in `$EDITOR` |
|
|
97
|
+
|
|
98
|
+
`ttheme help` lists everything. Preview's keys, directory pins, rotating new
|
|
99
|
+
tabs and every setting are in [docs/usage.md](docs/usage.md).
|
|
532
100
|
|
|
533
|
-
|
|
534
|
-
`2 picked` is the install set, and `(2/4)` on the series header is how many of
|
|
535
|
-
its shown palettes are in it. The dot and the bar are the palette's real cursor
|
|
536
|
-
and its ANSI colors.
|
|
101
|
+
## Terminal support
|
|
537
102
|
|
|
538
|
-
|
|
103
|
+
| | Ghostty | iTerm2 | kitty | Alacritty | WezTerm | Windows Terminal | Warp | Terminal.app |
|
|
104
|
+
|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|
|
105
|
+
| **Setup with `init`** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — |
|
|
106
|
+
| **Runtime repaint** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — | ✅ |
|
|
107
|
+
| **Background pictures** | ✅ | ✅ | ✅ | — | ◐ | — | — | — |
|
|
539
108
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
ttheme remove kyubey # and one fewer
|
|
544
|
-
ttheme update # new palettes, without an npm release
|
|
545
|
-
```
|
|
109
|
+
Nothing is emulated — a terminal that cannot express something does not get it.
|
|
110
|
+
Any other terminal that speaks OSC 4/10/11 gets runtime repainting. Why each cell
|
|
111
|
+
is what it is: [docs/terminals.md](docs/terminals.md).
|
|
546
112
|
|
|
547
|
-
|
|
548
|
-
`themes/` directory and the `theme =` line in its config, then the shell re-reads
|
|
549
|
-
them — the change is live in the tab you ran it in. The first palette you install
|
|
550
|
-
becomes the one new windows open with.
|
|
551
|
-
|
|
552
|
-
`update` refetches the catalog from the registry; every palette in it has already
|
|
553
|
-
passed the contrast gate in CI, and `add` checks the numbers again before it
|
|
554
|
-
writes anything.
|
|
555
|
-
|
|
556
|
-
Installed palettes are listed in `~/.config/ttheme/installed.json`, and the
|
|
557
|
-
catalog is cached in `~/.config/ttheme/catalog.json`.
|
|
558
|
-
|
|
559
|
-
## Terminal notes
|
|
560
|
-
|
|
561
|
-
WezTerm keeps an OSC-set palette per pane, but a picture belongs to the window:
|
|
562
|
-
the Lua module ttheme runs follows the active pane's `ttheme_shown` user var,
|
|
563
|
-
which the shell layer sets whenever the tab's palette changes, and reads the
|
|
564
|
-
picture from `backgrounds/<palette>.conf` itself — so a picture installed or
|
|
565
|
-
tuned from Ghostty or iTerm2 reaches WezTerm within a second.
|
|
566
|
-
|
|
567
|
-
kitty gets a watcher, `~/.config/ttheme/kitty.py`, which the kitty block loads:
|
|
568
|
-
the shell layer tells it what a window wears and shows through user vars
|
|
569
|
-
(`ttheme_worn`, `ttheme_shown`, `ttheme_startup`), and it answers with the
|
|
570
|
-
window's logo — kitty's per-window picture, drawn above the default background
|
|
571
|
-
and below any cell with a background of its own, which does not scroll — read
|
|
572
|
-
from `backgrounds/<palette>.conf` itself, so a picture tuned in another terminal
|
|
573
|
-
shows the next time a kitty window takes focus. kitty 0.49 draws every logo at
|
|
574
|
-
the global `window_logo_alpha` and scales every logo by `window_logo_scale`, so
|
|
575
|
-
the block sets those to 1 and 100 and the watcher fades the picture's own alpha
|
|
576
|
-
to the tuned opacity instead. kitty reloads its config by itself whenever
|
|
577
|
-
`kitty.conf` or a file it includes changes, and a reload resets every color an
|
|
578
|
-
OSC set; the watcher wraps the reload and puts each window's palette back, and
|
|
579
|
-
`sync` writes a file only when its content changed, so installing palettes
|
|
580
|
-
reloads nothing. The watcher reaches kitty windows opened after `init`.
|
|
581
|
-
|
|
582
|
-
Alacritty reloads its config by itself and keeps OSC colors through a reload.
|
|
583
|
-
`sync` puts its import in the config's own `[general]` table when there is one —
|
|
584
|
-
TOML allows a table once — and leaves a config that already imports files
|
|
585
|
-
there alone, with a note.
|
|
586
|
-
|
|
587
|
-
iTerm2 reads the colors an OSC sets as Display P3 — its default color space — so
|
|
588
|
-
its profiles and `.itermcolors` files are written in P3 too: a tab opened on a
|
|
589
|
-
`ttheme · <palette>` profile and a tab repainted to that palette land on the
|
|
590
|
-
same colors, and ttheme recognizes the palette either way.
|
|
591
|
-
|
|
592
|
-
## Adding a palette
|
|
593
|
-
|
|
594
|
-
One file — copy any of `themes/*.toml`. `CONTRIBUTING.md` has the rules for
|
|
595
|
-
sending one back; the short version is that this repository takes **color values
|
|
596
|
-
only and never images**:
|
|
597
|
-
|
|
598
|
-
```toml
|
|
599
|
-
[meta]
|
|
600
|
-
name = "madoka" # must match the filename
|
|
601
|
-
group = "Madoka Magica" # needs a [[group]] in themes/_groups.toml
|
|
602
|
-
order = 15 # position in the rotation
|
|
603
|
-
ansi_source = "Elegant + Magica" # what the harmonizer was fed
|
|
604
|
-
booru = "kaname_madoka" # booru character tag find searches
|
|
605
|
-
signature = ["cursor", "ansi1", "ansi3"] # the three slots the site draws as identity
|
|
606
|
-
|
|
607
|
-
[colors]
|
|
608
|
-
background = "#201516"
|
|
609
|
-
foreground = "#fbdbdd"
|
|
610
|
-
cursor = "#ffc1c6"
|
|
611
|
-
selection_background = "#553444"
|
|
612
|
-
ansi = [ ... 16 colors ... ]
|
|
613
|
-
```
|
|
113
|
+
## Background pictures
|
|
614
114
|
|
|
615
|
-
|
|
616
|
-
|
|
115
|
+
A palette can wear a picture behind the text. ttheme ships none: `ttheme
|
|
116
|
+
preview` → tab searches danbooru, konachan and yande.re for the character live
|
|
117
|
+
(safe-rated by default), or takes a picture you paste or drop, cuts the
|
|
118
|
+
character out on macOS, tints it to the palette and installs it on your machine
|
|
119
|
+
only. Ghostty shows the focused tab's picture, iTerm2 one per tab, kitty one per
|
|
120
|
+
window. See [docs/backgrounds.md](docs/backgrounds.md).
|
|
617
121
|
|
|
618
|
-
|
|
619
|
-
mise run build # regenerates dist/ for every terminal — fails on bad contrast
|
|
620
|
-
mise run build --only kitty # just one terminal's subtree
|
|
621
|
-
mise run test
|
|
622
|
-
mise run compat # the terminal compatibility cases, in each installed terminal
|
|
623
|
-
```
|
|
122
|
+
## Contributing
|
|
624
123
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
paints (read off a screenshot), `ttheme use <palette>` and its restore, cell size,
|
|
629
|
-
kitty graphics, synchronized output and focus reporting — and compares them
|
|
630
|
-
with `tests/compat/expect.tsv`: a case that used to pass and fails is a
|
|
631
|
-
regression and fails the run, and `--update` records what was measured.
|
|
632
|
-
|
|
633
|
-
All one hundred and eight currently pass unwaived — `kyubey` runs tightest at
|
|
634
|
-
4.28:1 where accents need 3:1: it is the one light palette, so every accent has
|
|
635
|
-
to darken enough to hold against a near-white background. If a palette genuinely
|
|
636
|
-
has to break a rule, waive it by name and say why; a waiver without a reason
|
|
637
|
-
fails the test suite.
|
|
638
|
-
|
|
639
|
-
```toml
|
|
640
|
-
[contrast]
|
|
641
|
-
waive = ["foreground"] # foreground | accents | ansi0-dark | light-ansi | ansi8-visible
|
|
642
|
-
reason = "why this palette is the exception"
|
|
643
|
-
```
|
|
124
|
+
A palette is one TOML file of color values — never images.
|
|
125
|
+
[CONTRIBUTING.md](CONTRIBUTING.md) has the rules, the file format and the
|
|
126
|
+
checks it must pass.
|
|
644
127
|
|
|
645
128
|
## Credits
|
|
646
129
|
|
|
@@ -661,3 +144,7 @@ audio or trademarked asset is redistributed here — only color values.
|
|
|
661
144
|
Terminal background images are downloaded from the booru you pick only when you
|
|
662
145
|
ask `find` for one, built on your own machine and written to
|
|
663
146
|
`~/.config/ttheme/backgrounds/`; none ship in this repository or on npm.
|
|
147
|
+
|
|
148
|
+
## License
|
|
149
|
+
|
|
150
|
+
[MIT](LICENSE)
|