@hortus/cli 0.0.0-stage → 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/dist/api.d.ts +53 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +15 -0
- package/dist/api.js.map +1 -0
- package/dist/app.d.ts +9 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +93 -0
- package/dist/app.js.map +1 -0
- package/dist/cli.d.ts +66 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +235 -0
- package/dist/cli.js.map +1 -0
- package/dist/command-menu.d.ts +33 -0
- package/dist/command-menu.d.ts.map +1 -0
- package/dist/command-menu.js +135 -0
- package/dist/command-menu.js.map +1 -0
- package/dist/commands.d.ts +36 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +73 -0
- package/dist/commands.js.map +1 -0
- package/dist/entry.d.ts +35 -0
- package/dist/entry.d.ts.map +1 -0
- package/dist/entry.js +96 -0
- package/dist/entry.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +58 -0
- package/dist/index.js.map +1 -0
- package/dist/markdown.d.ts +20 -0
- package/dist/markdown.d.ts.map +1 -0
- package/dist/markdown.js +233 -0
- package/dist/markdown.js.map +1 -0
- package/dist/prompt-input.d.ts +14 -0
- package/dist/prompt-input.d.ts.map +1 -0
- package/dist/prompt-input.js +139 -0
- package/dist/prompt-input.js.map +1 -0
- package/dist/session-picker.d.ts +9 -0
- package/dist/session-picker.d.ts.map +1 -0
- package/dist/session-picker.js +47 -0
- package/dist/session-picker.js.map +1 -0
- package/dist/status-bar.d.ts +3 -0
- package/dist/status-bar.d.ts.map +1 -0
- package/dist/status-bar.js +12 -0
- package/dist/status-bar.js.map +1 -0
- package/dist/transcript.d.ts +30 -0
- package/dist/transcript.d.ts.map +1 -0
- package/dist/transcript.js +164 -0
- package/dist/transcript.js.map +1 -0
- package/package.json +37 -3
- package/README.md +0 -3
package/dist/markdown.js
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import stringWidth from "string-width";
|
|
2
|
+
import { theme } from "./entry.js";
|
|
3
|
+
// `code` | **bold** | __bold__ | ~~strike~~ | *italic* | _italic_ | [label](url)
|
|
4
|
+
const INLINE = /(`+)(.+?)\1|\*\*(.+?)\*\*|__(.+?)__|~~(.+?)~~|\*(\S(?:.*?\S)?)\*|\b_(\S(?:.*?\S)?)_\b|\[([^\]]+)\]\(([^)\s]+)\)/gs;
|
|
5
|
+
export function inline(text, style = {}) {
|
|
6
|
+
const out = [];
|
|
7
|
+
let last = 0;
|
|
8
|
+
for (const m of text.matchAll(INLINE)) {
|
|
9
|
+
if (m.index > last)
|
|
10
|
+
out.push({ ...style, text: text.slice(last, m.index) });
|
|
11
|
+
const [, , code, b1, b2, strike, i1, i2, label, url] = m;
|
|
12
|
+
const bold = b1 ?? b2;
|
|
13
|
+
const italic = i1 ?? i2;
|
|
14
|
+
if (code !== undefined)
|
|
15
|
+
out.push({ ...style, color: theme.accent, text: code });
|
|
16
|
+
else if (bold !== undefined)
|
|
17
|
+
out.push(...inline(bold, { ...style, bold: true }));
|
|
18
|
+
else if (strike !== undefined)
|
|
19
|
+
out.push(...inline(strike, { ...style, strikethrough: true }));
|
|
20
|
+
else if (italic !== undefined)
|
|
21
|
+
out.push(...inline(italic, { ...style, italic: true }));
|
|
22
|
+
else if (label !== undefined) {
|
|
23
|
+
out.push(...inline(label, { ...style, color: theme.blue, underline: true }));
|
|
24
|
+
if (url !== label)
|
|
25
|
+
out.push({ ...style, color: theme.muted, text: ` (${url})` });
|
|
26
|
+
}
|
|
27
|
+
last = m.index + m[0].length;
|
|
28
|
+
}
|
|
29
|
+
if (last < text.length)
|
|
30
|
+
out.push({ ...style, text: text.slice(last) });
|
|
31
|
+
return out;
|
|
32
|
+
}
|
|
33
|
+
const graphemes = (s) => Array.from(new Intl.Segmenter().segment(s), (g) => g.segment);
|
|
34
|
+
/** Word-wraps at `width` columns without dropping any character, so a row's text concatenates back to the line. */
|
|
35
|
+
export function wrap(line, width) {
|
|
36
|
+
const rows = [];
|
|
37
|
+
let cur = "";
|
|
38
|
+
let w = 0;
|
|
39
|
+
let space = -1; // string index of the last space in `cur`
|
|
40
|
+
for (const g of graphemes(line)) {
|
|
41
|
+
const gw = stringWidth(g);
|
|
42
|
+
if (w + gw > width && cur) {
|
|
43
|
+
// break after the last space if there is one, else mid-word
|
|
44
|
+
const cut = space > 0 ? space + 1 : cur.length;
|
|
45
|
+
rows.push(cur.slice(0, cut));
|
|
46
|
+
cur = cur.slice(cut);
|
|
47
|
+
w = stringWidth(cur);
|
|
48
|
+
space = -1;
|
|
49
|
+
}
|
|
50
|
+
if (g === " ")
|
|
51
|
+
space = cur.length;
|
|
52
|
+
cur += g;
|
|
53
|
+
w += gw;
|
|
54
|
+
}
|
|
55
|
+
rows.push(cur);
|
|
56
|
+
return rows;
|
|
57
|
+
}
|
|
58
|
+
/** Text between columns [from, to) of a row. */
|
|
59
|
+
export function sliceCols(text, from, to) {
|
|
60
|
+
let col = 0;
|
|
61
|
+
let out = "";
|
|
62
|
+
for (const g of graphemes(text)) {
|
|
63
|
+
if (col >= from && col < to)
|
|
64
|
+
out += g;
|
|
65
|
+
col += stringWidth(g);
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
/** The parts of `spans` between columns [from, to). */
|
|
70
|
+
export function cutCols(spans, from, to) {
|
|
71
|
+
const out = [];
|
|
72
|
+
let col = 0;
|
|
73
|
+
for (const s of spans) {
|
|
74
|
+
const text = sliceCols(s.text, from - col, to - col);
|
|
75
|
+
if (text)
|
|
76
|
+
out.push({ ...s, text });
|
|
77
|
+
col += stringWidth(s.text);
|
|
78
|
+
}
|
|
79
|
+
return out;
|
|
80
|
+
}
|
|
81
|
+
const DELIM = /^\s*\|?\s*:?-+:?\s*(\|\s*:?-+:?\s*)*\|?\s*$/;
|
|
82
|
+
/** A table row's cells; `\|` escapes a pipe. ponytail: a `|` inside a code span still splits the cell. */
|
|
83
|
+
const cells = (row) => row
|
|
84
|
+
.trim()
|
|
85
|
+
.replace(/^\|/, "")
|
|
86
|
+
.replace(/(?<!\\)\|$/, "")
|
|
87
|
+
.split(/(?<!\\)\|/)
|
|
88
|
+
.map((c) => c.trim().replace(/\\\|/g, "|"));
|
|
89
|
+
const spanWidth = (spans) => stringWidth(spans.map((s) => s.text).join(""));
|
|
90
|
+
/**
|
|
91
|
+
* Lays out a table with columns padded to their widest cell. Wider than `width`, the widest columns shrink and
|
|
92
|
+
* their cells wrap inside the column, so no line soft-wraps and breaks the borders.
|
|
93
|
+
*/
|
|
94
|
+
function table(rows, width) {
|
|
95
|
+
const [head = [], delim = [], ...body] = rows.map(cells);
|
|
96
|
+
const grid = [head, ...body].map((r) => head.map((_, c) => inline(r[c] ?? "", r === head ? { bold: true } : {})));
|
|
97
|
+
const widths = head.map((_, c) => Math.max(1, ...grid.map((r) => spanWidth(r[c] ?? []))));
|
|
98
|
+
// ponytail: shrinks one column per step, O(overflow × columns); fine for terminal-sized tables.
|
|
99
|
+
// 2 columns minimum so a wide char still fits; below that the table soft-wraps.
|
|
100
|
+
for (let over = widths.reduce((a, w) => a + w + 3, -3) - width; over > 0; over--) {
|
|
101
|
+
const max = Math.max(...widths);
|
|
102
|
+
if (max <= 2)
|
|
103
|
+
break;
|
|
104
|
+
widths[widths.indexOf(max)] = max - 1;
|
|
105
|
+
}
|
|
106
|
+
// one grid row → as many lines as its tallest wrapped cell
|
|
107
|
+
const lines = (r) => {
|
|
108
|
+
const parts = r.map((cell, c) => {
|
|
109
|
+
let col = 0;
|
|
110
|
+
return wrap(cell.map((s) => s.text).join(""), widths[c] ?? 1).map((t) => {
|
|
111
|
+
const from = col;
|
|
112
|
+
col += stringWidth(t);
|
|
113
|
+
return cutCols(cell, from, col);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
return Array.from({ length: Math.max(...parts.map((p) => p.length)) }, (_, k) => line(parts.map((p) => p[k] ?? [])));
|
|
117
|
+
};
|
|
118
|
+
const line = (r) => r.flatMap((cell, c) => {
|
|
119
|
+
const pad = (widths[c] ?? 0) - spanWidth(cell);
|
|
120
|
+
const d = delim[c] ?? "";
|
|
121
|
+
const left = d.endsWith(":") ? (d.startsWith(":") ? Math.floor(pad / 2) : pad) : 0;
|
|
122
|
+
return [
|
|
123
|
+
...(c ? [{ dimColor: true, text: " │ " }] : []),
|
|
124
|
+
...(left ? [{ text: " ".repeat(left) }] : []),
|
|
125
|
+
...cell,
|
|
126
|
+
...(pad - left ? [{ text: " ".repeat(pad - left) }] : []),
|
|
127
|
+
];
|
|
128
|
+
});
|
|
129
|
+
return [
|
|
130
|
+
...lines(grid[0] ?? []),
|
|
131
|
+
[{ dimColor: true, text: widths.map((w) => "─".repeat(w)).join("─┼─") }],
|
|
132
|
+
...grid.slice(1).flatMap(lines),
|
|
133
|
+
];
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Renders markdown into one list of styled spans per output line: fences, headings, rules, tables, quotes,
|
|
137
|
+
* bullets, and inline styles, which may span the lines of a paragraph, quote or list item.
|
|
138
|
+
*/
|
|
139
|
+
export function markdown(text, width) {
|
|
140
|
+
const lines = text.split("\n");
|
|
141
|
+
const out = [];
|
|
142
|
+
// the current paragraph, quote or list item: inline styles may cross its line breaks
|
|
143
|
+
let group = [];
|
|
144
|
+
let kind;
|
|
145
|
+
const flush = (style = kind === "quote" ? { color: theme.muted } : {}) => {
|
|
146
|
+
if (!group.length)
|
|
147
|
+
return;
|
|
148
|
+
const split = [[]];
|
|
149
|
+
for (const s of inline(group.map((g) => g.text).join("\n"), style))
|
|
150
|
+
s.text.split("\n").forEach((t, k) => {
|
|
151
|
+
if (k)
|
|
152
|
+
split.push([]);
|
|
153
|
+
if (t)
|
|
154
|
+
split[split.length - 1]?.push({ ...s, text: t });
|
|
155
|
+
});
|
|
156
|
+
group.forEach((g, k) => {
|
|
157
|
+
out.push([...g.prefix, ...(split[k] ?? [])]);
|
|
158
|
+
});
|
|
159
|
+
group = [];
|
|
160
|
+
kind = undefined;
|
|
161
|
+
};
|
|
162
|
+
let fence;
|
|
163
|
+
for (let i = 0; i < lines.length; i++) {
|
|
164
|
+
const line = lines[i] ?? "";
|
|
165
|
+
const open = line.match(/^\s*(`{3,}|~{3,})/)?.[1];
|
|
166
|
+
if (open && (!fence || open.startsWith(fence))) {
|
|
167
|
+
flush();
|
|
168
|
+
fence = fence ? undefined : open;
|
|
169
|
+
out.push([{ color: theme.muted, text: line }]);
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
if (fence) {
|
|
173
|
+
out.push([{ color: theme.green, text: line }]);
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (!line.trim()) {
|
|
177
|
+
flush();
|
|
178
|
+
out.push([]);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
// setext heading: a paragraph underlined with === or ---
|
|
182
|
+
if (kind === "para" && /^ {0,3}(=+|-+) *$/.test(line)) {
|
|
183
|
+
flush({ color: theme.yellow, bold: true });
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
const heading = line.match(/^#{1,6}\s+(.*)$/);
|
|
187
|
+
const next = lines[i + 1] ?? "";
|
|
188
|
+
if (heading) {
|
|
189
|
+
flush();
|
|
190
|
+
out.push(inline(heading[1] ?? "", { color: theme.yellow, bold: true }));
|
|
191
|
+
}
|
|
192
|
+
else if (line.includes("|") && next.includes("|") && DELIM.test(next)) {
|
|
193
|
+
flush();
|
|
194
|
+
let end = i + 2;
|
|
195
|
+
while (lines[end]?.includes("|") && lines[end]?.trim())
|
|
196
|
+
end++;
|
|
197
|
+
out.push(...table(lines.slice(i, end), width));
|
|
198
|
+
i = end - 1;
|
|
199
|
+
}
|
|
200
|
+
else if (/^ {0,3}([-*_])( *\1){2,} *$/.test(line)) {
|
|
201
|
+
flush();
|
|
202
|
+
out.push([{ color: theme.muted, text: "─".repeat(width) }]);
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
const quote = line.match(/^(\s*)>\s?(.*)$/);
|
|
206
|
+
const bullet = line.match(/^(\s*)[-*+]\s+(.*)$/);
|
|
207
|
+
if (quote) {
|
|
208
|
+
if (kind !== "quote")
|
|
209
|
+
flush();
|
|
210
|
+
kind = "quote";
|
|
211
|
+
group.push({ prefix: [{ color: theme.muted, text: `${quote[1]}│ ` }], text: quote[2] ?? "" });
|
|
212
|
+
}
|
|
213
|
+
else if (bullet) {
|
|
214
|
+
flush();
|
|
215
|
+
kind = "bullet";
|
|
216
|
+
group.push({
|
|
217
|
+
prefix: [...(bullet[1] ? [{ text: bullet[1] }] : []), { color: theme.accent, text: "• " }],
|
|
218
|
+
text: bullet[2] ?? "",
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
// a plain line continues a paragraph or list item
|
|
223
|
+
if (kind === "quote")
|
|
224
|
+
flush();
|
|
225
|
+
kind ??= "para";
|
|
226
|
+
group.push({ prefix: [], text: line });
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
flush();
|
|
231
|
+
return out;
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type Key } from "ink";
|
|
2
|
+
/** Where ↑ (`-1`) / ↓ (`1`) takes the caret: the closest column on the neighbouring visual row; undefined past either end. */
|
|
3
|
+
export declare function moveRow(chars: string[], pos: number, width: number, dir: -1 | 1): number | undefined;
|
|
4
|
+
/** Multi-line text input: Enter submits, Shift+Enter (or Alt+Enter where the terminal can't report Shift) inserts a newline.
|
|
5
|
+
* ↑/↓ move between visual rows; `onCaretRow` reports the caret's row counted from the bottom, so a scroller can follow it.
|
|
6
|
+
* `onKey` sees every key first; returning true keeps it from the input. */
|
|
7
|
+
export declare function PromptInput({ value, onChange, onSubmit, onKey, onCaretRow, }: {
|
|
8
|
+
value: string;
|
|
9
|
+
onChange: (value: string) => void;
|
|
10
|
+
onSubmit: (value: string) => void;
|
|
11
|
+
onKey?: (input: string, key: Key) => boolean;
|
|
12
|
+
onCaretRow?: (fromBottom: number) => void;
|
|
13
|
+
}): import("react").JSX.Element;
|
|
14
|
+
//# sourceMappingURL=prompt-input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-input.d.ts","sourceRoot":"","sources":["../src/prompt-input.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,GAAG,EAMT,MAAM,KAAK,CAAC;AA8Cb,8HAA8H;AAC9H,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,sBAS/E;AAED;;2EAE2E;AAC3E,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,KAAK,EACL,UAAU,GACX,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;IAC7C,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C,+BAyEA"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Box, measureElement, Text, useBoxMetrics, useCursor, useInput, } from "ink";
|
|
3
|
+
import { useEffect, useRef, useState } from "react";
|
|
4
|
+
import stringWidth from "string-width";
|
|
5
|
+
import { wrap } from "./markdown.js";
|
|
6
|
+
/** `node`'s top-left on screen plus the visible row range of its clipping ancestors, undoing every `contentOffsetY`. */
|
|
7
|
+
function screenBox(node) {
|
|
8
|
+
const chain = [];
|
|
9
|
+
for (let n = node; n; n = n.parentNode)
|
|
10
|
+
chain.unshift(n);
|
|
11
|
+
let shift = 0;
|
|
12
|
+
let top = 0;
|
|
13
|
+
let bottom = Number.POSITIVE_INFINITY;
|
|
14
|
+
for (const n of chain) {
|
|
15
|
+
const m = measureElement(n);
|
|
16
|
+
if (n.style.overflow === "hidden" || n.style.overflowY === "hidden") {
|
|
17
|
+
top = Math.max(top, m.y - shift);
|
|
18
|
+
bottom = Math.min(bottom, m.y - shift + m.height);
|
|
19
|
+
}
|
|
20
|
+
shift += n.style.contentOffsetY ?? 0;
|
|
21
|
+
}
|
|
22
|
+
const m = measureElement(node);
|
|
23
|
+
return { x: m.x, y: m.y - shift, top, bottom };
|
|
24
|
+
}
|
|
25
|
+
/** Visual rows, as code-point ranges into `chars`, and the caret's row/column. */
|
|
26
|
+
function layout(chars, pos, width) {
|
|
27
|
+
// `end` is where the row's line ends, `last` whether the row ends it
|
|
28
|
+
const rows = [];
|
|
29
|
+
let lineStart = 0;
|
|
30
|
+
for (const line of chars.join("").split("\n")) {
|
|
31
|
+
const end = lineStart + [...line].length;
|
|
32
|
+
// a caret at the end of a line still needs a cell, so wrap with a space there
|
|
33
|
+
const wrapped = wrap(pos === end ? `${line} ` : line, width);
|
|
34
|
+
let start = lineStart;
|
|
35
|
+
for (const [r, text] of wrapped.entries()) {
|
|
36
|
+
rows.push({ text, start, end, last: r === wrapped.length - 1 });
|
|
37
|
+
start += [...text].length;
|
|
38
|
+
}
|
|
39
|
+
lineStart = end + 1;
|
|
40
|
+
}
|
|
41
|
+
const found = rows.findIndex((r) => pos < r.start + [...r.text].length);
|
|
42
|
+
const row = found === -1 ? rows.length - 1 : found;
|
|
43
|
+
const col = stringWidth(chars.slice(rows[row]?.start ?? 0, pos).join(""));
|
|
44
|
+
return { rows, caret: { row, col } };
|
|
45
|
+
}
|
|
46
|
+
/** Where ↑ (`-1`) / ↓ (`1`) takes the caret: the closest column on the neighbouring visual row; undefined past either end. */
|
|
47
|
+
export function moveRow(chars, pos, width, dir) {
|
|
48
|
+
const { rows, caret } = layout(chars, pos, width);
|
|
49
|
+
const to = rows[caret.row + dir];
|
|
50
|
+
if (!to)
|
|
51
|
+
return;
|
|
52
|
+
// not past the row: a wrapped row's last position belongs to the next one
|
|
53
|
+
const max = to.last ? to.end : to.start + [...to.text].length - 1;
|
|
54
|
+
let at = to.start;
|
|
55
|
+
while (at < max && stringWidth(chars.slice(to.start, at + 1).join("")) <= caret.col)
|
|
56
|
+
at++;
|
|
57
|
+
return at;
|
|
58
|
+
}
|
|
59
|
+
/** Multi-line text input: Enter submits, Shift+Enter (or Alt+Enter where the terminal can't report Shift) inserts a newline.
|
|
60
|
+
* ↑/↓ move between visual rows; `onCaretRow` reports the caret's row counted from the bottom, so a scroller can follow it.
|
|
61
|
+
* `onKey` sees every key first; returning true keeps it from the input. */
|
|
62
|
+
export function PromptInput({ value, onChange, onSubmit, onKey, onCaretRow, }) {
|
|
63
|
+
// cursor counts code points, so emoji move as one step
|
|
64
|
+
const chars = [...value];
|
|
65
|
+
// kept with the value it was placed in: a value the parent put there instead (the clear on submit, a menu fill)
|
|
66
|
+
// puts the caret at its end
|
|
67
|
+
const [cursor, setCursor] = useState({ value, pos: chars.length });
|
|
68
|
+
const pos = cursor.value === value ? cursor.pos : chars.length;
|
|
69
|
+
// wrap ourselves (instead of letting Ink) so we know which row/column the caret lands on
|
|
70
|
+
const ref = useRef(null);
|
|
71
|
+
const width = useBoxMetrics(ref).width || Number.MAX_SAFE_INTEGER;
|
|
72
|
+
const { rows, caret } = layout(chars, pos, width);
|
|
73
|
+
// keys can arrive faster than renders (e.g. held Backspace while a reply streams), so each one
|
|
74
|
+
// builds on the previous key's result, not on this render's possibly stale props
|
|
75
|
+
const latest = useRef({ chars, pos });
|
|
76
|
+
latest.current = { chars, pos };
|
|
77
|
+
const update = (next, at) => {
|
|
78
|
+
const text = next.join("");
|
|
79
|
+
latest.current = { chars: next, pos: at };
|
|
80
|
+
onChange(text);
|
|
81
|
+
setCursor({ value: text, pos: at });
|
|
82
|
+
const { rows, caret } = layout(next, at, width);
|
|
83
|
+
onCaretRow?.(rows.length - 1 - caret.row);
|
|
84
|
+
};
|
|
85
|
+
useInput((input, key) => {
|
|
86
|
+
if (onKey?.(input, key))
|
|
87
|
+
return;
|
|
88
|
+
const { chars, pos } = latest.current;
|
|
89
|
+
const insert = (text) => update([...chars.slice(0, pos), ...text, ...chars.slice(pos)], pos + [...text].length);
|
|
90
|
+
if (key.return) {
|
|
91
|
+
if (key.shift || key.meta)
|
|
92
|
+
insert("\n");
|
|
93
|
+
else
|
|
94
|
+
onSubmit(chars.join(""));
|
|
95
|
+
}
|
|
96
|
+
else if (key.upArrow || key.downArrow) {
|
|
97
|
+
const at = moveRow(chars, pos, width, key.upArrow ? -1 : 1);
|
|
98
|
+
if (at !== undefined)
|
|
99
|
+
update(chars, at);
|
|
100
|
+
}
|
|
101
|
+
else if (key.leftArrow || (key.ctrl && input === "b"))
|
|
102
|
+
update(chars, Math.max(0, pos - 1));
|
|
103
|
+
else if (key.rightArrow || (key.ctrl && input === "f"))
|
|
104
|
+
update(chars, Math.min(chars.length, pos + 1));
|
|
105
|
+
// Home/End stay within the current line of a multi-line input
|
|
106
|
+
else if (key.home || (key.ctrl && input === "a"))
|
|
107
|
+
update(chars, chars.slice(0, pos).lastIndexOf("\n") + 1);
|
|
108
|
+
else if (key.end || (key.ctrl && input === "e")) {
|
|
109
|
+
const nl = chars.indexOf("\n", pos);
|
|
110
|
+
update(chars, nl === -1 ? chars.length : nl);
|
|
111
|
+
}
|
|
112
|
+
else if (key.backspace) {
|
|
113
|
+
if (pos > 0)
|
|
114
|
+
update([...chars.slice(0, pos - 1), ...chars.slice(pos)], pos - 1);
|
|
115
|
+
}
|
|
116
|
+
else if (key.delete) {
|
|
117
|
+
if (pos < chars.length)
|
|
118
|
+
update([...chars.slice(0, pos), ...chars.slice(pos + 1)], pos);
|
|
119
|
+
}
|
|
120
|
+
else if (input && !key.ctrl && !key.meta)
|
|
121
|
+
insert(input.replace(/\r\n?/g, "\n"));
|
|
122
|
+
});
|
|
123
|
+
// the real terminal cursor sits on the caret, so the IME draws its preedit there; hidden when scrolled out of view.
|
|
124
|
+
// only the box's screen position needs layout (from the last frame); the caret is placed from this render so it doesn't lag a frame
|
|
125
|
+
const [box, setBox] = useState();
|
|
126
|
+
const { setCursorPosition } = useCursor();
|
|
127
|
+
const y = box && box.y + caret.row;
|
|
128
|
+
const screen = box && y !== undefined && y >= box.top && y < box.bottom ? { x: box.x + caret.col, y } : undefined;
|
|
129
|
+
setCursorPosition(screen);
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
if (!ref.current)
|
|
132
|
+
return;
|
|
133
|
+
const next = screenBox(ref.current);
|
|
134
|
+
if (next.x !== box?.x || next.y !== box?.y || next.top !== box?.top || next.bottom !== box?.bottom)
|
|
135
|
+
setBox(next);
|
|
136
|
+
});
|
|
137
|
+
return (_jsx(Box, { ref: ref, flexDirection: "column", width: "100%", children: rows.map(({ text }, i) => (_jsx(Text, { children: text || " " }, i))) }));
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=prompt-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-input.js","sourceRoot":"","sources":["../src/prompt-input.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SessionInfo } from "@hortus/core";
|
|
2
|
+
/** Sessions whose first user message contains every word of `query`, ignoring case. */
|
|
3
|
+
export declare function filterSessions(sessions: SessionInfo[], query: string): SessionInfo[];
|
|
4
|
+
/** Pick a session to resume: type to filter by first message, ↑/↓ to move, Enter to pick, Esc to quit. */
|
|
5
|
+
export declare function SessionPicker({ sessions, onPick, }: {
|
|
6
|
+
sessions: SessionInfo[];
|
|
7
|
+
onPick: (s: SessionInfo | undefined) => void;
|
|
8
|
+
}): import("react").JSX.Element;
|
|
9
|
+
//# sourceMappingURL=session-picker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-picker.d.ts","sourceRoot":"","sources":["../src/session-picker.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAKhD,uFAAuF;AACvF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,MAAM,iBAGpE;AAED,0GAA0G;AAC1G,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,MAAM,GACP,EAAE;IACD,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,EAAE,CAAC,CAAC,EAAE,WAAW,GAAG,SAAS,KAAK,IAAI,CAAC;CAC9C,+BA6CA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text, useApp, useInput, useWindowSize } from "ink";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { stamp, theme } from "./entry.js";
|
|
5
|
+
/** Sessions whose first user message contains every word of `query`, ignoring case. */
|
|
6
|
+
export function filterSessions(sessions, query) {
|
|
7
|
+
const words = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
8
|
+
return sessions.filter((s) => words.every((w) => s.title.toLowerCase().includes(w)));
|
|
9
|
+
}
|
|
10
|
+
/** Pick a session to resume: type to filter by first message, ↑/↓ to move, Enter to pick, Esc to quit. */
|
|
11
|
+
export function SessionPicker({ sessions, onPick, }) {
|
|
12
|
+
const { exit } = useApp();
|
|
13
|
+
const { rows } = useWindowSize();
|
|
14
|
+
const [query, setQuery] = useState("");
|
|
15
|
+
const [sel, setSel] = useState(0);
|
|
16
|
+
const shown = filterSessions(sessions, query);
|
|
17
|
+
const at = Math.min(sel, Math.max(0, shown.length - 1));
|
|
18
|
+
const done = (s) => {
|
|
19
|
+
onPick(s);
|
|
20
|
+
exit();
|
|
21
|
+
};
|
|
22
|
+
useInput((input, key) => {
|
|
23
|
+
if (key.escape || (key.ctrl && input === "c"))
|
|
24
|
+
done(undefined);
|
|
25
|
+
else if (key.return)
|
|
26
|
+
shown[at] && done(shown[at]);
|
|
27
|
+
else if (key.upArrow)
|
|
28
|
+
setSel(Math.max(0, at - 1));
|
|
29
|
+
else if (key.downArrow)
|
|
30
|
+
setSel(Math.min(shown.length - 1, at + 1));
|
|
31
|
+
// most terminals send DEL for Backspace, which Ink reports as `delete`
|
|
32
|
+
else if (key.backspace || key.delete)
|
|
33
|
+
setQuery((q) => q.slice(0, -1));
|
|
34
|
+
else if (input && !key.ctrl && !key.meta) {
|
|
35
|
+
setQuery((q) => q + input);
|
|
36
|
+
setSel(0);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
// keep the selection in view: a window of `height` rows around it
|
|
40
|
+
const height = Math.max(1, rows - 3);
|
|
41
|
+
const start = Math.max(0, Math.min(at - Math.floor(height / 2), shown.length - height));
|
|
42
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { color: theme.accent, children: "Resume session \u203A " }), query, _jsx(Text, { inverse: true, children: " " })] }), shown.length === 0 && _jsx(Text, { color: theme.dim, children: "No matching sessions" }), shown.slice(start, start + height).map((s, i) => {
|
|
43
|
+
const color = start + i === at ? theme.accent : undefined;
|
|
44
|
+
return (_jsxs(Text, { wrap: "truncate-end", color: color, children: [_jsxs(Text, { color: color ?? theme.dim, children: [stamp(s.created), " "] }), s.title.replace(/\s+/g, " ") || "(no messages)"] }, s.id));
|
|
45
|
+
})] }));
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=session-picker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-picker.js","sourceRoot":"","sources":["../src/session-picker.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-bar.d.ts","sourceRoot":"","sources":["../src/status-bar.tsx"],"names":[],"mappings":"AAKA,wGAAwG;AACxG,wBAAgB,SAAS,gCAaxB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from "ink";
|
|
3
|
+
import { useShallow } from "zustand/react/shallow";
|
|
4
|
+
import { useSession, useUi } from "./api.js";
|
|
5
|
+
import { theme, usageLine } from "./entry.js";
|
|
6
|
+
/** Built-in status bar: token usage (or the last copy) on the left, provider and model on the right. */
|
|
7
|
+
export function StatusBar() {
|
|
8
|
+
const messages = useSession((s) => s.messages);
|
|
9
|
+
const { turn, status, copied } = useUi(useShallow(({ turn, status, copied }) => ({ turn, status, copied })));
|
|
10
|
+
return (_jsxs(Box, { justifyContent: "space-between", children: [_jsx(Text, { color: theme.dim, wrap: "truncate", children: copied === undefined ? usageLine([...messages, ...turn], status?.window) : `Copied ${copied} chars` }), _jsx(Text, { color: theme.dim, wrap: "truncate", children: status && `(${status.name}) ${status.model}` })] }));
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=status-bar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-bar.js","sourceRoot":"","sources":["../src/status-bar.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE9C,wGAAwG;AACxG,MAAM,UAAU,SAAS;IACvB,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7G,OAAO,CACL,MAAC,GAAG,IAAC,cAAc,EAAC,eAAe,aACjC,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,EAAC,UAAU,YACpC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,QAAQ,EAAE,GAAG,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,MAAM,QAAQ,GAC/F,EACP,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,EAAC,UAAU,YACpC,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,KAAK,EAAE,GACxC,IACH,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type Entry } from "./entry.ts";
|
|
2
|
+
import { type Span } from "./markdown.ts";
|
|
3
|
+
/**
|
|
4
|
+
* One screen row. `text` is its plain text and `spans` the same text styled.
|
|
5
|
+
* `cont` = soft-wrapped continuation of the previous row (joined without a newline on copy).
|
|
6
|
+
*/
|
|
7
|
+
export interface Row {
|
|
8
|
+
kind: Entry["kind"];
|
|
9
|
+
text: string;
|
|
10
|
+
spans: Span[];
|
|
11
|
+
cont: boolean;
|
|
12
|
+
bold?: boolean;
|
|
13
|
+
}
|
|
14
|
+
interface Point {
|
|
15
|
+
row: number;
|
|
16
|
+
col: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function toRows(entries: Entry[], width: number): Row[];
|
|
19
|
+
export declare function selectionText(rows: Row[], a: Point, b: Point): string;
|
|
20
|
+
/**
|
|
21
|
+
* Fullscreen transcript: own scrolling (wheel, PgUp/PgDn) and own selection, since the app captures the mouse.
|
|
22
|
+
* Drag selects, release copies via OSC 52. Wheel events below the pane go to `onWheelBelow`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function Transcript({ entries, onWheelBelow, onCopy, }: {
|
|
25
|
+
entries: Entry[];
|
|
26
|
+
onWheelBelow: (delta: number) => void;
|
|
27
|
+
onCopy: (chars: number) => void;
|
|
28
|
+
}): import("react").JSX.Element;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=transcript.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcript.d.ts","sourceRoot":"","sources":["../src/transcript.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,KAAK,EAAiB,MAAM,YAAY,CAAC;AACvD,OAAO,EAAqB,KAAK,IAAI,EAAmB,MAAM,eAAe,CAAC;AAE9E;;;GAGG;AACH,MAAM,WAAW,GAAG;IAClB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AACD,UAAU,KAAK;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAuCD,wBAAgB,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE,CAS7D;AAoBD,wBAAgB,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,UAU5D;AAKD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,YAAY,EACZ,MAAM,GACP,EAAE;IACD,OAAO,EAAE,KAAK,EAAE,CAAC;IACjB,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC,+BAiGA"}
|