giggles 0.3.16 → 0.3.17
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 +1 -1
- package/dist/terminal/index.d.ts +23 -1
- package/dist/terminal/index.js +79 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ inspired by the [charmbracelet](https://github.com/charmbracelet) ecosystem, it
|
|
|
18
18
|
- built-in keybinding registry so your app can always show users what keys do what, in the current context — context-aware and accessible via a hook
|
|
19
19
|
- a component library covering most TUI use cases, from text inputs and autocomplete to virtual lists for large datasets — with sensible defaults and render props for full customization
|
|
20
20
|
- render markdown in the terminal, with full formatting and syntax-highlighted code block and diff support
|
|
21
|
-
- hand off terminal control to external programs like `vim` or `less` and reclaim it cleanly when they exit
|
|
21
|
+
- hand off terminal control to external programs like `vim` or `less` and reclaim it cleanly when they exit, or spawn processes and stream their output directly into your UI
|
|
22
22
|
- a consistent look out of the box, customizable from a single theme object
|
|
23
23
|
|
|
24
24
|
## your first TUI
|
package/dist/terminal/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SpawnOptionsWithoutStdio } from 'child_process';
|
|
1
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
3
|
import { ReactNode } from 'react';
|
|
3
4
|
|
|
@@ -5,6 +6,25 @@ type TerminalSize = {
|
|
|
5
6
|
rows: number;
|
|
6
7
|
columns: number;
|
|
7
8
|
};
|
|
9
|
+
type SpawnOptions = SpawnOptionsWithoutStdio & {
|
|
10
|
+
/**
|
|
11
|
+
* Inject FORCE_COLOR=1 and TERM=xterm-256color into the child process
|
|
12
|
+
* environment so tools that detect isTTY emit ANSI color codes.
|
|
13
|
+
*/
|
|
14
|
+
pty?: boolean;
|
|
15
|
+
};
|
|
16
|
+
type SpawnOutputLine = {
|
|
17
|
+
type: 'stdout' | 'stderr';
|
|
18
|
+
data: string;
|
|
19
|
+
};
|
|
20
|
+
type SpawnHandle = {
|
|
21
|
+
output: SpawnOutputLine[];
|
|
22
|
+
running: boolean;
|
|
23
|
+
exitCode: number | null;
|
|
24
|
+
error: Error | null;
|
|
25
|
+
run: (command: string, args?: string[], options?: SpawnOptions) => void;
|
|
26
|
+
kill: () => void;
|
|
27
|
+
};
|
|
8
28
|
|
|
9
29
|
declare function useTerminalSize(): TerminalSize;
|
|
10
30
|
|
|
@@ -22,4 +42,6 @@ declare function useShellOut(): {
|
|
|
22
42
|
}>;
|
|
23
43
|
};
|
|
24
44
|
|
|
25
|
-
|
|
45
|
+
declare function useSpawn(): SpawnHandle;
|
|
46
|
+
|
|
47
|
+
export { AlternateScreen, type SpawnHandle, type SpawnOptions, type SpawnOutputLine, type TerminalSize, useShellOut, useSpawn, useTerminalFocus, useTerminalSize };
|
package/dist/terminal/index.js
CHANGED
|
@@ -54,9 +54,88 @@ function useShellOut() {
|
|
|
54
54
|
run
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
|
+
|
|
58
|
+
// src/terminal/hooks/useSpawn.ts
|
|
59
|
+
import { spawn } from "child_process";
|
|
60
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
61
|
+
function useSpawn() {
|
|
62
|
+
const [output, setOutput] = useState2([]);
|
|
63
|
+
const [running, setRunning] = useState2(false);
|
|
64
|
+
const [exitCode, setExitCode] = useState2(null);
|
|
65
|
+
const [error, setError] = useState2(null);
|
|
66
|
+
const processRef = useRef2(null);
|
|
67
|
+
const cancelRef = useRef2(null);
|
|
68
|
+
useEffect2(() => {
|
|
69
|
+
return () => {
|
|
70
|
+
var _a, _b;
|
|
71
|
+
(_a = cancelRef.current) == null ? void 0 : _a.call(cancelRef);
|
|
72
|
+
(_b = processRef.current) == null ? void 0 : _b.kill();
|
|
73
|
+
};
|
|
74
|
+
}, []);
|
|
75
|
+
const run = useCallback2((command, args, options) => {
|
|
76
|
+
var _a, _b;
|
|
77
|
+
(_a = cancelRef.current) == null ? void 0 : _a.call(cancelRef);
|
|
78
|
+
(_b = processRef.current) == null ? void 0 : _b.kill();
|
|
79
|
+
processRef.current = null;
|
|
80
|
+
cancelRef.current = null;
|
|
81
|
+
let cancelled = false;
|
|
82
|
+
cancelRef.current = () => {
|
|
83
|
+
cancelled = true;
|
|
84
|
+
};
|
|
85
|
+
const { pty, ...spawnOptions } = options ?? {};
|
|
86
|
+
setOutput([]);
|
|
87
|
+
setRunning(true);
|
|
88
|
+
setExitCode(null);
|
|
89
|
+
setError(null);
|
|
90
|
+
const env = pty ? { ...process.env, FORCE_COLOR: "1", TERM: "xterm-256color", ...spawnOptions.env } : { ...process.env, ...spawnOptions.env };
|
|
91
|
+
let proc;
|
|
92
|
+
try {
|
|
93
|
+
proc = spawn(command, args ?? [], { ...spawnOptions, env, stdio: "pipe" });
|
|
94
|
+
} catch (err) {
|
|
95
|
+
setRunning(false);
|
|
96
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
97
|
+
cancelRef.current = null;
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
processRef.current = proc;
|
|
101
|
+
proc.stdout.on("data", (data) => {
|
|
102
|
+
if (!cancelled) setOutput((prev) => [...prev, { type: "stdout", data: data.toString() }]);
|
|
103
|
+
});
|
|
104
|
+
proc.stderr.on("data", (data) => {
|
|
105
|
+
if (!cancelled) setOutput((prev) => [...prev, { type: "stderr", data: data.toString() }]);
|
|
106
|
+
});
|
|
107
|
+
proc.on("error", (err) => {
|
|
108
|
+
if (!cancelled) {
|
|
109
|
+
cancelled = true;
|
|
110
|
+
setError(err);
|
|
111
|
+
setRunning(false);
|
|
112
|
+
processRef.current = null;
|
|
113
|
+
cancelRef.current = null;
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
proc.on("close", (code) => {
|
|
117
|
+
if (!cancelled) {
|
|
118
|
+
setRunning(false);
|
|
119
|
+
setExitCode(code);
|
|
120
|
+
processRef.current = null;
|
|
121
|
+
cancelRef.current = null;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}, []);
|
|
125
|
+
const kill = useCallback2(() => {
|
|
126
|
+
var _a, _b;
|
|
127
|
+
(_a = cancelRef.current) == null ? void 0 : _a.call(cancelRef);
|
|
128
|
+
cancelRef.current = null;
|
|
129
|
+
(_b = processRef.current) == null ? void 0 : _b.kill();
|
|
130
|
+
processRef.current = null;
|
|
131
|
+
setRunning(false);
|
|
132
|
+
}, []);
|
|
133
|
+
return { output, running, exitCode, error, run, kill };
|
|
134
|
+
}
|
|
57
135
|
export {
|
|
58
136
|
AlternateScreen,
|
|
59
137
|
useShellOut,
|
|
138
|
+
useSpawn,
|
|
60
139
|
useTerminalFocus,
|
|
61
140
|
useTerminalSize
|
|
62
141
|
};
|