@mariozechner/pi-tui 0.5.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 +655 -0
- package/dist/autocomplete.d.ts +44 -0
- package/dist/autocomplete.d.ts.map +1 -0
- package/dist/autocomplete.js +454 -0
- package/dist/autocomplete.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +23 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +75 -0
- package/dist/logger.js.map +1 -0
- package/dist/markdown-component.d.ts +14 -0
- package/dist/markdown-component.d.ts.map +1 -0
- package/dist/markdown-component.js +225 -0
- package/dist/markdown-component.js.map +1 -0
- package/dist/select-list.d.ts +21 -0
- package/dist/select-list.d.ts.map +1 -0
- package/dist/select-list.js +130 -0
- package/dist/select-list.js.map +1 -0
- package/dist/text-component.d.ts +13 -0
- package/dist/text-component.d.ts.map +1 -0
- package/dist/text-component.js +90 -0
- package/dist/text-component.js.map +1 -0
- package/dist/text-editor.d.ts +40 -0
- package/dist/text-editor.d.ts.map +1 -0
- package/dist/text-editor.js +670 -0
- package/dist/text-editor.js.map +1 -0
- package/dist/tui.d.ts +58 -0
- package/dist/tui.d.ts.map +1 -0
- package/dist/tui.js +391 -0
- package/dist/tui.js.map +1 -0
- package/dist/whitespace-component.d.ts +12 -0
- package/dist/whitespace-component.d.ts.map +1 -0
- package/dist/whitespace-component.js +21 -0
- package/dist/whitespace-component.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { marked } from "marked";
|
|
3
|
+
export class MarkdownComponent {
|
|
4
|
+
text;
|
|
5
|
+
lines = [];
|
|
6
|
+
previousLines = [];
|
|
7
|
+
constructor(text = "") {
|
|
8
|
+
this.text = text;
|
|
9
|
+
}
|
|
10
|
+
setText(text) {
|
|
11
|
+
this.text = text;
|
|
12
|
+
}
|
|
13
|
+
render(width) {
|
|
14
|
+
// Parse markdown to HTML-like tokens
|
|
15
|
+
const tokens = marked.lexer(this.text);
|
|
16
|
+
// Convert tokens to styled terminal output
|
|
17
|
+
const renderedLines = [];
|
|
18
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
19
|
+
const token = tokens[i];
|
|
20
|
+
const nextToken = tokens[i + 1];
|
|
21
|
+
const tokenLines = this.renderToken(token, width, nextToken?.type);
|
|
22
|
+
renderedLines.push(...tokenLines);
|
|
23
|
+
}
|
|
24
|
+
// Wrap lines to fit width
|
|
25
|
+
const wrappedLines = [];
|
|
26
|
+
for (const line of renderedLines) {
|
|
27
|
+
wrappedLines.push(...this.wrapLine(line, width));
|
|
28
|
+
}
|
|
29
|
+
this.previousLines = this.lines;
|
|
30
|
+
this.lines = wrappedLines;
|
|
31
|
+
// Determine if content changed
|
|
32
|
+
const changed = this.lines.length !== this.previousLines.length ||
|
|
33
|
+
this.lines.some((line, i) => line !== this.previousLines[i]);
|
|
34
|
+
return {
|
|
35
|
+
lines: this.lines,
|
|
36
|
+
changed,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
renderToken(token, width, nextTokenType) {
|
|
40
|
+
const lines = [];
|
|
41
|
+
switch (token.type) {
|
|
42
|
+
case "heading": {
|
|
43
|
+
const headingLevel = token.depth;
|
|
44
|
+
const headingPrefix = "#".repeat(headingLevel) + " ";
|
|
45
|
+
const headingText = this.renderInlineTokens(token.tokens || []);
|
|
46
|
+
if (headingLevel === 1) {
|
|
47
|
+
lines.push(chalk.bold.underline.yellow(headingText));
|
|
48
|
+
}
|
|
49
|
+
else if (headingLevel === 2) {
|
|
50
|
+
lines.push(chalk.bold.yellow(headingText));
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
lines.push(chalk.bold(headingPrefix + headingText));
|
|
54
|
+
}
|
|
55
|
+
lines.push(""); // Add spacing after headings
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
case "paragraph": {
|
|
59
|
+
const paragraphText = this.renderInlineTokens(token.tokens || []);
|
|
60
|
+
lines.push(paragraphText);
|
|
61
|
+
// Don't add spacing if next token is space or list
|
|
62
|
+
if (nextTokenType && nextTokenType !== "list" && nextTokenType !== "space") {
|
|
63
|
+
lines.push("");
|
|
64
|
+
}
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
case "code": {
|
|
68
|
+
lines.push(chalk.gray("```" + (token.lang || "")));
|
|
69
|
+
// Split code by newlines and style each line
|
|
70
|
+
const codeLines = token.text.split("\n");
|
|
71
|
+
for (const codeLine of codeLines) {
|
|
72
|
+
lines.push(chalk.dim(" ") + chalk.green(codeLine));
|
|
73
|
+
}
|
|
74
|
+
lines.push(chalk.gray("```"));
|
|
75
|
+
lines.push(""); // Add spacing after code blocks
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
case "list":
|
|
79
|
+
for (let i = 0; i < token.items.length; i++) {
|
|
80
|
+
const item = token.items[i];
|
|
81
|
+
const bullet = token.ordered ? `${i + 1}. ` : "- ";
|
|
82
|
+
const itemText = this.renderInlineTokens(item.tokens || []);
|
|
83
|
+
// Check if the item text contains multiple lines (embedded content)
|
|
84
|
+
const itemLines = itemText.split("\n").filter((line) => line.trim());
|
|
85
|
+
if (itemLines.length > 1) {
|
|
86
|
+
// First line is the list item
|
|
87
|
+
lines.push(chalk.cyan(bullet) + itemLines[0]);
|
|
88
|
+
// Rest are treated as separate content
|
|
89
|
+
for (let j = 1; j < itemLines.length; j++) {
|
|
90
|
+
lines.push(""); // Add spacing
|
|
91
|
+
lines.push(itemLines[j]);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
lines.push(chalk.cyan(bullet) + itemText);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Don't add spacing after lists if a space token follows
|
|
99
|
+
// (the space token will handle it)
|
|
100
|
+
break;
|
|
101
|
+
case "blockquote": {
|
|
102
|
+
const quoteText = this.renderInlineTokens(token.tokens || []);
|
|
103
|
+
const quoteLines = quoteText.split("\n");
|
|
104
|
+
for (const quoteLine of quoteLines) {
|
|
105
|
+
lines.push(chalk.gray("│ ") + chalk.italic(quoteLine));
|
|
106
|
+
}
|
|
107
|
+
lines.push(""); // Add spacing after blockquotes
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
case "hr":
|
|
111
|
+
lines.push(chalk.gray("─".repeat(Math.min(width, 80))));
|
|
112
|
+
lines.push(""); // Add spacing after horizontal rules
|
|
113
|
+
break;
|
|
114
|
+
case "html":
|
|
115
|
+
// Skip HTML for terminal output
|
|
116
|
+
break;
|
|
117
|
+
case "space":
|
|
118
|
+
// Space tokens represent blank lines in markdown
|
|
119
|
+
lines.push("");
|
|
120
|
+
break;
|
|
121
|
+
default:
|
|
122
|
+
// Handle any other token types as plain text
|
|
123
|
+
if ("text" in token && typeof token.text === "string") {
|
|
124
|
+
lines.push(token.text);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return lines;
|
|
128
|
+
}
|
|
129
|
+
renderInlineTokens(tokens) {
|
|
130
|
+
let result = "";
|
|
131
|
+
for (const token of tokens) {
|
|
132
|
+
switch (token.type) {
|
|
133
|
+
case "text":
|
|
134
|
+
// Text tokens in list items can have nested tokens for inline formatting
|
|
135
|
+
if (token.tokens && token.tokens.length > 0) {
|
|
136
|
+
result += this.renderInlineTokens(token.tokens);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
result += token.text;
|
|
140
|
+
}
|
|
141
|
+
break;
|
|
142
|
+
case "strong":
|
|
143
|
+
result += chalk.bold(this.renderInlineTokens(token.tokens || []));
|
|
144
|
+
break;
|
|
145
|
+
case "em":
|
|
146
|
+
result += chalk.italic(this.renderInlineTokens(token.tokens || []));
|
|
147
|
+
break;
|
|
148
|
+
case "codespan":
|
|
149
|
+
result += chalk.gray("`") + chalk.cyan(token.text) + chalk.gray("`");
|
|
150
|
+
break;
|
|
151
|
+
case "link": {
|
|
152
|
+
const linkText = this.renderInlineTokens(token.tokens || []);
|
|
153
|
+
result += chalk.underline.blue(linkText) + chalk.gray(` (${token.href})`);
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
case "br":
|
|
157
|
+
result += "\n";
|
|
158
|
+
break;
|
|
159
|
+
case "del":
|
|
160
|
+
result += chalk.strikethrough(this.renderInlineTokens(token.tokens || []));
|
|
161
|
+
break;
|
|
162
|
+
default:
|
|
163
|
+
// Handle any other inline token types as plain text
|
|
164
|
+
if ("text" in token && typeof token.text === "string") {
|
|
165
|
+
result += token.text;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
wrapLine(line, width) {
|
|
172
|
+
// Handle ANSI escape codes properly when wrapping
|
|
173
|
+
const wrapped = [];
|
|
174
|
+
// Handle undefined or null lines
|
|
175
|
+
if (!line) {
|
|
176
|
+
return [""];
|
|
177
|
+
}
|
|
178
|
+
// If line fits within width, return as-is
|
|
179
|
+
const visibleLength = this.getVisibleLength(line);
|
|
180
|
+
if (visibleLength <= width) {
|
|
181
|
+
return [line];
|
|
182
|
+
}
|
|
183
|
+
// Need to wrap - this is complex with ANSI codes
|
|
184
|
+
// For now, use a simple approach that may break styling at wrap points
|
|
185
|
+
let currentLine = "";
|
|
186
|
+
let currentLength = 0;
|
|
187
|
+
let i = 0;
|
|
188
|
+
while (i < line.length) {
|
|
189
|
+
if (line[i] === "\x1b" && line[i + 1] === "[") {
|
|
190
|
+
// ANSI escape sequence - include it without counting length
|
|
191
|
+
let j = i + 2;
|
|
192
|
+
while (j < line.length && line[j] && !/[mGKHJ]/.test(line[j])) {
|
|
193
|
+
j++;
|
|
194
|
+
}
|
|
195
|
+
if (j < line.length) {
|
|
196
|
+
currentLine += line.substring(i, j + 1);
|
|
197
|
+
i = j + 1;
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
// Regular character
|
|
205
|
+
if (currentLength >= width) {
|
|
206
|
+
wrapped.push(currentLine);
|
|
207
|
+
currentLine = "";
|
|
208
|
+
currentLength = 0;
|
|
209
|
+
}
|
|
210
|
+
currentLine += line[i];
|
|
211
|
+
currentLength++;
|
|
212
|
+
i++;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (currentLine) {
|
|
216
|
+
wrapped.push(currentLine);
|
|
217
|
+
}
|
|
218
|
+
return wrapped.length > 0 ? wrapped : [""];
|
|
219
|
+
}
|
|
220
|
+
getVisibleLength(str) {
|
|
221
|
+
// Remove ANSI escape codes and count visible characters
|
|
222
|
+
return (str || "").replace(/\x1b\[[0-9;]*m/g, "").length;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=markdown-component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-component.js","sourceRoot":"","sources":["../src/markdown-component.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Component, ComponentRenderResult } from "./tui.js";
|
|
2
|
+
export interface SelectItem {
|
|
3
|
+
value: string;
|
|
4
|
+
label: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class SelectList implements Component {
|
|
8
|
+
private items;
|
|
9
|
+
private filteredItems;
|
|
10
|
+
private selectedIndex;
|
|
11
|
+
private filter;
|
|
12
|
+
private maxVisible;
|
|
13
|
+
onSelect?: (item: SelectItem) => void;
|
|
14
|
+
onCancel?: () => void;
|
|
15
|
+
constructor(items: SelectItem[], maxVisible?: number);
|
|
16
|
+
setFilter(filter: string): void;
|
|
17
|
+
render(width: number): ComponentRenderResult;
|
|
18
|
+
handleInput(keyData: string): void;
|
|
19
|
+
getSelectedItem(): SelectItem | null;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=select-list.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select-list.d.ts","sourceRoot":"","sources":["../src/select-list.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAEjE,MAAM,WAAW,UAAU;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,UAAW,YAAW,SAAS;IAC3C,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,aAAa,CAAoB;IACzC,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,UAAU,CAAa;IAExB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;gBAEjB,KAAK,EAAE,UAAU,EAAE,EAAE,UAAU,GAAE,MAAU;IAMvD,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAO/B,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,qBAAqB;IA6F5C,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAwBlC,eAAe,IAAI,UAAU,GAAG,IAAI;CAIpC"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
export class SelectList {
|
|
3
|
+
items = [];
|
|
4
|
+
filteredItems = [];
|
|
5
|
+
selectedIndex = 0;
|
|
6
|
+
filter = "";
|
|
7
|
+
maxVisible = 5;
|
|
8
|
+
onSelect;
|
|
9
|
+
onCancel;
|
|
10
|
+
constructor(items, maxVisible = 5) {
|
|
11
|
+
this.items = items;
|
|
12
|
+
this.filteredItems = items;
|
|
13
|
+
this.maxVisible = maxVisible;
|
|
14
|
+
}
|
|
15
|
+
setFilter(filter) {
|
|
16
|
+
this.filter = filter;
|
|
17
|
+
this.filteredItems = this.items.filter((item) => item.value.toLowerCase().startsWith(filter.toLowerCase()));
|
|
18
|
+
// Reset selection when filter changes
|
|
19
|
+
this.selectedIndex = 0;
|
|
20
|
+
}
|
|
21
|
+
render(width) {
|
|
22
|
+
const lines = [];
|
|
23
|
+
// If no items match filter, show message
|
|
24
|
+
if (this.filteredItems.length === 0) {
|
|
25
|
+
lines.push(chalk.gray(" No matching commands"));
|
|
26
|
+
return { lines, changed: true };
|
|
27
|
+
}
|
|
28
|
+
// Calculate visible range with scrolling
|
|
29
|
+
const startIndex = Math.max(0, Math.min(this.selectedIndex - Math.floor(this.maxVisible / 2), this.filteredItems.length - this.maxVisible));
|
|
30
|
+
const endIndex = Math.min(startIndex + this.maxVisible, this.filteredItems.length);
|
|
31
|
+
// Render visible items
|
|
32
|
+
for (let i = startIndex; i < endIndex; i++) {
|
|
33
|
+
const item = this.filteredItems[i];
|
|
34
|
+
if (!item)
|
|
35
|
+
continue;
|
|
36
|
+
const isSelected = i === this.selectedIndex;
|
|
37
|
+
let line = "";
|
|
38
|
+
if (isSelected) {
|
|
39
|
+
// Use arrow indicator for selection
|
|
40
|
+
const prefix = chalk.blue("→ ");
|
|
41
|
+
const displayValue = item.label || item.value;
|
|
42
|
+
if (item.description && width > 40) {
|
|
43
|
+
// Calculate how much space we have for value + description
|
|
44
|
+
const maxValueLength = Math.min(displayValue.length, 30);
|
|
45
|
+
const truncatedValue = displayValue.substring(0, maxValueLength);
|
|
46
|
+
const spacing = " ".repeat(Math.max(1, 32 - truncatedValue.length));
|
|
47
|
+
// Calculate remaining space for description
|
|
48
|
+
const descriptionStart = prefix.length + truncatedValue.length + spacing.length - 2; // -2 for arrow color codes
|
|
49
|
+
const remainingWidth = width - descriptionStart - 2; // -2 for safety
|
|
50
|
+
if (remainingWidth > 10) {
|
|
51
|
+
const truncatedDesc = item.description.substring(0, remainingWidth);
|
|
52
|
+
line = prefix + chalk.blue(truncatedValue) + chalk.gray(spacing + truncatedDesc);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
// Not enough space for description
|
|
56
|
+
const maxWidth = width - 4; // 2 for arrow + space, 2 for safety
|
|
57
|
+
line = prefix + chalk.blue(displayValue.substring(0, maxWidth));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
// No description or not enough width
|
|
62
|
+
const maxWidth = width - 4; // 2 for arrow + space, 2 for safety
|
|
63
|
+
line = prefix + chalk.blue(displayValue.substring(0, maxWidth));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
const displayValue = item.label || item.value;
|
|
68
|
+
const prefix = " ";
|
|
69
|
+
if (item.description && width > 40) {
|
|
70
|
+
// Calculate how much space we have for value + description
|
|
71
|
+
const maxValueLength = Math.min(displayValue.length, 30);
|
|
72
|
+
const truncatedValue = displayValue.substring(0, maxValueLength);
|
|
73
|
+
const spacing = " ".repeat(Math.max(1, 32 - truncatedValue.length));
|
|
74
|
+
// Calculate remaining space for description
|
|
75
|
+
const descriptionStart = prefix.length + truncatedValue.length + spacing.length;
|
|
76
|
+
const remainingWidth = width - descriptionStart - 2; // -2 for safety
|
|
77
|
+
if (remainingWidth > 10) {
|
|
78
|
+
const truncatedDesc = item.description.substring(0, remainingWidth);
|
|
79
|
+
line = prefix + truncatedValue + chalk.gray(spacing + truncatedDesc);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
// Not enough space for description
|
|
83
|
+
const maxWidth = width - prefix.length - 2;
|
|
84
|
+
line = prefix + displayValue.substring(0, maxWidth);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
// No description or not enough width
|
|
89
|
+
const maxWidth = width - prefix.length - 2;
|
|
90
|
+
line = prefix + displayValue.substring(0, maxWidth);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
lines.push(line);
|
|
94
|
+
}
|
|
95
|
+
// Add scroll indicators if needed
|
|
96
|
+
if (startIndex > 0 || endIndex < this.filteredItems.length) {
|
|
97
|
+
const scrollInfo = chalk.gray(` (${this.selectedIndex + 1}/${this.filteredItems.length})`);
|
|
98
|
+
lines.push(scrollInfo);
|
|
99
|
+
}
|
|
100
|
+
return { lines, changed: true };
|
|
101
|
+
}
|
|
102
|
+
handleInput(keyData) {
|
|
103
|
+
// Up arrow
|
|
104
|
+
if (keyData === "\x1b[A") {
|
|
105
|
+
this.selectedIndex = Math.max(0, this.selectedIndex - 1);
|
|
106
|
+
}
|
|
107
|
+
// Down arrow
|
|
108
|
+
else if (keyData === "\x1b[B") {
|
|
109
|
+
this.selectedIndex = Math.min(this.filteredItems.length - 1, this.selectedIndex + 1);
|
|
110
|
+
}
|
|
111
|
+
// Enter
|
|
112
|
+
else if (keyData === "\r") {
|
|
113
|
+
const selectedItem = this.filteredItems[this.selectedIndex];
|
|
114
|
+
if (selectedItem && this.onSelect) {
|
|
115
|
+
this.onSelect(selectedItem);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Escape
|
|
119
|
+
else if (keyData === "\x1b") {
|
|
120
|
+
if (this.onCancel) {
|
|
121
|
+
this.onCancel();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
getSelectedItem() {
|
|
126
|
+
const item = this.filteredItems[this.selectedIndex];
|
|
127
|
+
return item || null;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=select-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select-list.js","sourceRoot":"","sources":["../src/select-list.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Component, ComponentRenderResult, Padding } from "./tui.js";
|
|
2
|
+
export declare class TextComponent implements Component {
|
|
3
|
+
private text;
|
|
4
|
+
private lastRenderedLines;
|
|
5
|
+
private padding;
|
|
6
|
+
constructor(text: string, padding?: Padding);
|
|
7
|
+
render(width: number): ComponentRenderResult;
|
|
8
|
+
setText(text: string): void;
|
|
9
|
+
getText(): string;
|
|
10
|
+
private arraysEqual;
|
|
11
|
+
private getVisibleLength;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=text-component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-component.d.ts","sourceRoot":"","sources":["../src/text-component.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAE1E,qBAAa,aAAc,YAAW,SAAS;IAC9C,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,iBAAiB,CAAgB;IACzC,OAAO,CAAC,OAAO,CAAoB;gBAEvB,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO;IAU3C,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,qBAAqB;IAkE5C,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI3B,OAAO,IAAI,MAAM;IAIjB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,gBAAgB;CAIxB"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
export class TextComponent {
|
|
2
|
+
text;
|
|
3
|
+
lastRenderedLines = [];
|
|
4
|
+
padding;
|
|
5
|
+
constructor(text, padding) {
|
|
6
|
+
this.text = text;
|
|
7
|
+
this.padding = {
|
|
8
|
+
top: padding?.top ?? 0,
|
|
9
|
+
bottom: padding?.bottom ?? 0,
|
|
10
|
+
left: padding?.left ?? 0,
|
|
11
|
+
right: padding?.right ?? 0,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
render(width) {
|
|
15
|
+
// Calculate available width after horizontal padding
|
|
16
|
+
const availableWidth = Math.max(1, width - this.padding.left - this.padding.right);
|
|
17
|
+
const leftPadding = " ".repeat(this.padding.left);
|
|
18
|
+
// First split by newlines to preserve line breaks
|
|
19
|
+
const textLines = this.text.split("\n");
|
|
20
|
+
const lines = [];
|
|
21
|
+
// Add top padding
|
|
22
|
+
for (let i = 0; i < this.padding.top; i++) {
|
|
23
|
+
lines.push("");
|
|
24
|
+
}
|
|
25
|
+
// Process each line for word wrapping
|
|
26
|
+
for (const textLine of textLines) {
|
|
27
|
+
if (textLine.length === 0) {
|
|
28
|
+
// Preserve empty lines with padding
|
|
29
|
+
lines.push(leftPadding);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
// Word wrapping with ANSI-aware length calculation
|
|
33
|
+
const words = textLine.split(" ");
|
|
34
|
+
let currentLine = "";
|
|
35
|
+
let currentVisibleLength = 0;
|
|
36
|
+
for (const word of words) {
|
|
37
|
+
const wordVisibleLength = this.getVisibleLength(word);
|
|
38
|
+
const spaceLength = currentLine ? 1 : 0;
|
|
39
|
+
if (currentVisibleLength + spaceLength + wordVisibleLength <= availableWidth) {
|
|
40
|
+
currentLine += (currentLine ? " " : "") + word;
|
|
41
|
+
currentVisibleLength += spaceLength + wordVisibleLength;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
if (currentLine) {
|
|
45
|
+
lines.push(leftPadding + currentLine);
|
|
46
|
+
}
|
|
47
|
+
currentLine = word;
|
|
48
|
+
currentVisibleLength = wordVisibleLength;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (currentLine) {
|
|
52
|
+
lines.push(leftPadding + currentLine);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Add bottom padding
|
|
57
|
+
for (let i = 0; i < this.padding.bottom; i++) {
|
|
58
|
+
lines.push("");
|
|
59
|
+
}
|
|
60
|
+
const newLines = lines.length > 0 ? lines : [""];
|
|
61
|
+
// Check if content changed
|
|
62
|
+
const changed = !this.arraysEqual(newLines, this.lastRenderedLines);
|
|
63
|
+
// Always cache the current rendered lines
|
|
64
|
+
this.lastRenderedLines = [...newLines];
|
|
65
|
+
return {
|
|
66
|
+
lines: newLines,
|
|
67
|
+
changed,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
setText(text) {
|
|
71
|
+
this.text = text;
|
|
72
|
+
}
|
|
73
|
+
getText() {
|
|
74
|
+
return this.text;
|
|
75
|
+
}
|
|
76
|
+
arraysEqual(a, b) {
|
|
77
|
+
if (a.length !== b.length)
|
|
78
|
+
return false;
|
|
79
|
+
for (let i = 0; i < a.length; i++) {
|
|
80
|
+
if (a[i] !== b[i])
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
getVisibleLength(str) {
|
|
86
|
+
// Remove ANSI escape codes and count visible characters
|
|
87
|
+
return (str || "").replace(/\x1b\[[0-9;]*m/g, "").length;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=text-component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-component.js","sourceRoot":"","sources":["../src/text-component.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { AutocompleteProvider } from "./autocomplete.js";
|
|
2
|
+
import type { Component, ComponentRenderResult } from "./tui.js";
|
|
3
|
+
export interface TextEditorConfig {
|
|
4
|
+
}
|
|
5
|
+
export declare class TextEditor implements Component {
|
|
6
|
+
private state;
|
|
7
|
+
private config;
|
|
8
|
+
private autocompleteProvider?;
|
|
9
|
+
private autocompleteList?;
|
|
10
|
+
private isAutocompleting;
|
|
11
|
+
private autocompletePrefix;
|
|
12
|
+
onSubmit?: (text: string) => void;
|
|
13
|
+
onChange?: (text: string) => void;
|
|
14
|
+
disableSubmit: boolean;
|
|
15
|
+
constructor(config?: TextEditorConfig);
|
|
16
|
+
configure(config: Partial<TextEditorConfig>): void;
|
|
17
|
+
setAutocompleteProvider(provider: AutocompleteProvider): void;
|
|
18
|
+
render(width: number): ComponentRenderResult;
|
|
19
|
+
handleInput(data: string): void;
|
|
20
|
+
private layoutText;
|
|
21
|
+
getText(): string;
|
|
22
|
+
setText(text: string): void;
|
|
23
|
+
private insertCharacter;
|
|
24
|
+
private handlePaste;
|
|
25
|
+
private addNewLine;
|
|
26
|
+
private handleBackspace;
|
|
27
|
+
private moveToLineStart;
|
|
28
|
+
private moveToLineEnd;
|
|
29
|
+
private handleForwardDelete;
|
|
30
|
+
private deleteCurrentLine;
|
|
31
|
+
private moveCursor;
|
|
32
|
+
private isAtStartOfMessage;
|
|
33
|
+
private tryTriggerAutocomplete;
|
|
34
|
+
private handleTabCompletion;
|
|
35
|
+
private handleSlashCommandCompletion;
|
|
36
|
+
private forceFileAutocomplete;
|
|
37
|
+
private cancelAutocomplete;
|
|
38
|
+
private updateAutocomplete;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=text-editor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-editor.d.ts","sourceRoot":"","sources":["../src/text-editor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAgC,MAAM,mBAAmB,CAAC;AAG5F,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAcjE,MAAM,WAAW,gBAAgB;CAEhC;AAED,qBAAa,UAAW,YAAW,SAAS;IAC3C,OAAO,CAAC,KAAK,CAIX;IAEF,OAAO,CAAC,MAAM,CAAwB;IAGtC,OAAO,CAAC,oBAAoB,CAAC,CAAuB;IACpD,OAAO,CAAC,gBAAgB,CAAC,CAAa;IACtC,OAAO,CAAC,gBAAgB,CAAkB;IAC1C,OAAO,CAAC,kBAAkB,CAAc;IAEjC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,aAAa,EAAE,OAAO,CAAS;gBAE1B,MAAM,CAAC,EAAE,gBAAgB;IAOrC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI;IAKlD,uBAAuB,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI;IAI7D,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,qBAAqB;IAsE5C,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IA8M/B,OAAO,CAAC,UAAU;IAsElB,OAAO,IAAI,MAAM;IAIjB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAkB3B,OAAO,CAAC,eAAe;IAiCvB,OAAO,CAAC,WAAW;IA0EnB,OAAO,CAAC,UAAU;IAmBlB,OAAO,CAAC,eAAe;IAgCvB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,mBAAmB;IAoB3B,OAAO,CAAC,iBAAiB;IAyBzB,OAAO,CAAC,UAAU;IAqBlB,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,sBAAsB;IAiD9B,OAAO,CAAC,mBAAmB;IAgB3B,OAAO,CAAC,4BAA4B;IAOpC,OAAO,CAAC,qBAAqB;IAoC7B,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,kBAAkB;CAoB1B"}
|