u-foo 2.3.16 → 2.3.18
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 +310 -293
- package/README.zh-CN.md +288 -289
- package/package.json +1 -1
- package/src/agent/internalRunner.js +11 -1
- package/src/chat/agentViewController.js +250 -28
- package/src/chat/index.js +7 -1
- package/src/chat/inputMath.js +24 -10
package/package.json
CHANGED
|
@@ -184,6 +184,16 @@ function createBusSender(projectRoot, subscriber) {
|
|
|
184
184
|
return { enqueue, flush };
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
+
function isChatUiSource(source = "") {
|
|
188
|
+
const value = String(source || "").trim();
|
|
189
|
+
return value === "chat-direct" || value === "chat-internal-agent-view";
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function shouldStreamReplyToPublisher(projectRoot, publisher, evt = {}) {
|
|
193
|
+
if (isChatUiSource(evt && evt.data ? evt.data.source : "")) return true;
|
|
194
|
+
return shouldForwardStreamToPublisher(projectRoot, publisher);
|
|
195
|
+
}
|
|
196
|
+
|
|
187
197
|
function drainQueue(queueFile) {
|
|
188
198
|
if (!fs.existsSync(queueFile)) return [];
|
|
189
199
|
const processingFile = `${queueFile}.processing.${process.pid}.${Date.now()}`;
|
|
@@ -304,7 +314,7 @@ async function handleEvent(
|
|
|
304
314
|
.filter(Boolean)
|
|
305
315
|
.join("\n\n");
|
|
306
316
|
const publisher = evt.publisher || "unknown";
|
|
307
|
-
const streamToPublisher =
|
|
317
|
+
const streamToPublisher = shouldStreamReplyToPublisher(projectRoot, publisher, evt);
|
|
308
318
|
|
|
309
319
|
const emitStreamDelta = (delta) => {
|
|
310
320
|
const text = String(delta || "");
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
const os = require("os");
|
|
2
|
+
const { version: packageVersion } = require("../../package.json");
|
|
3
|
+
|
|
1
4
|
function createAgentViewController(options = {}) {
|
|
2
5
|
const {
|
|
3
6
|
screen,
|
|
@@ -17,6 +20,7 @@ function createAgentViewController(options = {}) {
|
|
|
17
20
|
setAgentListWindowStart = () => {},
|
|
18
21
|
getAgentLabel = (id) => id,
|
|
19
22
|
getAgentStates = () => ({}),
|
|
23
|
+
getProjectRoot = () => process.cwd(),
|
|
20
24
|
setDashboardView = () => {},
|
|
21
25
|
setScreenGrabKeys = (value) => {
|
|
22
26
|
if (screen) screen.grabKeys = Boolean(value);
|
|
@@ -77,14 +81,64 @@ function createAgentViewController(options = {}) {
|
|
|
77
81
|
return Math.max(min, Math.min(max, normalized));
|
|
78
82
|
}
|
|
79
83
|
|
|
84
|
+
function charDisplayWidth(char = "") {
|
|
85
|
+
if (!char) return 0;
|
|
86
|
+
const code = char.codePointAt(0) || 0;
|
|
87
|
+
if (code === 0) return 0;
|
|
88
|
+
if (code < 32 || (code >= 0x7f && code < 0xa0)) return 0;
|
|
89
|
+
if ((code >= 0x0300 && code <= 0x036f) ||
|
|
90
|
+
(code >= 0x1ab0 && code <= 0x1aff) ||
|
|
91
|
+
(code >= 0x1dc0 && code <= 0x1dff) ||
|
|
92
|
+
(code >= 0x20d0 && code <= 0x20ff) ||
|
|
93
|
+
(code >= 0xfe20 && code <= 0xfe2f)) {
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
if ((code >= 0x1100 && code <= 0x115f) ||
|
|
97
|
+
code === 0x2329 ||
|
|
98
|
+
code === 0x232a ||
|
|
99
|
+
(code >= 0x2e80 && code <= 0xa4cf) ||
|
|
100
|
+
(code >= 0xac00 && code <= 0xd7a3) ||
|
|
101
|
+
(code >= 0xf900 && code <= 0xfaff) ||
|
|
102
|
+
(code >= 0xfe10 && code <= 0xfe19) ||
|
|
103
|
+
(code >= 0xfe30 && code <= 0xfe6f) ||
|
|
104
|
+
(code >= 0xff00 && code <= 0xff60) ||
|
|
105
|
+
(code >= 0xffe0 && code <= 0xffe6) ||
|
|
106
|
+
(code >= 0x1f300 && code <= 0x1faff)) {
|
|
107
|
+
return 2;
|
|
108
|
+
}
|
|
109
|
+
return 1;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function displayWidth(text = "") {
|
|
113
|
+
return Array.from(stripAnsi(String(text || ""))).reduce((sum, char) => sum + charDisplayWidth(char), 0);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function padToWidth(text = "", width = 1) {
|
|
117
|
+
const cells = displayWidth(text);
|
|
118
|
+
return String(text || "") + " ".repeat(Math.max(0, width - cells));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function truncateToWidth(text = "", width = 1) {
|
|
122
|
+
const target = Math.max(1, width);
|
|
123
|
+
let out = "";
|
|
124
|
+
let cells = 0;
|
|
125
|
+
for (const char of Array.from(stripAnsi(String(text || "")))) {
|
|
126
|
+
const charWidth = charDisplayWidth(char);
|
|
127
|
+
if (cells + charWidth > target) break;
|
|
128
|
+
out += char;
|
|
129
|
+
cells += charWidth;
|
|
130
|
+
}
|
|
131
|
+
return padToWidth(out, target);
|
|
132
|
+
}
|
|
133
|
+
|
|
80
134
|
function fitText(text = "", width = 1) {
|
|
81
135
|
const normalizedWidth = Math.max(1, width);
|
|
82
136
|
const clean = stripAnsi(String(text || "")).replace(/\r/g, "");
|
|
83
|
-
if (clean
|
|
84
|
-
return clean
|
|
137
|
+
if (displayWidth(clean) <= normalizedWidth) {
|
|
138
|
+
return padToWidth(clean, normalizedWidth);
|
|
85
139
|
}
|
|
86
|
-
if (normalizedWidth <= 1) return clean
|
|
87
|
-
return clean
|
|
140
|
+
if (normalizedWidth <= 1) return truncateToWidth(clean, normalizedWidth);
|
|
141
|
+
return `${truncateToWidth(clean, normalizedWidth - 1).trimEnd()}…`;
|
|
88
142
|
}
|
|
89
143
|
|
|
90
144
|
function horizontalLine(width = 80) {
|
|
@@ -95,17 +149,47 @@ function createAgentViewController(options = {}) {
|
|
|
95
149
|
return fitText(text, Math.max(1, width));
|
|
96
150
|
}
|
|
97
151
|
|
|
152
|
+
function sliceDisplayCells(text = "", startCell = 0, maxCells = 1) {
|
|
153
|
+
const targetStart = Math.max(0, startCell);
|
|
154
|
+
const targetWidth = Math.max(1, maxCells);
|
|
155
|
+
let out = "";
|
|
156
|
+
let cells = 0;
|
|
157
|
+
let started = false;
|
|
158
|
+
for (const char of Array.from(String(text || ""))) {
|
|
159
|
+
const charWidth = charDisplayWidth(char);
|
|
160
|
+
const nextCells = cells + charWidth;
|
|
161
|
+
if (!started) {
|
|
162
|
+
if (nextCells <= targetStart) {
|
|
163
|
+
cells = nextCells;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
started = true;
|
|
167
|
+
}
|
|
168
|
+
if (displayWidth(out) + charWidth > targetWidth) break;
|
|
169
|
+
out += char;
|
|
170
|
+
cells = nextCells;
|
|
171
|
+
}
|
|
172
|
+
return out;
|
|
173
|
+
}
|
|
174
|
+
|
|
98
175
|
function wrapTextLine(text = "", width = 80) {
|
|
99
176
|
const inner = Math.max(1, width);
|
|
100
177
|
const clean = stripAnsi(String(text || ""));
|
|
101
178
|
if (!clean) return [""];
|
|
102
179
|
const lines = [];
|
|
103
|
-
let
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
180
|
+
let current = "";
|
|
181
|
+
let cells = 0;
|
|
182
|
+
for (const char of Array.from(clean)) {
|
|
183
|
+
const charWidth = charDisplayWidth(char);
|
|
184
|
+
if (cells > 0 && cells + charWidth > inner) {
|
|
185
|
+
lines.push(current);
|
|
186
|
+
current = "";
|
|
187
|
+
cells = 0;
|
|
188
|
+
}
|
|
189
|
+
current += char;
|
|
190
|
+
cells += charWidth;
|
|
107
191
|
}
|
|
108
|
-
lines.push(
|
|
192
|
+
lines.push(current);
|
|
109
193
|
return lines;
|
|
110
194
|
}
|
|
111
195
|
|
|
@@ -122,14 +206,93 @@ function createAgentViewController(options = {}) {
|
|
|
122
206
|
processStdout.write(`\x1b[${row};1H\x1b[2K${content}`);
|
|
123
207
|
}
|
|
124
208
|
|
|
209
|
+
function forceScreenRepaint() {
|
|
210
|
+
if (typeof screen.realloc === "function") {
|
|
211
|
+
screen.realloc();
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
if (typeof screen.alloc === "function") {
|
|
215
|
+
screen.alloc(true);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function compactProjectPath(projectRoot = "") {
|
|
220
|
+
const raw = String(projectRoot || process.cwd() || "").trim();
|
|
221
|
+
const home = os.homedir();
|
|
222
|
+
if (home && (raw === home || raw.startsWith(`${home}/`))) {
|
|
223
|
+
return `~${raw.slice(home.length)}`;
|
|
224
|
+
}
|
|
225
|
+
return raw || ".";
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function borderedLines(lines = [], innerWidth = 56) {
|
|
229
|
+
const contentWidth = Math.max(1, innerWidth);
|
|
230
|
+
const out = [`╭${"─".repeat(contentWidth + 2)}╮`];
|
|
231
|
+
for (const line of lines) {
|
|
232
|
+
out.push(`│ ${fitText(line, contentWidth)} │`);
|
|
233
|
+
}
|
|
234
|
+
out.push(`╰${"─".repeat(contentWidth + 2)}╯`);
|
|
235
|
+
return out;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function normalizeAgentKind(agentId = "") {
|
|
239
|
+
const text = String(agentId || "").trim().toLowerCase();
|
|
240
|
+
if (text.startsWith("codex:") || text === "codex") return "codex";
|
|
241
|
+
if (text.startsWith("claude:") || text.startsWith("claude-code:") || text === "claude" || text === "claude-code") {
|
|
242
|
+
return "claude";
|
|
243
|
+
}
|
|
244
|
+
return "internal";
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function buildClaudeStartupLines(agentLabel = "", width = 80) {
|
|
248
|
+
const label = String(agentLabel || "").trim();
|
|
249
|
+
const projectPath = compactProjectPath(getProjectRoot());
|
|
250
|
+
const product = "Claude Code";
|
|
251
|
+
const detail = label ? `${label} · managed headless` : "managed headless";
|
|
252
|
+
const lines = [
|
|
253
|
+
` ▐▛███▜▌${product} v${packageVersion}`,
|
|
254
|
+
`▝▜█████▛▘${detail}`,
|
|
255
|
+
` ▘▘▝▝${projectPath}`,
|
|
256
|
+
"",
|
|
257
|
+
];
|
|
258
|
+
if (width < 44) return lines;
|
|
259
|
+
return lines.map((line) => padToWidth(line, Math.min(58, Math.max(1, width))));
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function buildCodexStartupLines(agentLabel = "", width = 80) {
|
|
263
|
+
const label = String(agentLabel || "").trim();
|
|
264
|
+
const projectPath = compactProjectPath(getProjectRoot());
|
|
265
|
+
if (width < 36) {
|
|
266
|
+
return [
|
|
267
|
+
`>_ OpenAI Codex`,
|
|
268
|
+
label ? `model: ${label}` : "model: managed headless",
|
|
269
|
+
`directory: ${projectPath}`,
|
|
270
|
+
"",
|
|
271
|
+
];
|
|
272
|
+
}
|
|
273
|
+
const innerWidth = Math.min(56, Math.max(24, width - 4));
|
|
274
|
+
return [
|
|
275
|
+
...borderedLines([
|
|
276
|
+
`>_ OpenAI Codex (ufoo v${packageVersion})`,
|
|
277
|
+
"",
|
|
278
|
+
`model: ${label ? `${label} · managed headless` : "managed headless"}`,
|
|
279
|
+
`directory: ${projectPath}`,
|
|
280
|
+
], innerWidth),
|
|
281
|
+
"",
|
|
282
|
+
];
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function buildInternalStartupLines(agentId = "", agentLabel = "", width = 80) {
|
|
286
|
+
const kind = normalizeAgentKind(agentId);
|
|
287
|
+
if (kind === "codex") return buildCodexStartupLines(agentLabel || agentId, width);
|
|
288
|
+
return buildClaudeStartupLines(agentLabel || agentId, width);
|
|
289
|
+
}
|
|
290
|
+
|
|
125
291
|
function resetBusView(agentId) {
|
|
126
292
|
busInputValue = "";
|
|
127
293
|
busInputCursor = 0;
|
|
128
294
|
const label = getAgentLabel(agentId);
|
|
129
|
-
busLogLines =
|
|
130
|
-
`ufoo internal · ${label}`,
|
|
131
|
-
"",
|
|
132
|
-
];
|
|
295
|
+
busLogLines = buildInternalStartupLines(agentId, label, getCols());
|
|
133
296
|
}
|
|
134
297
|
|
|
135
298
|
function appendBusLog(text = "") {
|
|
@@ -148,15 +311,18 @@ function createAgentViewController(options = {}) {
|
|
|
148
311
|
}
|
|
149
312
|
|
|
150
313
|
function getBusInputViewport(width) {
|
|
151
|
-
const inner = Math.max(1, width -
|
|
314
|
+
const inner = Math.max(1, width - 2);
|
|
152
315
|
const value = String(busInputValue || "").replace(/\n/g, "⏎");
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
316
|
+
const beforeCursor = String(busInputValue || "").slice(0, busInputCursor).replace(/\n/g, "⏎");
|
|
317
|
+
const cursorCells = displayWidth(beforeCursor);
|
|
318
|
+
let startCell = 0;
|
|
319
|
+
if (cursorCells >= inner) {
|
|
320
|
+
startCell = cursorCells - inner + 1;
|
|
156
321
|
}
|
|
322
|
+
const text = sliceDisplayCells(value, startCell, inner);
|
|
157
323
|
return {
|
|
158
|
-
text
|
|
159
|
-
cursorCol: Math.max(0,
|
|
324
|
+
text,
|
|
325
|
+
cursorCol: Math.max(0, cursorCells - startCell),
|
|
160
326
|
};
|
|
161
327
|
}
|
|
162
328
|
|
|
@@ -284,7 +450,7 @@ function createAgentViewController(options = {}) {
|
|
|
284
450
|
viewingAgent = null;
|
|
285
451
|
|
|
286
452
|
processStdout.write(`\x1b[1;${rows}r`);
|
|
287
|
-
processStdout.write("\x1b[
|
|
453
|
+
processStdout.write("\x1b[?25h");
|
|
288
454
|
|
|
289
455
|
if (detachedChildren) {
|
|
290
456
|
for (const child of detachedChildren) screen.append(child);
|
|
@@ -296,9 +462,7 @@ function createAgentViewController(options = {}) {
|
|
|
296
462
|
setDashboardView("agents");
|
|
297
463
|
setSelectedAgentIndex(-1);
|
|
298
464
|
setScreenGrabKeys(false);
|
|
299
|
-
|
|
300
|
-
screen.alloc();
|
|
301
|
-
}
|
|
465
|
+
forceScreenRepaint();
|
|
302
466
|
clearTargetAgent();
|
|
303
467
|
renderDashboard();
|
|
304
468
|
focusInput();
|
|
@@ -333,10 +497,66 @@ function createAgentViewController(options = {}) {
|
|
|
333
497
|
renderBusView();
|
|
334
498
|
}
|
|
335
499
|
|
|
500
|
+
function inputBoundaries(text = "") {
|
|
501
|
+
const source = String(text || "");
|
|
502
|
+
if (!source) return [0];
|
|
503
|
+
try {
|
|
504
|
+
if (typeof Intl !== "undefined" && typeof Intl.Segmenter === "function") {
|
|
505
|
+
const segmenter = new Intl.Segmenter(undefined, { granularity: "grapheme" });
|
|
506
|
+
const boundaries = [0];
|
|
507
|
+
for (const part of segmenter.segment(source)) {
|
|
508
|
+
boundaries.push(part.index + part.segment.length);
|
|
509
|
+
}
|
|
510
|
+
return Array.from(new Set(boundaries)).sort((a, b) => a - b);
|
|
511
|
+
}
|
|
512
|
+
} catch {
|
|
513
|
+
// Fall through to code point boundaries.
|
|
514
|
+
}
|
|
515
|
+
const boundaries = [0];
|
|
516
|
+
let offset = 0;
|
|
517
|
+
for (const char of Array.from(source)) {
|
|
518
|
+
offset += char.length;
|
|
519
|
+
boundaries.push(offset);
|
|
520
|
+
}
|
|
521
|
+
return boundaries;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
function clampInputCursor(pos = busInputCursor) {
|
|
525
|
+
const boundaries = inputBoundaries(busInputValue);
|
|
526
|
+
const target = clamp(pos, 0, busInputValue.length);
|
|
527
|
+
let best = 0;
|
|
528
|
+
for (const boundary of boundaries) {
|
|
529
|
+
if (boundary <= target) best = boundary;
|
|
530
|
+
else break;
|
|
531
|
+
}
|
|
532
|
+
return best;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
function previousInputBoundary(pos = busInputCursor) {
|
|
536
|
+
const boundaries = inputBoundaries(busInputValue);
|
|
537
|
+
const target = clamp(pos, 0, busInputValue.length);
|
|
538
|
+
let prev = 0;
|
|
539
|
+
for (const boundary of boundaries) {
|
|
540
|
+
if (boundary < target) prev = boundary;
|
|
541
|
+
else break;
|
|
542
|
+
}
|
|
543
|
+
return prev;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
function nextInputBoundary(pos = busInputCursor) {
|
|
547
|
+
const boundaries = inputBoundaries(busInputValue);
|
|
548
|
+
const target = clamp(pos, 0, busInputValue.length);
|
|
549
|
+
for (const boundary of boundaries) {
|
|
550
|
+
if (boundary > target) return boundary;
|
|
551
|
+
}
|
|
552
|
+
return busInputValue.length;
|
|
553
|
+
}
|
|
554
|
+
|
|
336
555
|
function deleteBusInputBeforeCursor() {
|
|
337
556
|
if (busInputCursor <= 0) return;
|
|
338
|
-
|
|
339
|
-
|
|
557
|
+
const previous = previousInputBoundary();
|
|
558
|
+
busInputValue = busInputValue.slice(0, previous) + busInputValue.slice(busInputCursor);
|
|
559
|
+
busInputCursor = previous;
|
|
340
560
|
renderBusView();
|
|
341
561
|
}
|
|
342
562
|
|
|
@@ -392,12 +612,12 @@ function createAgentViewController(options = {}) {
|
|
|
392
612
|
return true;
|
|
393
613
|
}
|
|
394
614
|
if (keyName === "left") {
|
|
395
|
-
busInputCursor =
|
|
615
|
+
busInputCursor = previousInputBoundary();
|
|
396
616
|
renderBusView();
|
|
397
617
|
return true;
|
|
398
618
|
}
|
|
399
619
|
if (keyName === "right") {
|
|
400
|
-
busInputCursor =
|
|
620
|
+
busInputCursor = nextInputBoundary();
|
|
401
621
|
renderBusView();
|
|
402
622
|
return true;
|
|
403
623
|
}
|
|
@@ -417,7 +637,9 @@ function createAgentViewController(options = {}) {
|
|
|
417
637
|
}
|
|
418
638
|
if (keyName === "delete") {
|
|
419
639
|
if (busInputCursor < busInputValue.length) {
|
|
420
|
-
|
|
640
|
+
const next = nextInputBoundary();
|
|
641
|
+
busInputValue = busInputValue.slice(0, busInputCursor) + busInputValue.slice(next);
|
|
642
|
+
busInputCursor = clampInputCursor();
|
|
421
643
|
renderBusView();
|
|
422
644
|
}
|
|
423
645
|
return true;
|
package/src/chat/index.js
CHANGED
|
@@ -355,7 +355,12 @@ async function runChat(projectRoot, options = {}) {
|
|
|
355
355
|
let preferredCol = null;
|
|
356
356
|
|
|
357
357
|
function getInnerWidth() {
|
|
358
|
-
|
|
358
|
+
let promptWidth = 2;
|
|
359
|
+
try {
|
|
360
|
+
if (promptBox && typeof promptBox.width === "number") promptWidth = promptBox.width;
|
|
361
|
+
} catch {
|
|
362
|
+
promptWidth = 2;
|
|
363
|
+
}
|
|
359
364
|
return inputMath.getInnerWidth({ input, screen, promptWidth });
|
|
360
365
|
}
|
|
361
366
|
|
|
@@ -1538,6 +1543,7 @@ async function runChat(projectRoot, options = {}) {
|
|
|
1538
1543
|
}
|
|
1539
1544
|
return states;
|
|
1540
1545
|
},
|
|
1546
|
+
getProjectRoot: () => activeProjectRoot,
|
|
1541
1547
|
setDashboardView: (value) => {
|
|
1542
1548
|
dashboardView = value;
|
|
1543
1549
|
},
|
package/src/chat/inputMath.js
CHANGED
|
@@ -50,10 +50,18 @@ function safeStrWidth(strWidth, value) {
|
|
|
50
50
|
return Array.from(expanded).length;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
function safeRead(getter, fallback = undefined) {
|
|
54
|
+
try {
|
|
55
|
+
return getter();
|
|
56
|
+
} catch {
|
|
57
|
+
return fallback;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
53
61
|
function getInnerWidth({ input, screen, promptWidth = 2 }) {
|
|
54
62
|
const targetInput = input && typeof input === "object" ? input : {};
|
|
55
63
|
const targetScreen = screen && typeof screen === "object" ? screen : {};
|
|
56
|
-
let lpos = targetInput.lpos || null;
|
|
64
|
+
let lpos = safeRead(() => targetInput.lpos, null) || null;
|
|
57
65
|
if (!lpos && typeof targetInput._getCoords === "function") {
|
|
58
66
|
try {
|
|
59
67
|
lpos = targetInput._getCoords();
|
|
@@ -64,21 +72,27 @@ function getInnerWidth({ input, screen, promptWidth = 2 }) {
|
|
|
64
72
|
if (lpos && Number.isFinite(lpos.xl) && Number.isFinite(lpos.xi)) {
|
|
65
73
|
return Math.max(1, lpos.xl - lpos.xi);
|
|
66
74
|
}
|
|
67
|
-
|
|
68
|
-
if (typeof
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
75
|
+
const inputWidth = safeRead(() => targetInput.width);
|
|
76
|
+
if (typeof inputWidth === "number") return Math.max(1, inputWidth);
|
|
77
|
+
if (typeof inputWidth === "string") {
|
|
78
|
+
const match = inputWidth.match(/^100%-([0-9]+)$/);
|
|
79
|
+
const screenWidth = safeRead(() => targetScreen.width);
|
|
80
|
+
if (match && typeof screenWidth === "number") {
|
|
81
|
+
return Math.max(1, screenWidth - parseInt(match[1], 10));
|
|
72
82
|
}
|
|
73
83
|
}
|
|
74
|
-
|
|
75
|
-
if (typeof
|
|
84
|
+
const screenWidth = safeRead(() => targetScreen.width);
|
|
85
|
+
if (typeof screenWidth === "number") return Math.max(1, screenWidth - promptWidth);
|
|
86
|
+
const screenCols = safeRead(() => targetScreen.cols);
|
|
87
|
+
if (typeof screenCols === "number") return Math.max(1, screenCols - promptWidth);
|
|
76
88
|
return 1;
|
|
77
89
|
}
|
|
78
90
|
|
|
79
91
|
function getWrapWidth(input, fallbackWidth) {
|
|
80
|
-
|
|
81
|
-
|
|
92
|
+
const clines = safeRead(() => input && input._clines, null);
|
|
93
|
+
const clinesWidth = safeRead(() => clines && clines.width);
|
|
94
|
+
if (typeof clinesWidth === "number") {
|
|
95
|
+
return Math.max(1, clinesWidth);
|
|
82
96
|
}
|
|
83
97
|
return Math.max(1, fallbackWidth || 1);
|
|
84
98
|
}
|