@aiwayds/dsh-tui-pi 0.8.2 → 0.9.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 +44 -3
- package/README.zh.md +36 -3
- package/assets/fonts/LICENSE-Hack.txt +45 -0
- package/assets/fonts/LICENSE-NerdFonts.txt +126 -0
- package/assets/fonts/LICENSE-NotoSansSymbols.txt +93 -0
- package/assets/fonts/LICENSE-NotoSansSymbols2.txt +93 -0
- package/assets/fonts/dsh-tui-pi-nerd.ttf +0 -0
- package/assets/fonts-gen.mjs +219 -0
- package/assets/whale-gen.mjs +169 -0
- package/assets/whale-source.png +0 -0
- package/lib/agents.js +1 -1
- package/lib/agents.js.map +1 -1
- package/lib/canvas-terminal.d.ts +17 -11
- package/lib/canvas-terminal.js +62 -24
- package/lib/canvas-terminal.js.map +1 -1
- package/lib/dsh-events.d.ts +32 -3
- package/lib/dsh-events.js +14 -0
- package/lib/dsh-events.js.map +1 -1
- package/lib/font-detect.d.ts +66 -0
- package/lib/font-detect.js +124 -0
- package/lib/font-detect.js.map +1 -0
- package/lib/footer.d.ts +3 -2
- package/lib/footer.js +16 -8
- package/lib/footer.js.map +1 -1
- package/lib/icons.d.ts +53 -0
- package/lib/icons.js +78 -0
- package/lib/icons.js.map +1 -0
- package/lib/index.js +44 -13
- package/lib/index.js.map +1 -1
- package/lib/live-widgets.d.ts +16 -5
- package/lib/live-widgets.js +29 -8
- package/lib/live-widgets.js.map +1 -1
- package/lib/messages.js +2 -1
- package/lib/messages.js.map +1 -1
- package/lib/session.d.ts +99 -16
- package/lib/session.js +322 -64
- package/lib/session.js.map +1 -1
- package/lib/sessions.d.ts +15 -0
- package/lib/sessions.js +18 -3
- package/lib/sessions.js.map +1 -1
- package/lib/settings.js +2 -2
- package/lib/skills.d.ts +19 -3
- package/lib/skills.js +43 -10
- package/lib/skills.js.map +1 -1
- package/lib/subagent-policy.d.ts +11 -11
- package/lib/subagent-policy.js +17 -15
- package/lib/subagent-policy.js.map +1 -1
- package/lib/subagent-viewer.d.ts +20 -5
- package/lib/subagent-viewer.js +29 -15
- package/lib/subagent-viewer.js.map +1 -1
- package/lib/theme-settings.d.ts +25 -10
- package/lib/theme-settings.js +40 -14
- package/lib/theme-settings.js.map +1 -1
- package/lib/tokens.d.ts +38 -0
- package/lib/tokens.js +68 -0
- package/lib/tokens.js.map +1 -0
- package/lib/tui.js +15 -6
- package/lib/tui.js.map +1 -1
- package/package.json +2 -1
- package/scripts/install-font.mjs +329 -0
package/lib/tui.js
CHANGED
|
@@ -30,17 +30,24 @@ export function startTui(options = {}) {
|
|
|
30
30
|
// getter, baked closures below) observes the new bundle on the next call.
|
|
31
31
|
let themeRef = resolveTheme(process.env, options.themePreference ?? 'auto');
|
|
32
32
|
// App-owned canvas: the write-stream decorator injects the palette's
|
|
33
|
-
// canvas
|
|
34
|
-
// canvas-terminal.ts), so a theme switch
|
|
35
|
-
// only the surfaces that paint their own
|
|
36
|
-
//
|
|
33
|
+
// canvas colors around every erase sequence and after every color reset
|
|
34
|
+
// (BCE + re-injection — see canvas-terminal.ts), so a theme switch
|
|
35
|
+
// recolors the WHOLE screen, not only the surfaces that paint their own
|
|
36
|
+
// colors. The foreground matters as much as the background: unstyled
|
|
37
|
+
// content (editor input, unselected picker rows) would otherwise fall
|
|
38
|
+
// back to the terminal's default foreground — dark text when the host
|
|
39
|
+
// terminal is light-themed (pi never paints a canvas so its unstyled
|
|
40
|
+
// text always matches; we paint, so we own both channels). Without the
|
|
41
|
+
// canvas the terminal default background shows through and "freezes" on
|
|
37
42
|
// switch — most visible inside cmux/gostty, where the pane background
|
|
38
43
|
// belongs to the multiplexer. DSH_TUI_TRANSPARENT=1 opts back into the
|
|
39
44
|
// old see-through canvas for users who want their terminal theme to stay
|
|
40
45
|
// visible.
|
|
41
46
|
const paintCanvas = process.env.DSH_TUI_TRANSPARENT !== '1';
|
|
42
|
-
if (paintCanvas)
|
|
47
|
+
if (paintCanvas) {
|
|
43
48
|
terminal.setCanvasBackground(ansiBg(themeRef.palette.canvas));
|
|
49
|
+
terminal.setCanvasForeground(ansiFg(themeRef.palette.fgDefault));
|
|
50
|
+
}
|
|
44
51
|
// ------------------------------------------------------------- component tree --
|
|
45
52
|
// Live Todos widget, pinned ABOVE the chat input: a plain Container with
|
|
46
53
|
// auto height — it renders zero rows while empty and grows to its
|
|
@@ -172,8 +179,10 @@ export function startTui(options = {}) {
|
|
|
172
179
|
if (theme === themeRef)
|
|
173
180
|
return;
|
|
174
181
|
themeRef = theme;
|
|
175
|
-
if (paintCanvas)
|
|
182
|
+
if (paintCanvas) {
|
|
176
183
|
terminal.setCanvasBackground(ansiBg(theme.palette.canvas));
|
|
184
|
+
terminal.setCanvasForeground(ansiFg(theme.palette.fgDefault));
|
|
185
|
+
}
|
|
177
186
|
rebuildEditor();
|
|
178
187
|
// Forced full redraw: the diff renderer skips content-unchanged rows
|
|
179
188
|
// (blank fillers render as '' under both themes), which would leave
|
package/lib/tui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tui.js","sourceRoot":"","sources":["../src/tui.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EACL,SAAS,EACT,UAAU,EACV,eAAe,EACf,UAAU,EACV,MAAM,EACN,IAAI,EACJ,YAAY,EACZ,MAAM,GAGP,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAoC,MAAM,aAAa,CAAA;AAClG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAuC,MAAM,kBAAkB,CAAA;AAqE3G,MAAM,UAAU,QAAQ,CAAC,UAA2B,EAAE;IACpD,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,IAAI,eAAe,EAAE,CAAC,CAAA;IAC1D,MAAM,GAAG,GAAG,IAAI,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IAC5C,wEAAwE;IACxE,0EAA0E;IAC1E,IAAI,QAAQ,GAAa,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,eAAe,IAAI,MAAM,CAAC,CAAA;IACrF,qEAAqE;IACrE,
|
|
1
|
+
{"version":3,"file":"tui.js","sourceRoot":"","sources":["../src/tui.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiwayds/dsh-tui-pi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "pi-style terminal UI for DeepSeek Harness (dsh) — pi-tui look & feel, dsh slash commands, GitHub light/dark themes, powerline footer",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"cordis.patch.yml",
|
|
33
33
|
"scripts",
|
|
34
34
|
"templates",
|
|
35
|
+
"assets",
|
|
35
36
|
"README.md",
|
|
36
37
|
"LICENSE"
|
|
37
38
|
],
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Install the bundled terminal font and point the user's terminal at it.
|
|
4
|
+
*
|
|
5
|
+
* The TUI's icon-set self-adaptation (src/icons.ts) resolves 'auto' to the
|
|
6
|
+
* powerline glyphs only when a Nerd/Powerline-capable font is the terminal's
|
|
7
|
+
* MAIN font — no default terminal font ships the powerline separator U+E0B0,
|
|
8
|
+
* so without one 'auto' falls back to the plain Unicode stand-ins. This
|
|
9
|
+
* script installs the tiny bundled subset (assets/fonts/dsh-tui-pi-nerd.ttf,
|
|
10
|
+
* ASCII + U+E0B0 + the whole project glyph set, ~170KB) and flips the
|
|
11
|
+
* terminal to it, preserving the current font size where the terminal
|
|
12
|
+
* expresses one.
|
|
13
|
+
*
|
|
14
|
+
* Zero dependencies and fully best-effort: every step is wrapped in
|
|
15
|
+
* try/catch — a failure logs a warning and the script moves on. It never
|
|
16
|
+
* aborts mid-way and never corrupts user configuration (config files are
|
|
17
|
+
* backed up before editing and restored on failure; preferences are only
|
|
18
|
+
* written through PlistBuddy/gsettings/defaults with the original value
|
|
19
|
+
* read first).
|
|
20
|
+
*
|
|
21
|
+
* - Font install
|
|
22
|
+
* macOS → cp → ~/Library/Fonts/ (physical copy, never a symlink)
|
|
23
|
+
* Linux → cp → ~/.local/share/fonts/ + fc-cache -f
|
|
24
|
+
* other → skipped (no free font directory)
|
|
25
|
+
*
|
|
26
|
+
* - Terminal config (best-effort, per platform/terminal)
|
|
27
|
+
* macOS iTerm2 → PlistBuddy against the Default Bookmark's
|
|
28
|
+
* "Normal Font" (PostScript name DSHTUINerd,
|
|
29
|
+
* keeping the current size); `defaults write
|
|
30
|
+
* com.googlecode.iterm2 "Normal Font"` as an
|
|
31
|
+
* extra best-effort key.
|
|
32
|
+
* macOS Terminal.app → skipped — its font is a binary blob in the
|
|
33
|
+
* plist; set it by hand (Settings → Profiles →
|
|
34
|
+
* Text → Font).
|
|
35
|
+
* Linux GNOME Terminal → gsettings set use-system-font=false + font on
|
|
36
|
+
* the default profile.
|
|
37
|
+
* Linux kitty / alacritty / wezterm → edit the config file
|
|
38
|
+
* (font_family / [font] family / wezterm.font),
|
|
39
|
+
* backing the file up first and restoring on
|
|
40
|
+
* failure.
|
|
41
|
+
* SSH / xterm / urxvt / unknown / Windows → skipped (no safe write).
|
|
42
|
+
*
|
|
43
|
+
* Usage: node scripts/install-font.mjs
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
import { execFileSync } from 'node:child_process'
|
|
47
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
48
|
+
import { homedir } from 'node:os'
|
|
49
|
+
import { dirname, join } from 'node:path'
|
|
50
|
+
import { fileURLToPath } from 'node:url'
|
|
51
|
+
|
|
52
|
+
const repoRoot = dirname(dirname(fileURLToPath(import.meta.url)))
|
|
53
|
+
const FONT_SRC = join(repoRoot, 'assets', 'fonts', 'dsh-tui-pi-nerd.ttf')
|
|
54
|
+
const FONT_FILE = 'dsh-tui-pi-nerd.ttf'
|
|
55
|
+
/** Family name (font nameID 1) — GNOME/kitty/alacritty/wezterm use this. */
|
|
56
|
+
const FONT_FAMILY = 'DSH TUI Nerd'
|
|
57
|
+
/** PostScript name (font nameID 6) — iTerm2's "Normal Font" key uses this. */
|
|
58
|
+
const FONT_POSTSCRIPT = 'DSHTUINerd'
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The install environment — the real platform/home by default, injected by
|
|
62
|
+
* tests (test scripts point it at a sandbox home / a fake platform to drive
|
|
63
|
+
* the copy + config paths without touching the real home).
|
|
64
|
+
*/
|
|
65
|
+
export const env = {
|
|
66
|
+
platform: process.platform,
|
|
67
|
+
home: homedir(),
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const PLISTBUDDY = '/usr/libexec/PlistBuddy'
|
|
71
|
+
|
|
72
|
+
const log = {
|
|
73
|
+
info: (msg) => console.log(`[install-font] ${msg}`),
|
|
74
|
+
ok: (msg) => console.log(`[install-font] ✓ ${msg}`),
|
|
75
|
+
warn: (msg) => console.warn(`[install-font] ! ${msg}`),
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Run a command; `null` on failure (missing binary, nonzero exit). */
|
|
79
|
+
export function sh(cmd, args) {
|
|
80
|
+
try {
|
|
81
|
+
return execFileSync(cmd, args, { stdio: ['ignore', 'pipe', 'pipe'], encoding: 'utf8' }).trim()
|
|
82
|
+
} catch {
|
|
83
|
+
return null
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** True when the script runs inside an SSH session (terminal config would hit the remote). */
|
|
88
|
+
function isSsh() {
|
|
89
|
+
return Boolean(process.env.SSH_CONNECTION || process.env.SSH_TTY)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ------------------------------------------------------------- font install --
|
|
93
|
+
|
|
94
|
+
/** Copy the bundled font into the platform font directory; false when skipped. */
|
|
95
|
+
export function installFont() {
|
|
96
|
+
if (env.platform === 'darwin') {
|
|
97
|
+
const dir = join(env.home, 'Library', 'Fonts')
|
|
98
|
+
mkdirSync(dir, { recursive: true })
|
|
99
|
+
copyFileSync(FONT_SRC, join(dir, FONT_FILE))
|
|
100
|
+
return dir
|
|
101
|
+
}
|
|
102
|
+
if (env.platform === 'linux') {
|
|
103
|
+
const dir = join(env.home, '.local', 'share', 'fonts')
|
|
104
|
+
mkdirSync(dir, { recursive: true })
|
|
105
|
+
copyFileSync(FONT_SRC, join(dir, FONT_FILE))
|
|
106
|
+
// Refresh the fontconfig cache so the family resolves immediately.
|
|
107
|
+
const refreshed = sh('fc-cache', ['-f', dir])
|
|
108
|
+
if (refreshed === null) log.warn('fc-cache refresh skipped (fc-cache not found)')
|
|
109
|
+
return dir
|
|
110
|
+
}
|
|
111
|
+
log.warn(`font install skipped on ${env.platform} (no free font directory; copy ${FONT_FILE} by hand)`)
|
|
112
|
+
return null
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// --------------------------------------------------------- config file edit --
|
|
116
|
+
|
|
117
|
+
/** Edit a text config file under a backup; restore on failure. Returns true when changed. */
|
|
118
|
+
function editConfigWithBackup(path, transform) {
|
|
119
|
+
if (!existsSync(path)) return false
|
|
120
|
+
const backup = `${path}.dsh-tui.bak`
|
|
121
|
+
try {
|
|
122
|
+
if (!existsSync(backup)) copyFileSync(path, backup)
|
|
123
|
+
const changed = transform(readFileSync(path, 'utf8'))
|
|
124
|
+
if (changed === null) return false
|
|
125
|
+
writeFileSync(path, changed)
|
|
126
|
+
return true
|
|
127
|
+
} catch (error) {
|
|
128
|
+
// Restore the original so a botched edit never leaves a broken config.
|
|
129
|
+
try { copyFileSync(backup, path) } catch { /* best effort */ }
|
|
130
|
+
throw error
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** kitty: `font_family` (replace the existing line, or append one). */
|
|
135
|
+
export function kittyTransform(text) {
|
|
136
|
+
const line = `font_family ${FONT_FAMILY}`
|
|
137
|
+
if (/^\s*font_family\b/m.test(text)) return text.replace(/^\s*font_family\s+.*$/m, line)
|
|
138
|
+
return `${text.replace(/\s*$/, '')}\n${line}\n`
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** alacritty (TOML): `family = "…"` under `[font]`; append a `[font.normal]` block when absent. */
|
|
142
|
+
export function alacrittyTomlTransform(text) {
|
|
143
|
+
if (text.includes('[font')) {
|
|
144
|
+
if (/^\s*family\s*=/m.test(text)) return text.replace(/^(\s*family\s*=\s*")[^"]*(".*)$/m, `$1${FONT_FAMILY}$2`)
|
|
145
|
+
return `${text.replace(/\s*$/, '')}\n[font.normal]\nfamily = "${FONT_FAMILY}"\n`
|
|
146
|
+
}
|
|
147
|
+
return `${text.replace(/\s*$/, '')}\n[font.normal]\nfamily = "${FONT_FAMILY}"\n`
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** alacritty (legacy YAML): `family: "…"` under `font: normal:`; append otherwise. */
|
|
151
|
+
export function alacrittyYmlTransform(text) {
|
|
152
|
+
if (/^font:\s*\n(\s*)normal:\s*\n\s*family:/m.test(text)) {
|
|
153
|
+
return text.replace(/^(font:\s*\n\s*normal:\s*\n\s*family:).*$/m, `$1 "${FONT_FAMILY}"`)
|
|
154
|
+
}
|
|
155
|
+
return `${text.replace(/\s*$/, '')}\nfont:\n normal:\n family: "${FONT_FAMILY}"\n`
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** wezterm: replace `wezterm.font("…")` calls / `config.font`, or append a font line. */
|
|
159
|
+
export function weztermTransform(text) {
|
|
160
|
+
// wezterm.font_with_fallback("Primary", "Fallback", …) — replace only the
|
|
161
|
+
// primary font so the user's fallback list survives.
|
|
162
|
+
if (/wezterm\.font_with_fallback\(\s*"[^"]*"/.test(text)) {
|
|
163
|
+
return text.replace(/wezterm\.font_with_fallback\(\s*"[^"]*"/g, `wezterm.font_with_fallback("${FONT_FAMILY}"`)
|
|
164
|
+
}
|
|
165
|
+
if (/wezterm\.font\(\s*"[^"]*"\s*\)/.test(text)) {
|
|
166
|
+
return text.replace(/wezterm\.font\(\s*"[^"]*"\s*\)/g, `wezterm.font("${FONT_FAMILY}")`)
|
|
167
|
+
}
|
|
168
|
+
const append = `config.font = wezterm.font("${FONT_FAMILY}")`
|
|
169
|
+
if (/^\s*config\.font\s*=/m.test(text)) return text.replace(/^\s*config\.font\s*=.*$/m, append)
|
|
170
|
+
return `${text.replace(/\s*$/, '')}\n${append}\n`
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// ------------------------------------------------------------- iTerm2 (mac) --
|
|
174
|
+
|
|
175
|
+
/** PlistBuddy read of one key; `null` when the key/file is absent. */
|
|
176
|
+
function pbGet(plist, key) {
|
|
177
|
+
return sh(PLISTBUDDY, ['-c', `Print :${key}`, plist])
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** The trailing font-size number of an iTerm2 "Normal Font" value ("Menlo-Regular 13" → "13"). */
|
|
181
|
+
export function parseFontSize(value) {
|
|
182
|
+
const match = value === null ? null : value.match(/(\d+(?:\.\d+)?)\s*$/)
|
|
183
|
+
return match === null ? '12' : match[1]
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** macOS iTerm2: point the default bookmark's "Normal Font" at the bundled font. */
|
|
187
|
+
export function configureIterm2() {
|
|
188
|
+
const plist = join(env.home, 'Library', 'Preferences', 'com.googlecode.iterm2.plist')
|
|
189
|
+
if (!existsSync(plist)) return 'iTerm2 plist not found (start iTerm2 once, then re-run)'
|
|
190
|
+
// PlistBuddy paths: keys with spaces MUST be quoted (`:"New Bookmarks"`).
|
|
191
|
+
const guid = pbGet(plist, '"Default Bookmark Guid"')
|
|
192
|
+
if (guid === null) return 'no Default Bookmark Guid in the iTerm2 plist'
|
|
193
|
+
// Find the bookmark index carrying the default guid (bounded scan).
|
|
194
|
+
let index = -1
|
|
195
|
+
for (let i = 0; i < 128; i++) {
|
|
196
|
+
const candidate = pbGet(plist, `"New Bookmarks":${i}:Guid`)
|
|
197
|
+
if (candidate === null) break
|
|
198
|
+
if (candidate === guid) { index = i; break }
|
|
199
|
+
}
|
|
200
|
+
if (index < 0) return `default bookmark (${guid}) not found in New Bookmarks`
|
|
201
|
+
const size = parseFontSize(pbGet(plist, `"New Bookmarks":${index}:"Normal Font"`))
|
|
202
|
+
const value = `${FONT_POSTSCRIPT} ${size}`
|
|
203
|
+
// Prefer a targeted write on the default bookmark; a direct `defaults write`
|
|
204
|
+
// of the legacy "Normal Font" key is a harmless best-effort extra.
|
|
205
|
+
const pb = sh(PLISTBUDDY, ['-c', `Set :"New Bookmarks":${index}:"Normal Font" "${value}"`, plist])
|
|
206
|
+
const dw = sh('defaults', ['write', 'com.googlecode.iterm2', 'Normal Font', '-string', value])
|
|
207
|
+
if (pb === null && dw === null) return `could not write iTerm2 "Normal Font" (${value})`
|
|
208
|
+
return `iTerm2 default bookmark → "${value}" (size preserved)`
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// ------------------------------------------------------ GNOME Terminal (linux) --
|
|
212
|
+
|
|
213
|
+
/** Strip the surrounding quotes gsettings wraps string values in (`'Ubuntu Mono 11'`). */
|
|
214
|
+
function unquote(value) {
|
|
215
|
+
return value === null ? null : value.replace(/^'|'$/g, '')
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* The font size to preserve when switching a GNOME Terminal profile to the
|
|
220
|
+
* bundled font — the font actually in use: the profile's `font` while
|
|
221
|
+
* `use-system-font` is false, else the desktop monospace font. Raw gsettings
|
|
222
|
+
* string values (possibly null / quoted) in, a numeric size string out, '12'
|
|
223
|
+
* fallback when nothing readable.
|
|
224
|
+
*/
|
|
225
|
+
export function gnomeSizeToPreserve(useSystemFont, profileFont, desktopMono) {
|
|
226
|
+
if (useSystemFont === 'true') return parseFontSize(unquote(desktopMono))
|
|
227
|
+
return parseFontSize(unquote(profileFont))
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/** Linux GNOME Terminal: switch the default profile off system font + set ours. */
|
|
231
|
+
export function configureGnomeTerminal() {
|
|
232
|
+
const profileId = sh('gsettings', ['get', 'org.gnome.Terminal.ProfilesList', 'default'])
|
|
233
|
+
if (profileId === null) return 'gsettings not available (no GNOME Terminal?)'
|
|
234
|
+
const id = profileId.replace(/^'|'$/g, '')
|
|
235
|
+
if (id === '') return 'no default GNOME Terminal profile'
|
|
236
|
+
const base = `org.gnome.Terminal.Legacy.Profile:/org/gnome/terminal/legacy/profiles:/:${id}/`
|
|
237
|
+
// Preserve the current font size: read the font in use before flipping
|
|
238
|
+
// use-system-font off, then backfill our family at that size.
|
|
239
|
+
const size = gnomeSizeToPreserve(
|
|
240
|
+
sh('gsettings', ['get', base, 'use-system-font']),
|
|
241
|
+
sh('gsettings', ['get', base, 'font']),
|
|
242
|
+
sh('gsettings', ['get', 'org.gnome.desktop.interface', 'monospace-font-name']),
|
|
243
|
+
)
|
|
244
|
+
const s1 = sh('gsettings', ['set', base, 'use-system-font', 'false'])
|
|
245
|
+
const s2 = sh('gsettings', ['set', base, 'font', `${FONT_FAMILY} ${size}`])
|
|
246
|
+
if (s1 === null || s2 === null) return `gsettings write failed for profile ${id}`
|
|
247
|
+
return `GNOME Terminal profile ${id} → "${FONT_FAMILY} ${size}" (use-system-font off)`
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// ------------------------------------------------------ linux config terminals --
|
|
251
|
+
|
|
252
|
+
/** Linux kitty/alacritty/wezterm: edit the detected config files (best-effort). */
|
|
253
|
+
export function configureLinuxConfigFiles() {
|
|
254
|
+
const candidates = [
|
|
255
|
+
[join(env.home, '.config', 'kitty', 'kitty.conf'), kittyTransform, 'kitty'],
|
|
256
|
+
[join(env.home, '.config', 'alacritty', 'alacritty.toml'), alacrittyTomlTransform, 'alacritty'],
|
|
257
|
+
[join(env.home, '.config', 'alacritty', 'alacritty.yml'), alacrittyYmlTransform, 'alacritty'],
|
|
258
|
+
[join(env.home, '.config', 'wezterm', 'wezterm.lua'), weztermTransform, 'wezterm'],
|
|
259
|
+
]
|
|
260
|
+
const changed = []
|
|
261
|
+
for (const [path, transform, name] of candidates) {
|
|
262
|
+
if (!existsSync(path)) continue
|
|
263
|
+
try {
|
|
264
|
+
if (editConfigWithBackup(path, transform)) changed.push(`${name} (${path})`)
|
|
265
|
+
} catch (error) {
|
|
266
|
+
log.warn(`${name} config edit failed (${path} restored): ${error instanceof Error ? error.message : String(error)}`)
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return changed
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// --------------------------------------------------------------- dispatcher --
|
|
273
|
+
|
|
274
|
+
/** Best-effort per-platform terminal configuration; returns the summary line. */
|
|
275
|
+
export function configureTerminal() {
|
|
276
|
+
if (isSsh()) {
|
|
277
|
+
log.warn('SSH session detected — skipping terminal config (set the font in the local terminal)')
|
|
278
|
+
return null
|
|
279
|
+
}
|
|
280
|
+
if (env.platform === 'darwin') {
|
|
281
|
+
const result = (() => { try { return configureIterm2() } catch (error) { return `iTerm2 config failed: ${error instanceof Error ? error.message : String(error)}` } })()
|
|
282
|
+
log.ok(result)
|
|
283
|
+
log.warn('Terminal.app is not supported (its font is a binary blob) — set it in Settings → Profiles → Text')
|
|
284
|
+
return result
|
|
285
|
+
}
|
|
286
|
+
if (env.platform === 'linux') {
|
|
287
|
+
const gnome = (() => { try { return configureGnomeTerminal() } catch (error) { return `GNOME Terminal config failed: ${error instanceof Error ? error.message : String(error)}` } })()
|
|
288
|
+
log.ok(gnome)
|
|
289
|
+
const changed = configureLinuxConfigFiles()
|
|
290
|
+
if (changed.length === 0) log.warn('no kitty/alacritty/wezterm config file found to edit')
|
|
291
|
+
for (const entry of changed) log.ok(`config updated: ${entry}`)
|
|
292
|
+
return `${gnome}${changed.length > 0 ? `; ${changed.length} config file(s) updated` : ''}`
|
|
293
|
+
}
|
|
294
|
+
log.warn(`terminal config not supported on ${env.platform} (xterm/urxvt/Windows) — set the font by hand`)
|
|
295
|
+
return null
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// ------------------------------------------------------------------- main --
|
|
299
|
+
|
|
300
|
+
function main() {
|
|
301
|
+
log.info('dsh-tui-pi font installer (icon-set "auto" needs a Nerd/Powerline font)')
|
|
302
|
+
if (!existsSync(FONT_SRC)) {
|
|
303
|
+
log.warn(`bundled font not found: ${FONT_SRC}`)
|
|
304
|
+
log.warn('generate it first with: node assets/fonts-gen.mjs')
|
|
305
|
+
return
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
let installDir = null
|
|
309
|
+
try {
|
|
310
|
+
installDir = installFont()
|
|
311
|
+
if (installDir !== null) log.ok(`installed ${FONT_FILE} → ${installDir}`)
|
|
312
|
+
} catch (error) {
|
|
313
|
+
log.warn(`font install failed: ${error instanceof Error ? error.message : String(error)}`)
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const summary = installDir !== null ? configureTerminal() : null
|
|
317
|
+
|
|
318
|
+
log.info('--- result ---')
|
|
319
|
+
log.info(installDir !== null
|
|
320
|
+
? `font installed: ${FONT_FILE} (${FONT_FAMILY} / ${FONT_POSTSCRIPT})`
|
|
321
|
+
: 'font NOT installed — see the warnings above')
|
|
322
|
+
log.info(summary !== null ? `terminal config: ${summary}` : 'terminal config: skipped — see the notes above')
|
|
323
|
+
log.info('restart the terminal (or open a new tab) — auto icon-set now resolves to the powerline glyphs')
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Run directly (`node scripts/install-font.mjs`); importable for tests otherwise.
|
|
327
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
328
|
+
main()
|
|
329
|
+
}
|