@havocrao/picktui 0.1.0 → 0.1.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.
@@ -0,0 +1,48 @@
1
+ import type { Candidate, FilterOptions } from './types.js';
2
+ export declare function setColorEnabled(v: boolean): void;
3
+ export declare function isColorEnabled(): boolean;
4
+ /** 过滤选择器配置。 */
5
+ export interface ModelOpts {
6
+ title: string;
7
+ subtitle?: string;
8
+ cands: Candidate[];
9
+ query: string;
10
+ filterOpts: FilterOptions;
11
+ initial: number;
12
+ jumpKeys: boolean;
13
+ statusHint: string;
14
+ multi: boolean;
15
+ selected: string[];
16
+ }
17
+ /** TUI 状态(不可变更新)。 */
18
+ export interface UiModel {
19
+ opts: ModelOpts;
20
+ filtered: Candidate[];
21
+ query: string;
22
+ cursor: number;
23
+ scrollY: number;
24
+ height: number;
25
+ width: number;
26
+ phase: number;
27
+ cancelled: boolean;
28
+ quit: boolean;
29
+ selected: Set<string>;
30
+ }
31
+ /** 按键(数字 '1'...'9'、字母等作为字符串传入)。 */
32
+ export type KeyLike = string | {
33
+ type: 'char';
34
+ value: string;
35
+ };
36
+ export declare function newModel(opts: ModelOpts): UiModel;
37
+ /** 多选模式:按 Cands 顺序返回勾选的 Value 列表。 */
38
+ export declare function selectedValues(m: UiModel): string[];
39
+ /** 处理一个按键,返回新模型(不可变;变化时替换字段)。 */
40
+ export declare function update(m: UiModel, key: KeyLike): UiModel;
41
+ /** 渲染整屏画面(带 ANSI 样式)。 */
42
+ export declare function view(m: UiModel): string;
43
+ /** 按显示宽度截断 s,超长末尾补 …。 */
44
+ export declare function truncateWidth(s: string, maxWidth: number): string;
45
+ /** 字符显示宽度(简化 wcwidth:CJK/全角=2,控制符=0,其余=1)。 */
46
+ export declare function charWidth(ch: string): number;
47
+ /** 字符串显示宽度。 */
48
+ export declare function displayWidth(s: string): number;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * toml — 极简 TOML 子集解析/编码(仅覆盖 history.toml / confirm.toml 所需结构)。
3
+ *
4
+ * 兼容 Go 引擎(BurntSushi/toml)写出的文件:
5
+ * - 注释行(# …)、空行
6
+ * - 表头 `[table]` / `["quoted key"]`
7
+ * - `key = "string"`(含基本字符串转义 \n \t \" \\ \r \b \f \uXXXX)
8
+ * - `"label" = ["a", "b"]`(字符串数组)
9
+ * 值仅支持 string / string[]——本包状态文件所需的最小类型集。
10
+ */
11
+ export type TomlValue = string | string[];
12
+ /** 解析结果:表名 → { key: 值 }(保持文件内出现顺序)。 */
13
+ export type TomlDoc = Map<string, Map<string, TomlValue>>;
14
+ /** 转义字符串内容(写入值时用)。 */
15
+ export declare function escapeTomlString(s: string): string;
16
+ /** 带引号的字符串字面量(含转义)。 */
17
+ export declare function quoteTomlString(s: string): string;
18
+ /** 表头/键名编码:裸 key 直接输出,否则带引号。 */
19
+ export declare function keyLiteral(key: string): string;
20
+ /**
21
+ * 解析 TOML 子集。无法解析的行跳过(容错:状态文件损坏不阻断主流程)。
22
+ * 无任何可解析内容时返回 null。
23
+ */
24
+ export declare function parseToml(text: string): TomlDoc | null;
@@ -0,0 +1,42 @@
1
+ import { ReadStream, WriteStream } from 'node:tty';
2
+ /** 交互终端句柄。 */
3
+ export interface Tty {
4
+ read: ReadStream;
5
+ write: WriteStream;
6
+ /** 终端尺寸(列)。 */
7
+ columns: number;
8
+ /** 终端尺寸(行)。 */
9
+ rows: number;
10
+ }
11
+ /** 按键(对齐引擎 model 的键位集合;数字作为字符处理)。 */
12
+ export type Key = 'enter' | 'esc' | 'up' | 'down' | 'tab' | 'backspace' | 'ctrl+u' | 'ctrl+w' | 'ctrl+c' | 'ctrl+p' | 'ctrl+n' | 'space' | {
13
+ type: 'char';
14
+ value: string;
15
+ };
16
+ /** 尝试打开交互终端;不可用返回 null(调用方退化为非交互)。 */
17
+ export declare function openTty(): Tty | null;
18
+ /** 进入交互模式:备用屏幕 + 隐藏光标 + raw input。 */
19
+ export declare function enterInteractive(tty: Tty): void;
20
+ /** 退出交互模式:恢复原始终端状态。 */
21
+ export declare function exitInteractive(tty: Tty): void;
22
+ /** 全量重绘一帧画面。 */
23
+ export declare function renderFrame(tty: Tty, frame: string): void;
24
+ /** 单行确认询问(auto 首次确认):canonical 输入整行 y/N,超时默认拒绝。 */
25
+ export declare function promptConfirm(tty: Tty, text: string, timeoutMs?: number): Promise<string | null>;
26
+ /**
27
+ * KeyReader — raw 输入流 → 按键序列解析。
28
+ *
29
+ * 支持:ASCII 字符、UTF-8 多字节字符、回车/退格/控制键、CSI 序列
30
+ * (\x1b[A 上、\x1b[B 下、\x1b[C 右、\x1b[D 左)。
31
+ */
32
+ export declare class KeyReader {
33
+ private decoder;
34
+ private buf;
35
+ private waiters;
36
+ private closed;
37
+ constructor(readStream: ReadStream);
38
+ /** 取下一个按键;流关闭返回 null。 */
39
+ next(): Promise<Key | null>;
40
+ private pumpEnd;
41
+ private pump;
42
+ }
@@ -1,23 +1,35 @@
1
+ import { type UiModel } from './model.js';
2
+ import { type Tty } from './tty.js';
1
3
  import type { Candidate, PickFlags } from './types.js';
4
+ /** 非交互开关环境变量(值为 "off" 时 pick 跳过 TUI)。 */
5
+ export declare const OFF_ENV = "PICKTUI_PICK";
2
6
  /**
3
7
  * pick — 交互过滤选择(fzf 风格)。
4
8
  *
5
- * @param cands 候选(经 stdin 传入,与位置参数等价且无 argv 长度限制)
6
- * @param flags 透传引擎 flags(query/label/sep/fuzzy/select1/auto
7
- * @returns 选中值;用户取消(esc/ctrl+c,退出码 130)返回 null
9
+ * @param cands 候选(不传时从宿主 stdin 管道读取)
10
+ * @param flags query/label/sep/fuzzy/select1/auto
11
+ * @returns 选中值;用户取消(esc/ctrl+c)返回 null
8
12
  */
9
13
  export declare function pick(cands?: (string | Candidate)[], flags?: PickFlags): Promise<string | null>;
10
14
  /**
11
15
  * menu — 多值缩写 TUI 菜单(数字 1-9 直选)。
12
- *
13
- * @param label 菜单标题与选择记忆键
14
- * @param cands 候选(经位置参数传入,注意 argv 长度限制;超长场景用 pick)
15
- * @returns 选中值;取消返回 null
16
+ * @returns 选中值;取消返回 null;参数不足抛 PicktuiError(退出码 2)
16
17
  */
17
18
  export declare function menu(label: string, cands: string[]): Promise<string | null>;
18
19
  /**
19
- * rawPick — 透传任意引擎 pick 参数(--from/--map 等绑定未包装的 flags)。
20
- *
20
+ * rawPick — 透传引擎 pick 参数(--from/--map/-q/--label/--sep/--fuzzy/-1/--auto)。
21
21
  * @example rawPick(['--from', 'git branch', '--label', 'git co', '-1'])
22
22
  */
23
23
  export declare function rawPick(args: string[]): Promise<string | null>;
24
+ /** 在 tty 上运行 TUI 选择器,返回(取消, 选中值, 多选勾选)。 */
25
+ export declare function runTui(model: UiModel, tty: Tty): Promise<{
26
+ cancelled: boolean;
27
+ value: string;
28
+ selected: string[];
29
+ }>;
30
+ /**
31
+ * 扫描 mapper 命令,识别"解释器 + 脚本路径"形态,返回第一个不存在的脚本文件路径。
32
+ * 保守策略:跳过 flags/引号/变量/管道等 shell 语法,只检查形如路径的 token
33
+ * (/ ./ ../ ~/ 前缀、带常见脚本扩展名),避免误拦 node -e / python3 -m 等合法用法。
34
+ */
35
+ export declare function mapperScriptMissing(mapper: string): string;
@@ -52,10 +52,3 @@ export declare class PicktuiError extends Error {
52
52
  export interface ResolveResult {
53
53
  value: string;
54
54
  }
55
- /** 引擎 version 输出("picktui <semver>")。 */
56
- export interface EngineVersion {
57
- /** 完整输出行,如 "picktui 0.1.0"。 */
58
- raw: string;
59
- /** 语义化版本号,如 "0.1.0"。 */
60
- version: string;
61
- }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@havocrao/picktui",
3
- "version": "0.1.0",
4
- "description": "TUI candidate picker — TS/JS bindings for the picktui engine (protocol v1). Filter / pick / history / confirm, tree-shakable, same behavior as the Go engine.",
3
+ "version": "0.1.1",
4
+ "description": "TUI candidate picker — pure TypeScript implementation. Filter / pick / history / confirm, zero runtime dependencies, same semantics as the Go engine (no binary required).",
5
5
  "license": "MIT",
6
6
  "author": "havoc-rao",
7
7
  "keywords": [
@@ -59,7 +59,7 @@
59
59
  },
60
60
  "scripts": {
61
61
  "build": "tsc -p tsconfig.esm.json && tsc -p tsconfig.cjs.json && node scripts/fixup.mjs",
62
- "pretest": "node scripts/build-engine.mjs",
62
+ "pretest": "npm run build",
63
63
  "test": "node --test \"test/*.test.mjs\"",
64
64
  "test:pack": "npm run build && node scripts/test-pack.mjs",
65
65
  "prepack": "npm run build"
@@ -68,4 +68,4 @@
68
68
  "@types/node": "^26.4.1",
69
69
  "typescript": "^5.5.0"
70
70
  }
71
- }
71
+ }