dshtui-format-setting 0.3.1
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/CHANGELOG.md +23 -0
- package/LICENSE +21 -0
- package/README.md +50 -0
- package/README.zh.md +41 -0
- package/cordis.patch.yml +4 -0
- package/dsh-plugin.json +30 -0
- package/lib/index.js +151 -0
- package/lib/win32.js +117 -0
- package/package.json +34 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
## 0.3.1 (2026-09-13)
|
|
6
|
+
|
|
7
|
+
- Documentation only: added an English `README.md` and moved the Chinese copy to
|
|
8
|
+
`README.zh.md`, with reciprocal language links. The settings card was already
|
|
9
|
+
bilingual and the code is unchanged.
|
|
10
|
+
- Both READMEs now state the platform limitation and the settings surface
|
|
11
|
+
explicitly, and the published `files` list carries `README.zh.md` and this
|
|
12
|
+
changelog.
|
|
13
|
+
|
|
14
|
+
## 0.3.0 (2026-09-12)
|
|
15
|
+
|
|
16
|
+
- The “Style / Startup window settings” group page was removed: the section is
|
|
17
|
+
now named **Window** and the maximize switch sits directly on the card.
|
|
18
|
+
|
|
19
|
+
## 0.2.0 (2026-09-07)
|
|
20
|
+
|
|
21
|
+
- Removed the font settings (5+ families, 12–28 sizes, per-user font
|
|
22
|
+
installation), the size presets and “save current size”.
|
|
23
|
+
- Kept a single window control: maximize the terminal on startup.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 VviLliAm-qwq
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# dshtui-format-setting
|
|
2
|
+
|
|
3
|
+
**English** · [中文](README.zh.md)
|
|
4
|
+
|
|
5
|
+
Lightweight window settings for dsh-tui.
|
|
6
|
+
|
|
7
|
+
- **Maximize on startup** — dsh-tui maximizes the terminal window when it starts.
|
|
8
|
+
It lives in the **Window** section of the settings screen: one switch, applied
|
|
9
|
+
the moment it is turned on.
|
|
10
|
+
- The switch is shown directly on the section card; there is no group page to
|
|
11
|
+
open first (since 0.3.0).
|
|
12
|
+
- The settings card is bilingual (Chinese/English), rendered by the host in the
|
|
13
|
+
language `/lang` selected.
|
|
14
|
+
- Window control goes through Win32 APIs (the classic console host); any other
|
|
15
|
+
host degrades to a warning log instead of failing.
|
|
16
|
+
- **Removed in 0.2.0:** font settings (5+ families, 12–28 sizes, per-user font
|
|
17
|
+
installation), size presets and “save current size”.
|
|
18
|
+
- **0.3.0:** the “Style / Startup window settings” group page is gone; the
|
|
19
|
+
section is named **Window** and the switch sits directly on it.
|
|
20
|
+
|
|
21
|
+
Restart dsh-tui after installing.
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
dsh plugin --profile dsh-tui add dshtui-format-setting
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Restart dsh-tui (`/restart`) afterwards.
|
|
30
|
+
|
|
31
|
+
## Settings
|
|
32
|
+
|
|
33
|
+
| Field | Type | Default | Meaning |
|
|
34
|
+
| --- | --- | --- | --- |
|
|
35
|
+
| Maximize on startup | boolean | `false` | Maximize the terminal window when dsh-tui starts; turning it on applies immediately. |
|
|
36
|
+
|
|
37
|
+
## Limitations
|
|
38
|
+
|
|
39
|
+
- Window control is Win32-only (the classic console host). On other hosts the
|
|
40
|
+
plugin logs a warning and does nothing.
|
|
41
|
+
- The plugin registers the settings namespace `dshtui-format-setting`; a host
|
|
42
|
+
without a settings service keeps the switch inert rather than failing.
|
|
43
|
+
|
|
44
|
+
## Publishing
|
|
45
|
+
|
|
46
|
+
- **Repository**: <https://github.com/VviLliAm-qwq/dshtui-format-setting> (public)
|
|
47
|
+
|
|
48
|
+
## License
|
|
49
|
+
|
|
50
|
+
MIT — see [LICENSE](LICENSE).
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# dshtui-format-setting
|
|
2
|
+
|
|
3
|
+
**中文** · [English](README.md)
|
|
4
|
+
|
|
5
|
+
dsh-tui 窗口设置插件(精简版)。
|
|
6
|
+
|
|
7
|
+
- **开机时最大化**:dsh-tui 启动时将终端窗口最大化。设置项位于设置页的「窗口设置」分区:单个开关,打开即立即应用。
|
|
8
|
+
- 开关**直接显示在分区卡片上**,无需再点进分组页面(0.3.0 起)。
|
|
9
|
+
- 设置卡片中英双语,由宿主按 `/lang` 当前语言渲染。
|
|
10
|
+
- 窗口控制通过 Win32 API(经典控制台宿主)完成;其他宿主降级为一条警告日志,不会导致启动失败。
|
|
11
|
+
- **0.2.0 起移除**:字体设置(5+ 字体种类、12–28 档大小、随包字体用户级安装)、尺寸预设、保存当前尺寸。
|
|
12
|
+
- **0.3.0**:「样式 / 启动窗口设置」分组页移除,分区更名为「窗口设置」,开关直达。
|
|
13
|
+
|
|
14
|
+
安装后需重启 dsh-tui 生效。
|
|
15
|
+
|
|
16
|
+
## 安装
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
dsh plugin --profile dsh-tui add dshtui-format-setting
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
之后在 dsh-tui 内 `/restart` 生效。
|
|
23
|
+
|
|
24
|
+
## 设置
|
|
25
|
+
|
|
26
|
+
| 字段 | 类型 | 默认 | 说明 |
|
|
27
|
+
| --- | --- | --- | --- |
|
|
28
|
+
| Maximize on startup / 开机时最大化 | boolean | `false` | dsh-tui 启动时将终端窗口最大化;打开此开关时立即应用。 |
|
|
29
|
+
|
|
30
|
+
## 已知限制
|
|
31
|
+
|
|
32
|
+
- 窗口控制仅支持 Win32(经典控制台宿主);其他宿主只记一条警告,不做任何事。
|
|
33
|
+
- 插件读写设置命名空间 `dshtui-format-setting`;宿主没有设置服务时,开关保持惰性而不会报错。
|
|
34
|
+
|
|
35
|
+
## 发布
|
|
36
|
+
|
|
37
|
+
- **仓库**:<https://github.com/VviLliAm-qwq/dshtui-format-setting>(公开)
|
|
38
|
+
|
|
39
|
+
## 许可
|
|
40
|
+
|
|
41
|
+
MIT — 见 [LICENSE](LICENSE)。
|
package/cordis.patch.yml
ADDED
package/dsh-plugin.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://dsh.community/schemas/dsh-plugin-0.15.json",
|
|
3
|
+
"manifestVersion": "0.15",
|
|
4
|
+
"id": "com.dsh-tui.dshtui-format-setting",
|
|
5
|
+
"name": "dshtui-format-setting",
|
|
6
|
+
"version": "0.3.1",
|
|
7
|
+
"facets": {
|
|
8
|
+
"host": {
|
|
9
|
+
"entry": "lib/index.js",
|
|
10
|
+
"apiVersion": "v1alpha1"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"requires": {
|
|
14
|
+
"contracts": [
|
|
15
|
+
{
|
|
16
|
+
"apiVersion": "tui.dsh/v1alpha1",
|
|
17
|
+
"kind": "SettingsSection"
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"contributes": {
|
|
22
|
+
"commands": []
|
|
23
|
+
},
|
|
24
|
+
"permissions": [],
|
|
25
|
+
"subscriptions": [],
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"source": {
|
|
28
|
+
"repository": "https://github.com/VviLliAm-qwq/dshtui-format-setting"
|
|
29
|
+
}
|
|
30
|
+
}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dshtui-format-setting — startup-window "maximize on startup" toggle for
|
|
3
|
+
* dsh-tui, surfaced as a native "Window" settings section (zh/en). On
|
|
4
|
+
* dsh-tui start (and again when the toggle is switched on) the user's
|
|
5
|
+
* terminal window is maximized.
|
|
6
|
+
*
|
|
7
|
+
* Since 0.3.0 the toggle is rendered directly on the section card — the
|
|
8
|
+
* "Startup Window" group page was removed so no subpage click is needed.
|
|
9
|
+
*
|
|
10
|
+
* Font settings (family/size/pixel-font install), size presets and
|
|
11
|
+
* save-current-size were removed in 0.2.0.
|
|
12
|
+
*
|
|
13
|
+
* @module dshtui-format-setting
|
|
14
|
+
*/
|
|
15
|
+
import { dirname, join } from 'node:path';
|
|
16
|
+
import { fileURLToPath } from 'node:url';
|
|
17
|
+
import z from '@deepseek-ai/schemastery';
|
|
18
|
+
import { appendFileSync } from 'node:fs';
|
|
19
|
+
import { homedir } from 'node:os';
|
|
20
|
+
import * as win32 from './win32.js';
|
|
21
|
+
|
|
22
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
23
|
+
const DIAG_LOG = join(homedir(), '.dsh-tui', 'dshtui-format-setting.log');
|
|
24
|
+
|
|
25
|
+
/** Append a diagnostic line (best-effort; never throws). */
|
|
26
|
+
function diag(line) {
|
|
27
|
+
try { appendFileSync(DIAG_LOG, `${new Date().toISOString()} ${line}\n`); } catch { /* ignore */ }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const name = 'dshtui-format-setting';
|
|
31
|
+
|
|
32
|
+
/** Settings schema (stored in the dsh settings service as `dshtui-format-setting`). */
|
|
33
|
+
export const Config = z.object({
|
|
34
|
+
maximizeOnStartup: z.boolean().default(true),
|
|
35
|
+
});
|
|
36
|
+
/** Explicit boot defaults (mirrors the schema defaults). */
|
|
37
|
+
const DEFAULT_CONFIG = {
|
|
38
|
+
maximizeOnStartup: true,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/** Register the native "Window" settings section: a single maximize toggle,
|
|
42
|
+
* rendered directly on the card (no group page, no extra click). */
|
|
43
|
+
function registerSection(sections) {
|
|
44
|
+
return sections.register({
|
|
45
|
+
ns: 'dshtui-format-setting',
|
|
46
|
+
title: 'Window',
|
|
47
|
+
descriptions: { zh: '窗口设置', en: 'Window' },
|
|
48
|
+
fields: [
|
|
49
|
+
{
|
|
50
|
+
path: ['maximizeOnStartup'], label: 'Maximize on startup', descriptions: { zh: '开机时最大化', en: 'Maximize on startup' },
|
|
51
|
+
kind: 'boolean',
|
|
52
|
+
hint: 'Maximizes the terminal window when dsh-tui starts; toggling this on applies it immediately.',
|
|
53
|
+
hintDescriptions: { zh: 'dsh-tui 启动时将终端窗口最大化;打开此开关时立即应用。', en: 'Maximizes the terminal window when dsh-tui starts; toggling this on applies it immediately.' },
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Maximize the user's terminal window (best-effort, diag-logged). */
|
|
60
|
+
function applyMaximize(cfg, source) {
|
|
61
|
+
if (!cfg.maximizeOnStartup) {
|
|
62
|
+
diag(`${source}: maximizeOnStartup off — skipped`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const hwnd = win32.findHostWindow();
|
|
66
|
+
if (hwnd === null) {
|
|
67
|
+
diag(`${source}: no terminal window found`);
|
|
68
|
+
ctxLogger?.warn?.('dshtui-format-setting: no terminal window found — maximize skipped');
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const res = win32.setWindowState(hwnd, 'maximized');
|
|
72
|
+
diag(`${source}: setWindowState maximized => ${res.ok ? 'ok' : res.error}`);
|
|
73
|
+
if (!res.ok) ctxLogger?.warn?.(`dshtui-format-setting: maximize failed: ${res.error}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// module-level logger bridge (set in apply)
|
|
77
|
+
let ctxLogger = null;
|
|
78
|
+
|
|
79
|
+
const RETRY_MS = 400;
|
|
80
|
+
const RETRY_LIMIT = 60; // ~24s of service readiness attempts
|
|
81
|
+
|
|
82
|
+
export function apply(ctx, config) {
|
|
83
|
+
diag('apply started');
|
|
84
|
+
ctxLogger = ctx.logger;
|
|
85
|
+
ctx.effect(function* () {
|
|
86
|
+
let scope = null;
|
|
87
|
+
let sectionRegistered = false;
|
|
88
|
+
let sectionDisposer = null;
|
|
89
|
+
let watchDisposer = null;
|
|
90
|
+
let applied = false;
|
|
91
|
+
let attempts = 0;
|
|
92
|
+
let retryTimer = null;
|
|
93
|
+
|
|
94
|
+
function tryOnce() {
|
|
95
|
+
// settings namespace
|
|
96
|
+
if (scope === null) {
|
|
97
|
+
const settings = ctx.get('settings');
|
|
98
|
+
if (settings !== undefined) {
|
|
99
|
+
try {
|
|
100
|
+
scope = settings.register('dshtui-format-setting', Config);
|
|
101
|
+
diag('settings namespace registered');
|
|
102
|
+
ctxLogger?.info?.('dshtui-format-setting: settings namespace registered');
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
ctxLogger?.warn?.(`dshtui-format-setting: settings register failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// settings section
|
|
110
|
+
if (!sectionRegistered) {
|
|
111
|
+
const sections = ctx.get('tuiSettingsSections');
|
|
112
|
+
if (sections !== undefined) {
|
|
113
|
+
try {
|
|
114
|
+
sectionDisposer = registerSection(sections);
|
|
115
|
+
sectionRegistered = true;
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
ctxLogger?.warn?.(`dshtui-format-setting: settings section failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// boot application + live watch, once the namespace is registered
|
|
123
|
+
if (scope !== null && !applied) {
|
|
124
|
+
applied = true;
|
|
125
|
+
const bootCfg = { ...DEFAULT_CONFIG, ...scope.get() };
|
|
126
|
+
applyMaximize(bootCfg, 'boot');
|
|
127
|
+
watchDisposer = scope.watch((next) => {
|
|
128
|
+
applyMaximize({ ...DEFAULT_CONFIG, ...next }, 'watch');
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
// done?
|
|
132
|
+
if (scope !== null && sectionRegistered && applied) {
|
|
133
|
+
if (retryTimer !== null) { clearInterval(retryTimer); retryTimer = null; }
|
|
134
|
+
}
|
|
135
|
+
else if (++attempts >= RETRY_LIMIT) {
|
|
136
|
+
ctxLogger?.warn?.(`dshtui-format-setting: services did not all appear within ${(RETRY_LIMIT * RETRY_MS) / 1000}s (settings=${scope !== null}, section=${sectionRegistered}, applied=${applied})`);
|
|
137
|
+
if (retryTimer !== null) { clearInterval(retryTimer); retryTimer = null; }
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
retryTimer = setInterval(tryOnce, RETRY_MS);
|
|
142
|
+
tryOnce();
|
|
143
|
+
|
|
144
|
+
yield () => {
|
|
145
|
+
if (retryTimer !== null) clearInterval(retryTimer);
|
|
146
|
+
try { watchDisposer?.(); } catch { /* best-effort */ }
|
|
147
|
+
try { sectionDisposer?.(); } catch { /* best-effort */ }
|
|
148
|
+
ctxLogger = null;
|
|
149
|
+
};
|
|
150
|
+
}, 'dshtui-format-setting lifecycle');
|
|
151
|
+
}
|
package/lib/win32.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin koffi wrappers for the Win32 window APIs the dshtui-format-setting
|
|
3
|
+
* plugin needs: locate the user's terminal window and maximize it.
|
|
4
|
+
*
|
|
5
|
+
* Architecture note (verified): the dsh-tui plugin runs in the profile-host
|
|
6
|
+
* process, whose own console is a hidden ConPTY (0x0). The USER's terminal
|
|
7
|
+
* window is a separate top-level window — `CASCADIA_HOSTING_WINDOW_CLASS`
|
|
8
|
+
* (Windows Terminal) or `ConsoleWindowClass` (classic console). We enumerate
|
|
9
|
+
* visible host-class windows and pick by priority: the foreground window when
|
|
10
|
+
* it is a host-class window, then the first visible one whose title mentions
|
|
11
|
+
* a shell/dsh keyword, then the first visible one.
|
|
12
|
+
*
|
|
13
|
+
* Font-default and window-size APIs were removed in 0.2.0.
|
|
14
|
+
*
|
|
15
|
+
* Every call returns a plain result ({ok:true,...} | {ok:false, error}).
|
|
16
|
+
*/
|
|
17
|
+
import koffi from 'koffi';
|
|
18
|
+
|
|
19
|
+
const PVOID = koffi.pointer('void');
|
|
20
|
+
const CALLBACK = koffi.pointer(koffi.proto('int (void* hwnd)'));
|
|
21
|
+
|
|
22
|
+
const SW_MINIMIZE = 6;
|
|
23
|
+
const SW_MAXIMIZE = 3;
|
|
24
|
+
const SW_RESTORE = 9;
|
|
25
|
+
const HOST_CLASSES = new Set(['ConsoleWindowClass', 'CASCADIA_HOSTING_WINDOW_CLASS']);
|
|
26
|
+
const TITLE_KEYWORDS = ['powershell', 'command prompt', 'cmd', 'deepseek', 'dsh', 'terminal'];
|
|
27
|
+
|
|
28
|
+
let libs = null;
|
|
29
|
+
function bind() {
|
|
30
|
+
if (libs !== null) return libs;
|
|
31
|
+
const user32 = koffi.load('user32.dll');
|
|
32
|
+
const api = (lib, n, r, a) => lib.func('__stdcall', n, r, a);
|
|
33
|
+
libs = {
|
|
34
|
+
user32,
|
|
35
|
+
isWindowVisible: api(user32, 'IsWindowVisible', 'int', [PVOID]),
|
|
36
|
+
getClassNameW: api(user32, 'GetClassNameW', 'int', [PVOID, 'void*', 'int']),
|
|
37
|
+
getWindowTextW: api(user32, 'GetWindowTextW', 'int', [PVOID, 'void*', 'int']),
|
|
38
|
+
enumWindows: api(user32, 'EnumWindows', 'int', [CALLBACK, 'void*']),
|
|
39
|
+
getForegroundWindow: api(user32, 'GetForegroundWindow', PVOID, []),
|
|
40
|
+
showWindow: api(user32, 'ShowWindow', 'int', [PVOID, 'int']),
|
|
41
|
+
};
|
|
42
|
+
return libs;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function wstr(buf) {
|
|
46
|
+
let i = 0;
|
|
47
|
+
for (i = 0; i + 1 < buf.length; i += 2) {
|
|
48
|
+
if (buf[i] === 0 && buf[i + 1] === 0) break;
|
|
49
|
+
}
|
|
50
|
+
return buf.subarray(0, i).toString('utf16le');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function classNameOf(hwnd) {
|
|
54
|
+
const buf = Buffer.alloc(400);
|
|
55
|
+
bind().getClassNameW(hwnd, buf, 200);
|
|
56
|
+
return wstr(buf);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Locate the user's terminal window.
|
|
61
|
+
* Strategy — enumerate visible host-class windows and pick by priority:
|
|
62
|
+
* 1. the foreground window when it is a host-class window;
|
|
63
|
+
* 2. the first visible host-class window whose title mentions a shell/dsh
|
|
64
|
+
* keyword (powershell/cmd/dsh/deepseek/…);
|
|
65
|
+
* 3. the first visible host-class window.
|
|
66
|
+
*/
|
|
67
|
+
export function findHostWindow() {
|
|
68
|
+
try {
|
|
69
|
+
const b = bind();
|
|
70
|
+
const fg = b.getForegroundWindow();
|
|
71
|
+
if (fg !== null && b.isWindowVisible(fg) && HOST_CLASSES.has(classNameOf(fg))) return fg;
|
|
72
|
+
const windows = enumerateHostWindows(b);
|
|
73
|
+
if (windows.length === 0) return null;
|
|
74
|
+
const byKeyword = windows.filter(w => TITLE_KEYWORDS.some(k => w.title.toLowerCase().includes(k)));
|
|
75
|
+
if (byKeyword.length > 0) return byKeyword[0].hwnd;
|
|
76
|
+
return windows[0].hwnd;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** All visible top-level windows whose class is a console host. */
|
|
84
|
+
function enumerateHostWindows(b) {
|
|
85
|
+
const list = [];
|
|
86
|
+
let cb = null;
|
|
87
|
+
const instance = koffi.register((hwnd) => {
|
|
88
|
+
if (!b.isWindowVisible(hwnd)) return 1;
|
|
89
|
+
let cls;
|
|
90
|
+
try { cls = classNameOf(hwnd); } catch { return 1; }
|
|
91
|
+
if (!HOST_CLASSES.has(cls)) return 1;
|
|
92
|
+
const titleBuf = Buffer.alloc(1200);
|
|
93
|
+
b.getWindowTextW(hwnd, titleBuf, 600);
|
|
94
|
+
list.push({ hwnd, title: wstr(titleBuf) });
|
|
95
|
+
return 1;
|
|
96
|
+
}, CALLBACK);
|
|
97
|
+
cb = instance;
|
|
98
|
+
try {
|
|
99
|
+
b.enumWindows(cb, null);
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
try { cb?.unref?.(); } catch { /* best-effort */ }
|
|
103
|
+
}
|
|
104
|
+
return list;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Minimize / restore / maximize the given terminal window. */
|
|
108
|
+
export function setWindowState(hwnd, state) {
|
|
109
|
+
try {
|
|
110
|
+
const cmd = state === 'minimized' ? SW_MINIMIZE : state === 'maximized' ? SW_MAXIMIZE : SW_RESTORE;
|
|
111
|
+
bind().showWindow(hwnd, cmd);
|
|
112
|
+
return { ok: true, state };
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
return { ok: false, error: error instanceof Error ? error.message : String(error) };
|
|
116
|
+
}
|
|
117
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dshtui-format-setting",
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "Window settings for dsh-tui (lightweight): startup-window maximize toggle, native Window settings section (toggle directly on card, no group page), zh/en. Font and size-preset settings removed in 0.2.0; group page removed in 0.3.0.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/VviLliAm-qwq/dshtui-format-setting.git"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"main": "lib/index.js",
|
|
12
|
+
"files": [
|
|
13
|
+
"lib",
|
|
14
|
+
"dsh-plugin.json",
|
|
15
|
+
"cordis.patch.yml",
|
|
16
|
+
"README.md",
|
|
17
|
+
"README.zh.md",
|
|
18
|
+
"CHANGELOG.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"dsh": {
|
|
22
|
+
"bundle": {
|
|
23
|
+
"patch": "./cordis.patch.yml"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": "^22.19 || >=24"
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
31
|
+
"@deepseek-ai/schemastery": "^3.18.1",
|
|
32
|
+
"koffi": "^3.1.0"
|
|
33
|
+
}
|
|
34
|
+
}
|