ghostty-theme 1.0.0
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 +79 -0
- package/dist/commands/add.d.ts +4 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +49 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/list.d.ts +4 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +31 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/random.d.ts +4 -0
- package/dist/commands/random.d.ts.map +1 -0
- package/dist/commands/random.js +26 -0
- package/dist/commands/random.js.map +1 -0
- package/dist/commands/remove.d.ts +2 -0
- package/dist/commands/remove.d.ts.map +1 -0
- package/dist/commands/remove.js +31 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/commands/set.d.ts +2 -0
- package/dist/commands/set.d.ts.map +1 -0
- package/dist/commands/set.js +19 -0
- package/dist/commands/set.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/config.d.ts +4 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +45 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/favorites.d.ts +6 -0
- package/dist/lib/favorites.d.ts.map +1 -0
- package/dist/lib/favorites.js +73 -0
- package/dist/lib/favorites.js.map +1 -0
- package/dist/lib/prompt.d.ts +7 -0
- package/dist/lib/prompt.d.ts.map +1 -0
- package/dist/lib/prompt.js +161 -0
- package/dist/lib/prompt.js.map +1 -0
- package/dist/lib/themes.d.ts +6 -0
- package/dist/lib/themes.d.ts.map +1 -0
- package/dist/lib/themes.js +25 -0
- package/dist/lib/themes.js.map +1 -0
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# ghostty-theme
|
|
2
|
+
|
|
3
|
+
> Switch [Ghostty](https://ghostty.org) themes from your terminal — with fuzzy search, favorites, and random mode.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install -g ghostty-theme
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
> **Requires**: [Ghostty](https://ghostty.org) terminal installed and available in your `PATH`.
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
ghostty-theme # Browse favorites interactively
|
|
20
|
+
ghostty-theme list # Same as above
|
|
21
|
+
ghostty-theme list --all # Browse all available themes
|
|
22
|
+
ghostty-theme set <name> # Set theme directly by name
|
|
23
|
+
ghostty-theme random # Random theme from favorites
|
|
24
|
+
ghostty-theme random --all # Random theme from all themes
|
|
25
|
+
ghostty-theme add <name> # Add a theme to favorites
|
|
26
|
+
ghostty-theme add -c # Add the current theme to favorites
|
|
27
|
+
ghostty-theme remove # Remove a theme from favorites (interactive)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Interactive Selector
|
|
31
|
+
|
|
32
|
+
Running `ghostty-theme` opens a fuzzy-searchable theme picker:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
Favorites:
|
|
36
|
+
Type to search, ↑↓/jk to move, Enter to select, q to cancel
|
|
37
|
+
Cobalt2
|
|
38
|
+
❯ TokyoNight *
|
|
39
|
+
Dracula
|
|
40
|
+
Catppuccin Mocha
|
|
41
|
+
Nord
|
|
42
|
+
▼ 7 more below
|
|
43
|
+
12 items
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
- **Type** to fuzzy search
|
|
47
|
+
- **↑↓** or **j/k** to navigate
|
|
48
|
+
- **Enter** to apply
|
|
49
|
+
- **q** / **Esc** to cancel
|
|
50
|
+
- Active theme is marked with `*`
|
|
51
|
+
|
|
52
|
+
### Favorites
|
|
53
|
+
|
|
54
|
+
Your favorite themes are stored in `~/.config/ghostty-theme-cli/favorites.json`. On first run, a curated set of popular dark themes is added automatically:
|
|
55
|
+
|
|
56
|
+
Cobalt2, TokyoNight, Dracula, Catppuccin Mocha, Nord, Gruvbox Dark, Solarized Dark Higher Contrast, Atom One Dark, Ayu, Kanagawa Dragon, Rose Pine, Everforest Dark Hard
|
|
57
|
+
|
|
58
|
+
### Random Mode
|
|
59
|
+
|
|
60
|
+
Feeling adventurous? Shuffle through your favorites (or all themes) with a single command:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
ghostty-theme random # Pick from favorites
|
|
64
|
+
ghostty-theme random --all # Pick from everything
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
It always picks a different theme from the one currently set.
|
|
68
|
+
|
|
69
|
+
## How It Works
|
|
70
|
+
|
|
71
|
+
- Reads available themes via `ghostty +list-themes`
|
|
72
|
+
- Directly edits the `theme = ...` line in your Ghostty config (`~/.config/ghostty/config`)
|
|
73
|
+
- Ghostty live-reloads, so theme changes apply instantly — no restart needed
|
|
74
|
+
|
|
75
|
+
You can override the config path with the `GHOSTTY_CONFIG_PATH` environment variable.
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAMA,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA+CxG"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { addFavorite, loadFavorites } from "../lib/favorites.js";
|
|
3
|
+
import { findTheme, getThemeNames } from "../lib/themes.js";
|
|
4
|
+
import { getCurrentTheme } from "../lib/config.js";
|
|
5
|
+
import { select } from "../lib/prompt.js";
|
|
6
|
+
export async function addCommand(name, options) {
|
|
7
|
+
if (options.current) {
|
|
8
|
+
const current = getCurrentTheme();
|
|
9
|
+
if (!current) {
|
|
10
|
+
console.error(chalk.red("No theme is currently set."));
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
if (addFavorite(current)) {
|
|
14
|
+
console.log(chalk.green(`Added "${current}" to favorites.`));
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
console.log(chalk.yellow(`"${current}" is already in favorites.`));
|
|
18
|
+
}
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (name) {
|
|
22
|
+
const resolved = findTheme(name);
|
|
23
|
+
if (!resolved) {
|
|
24
|
+
console.error(chalk.red(`Theme "${name}" not found.`));
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
if (addFavorite(resolved)) {
|
|
28
|
+
console.log(chalk.green(`Added "${resolved}" to favorites.`));
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
console.log(chalk.yellow(`"${resolved}" is already in favorites.`));
|
|
32
|
+
}
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
// Interactive: show all themes excluding already favorited
|
|
36
|
+
const favorites = new Set(loadFavorites().map((f) => f.toLowerCase()));
|
|
37
|
+
const allThemes = getThemeNames().filter((t) => !favorites.has(t.toLowerCase()));
|
|
38
|
+
const selected = await select({
|
|
39
|
+
message: "Select a theme to add to favorites:",
|
|
40
|
+
items: allThemes,
|
|
41
|
+
});
|
|
42
|
+
if (!selected) {
|
|
43
|
+
console.log(chalk.dim("Cancelled."));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
addFavorite(selected);
|
|
47
|
+
console.log(chalk.green(`Added "${selected}" to favorites.`));
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=add.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAwB,EAAE,OAA8B;IACvF,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,OAAO,GAAG,eAAe,EAAE,CAAC;QAClC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC,CAAC;YACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,IAAI,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,OAAO,iBAAiB,CAAC,CAAC,CAAC;QAC/D,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,OAAO,4BAA4B,CAAC,CAAC,CAAC;QACrE,CAAC;QACD,OAAO;IACT,CAAC;IAED,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,IAAI,cAAc,CAAC,CAAC,CAAC;YACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,QAAQ,iBAAiB,CAAC,CAAC,CAAC;QAChE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,QAAQ,4BAA4B,CAAC,CAAC,CAAC;QACtE,CAAC;QACD,OAAO;IACT,CAAC;IAED,2DAA2D;IAC3D,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACvE,MAAM,SAAS,GAAG,aAAa,EAAE,CAAC,MAAM,CACtC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CACvC,CAAC;IAEF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC;QAC5B,OAAO,EAAE,qCAAqC;QAC9C,KAAK,EAAE,SAAS;KACjB,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;QACrC,OAAO;IACT,CAAC;IAED,WAAW,CAAC,QAAQ,CAAC,CAAC;IACtB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,QAAQ,iBAAiB,CAAC,CAAC,CAAC;AAChE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAMA,wBAAsB,WAAW,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA4B3E"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { setTheme, getCurrentTheme } from "../lib/config.js";
|
|
3
|
+
import { getThemeNames } from "../lib/themes.js";
|
|
4
|
+
import { loadFavorites } from "../lib/favorites.js";
|
|
5
|
+
import { select } from "../lib/prompt.js";
|
|
6
|
+
export async function listCommand(options) {
|
|
7
|
+
const items = options.all ? getThemeNames() : loadFavorites();
|
|
8
|
+
const currentTheme = getCurrentTheme();
|
|
9
|
+
if (items.length === 0) {
|
|
10
|
+
console.log(chalk.yellow("No themes to display."));
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const selected = await select({
|
|
14
|
+
message: options.all ? "All themes:" : "Favorites:",
|
|
15
|
+
items,
|
|
16
|
+
currentTheme,
|
|
17
|
+
});
|
|
18
|
+
if (!selected) {
|
|
19
|
+
console.log(chalk.dim("Cancelled."));
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const prev = getCurrentTheme();
|
|
23
|
+
setTheme(selected);
|
|
24
|
+
if (prev) {
|
|
25
|
+
console.log(chalk.dim(`${prev} →`) + " " + chalk.bold.green(selected));
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
console.log(chalk.bold.green(`Theme set to: ${selected}`));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAA0B;IAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IAC9D,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;IAEvC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC,CAAC;QACnD,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC;QAC5B,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY;QACnD,KAAK;QACL,YAAY;KACb,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;QACrC,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAEnB,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IACzE,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,iBAAiB,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC7D,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"random.d.ts","sourceRoot":"","sources":["../../src/commands/random.ts"],"names":[],"mappings":"AAKA,wBAAgB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAsB9D"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { setTheme, getCurrentTheme } from "../lib/config.js";
|
|
3
|
+
import { getThemeNames } from "../lib/themes.js";
|
|
4
|
+
import { loadFavorites } from "../lib/favorites.js";
|
|
5
|
+
export function randomCommand(options) {
|
|
6
|
+
const pool = options.all ? getThemeNames() : loadFavorites();
|
|
7
|
+
if (pool.length === 0) {
|
|
8
|
+
console.error(chalk.red("No themes available."));
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
const current = getCurrentTheme();
|
|
12
|
+
// Try to pick something different from current
|
|
13
|
+
let candidates = pool.filter((t) => t !== current);
|
|
14
|
+
if (candidates.length === 0)
|
|
15
|
+
candidates = pool;
|
|
16
|
+
const picked = candidates[Math.floor(Math.random() * candidates.length)];
|
|
17
|
+
const prev = getCurrentTheme();
|
|
18
|
+
setTheme(picked);
|
|
19
|
+
if (prev) {
|
|
20
|
+
console.log(chalk.dim(`${prev} →`) + " " + chalk.bold.green(picked));
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
console.log(chalk.bold.green(`Theme set to: ${picked}`));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=random.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"random.js","sourceRoot":"","sources":["../../src/commands/random.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,UAAU,aAAa,CAAC,OAA0B;IACtD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IAE7D,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,eAAe,EAAE,CAAC;IAClC,+CAA+C;IAC/C,IAAI,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC;IACnD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,UAAU,GAAG,IAAI,CAAC;IAE/C,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IACzE,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEjB,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACvE,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,iBAAiB,MAAM,EAAE,CAAC,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../../src/commands/remove.ts"],"names":[],"mappings":"AAIA,wBAAsB,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6BhE"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { removeFavorite, loadFavorites } from "../lib/favorites.js";
|
|
3
|
+
import { select } from "../lib/prompt.js";
|
|
4
|
+
export async function removeCommand(name) {
|
|
5
|
+
if (name) {
|
|
6
|
+
if (removeFavorite(name)) {
|
|
7
|
+
console.log(chalk.green(`Removed "${name}" from favorites.`));
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
console.log(chalk.yellow(`"${name}" is not in favorites.`));
|
|
11
|
+
}
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
// Interactive: show favorites
|
|
15
|
+
const favorites = loadFavorites();
|
|
16
|
+
if (favorites.length === 0) {
|
|
17
|
+
console.log(chalk.yellow("No favorites to remove."));
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const selected = await select({
|
|
21
|
+
message: "Select a theme to remove from favorites:",
|
|
22
|
+
items: favorites,
|
|
23
|
+
});
|
|
24
|
+
if (!selected) {
|
|
25
|
+
console.log(chalk.dim("Cancelled."));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
removeFavorite(selected);
|
|
29
|
+
console.log(chalk.green(`Removed "${selected}" from favorites.`));
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=remove.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remove.js","sourceRoot":"","sources":["../../src/commands/remove.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAa;IAC/C,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,IAAI,mBAAmB,CAAC,CAAC,CAAC;QAChE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,wBAAwB,CAAC,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO;IACT,CAAC;IAED,8BAA8B;IAC9B,MAAM,SAAS,GAAG,aAAa,EAAE,CAAC;IAClC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,yBAAyB,CAAC,CAAC,CAAC;QACrD,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC;QAC5B,OAAO,EAAE,0CAA0C;QACnD,KAAK,EAAE,SAAS;KACjB,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;QACrC,OAAO;IACT,CAAC;IAED,cAAc,CAAC,QAAQ,CAAC,CAAC;IACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,QAAQ,mBAAmB,CAAC,CAAC,CAAC;AACpE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../src/commands/set.ts"],"names":[],"mappings":"AAIA,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAe7C"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { setTheme, getCurrentTheme } from "../lib/config.js";
|
|
3
|
+
import { findTheme } from "../lib/themes.js";
|
|
4
|
+
export function setCommand(name) {
|
|
5
|
+
const resolved = findTheme(name);
|
|
6
|
+
if (!resolved) {
|
|
7
|
+
console.error(chalk.red(`Theme "${name}" not found.`));
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
const prev = getCurrentTheme();
|
|
11
|
+
setTheme(resolved);
|
|
12
|
+
if (prev) {
|
|
13
|
+
console.log(chalk.dim(`${prev} →`) + " " + chalk.bold.green(resolved));
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
console.log(chalk.bold.green(`Theme set to: ${resolved}`));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=set.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set.js","sourceRoot":"","sources":["../../src/commands/set.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,IAAI,cAAc,CAAC,CAAC,CAAC;QACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAEnB,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IACzE,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,iBAAiB,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC7D,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { setCommand } from "./commands/set.js";
|
|
4
|
+
import { randomCommand } from "./commands/random.js";
|
|
5
|
+
import { addCommand } from "./commands/add.js";
|
|
6
|
+
import { removeCommand } from "./commands/remove.js";
|
|
7
|
+
import { listCommand } from "./commands/list.js";
|
|
8
|
+
const program = new Command();
|
|
9
|
+
program
|
|
10
|
+
.name("ghostty-theme")
|
|
11
|
+
.description("CLI tool for managing Ghostty terminal themes")
|
|
12
|
+
.version("1.0.0");
|
|
13
|
+
program
|
|
14
|
+
.command("set <name>")
|
|
15
|
+
.description("Set theme by name")
|
|
16
|
+
.action(setCommand);
|
|
17
|
+
program
|
|
18
|
+
.command("random")
|
|
19
|
+
.description("Apply a random theme from favorites")
|
|
20
|
+
.option("--all", "Pick from all themes instead of favorites")
|
|
21
|
+
.action(randomCommand);
|
|
22
|
+
program
|
|
23
|
+
.command("add [name]")
|
|
24
|
+
.description("Add a theme to favorites")
|
|
25
|
+
.option("-c, --current", "Add the currently applied theme")
|
|
26
|
+
.action(addCommand);
|
|
27
|
+
program
|
|
28
|
+
.command("remove [name]")
|
|
29
|
+
.description("Remove a theme from favorites")
|
|
30
|
+
.action(removeCommand);
|
|
31
|
+
program
|
|
32
|
+
.command("list")
|
|
33
|
+
.description("Browse themes interactively")
|
|
34
|
+
.option("--all", "Show all themes instead of favorites")
|
|
35
|
+
.action(listCommand);
|
|
36
|
+
// Default action (no command) → show favorites interactively
|
|
37
|
+
program.action(async () => {
|
|
38
|
+
await listCommand({ all: false });
|
|
39
|
+
});
|
|
40
|
+
program.parse();
|
|
41
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,eAAe,CAAC;KACrB,WAAW,CAAC,+CAA+C,CAAC;KAC5D,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,YAAY,CAAC;KACrB,WAAW,CAAC,mBAAmB,CAAC;KAChC,MAAM,CAAC,UAAU,CAAC,CAAC;AAEtB,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,qCAAqC,CAAC;KAClD,MAAM,CAAC,OAAO,EAAE,2CAA2C,CAAC;KAC5D,MAAM,CAAC,aAAa,CAAC,CAAC;AAEzB,OAAO;KACJ,OAAO,CAAC,YAAY,CAAC;KACrB,WAAW,CAAC,0BAA0B,CAAC;KACvC,MAAM,CAAC,eAAe,EAAE,iCAAiC,CAAC;KAC1D,MAAM,CAAC,UAAU,CAAC,CAAC;AAEtB,OAAO;KACJ,OAAO,CAAC,eAAe,CAAC;KACxB,WAAW,CAAC,+BAA+B,CAAC;KAC5C,MAAM,CAAC,aAAa,CAAC,CAAC;AAEzB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,6BAA6B,CAAC;KAC1C,MAAM,CAAC,OAAO,EAAE,sCAAsC,CAAC;KACvD,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,6DAA6D;AAC7D,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE;IACxB,MAAM,WAAW,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;AACpC,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAWA,wBAAgB,UAAU,IAAI,MAAM,CAMnC;AAED,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAU/C;AAED,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAoBhD"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
function getConfigPath() {
|
|
5
|
+
return (process.env.GHOSTTY_CONFIG_PATH ||
|
|
6
|
+
join(homedir(), ".config", "ghostty", "config"));
|
|
7
|
+
}
|
|
8
|
+
export function readConfig() {
|
|
9
|
+
try {
|
|
10
|
+
return readFileSync(getConfigPath(), "utf-8");
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return "";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function getCurrentTheme() {
|
|
17
|
+
const content = readConfig();
|
|
18
|
+
const lines = content.split("\n");
|
|
19
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
20
|
+
const match = lines[i].match(/^theme\s*=\s*(.+)$/);
|
|
21
|
+
if (match) {
|
|
22
|
+
return match[1].trim();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
export function setTheme(themeName) {
|
|
28
|
+
const configPath = getConfigPath();
|
|
29
|
+
let content = readConfig();
|
|
30
|
+
const lines = content.split("\n");
|
|
31
|
+
let found = false;
|
|
32
|
+
for (let i = 0; i < lines.length; i++) {
|
|
33
|
+
if (/^theme\s*=/.test(lines[i])) {
|
|
34
|
+
lines[i] = `theme = ${themeName}`;
|
|
35
|
+
found = true;
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (!found) {
|
|
40
|
+
// Add before first non-empty, non-comment line, or at the top
|
|
41
|
+
lines.unshift(`theme = ${themeName}`);
|
|
42
|
+
}
|
|
43
|
+
writeFileSync(configPath, lines.join("\n"), "utf-8");
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,SAAS,aAAa;IACpB,OAAO,CACL,OAAO,CAAC,GAAG,CAAC,mBAAmB;QAC/B,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,CAChD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,aAAa,EAAE,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACnD,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,SAAiB;IACxC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAElC,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAChC,KAAK,CAAC,CAAC,CAAC,GAAG,WAAW,SAAS,EAAE,CAAC;YAClC,KAAK,GAAG,IAAI,CAAC;YACb,MAAM;QACR,CAAC;IACH,CAAC;IAED,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,8DAA8D;QAC9D,KAAK,CAAC,OAAO,CAAC,WAAW,SAAS,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,aAAa,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function loadFavorites(): string[];
|
|
2
|
+
export declare function saveFavorites(themes: string[]): void;
|
|
3
|
+
export declare function addFavorite(name: string): boolean;
|
|
4
|
+
export declare function removeFavorite(name: string): boolean;
|
|
5
|
+
export declare function isFavorite(name: string): boolean;
|
|
6
|
+
//# sourceMappingURL=favorites.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"favorites.d.ts","sourceRoot":"","sources":["../../src/lib/favorites.ts"],"names":[],"mappings":"AA+BA,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAgBxC;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAIpD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQjD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAWpD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGhD"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
2
|
+
import { join, dirname } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
const DEFAULT_FAVORITES = [
|
|
5
|
+
"Cobalt2",
|
|
6
|
+
"TokyoNight",
|
|
7
|
+
"Dracula",
|
|
8
|
+
"Catppuccin Mocha",
|
|
9
|
+
"Nord",
|
|
10
|
+
"Gruvbox Dark",
|
|
11
|
+
"Solarized Dark Higher Contrast",
|
|
12
|
+
"Atom One Dark",
|
|
13
|
+
"Ayu",
|
|
14
|
+
"Kanagawa Dragon",
|
|
15
|
+
"Rose Pine",
|
|
16
|
+
"Everforest Dark Hard",
|
|
17
|
+
];
|
|
18
|
+
function getFavoritesPath() {
|
|
19
|
+
return join(homedir(), ".config", "ghostty-theme-cli", "favorites.json");
|
|
20
|
+
}
|
|
21
|
+
function ensureDir() {
|
|
22
|
+
const dir = dirname(getFavoritesPath());
|
|
23
|
+
if (!existsSync(dir)) {
|
|
24
|
+
mkdirSync(dir, { recursive: true });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export function loadFavorites() {
|
|
28
|
+
const path = getFavoritesPath();
|
|
29
|
+
if (!existsSync(path)) {
|
|
30
|
+
// Initialize with defaults on first run
|
|
31
|
+
ensureDir();
|
|
32
|
+
const data = { themes: DEFAULT_FAVORITES };
|
|
33
|
+
writeFileSync(path, JSON.stringify(data, null, 2), "utf-8");
|
|
34
|
+
return DEFAULT_FAVORITES;
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
const content = readFileSync(path, "utf-8");
|
|
38
|
+
const data = JSON.parse(content);
|
|
39
|
+
return data.themes;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return DEFAULT_FAVORITES;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export function saveFavorites(themes) {
|
|
46
|
+
ensureDir();
|
|
47
|
+
const data = { themes };
|
|
48
|
+
writeFileSync(getFavoritesPath(), JSON.stringify(data, null, 2), "utf-8");
|
|
49
|
+
}
|
|
50
|
+
export function addFavorite(name) {
|
|
51
|
+
const favorites = loadFavorites();
|
|
52
|
+
if (favorites.some((f) => f.toLowerCase() === name.toLowerCase())) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
favorites.push(name);
|
|
56
|
+
saveFavorites(favorites);
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
export function removeFavorite(name) {
|
|
60
|
+
const favorites = loadFavorites();
|
|
61
|
+
const idx = favorites.findIndex((f) => f.toLowerCase() === name.toLowerCase());
|
|
62
|
+
if (idx === -1) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
favorites.splice(idx, 1);
|
|
66
|
+
saveFavorites(favorites);
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
export function isFavorite(name) {
|
|
70
|
+
const favorites = loadFavorites();
|
|
71
|
+
return favorites.some((f) => f.toLowerCase() === name.toLowerCase());
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=favorites.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"favorites.js","sourceRoot":"","sources":["../../src/lib/favorites.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/lib/prompt.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAsLrE"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
export function select(options) {
|
|
3
|
+
return new Promise((resolve) => {
|
|
4
|
+
const { message, items, currentTheme } = options;
|
|
5
|
+
if (items.length === 0) {
|
|
6
|
+
console.log(chalk.yellow("No items to display."));
|
|
7
|
+
resolve(null);
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
const stdin = process.stdin;
|
|
11
|
+
const stdout = process.stdout;
|
|
12
|
+
let cursor = 0;
|
|
13
|
+
let searchQuery = "";
|
|
14
|
+
let filteredItems = [...items];
|
|
15
|
+
let renderedLines = 0;
|
|
16
|
+
function getPageSize() {
|
|
17
|
+
// Reserve lines for: message, search bar, bottom hint, and padding
|
|
18
|
+
return Math.max(1, (stdout.rows || 24) - 4);
|
|
19
|
+
}
|
|
20
|
+
function getFilteredItems() {
|
|
21
|
+
if (searchQuery === "")
|
|
22
|
+
return items;
|
|
23
|
+
const q = searchQuery.toLowerCase();
|
|
24
|
+
return items.filter((item) => item.toLowerCase().includes(q));
|
|
25
|
+
}
|
|
26
|
+
function render() {
|
|
27
|
+
// Clear previous output
|
|
28
|
+
if (renderedLines > 0) {
|
|
29
|
+
stdout.write(`\x1B[${renderedLines}A`);
|
|
30
|
+
for (let i = 0; i < renderedLines; i++) {
|
|
31
|
+
stdout.write("\x1B[2K\n");
|
|
32
|
+
}
|
|
33
|
+
stdout.write(`\x1B[${renderedLines}A`);
|
|
34
|
+
}
|
|
35
|
+
const lines = [];
|
|
36
|
+
// Header
|
|
37
|
+
lines.push(chalk.bold.cyan(message));
|
|
38
|
+
// Search bar
|
|
39
|
+
if (searchQuery) {
|
|
40
|
+
lines.push(chalk.dim(` 🔍 search: ${searchQuery}`));
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
lines.push(chalk.dim(" Type to search, ↑↓/jk to move, Enter to select, q to cancel"));
|
|
44
|
+
}
|
|
45
|
+
filteredItems = getFilteredItems();
|
|
46
|
+
if (filteredItems.length === 0) {
|
|
47
|
+
lines.push(chalk.yellow(" No matches found."));
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
// Clamp cursor
|
|
51
|
+
if (cursor >= filteredItems.length) {
|
|
52
|
+
cursor = filteredItems.length - 1;
|
|
53
|
+
}
|
|
54
|
+
if (cursor < 0)
|
|
55
|
+
cursor = 0;
|
|
56
|
+
const pageSize = getPageSize();
|
|
57
|
+
const total = filteredItems.length;
|
|
58
|
+
// Calculate viewport
|
|
59
|
+
let start = 0;
|
|
60
|
+
if (total > pageSize) {
|
|
61
|
+
start = Math.max(0, cursor - Math.floor(pageSize / 2));
|
|
62
|
+
if (start + pageSize > total) {
|
|
63
|
+
start = total - pageSize;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const end = Math.min(start + pageSize, total);
|
|
67
|
+
if (start > 0) {
|
|
68
|
+
lines.push(chalk.dim(` ▲ ${start} more above`));
|
|
69
|
+
}
|
|
70
|
+
for (let i = start; i < end; i++) {
|
|
71
|
+
const item = filteredItems[i];
|
|
72
|
+
const isCurrent = currentTheme && item.toLowerCase() === currentTheme.toLowerCase();
|
|
73
|
+
const marker = isCurrent ? chalk.green(" *") : " ";
|
|
74
|
+
if (i === cursor) {
|
|
75
|
+
lines.push(chalk.bgBlue.white(`❯ ${item}`) + marker);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
lines.push(` ${item}${marker}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (end < total) {
|
|
82
|
+
lines.push(chalk.dim(` ▼ ${total - end} more below`));
|
|
83
|
+
}
|
|
84
|
+
lines.push(chalk.dim(` ${total} items`));
|
|
85
|
+
}
|
|
86
|
+
const output = lines.join("\n") + "\n";
|
|
87
|
+
stdout.write(output);
|
|
88
|
+
renderedLines = lines.length;
|
|
89
|
+
}
|
|
90
|
+
// Setup raw mode
|
|
91
|
+
const wasRaw = stdin.isRaw;
|
|
92
|
+
stdin.setRawMode(true);
|
|
93
|
+
stdin.resume();
|
|
94
|
+
stdin.setEncoding("utf-8");
|
|
95
|
+
function cleanup() {
|
|
96
|
+
stdin.setRawMode(wasRaw ?? false);
|
|
97
|
+
stdin.pause();
|
|
98
|
+
stdin.removeListener("data", onKeypress);
|
|
99
|
+
}
|
|
100
|
+
function onKeypress(data) {
|
|
101
|
+
const key = typeof data === "string" ? data : data.toString("utf-8");
|
|
102
|
+
// Ctrl+C
|
|
103
|
+
if (key === "\x03") {
|
|
104
|
+
cleanup();
|
|
105
|
+
stdout.write("\n");
|
|
106
|
+
process.exit(0);
|
|
107
|
+
}
|
|
108
|
+
// Escape or q (only when not searching)
|
|
109
|
+
if ((key === "\x1B" || (key === "q" && searchQuery === "")) && key.length === 1) {
|
|
110
|
+
cleanup();
|
|
111
|
+
stdout.write("\n");
|
|
112
|
+
resolve(null);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
// Enter
|
|
116
|
+
if (key === "\r" || key === "\n") {
|
|
117
|
+
cleanup();
|
|
118
|
+
const selected = filteredItems[cursor];
|
|
119
|
+
stdout.write("\n");
|
|
120
|
+
if (selected) {
|
|
121
|
+
resolve(selected);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
resolve(null);
|
|
125
|
+
}
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
// Arrow up / k (when not searching)
|
|
129
|
+
if (key === "\x1B[A" || (key === "k" && searchQuery === "")) {
|
|
130
|
+
cursor = Math.max(0, cursor - 1);
|
|
131
|
+
render();
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
// Arrow down / j (when not searching)
|
|
135
|
+
if (key === "\x1B[B" || (key === "j" && searchQuery === "")) {
|
|
136
|
+
cursor = Math.min(filteredItems.length - 1, cursor + 1);
|
|
137
|
+
render();
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
// Backspace
|
|
141
|
+
if (key === "\x7F" || key === "\b") {
|
|
142
|
+
if (searchQuery.length > 0) {
|
|
143
|
+
searchQuery = searchQuery.slice(0, -1);
|
|
144
|
+
cursor = 0;
|
|
145
|
+
render();
|
|
146
|
+
}
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
// Printable characters → search
|
|
150
|
+
if (key.length === 1 && key >= " " && key <= "~") {
|
|
151
|
+
searchQuery += key;
|
|
152
|
+
cursor = 0;
|
|
153
|
+
render();
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
stdin.on("data", onKeypress);
|
|
158
|
+
render();
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/lib/prompt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Theme } from "../types.js";
|
|
2
|
+
export declare function listAllThemes(): Theme[];
|
|
3
|
+
export declare function getThemeNames(): string[];
|
|
4
|
+
export declare function themeExists(name: string): boolean;
|
|
5
|
+
export declare function findTheme(name: string): string | undefined;
|
|
6
|
+
//# sourceMappingURL=themes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"themes.d.ts","sourceRoot":"","sources":["../../src/lib/themes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,wBAAgB,aAAa,IAAI,KAAK,EAAE,CAavC;AAED,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAExC;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAIjD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAI1D"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
export function listAllThemes() {
|
|
3
|
+
const output = execSync("ghostty +list-themes", { encoding: "utf-8" });
|
|
4
|
+
return output
|
|
5
|
+
.trim()
|
|
6
|
+
.split("\n")
|
|
7
|
+
.filter((line) => line.length > 0)
|
|
8
|
+
.map((line) => {
|
|
9
|
+
const match = line.match(/^(.+?)\s+\((.+?)\)$/);
|
|
10
|
+
if (match) {
|
|
11
|
+
return { name: match[1], source: match[2] };
|
|
12
|
+
}
|
|
13
|
+
return { name: line.trim(), source: "unknown" };
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export function getThemeNames() {
|
|
17
|
+
return listAllThemes().map((t) => t.name);
|
|
18
|
+
}
|
|
19
|
+
export function themeExists(name) {
|
|
20
|
+
return getThemeNames().some((t) => t.toLowerCase() === name.toLowerCase());
|
|
21
|
+
}
|
|
22
|
+
export function findTheme(name) {
|
|
23
|
+
return getThemeNames().find((t) => t.toLowerCase() === name.toLowerCase());
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=themes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"themes.js","sourceRoot":"","sources":["../../src/lib/themes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAG9C,MAAM,UAAU,aAAa;IAC3B,MAAM,MAAM,GAAG,QAAQ,CAAC,sBAAsB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IACvE,OAAO,MAAM;SACV,IAAI,EAAE;SACN,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;SACjC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QAChD,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9C,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAClD,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,aAAa,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,aAAa,EAAE,CAAC,IAAI,CACzB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,WAAW,EAAE,CAC9C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,aAAa,EAAE,CAAC,IAAI,CACzB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,WAAW,EAAE,CAC9C,CAAC;AACJ,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ghostty-theme",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI tool for managing Ghostty terminal themes",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"ghostty-theme": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsx src/index.ts",
|
|
13
|
+
"prepublishOnly": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"keywords": [
|
|
19
|
+
"ghostty",
|
|
20
|
+
"theme",
|
|
21
|
+
"terminal",
|
|
22
|
+
"cli"
|
|
23
|
+
],
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"chalk": "^5.4.1",
|
|
27
|
+
"commander": "^13.1.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/node": "^22.13.4",
|
|
31
|
+
"tsx": "^4.19.3",
|
|
32
|
+
"typescript": "^5.7.3"
|
|
33
|
+
}
|
|
34
|
+
}
|