@kecan0406/ttheme 1.0.30 → 1.0.32

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 CHANGED
@@ -18,6 +18,54 @@ Two things separate this from the usual color-scheme dump:
18
18
  - **Colors switch at runtime, not just at startup.** Tabs get different palettes
19
19
  in the same window, and any tab can be repainted at any time.
20
20
 
21
+ ## Terminal support
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
+ | **Font** | ![Done][done] | ![No][no] | ![Done][done] | ![Done][done] | ![Done][done] | ![No][no] | ![No][no] | ![No][no] | ![No][no] |
32
+ | **Shader** | ![Done][done] | ![No][no] | ![No][no] | ![No][no] | ![No][no] | ![No][no] | ![No][no] | ![No][no] | ![No][no] |
33
+ | **Background pictures** | ![Done][done] | ![Done][done] | ![Done][done] | ![No][no] | ![Partial][partial] | ![No][no] | ![No][no] | ![No][no] | ![No][no] |
34
+
35
+ - **Setup with `init`** — iTerm2 is offered on macOS only, Windows Terminal
36
+ from WSL (or a native Windows zsh), where init writes a settings fragment on
37
+ the Windows side. Warp gets its themes, and the default palette through its
38
+ `settings.toml` (the Warp builds that have one).
39
+ - **Palette files** — iTerm2 gets one dynamic profile per palette, plus
40
+ `.itermcolors` in the archive; Windows Terminal gets one fragment carrying
41
+ every installed scheme.
42
+ - **Runtime repaint** — OSC escape sequences everywhere, per pane in kitty,
43
+ WezTerm and Windows Terminal, one color per sequence (Alacritty drops an OSC 4
44
+ carrying more than seven). kitty and Windows Terminal reset every OSC color
45
+ when their config reloads, so a changed default would undo the palettes open
46
+ tabs wear: kitty's watcher puts each window's palette back as the reload ends,
47
+ and a Windows Terminal tab repaints itself at its next prompt or focus.
48
+ Terminal.app takes every OSC color but no OSC reset, so ttheme reads its
49
+ colors when the shell starts and puts them back itself. Warp answers OSC
50
+ color queries but paints one theme app-wide and never the background an OSC
51
+ sets, so the shell layer stays off there and `ttheme <palette>` points you at
52
+ `ttheme default <palette>`, which puts the palette on every Warp window; any other terminal that speaks OSC 4/10/11 (foot, Konsole,
53
+ VTE-based terminals…) gets repainting and nothing else.
54
+ - **Font** — family and size everywhere it is marked; Ghostty also maps
55
+ codepoints to fonts. iTerm2 keeps the font of your own profile, Windows
56
+ Terminal and Warp the one you set in them.
57
+ - **Background pictures** — `find`, `ttheme image` and `preview`'s live
58
+ backdrop. Ghostty shows one picture app-wide, following the focused tab;
59
+ iTerm2 (3.7 or newer) shows one per tab and kitty one per window (a split
60
+ pane included), both with the same preview, tuning and find. WezTerm shows the
61
+ picture of the active tab per window and switches it as `preview` moves, but
62
+ has no in-terminal preview or tuning — find and tune from Ghostty, iTerm2 or
63
+ kitty. Alacritty has no graphics at all. Cut-outs and baked crops need macOS.
64
+
65
+ [done]: https://img.shields.io/badge/Done-2ea44f?style=flat-square
66
+ [partial]: https://img.shields.io/badge/Partial-e3b341?style=flat-square
67
+ [no]: https://img.shields.io/badge/Not%20supported-d0d7de?style=flat-square
68
+
21
69
  ## Palettes
22
70
 
23
71
  | Group | Palettes |
@@ -57,7 +105,7 @@ came from — `ttheme` prints it, and it is in the theme's TOML.
57
105
 
58
106
  ## Install
59
107
 
60
- **Ghostty, kitty, Alacritty or iTerm2** — one command, no clone:
108
+ **Ghostty, kitty, Alacritty, WezTerm, iTerm2, Windows Terminal or Warp** — one command, no clone:
61
109
 
62
110
  ```sh
63
111
  npx @kecan0406/ttheme@latest init
@@ -80,14 +128,25 @@ init makes it iTerm2's default profile, so new tabs and windows open wearing the
80
128
  palette and its picture from their first frame and follow `ttheme default` from
81
129
  then on. iTerm2 reads its default profile only when it starts, so quit and
82
130
  reopen it once after init. The profile it replaces stays the parent of every
83
- ttheme profile, so your font and keys carry over, and `keep` gives it back. It ends with a receipt, paints the first palette onto the tab you
131
+ ttheme profile, so your font and keys carry over, and `keep` gives it back.
132
+ WezTerm's config is Lua, so init puts a two-line block that runs
133
+ `~/.config/ttheme/wezterm.lua` just before your config's `return config` (or
134
+ writes a small `wezterm.lua` when there is none); WezTerm reloads it by itself.
135
+ Windows Terminal gets a fragment,
136
+ `%LOCALAPPDATA%\Microsoft\Windows Terminal\Fragments\ttheme\ttheme.json`,
137
+ with every installed scheme and the default palette on the profile init ran in —
138
+ `settings.json` is never edited, only touched so the terminal reloads. Warp gets
139
+ a theme per palette, `~/.warp/themes/ttheme-<palette>.yaml`, and the default
140
+ palette as the one `theme` key of `[appearance.themes]` in `~/.warp/settings.toml`
141
+ — Warp applies it within a few seconds, and `keep` puts back the theme you had.
142
+ It ends with a receipt, paints the first palette onto the tab you
84
143
  ran it in (not under `keep`) and lists what to do next (`exec zsh` for the
85
144
  `ttheme` command here, a terminal restart for new tabs).
86
145
  Running it again updates in place; `--yes` skips every prompt and installs no
87
146
  palettes — `ttheme browse` opens the full catalog any time, to add or drop
88
147
  single palettes.
89
148
 
90
- **WezTerm, or any of them by hand** — one archive per terminal in the
149
+ **Any of them by hand** — one archive per terminal in the
91
150
  [latest release](https://github.com/kecan0406/ttheme/releases/latest):
92
151
 
93
152
  ```sh
@@ -111,6 +170,15 @@ cp wezterm/colors/miku.toml ~/.config/wezterm/colors/
111
170
 
112
171
  # iTerm2 — open a .itermcolors to add it to Settings > Profiles > Colors presets
113
172
  curl -L $REL/ttheme-iterm2.tar.gz | tar xz
173
+
174
+ # windows terminal — every scheme in one fragment
175
+ curl -L $REL/ttheme-windows-terminal.tar.gz | tar xz
176
+ # copy windows-terminal/ttheme.json into
177
+ # %LOCALAPPDATA%\Microsoft\Windows Terminal\Fragments\ttheme\
178
+
179
+ # warp
180
+ curl -L $REL/ttheme-warp.tar.gz | tar xz
181
+ cp warp/themes/ttheme-miku.yaml ~/.warp/themes/
114
182
  ```
115
183
 
116
184
  The kitty, Alacritty and WezTerm archives also carry a `config/` file per theme
@@ -266,6 +334,26 @@ half remember; `↑`/`↓` pick one and enter searches it. A palette with no `me
266
334
  find on that empty query, so it can have a background too. `o` opens the post's
267
335
  page in a browser.
268
336
 
337
+ A picture of your own goes in the same way. Drop an image file on the window
338
+ while find is open, or paste it — a file copied in Finder, its path, or a link
339
+ to the image — and find tries it on as if it were a post. `ctrl+v` (or `v`
340
+ outside the search field, `alt+v` on Windows) reads the clipboard itself, which
341
+ is how a screenshot or a browser's "Copy Image" gets in, since no terminal
342
+ pastes picture data as text — on macOS ctrl+shift+cmd+4 takes a screenshot
343
+ straight to the clipboard. When the window comes back into focus with a picture
344
+ on the clipboard, find says so for a few seconds; text on the clipboard that is
345
+ neither a file nor a link goes into the search field instead. Every terminal hands a dropped
346
+ file over as its path, each quoted its own way, and find reads them all; kitty
347
+ and iTerm2 3.7 also deliver the dropped picture itself through kitty's
348
+ drag-and-drop protocol, so a picture dragged out of a browser works there too,
349
+ and kitty's clipboard protocol makes Cmd+V with a picture on the clipboard work
350
+ directly, over ssh as well. PNG and JPEG work everywhere; macOS converts any
351
+ other picture (HEIC, WebP, GIF, TIFF…) and shrinks one over 25 megapixels. The
352
+ installed picture is named `local` in the conf's `# from` line, with the file or
353
+ link it came from, and keeps its original under `backgrounds/originals/` like a
354
+ booru post. Over ssh `ctrl+v` can only reach the clipboard through kitty's protocol,
355
+ since the clipboard is on your own machine.
356
+
269
357
  Enter tries the picture on: ttheme downloads the original and paints the whole
270
358
  window with it the way the installed background will look — tinted with the
271
359
  palette, cropped with headroom above the face, at the opacity the contrast gate
@@ -308,7 +396,7 @@ conf opens with where the picture came from —
308
396
  panel shows it next to the palette's name.
309
397
 
310
398
  `preview` shows the background of the palette under the cursor while you
311
- browse: through the kitty graphics protocol (Ghostty, and iTerm2 3.7 or newer)
399
+ browse: through the kitty graphics protocol (Ghostty, kitty, and iTerm2 3.7 or newer)
312
400
  it draws that palette's `background-image` where Ghostty would place it, faded by
313
401
  `background-image-opacity`, behind the list — or just its plain background when
314
402
  it has no file. Only PNG images preview.
@@ -449,24 +537,38 @@ writes anything.
449
537
  Installed palettes are listed in `~/.config/ttheme/installed.json`, and the
450
538
  catalog is cached in `~/.config/ttheme/catalog.json`.
451
539
 
452
- ## What each terminal can actually do
453
-
454
- Nothing is emulated — a terminal that cannot express something simply does not
455
- get it.
456
-
457
- | | palette file | runtime switching | font | shader |
458
- |---|---|---|---|---|
459
- | **Ghostty** | ✅ | ✅ native adapter | ✅ incl. per-codepoint map | ✅ |
460
- | **kitty** | ✅ | ✅ native adapter | family + size | ✗ |
461
- | **WezTerm** | ✅ | OSC — per window, never per pane | family + size | ✗ |
462
- | **Alacritty** | ✅ | OSC only (no runtime color API exists) | family + size | ✗ |
463
- | **iTerm2** | ✅ a profile per palette | OSC | profile-only | ✗ |
464
- | anything else | — | OSC, if it speaks it | — | ✗ |
540
+ ## Terminal notes
465
541
 
466
542
  Ghostty is the only terminal here with GLSL shaders, and the only one with
467
543
  per-codepoint font mapping — which is why the Hangul→D2Coding rule survives only
468
544
  in its build.
469
545
 
546
+ WezTerm keeps an OSC-set palette per pane, but a picture belongs to the window:
547
+ the Lua module ttheme runs follows the active pane's `ttheme_shown` user var,
548
+ which the shell layer sets whenever the tab's palette changes, and reads the
549
+ picture from `backgrounds/<palette>.conf` itself — so a picture installed or
550
+ tuned from Ghostty or iTerm2 reaches WezTerm within a second.
551
+
552
+ kitty gets a watcher, `~/.config/ttheme/kitty.py`, which the kitty block loads:
553
+ the shell layer tells it what a window wears and shows through user vars
554
+ (`ttheme_worn`, `ttheme_shown`, `ttheme_startup`), and it answers with the
555
+ window's logo — kitty's per-window picture, drawn above the default background
556
+ and below any cell with a background of its own, which does not scroll — read
557
+ from `backgrounds/<palette>.conf` itself, so a picture tuned in another terminal
558
+ shows the next time a kitty window takes focus. kitty 0.49 draws every logo at
559
+ the global `window_logo_alpha` and scales every logo by `window_logo_scale`, so
560
+ the block sets those to 1 and 100 and the watcher fades the picture's own alpha
561
+ to the tuned opacity instead. kitty reloads its config by itself whenever
562
+ `kitty.conf` or a file it includes changes, and a reload resets every color an
563
+ OSC set; the watcher wraps the reload and puts each window's palette back, and
564
+ `sync` writes a file only when its content changed, so installing palettes
565
+ reloads nothing. The watcher reaches kitty windows opened after `init`.
566
+
567
+ Alacritty reloads its config by itself and keeps OSC colors through a reload.
568
+ `sync` puts its import in the config's own `[general]` table when there is one —
569
+ TOML allows a table once — and leaves a config that already imports files
570
+ there alone, with a note.
571
+
470
572
  iTerm2 reads the colors an OSC sets as Display P3 — its default color space — so
471
573
  its profiles and `.itermcolors` files are written in P3 too: a tab opened on a
472
574
  `ttheme · <palette>` profile and a tab repainted to that palette land on the
@@ -500,11 +602,20 @@ never in a theme file. `[font]` and `[ghostty]` are inherited from
500
602
  `themes/_defaults.toml` unless the theme overrides them. Then:
501
603
 
502
604
  ```sh
503
- mise run build # regenerates dist/ for all five terminals — fails on bad contrast
605
+ mise run build # regenerates dist/ for every terminal — fails on bad contrast
504
606
  mise run build --only kitty # just one terminal's subtree
505
607
  mise run test
608
+ mise run compat # the terminal compatibility cases, in each installed terminal
506
609
  ```
507
610
 
611
+ `mise run compat` opens each installed terminal behind your windows on a
612
+ throwaway home (`mise run sandbox`), runs the cases in `tests/compat/cases.zsh`
613
+ inside it — adapter detection, OSC set/query/reset, what the window really
614
+ paints (read off a screenshot), `ttheme <palette>` and its restore, cell size,
615
+ kitty graphics, synchronized output and focus reporting — and compares them
616
+ with `tests/compat/expect.tsv`: a case that used to pass and fails is a
617
+ regression and fails the run, and `--update` records what was measured.
618
+
508
619
  All one hundred and eight currently pass unwaived — `kyubey` runs tightest at
509
620
  4.28:1 where accents need 3:1: it is the one light palette, so every accent has
510
621
  to darken enough to hold against a near-white background. If a palette genuinely