parallel-codex-tui 0.1.3 → 0.1.4
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/.parallel-codex/config.example.toml +90 -3
- package/README.md +240 -21
- package/dist/bootstrap.js +37 -17
- package/dist/cli-args.js +34 -3
- package/dist/cli-help.js +20 -0
- package/dist/cli-startup-recovery.js +70 -0
- package/dist/cli-workspace-picker.js +330 -0
- package/dist/cli-workspace-transition.js +33 -0
- package/dist/cli-workspace.js +7 -71
- package/dist/cli.js +221 -23
- package/dist/core/collaboration-timeline.js +261 -0
- package/dist/core/config-errors.js +14 -0
- package/dist/core/config.js +154 -24
- package/dist/core/file-store.js +119 -6
- package/dist/core/lease-finalization.js +22 -0
- package/dist/core/paths.js +7 -0
- package/dist/core/process-identity.js +48 -0
- package/dist/core/process-mutation-turn.js +128 -0
- package/dist/core/process-ownership.js +276 -0
- package/dist/core/process-tree.js +90 -0
- package/dist/core/router-audit.js +155 -0
- package/dist/core/router-redaction.js +31 -0
- package/dist/core/router.js +462 -35
- package/dist/core/session-index.js +188 -37
- package/dist/core/session-manager.js +1086 -40
- package/dist/core/task-state-machine.js +17 -0
- package/dist/core/workspace-commit-recovery.js +118 -0
- package/dist/core/workspace.js +19 -11
- package/dist/doctor.js +343 -23
- package/dist/domain/schemas.js +127 -6
- package/dist/orchestrator/collaboration-channel.js +255 -4
- package/dist/orchestrator/feature-plan.js +70 -0
- package/dist/orchestrator/judge-artifacts.js +236 -0
- package/dist/orchestrator/orchestrator.js +1749 -202
- package/dist/orchestrator/prompts.js +126 -2
- package/dist/orchestrator/supervisor-summary.js +56 -2
- package/dist/orchestrator/workspace-sandbox.js +911 -0
- package/dist/tui/App.js +2830 -153
- package/dist/tui/AppShell.js +188 -23
- package/dist/tui/CollaborationTimelineView.js +327 -0
- package/dist/tui/FeatureBoardView.js +227 -0
- package/dist/tui/InputBar.js +514 -57
- package/dist/tui/RouterDiagnosticsView.js +469 -0
- package/dist/tui/StatusBar.js +610 -57
- package/dist/tui/TaskSessionsView.js +207 -0
- package/dist/tui/TerminalOutput.js +53 -9
- package/dist/tui/WorkerOutputView.js +1403 -161
- package/dist/tui/WorkerOverviewView.js +250 -0
- package/dist/tui/chat-history.js +25 -0
- package/dist/tui/chat-input.js +67 -19
- package/dist/tui/chat-paste.js +76 -0
- package/dist/tui/display-width.js +41 -3
- package/dist/tui/incremental-text-file.js +101 -0
- package/dist/tui/keyboard.js +46 -0
- package/dist/tui/markdown-text.js +14 -0
- package/dist/tui/raw-input-decoder.js +3 -0
- package/dist/tui/scrolling.js +2 -1
- package/dist/tui/status-line.js +318 -11
- package/dist/tui/task-memory.js +13 -1
- package/dist/tui/task-result.js +105 -0
- package/dist/tui/terminal-screen.js +13 -1
- package/dist/tui/theme-contrast.js +144 -0
- package/dist/tui/theme-preview.js +109 -0
- package/dist/tui/theme.js +158 -0
- package/dist/version.js +1 -1
- package/dist/workers/capabilities.js +212 -0
- package/dist/workers/live-probe.js +176 -0
- package/dist/workers/mock-adapter.js +39 -6
- package/dist/workers/native-attach.js +78 -3
- package/dist/workers/process-adapter.js +570 -77
- package/dist/workers/registry.js +4 -2
- package/package.json +5 -2
package/dist/tui/InputBar.js
CHANGED
|
@@ -1,39 +1,110 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
|
-
import { compactTailByDisplayWidth, displayWidth } from "./display-width.js";
|
|
4
|
-
|
|
5
|
-
export function InputBar({ mode, busy = false, hasWorkers = false, nativeClosed = false,
|
|
3
|
+
import { compactEndByDisplayWidth, compactTailByDisplayWidth, displayWidth } from "./display-width.js";
|
|
4
|
+
import { TUI_THEME } from "./theme.js";
|
|
5
|
+
export function InputBar({ mode, ready = true, busy = false, routeFallback = false, collaborationDetail = false, collaborationUnresolved = false, collaborationBack = "workers", featureCanCancel = false, featureCancelConfirm = false, taskSessionAction = null, taskSessionsIncludeArchived = false, canRetry = false, hasWorkers = false, hasActiveTask = false, hasTaskResult = false, taskResultExpanded = false, chatScrollOffset = 0, chatMaxScrollOffset = 0, nativeClosed = false, searchMatchIndex = 0, searchMatchCount = 0, value, cursor, terminalWidth: providedTerminalWidth, onChange, onSubmit }) {
|
|
6
|
+
const terminalWidth = providedTerminalWidth ?? process.stdout.columns ?? 120;
|
|
7
|
+
const fillRail = providedTerminalWidth !== undefined || typeof process.stdout.columns === "number";
|
|
8
|
+
if (mode === "worker-search") {
|
|
9
|
+
const suffix = workerSearchInputSuffix(terminalWidth, searchMatchIndex, searchMatchCount);
|
|
10
|
+
const prefix = terminalWidth < 4 ? "/" : "/ ";
|
|
11
|
+
const textBudget = Math.max(1, terminalWidth - (terminalWidth > 1 ? 2 : 0));
|
|
12
|
+
const valueWidth = Math.max(1, textBudget - displayWidth(prefix) - 1 - displayWidth(suffix));
|
|
13
|
+
const display = chatInputDisplayParts(value, cursor ?? Array.from(value).length, valueWidth + 6);
|
|
14
|
+
const textWidth = displayWidth(`${prefix}${display.before}|${display.after}${suffix}`);
|
|
15
|
+
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: textWidth, fill: fillRail, children: [_jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: prefix }), _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.text, children: display.before }), _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: "|" }), _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.text, children: display.after }), suffix ? _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.muted, children: suffix }) : null] }));
|
|
16
|
+
}
|
|
17
|
+
if (mode === "sessions") {
|
|
18
|
+
if (taskSessionAction?.type === "rename") {
|
|
19
|
+
const prefix = terminalWidth < 12 ? "> " : "rename > ";
|
|
20
|
+
const valueWidth = Math.max(1, terminalWidth - displayWidth(prefix) - 3);
|
|
21
|
+
const display = chatInputDisplayParts(taskSessionAction.value, taskSessionAction.cursor, valueWidth);
|
|
22
|
+
const textWidth = displayWidth(`${prefix}${display.before}|${display.after}`);
|
|
23
|
+
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: textWidth, fill: fillRail, children: [_jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: prefix }), _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.text, children: display.before }), _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: "|" }), _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.text, children: display.after })] }));
|
|
24
|
+
}
|
|
25
|
+
if (taskSessionAction?.type === "delete") {
|
|
26
|
+
const hints = taskSessionDeleteInputHints(terminalWidth, taskSessionAction.title);
|
|
27
|
+
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(`${hints.label}${hints.detail}`), fill: fillRail, children: [_jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.danger, bold: true, children: hints.label }), hints.detail ? _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.muted, children: hints.detail }) : null] }));
|
|
28
|
+
}
|
|
29
|
+
const hints = taskSessionsInputHints(terminalWidth, taskSessionsIncludeArchived);
|
|
30
|
+
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(`${hints.label}${hints.detail}`), fill: fillRail, children: [_jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: hints.label }), hints.detail ? _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.muted, children: hints.detail }) : null] }));
|
|
31
|
+
}
|
|
32
|
+
if (mode === "collaboration") {
|
|
33
|
+
const hints = collaborationDetail
|
|
34
|
+
? collaborationDetailInputHints(terminalWidth)
|
|
35
|
+
: collaborationTimelineInputHints(terminalWidth, collaborationUnresolved, collaborationBack);
|
|
36
|
+
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(`${hints.label}${hints.detail}`), fill: fillRail, children: [_jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: hints.label }), hints.detail ? _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.muted, children: hints.detail }) : null] }));
|
|
37
|
+
}
|
|
38
|
+
if (mode === "features") {
|
|
39
|
+
const hints = featureBoardInputHints(terminalWidth, {
|
|
40
|
+
canCancel: featureCanCancel,
|
|
41
|
+
confirmCancel: featureCancelConfirm,
|
|
42
|
+
canRetry
|
|
43
|
+
});
|
|
44
|
+
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(`${hints.label}${hints.detail}`), fill: fillRail, children: [_jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: hints.label }), hints.detail ? _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.muted, children: hints.detail }) : null] }));
|
|
45
|
+
}
|
|
46
|
+
if (mode === "workers") {
|
|
47
|
+
const hints = workerOverviewInputHints(terminalWidth);
|
|
48
|
+
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(`${hints.label}${hints.detail}`), fill: fillRail, children: [_jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: hints.label }), hints.detail ? _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.muted, children: hints.detail }) : null] }));
|
|
49
|
+
}
|
|
6
50
|
if (mode === "worker") {
|
|
7
51
|
const hints = workerInputHints(terminalWidth);
|
|
8
|
-
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(`${hints.label}${hints.detail}`), children: [_jsx(Text, { backgroundColor:
|
|
52
|
+
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(`${hints.label}${hints.detail}`), fill: fillRail, children: [_jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: hints.label }), hints.detail ? _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.muted, children: hints.detail }) : null] }));
|
|
9
53
|
}
|
|
10
54
|
if (mode === "native") {
|
|
11
55
|
const hints = nativeInputHints(terminalWidth, nativeClosed);
|
|
12
|
-
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(`${hints.label}${hints.detail}`), children: [_jsx(Text, { backgroundColor:
|
|
56
|
+
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(`${hints.label}${hints.detail}`), fill: fillRail, children: [_jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: hints.label }), hints.detail ? _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.muted, children: hints.detail }) : null] }));
|
|
57
|
+
}
|
|
58
|
+
if (mode === "router") {
|
|
59
|
+
const hints = routerInputHints(terminalWidth);
|
|
60
|
+
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(`${hints.label}${hints.detail}`), fill: fillRail, children: [_jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: hints.label }), hints.detail ? _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.muted, children: hints.detail }) : null] }));
|
|
61
|
+
}
|
|
62
|
+
if (!ready) {
|
|
63
|
+
const starting = chatStartingDisplayValue(terminalWidth);
|
|
64
|
+
return (_jsx(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(starting), fill: fillRail, children: _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.muted, children: starting }) }));
|
|
65
|
+
}
|
|
66
|
+
if (routeFallback) {
|
|
67
|
+
const hints = routeFallbackInputHints(terminalWidth);
|
|
68
|
+
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(`${hints.label}${hints.detail}`), fill: fillRail, children: [_jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.warning, bold: true, children: hints.label }), hints.detail ? _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.text, children: hints.detail }) : null] }));
|
|
13
69
|
}
|
|
14
70
|
const busyText = chatBusyDisplayValue(terminalWidth);
|
|
15
71
|
const prompt = busy ? "run" : ">";
|
|
16
72
|
if (busy) {
|
|
17
|
-
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(busyText ? `${prompt} ${busyText}` : prompt), children: [_jsx(Text, { backgroundColor:
|
|
73
|
+
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(busyText ? `${prompt} ${busyText}` : prompt), fill: fillRail, children: [_jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.warning, bold: true, children: prompt }), busyText ? (_jsxs(_Fragment, { children: [_jsx(Text, { backgroundColor: TUI_THEME.rail, children: " " }), _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.warning, children: busyText })] })) : null] }));
|
|
18
74
|
}
|
|
19
75
|
if (value) {
|
|
20
|
-
const
|
|
21
|
-
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(`${prompt} ${
|
|
76
|
+
const display = chatInputDisplayParts(value, cursor ?? Array.from(value).length, terminalWidth);
|
|
77
|
+
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(`${prompt} ${display.before}|${display.after}`), fill: fillRail, children: [_jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: prompt }), _jsx(Text, { backgroundColor: TUI_THEME.rail, children: " " }), _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.text, children: display.before }), _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: "|" }), _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.text, children: display.after })] }));
|
|
22
78
|
}
|
|
23
79
|
const hasLeadingPromptSpace = terminalWidth >= 10;
|
|
24
|
-
const placeholder = chatPlaceholderDisplayText(terminalWidth, {
|
|
25
|
-
|
|
80
|
+
const placeholder = chatPlaceholderDisplayText(terminalWidth, {
|
|
81
|
+
hasWorkers,
|
|
82
|
+
hasActiveTask,
|
|
83
|
+
hasTaskResult,
|
|
84
|
+
taskResultExpanded,
|
|
85
|
+
canRetry,
|
|
86
|
+
scrollOffset: chatScrollOffset,
|
|
87
|
+
maxScrollOffset: chatMaxScrollOffset
|
|
88
|
+
}, { leadingSpace: hasLeadingPromptSpace });
|
|
89
|
+
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(`${prompt}${hasLeadingPromptSpace ? " " : ""}|${placeholder}`), fill: fillRail, children: [_jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: prompt }), hasLeadingPromptSpace ? _jsx(Text, { backgroundColor: TUI_THEME.rail, children: " " }) : null, _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: "|" }), _jsx(Text, { backgroundColor: TUI_THEME.rail, color: canRetry ? TUI_THEME.warning : hasTaskResult ? TUI_THEME.accent : TUI_THEME.muted, children: placeholder })] }));
|
|
90
|
+
}
|
|
91
|
+
function InputRail({ fill, terminalWidth, textWidth, children }) {
|
|
92
|
+
const { leadingWidth, trailingWidth } = inputRailLayout(terminalWidth, textWidth, { fill });
|
|
93
|
+
return (_jsxs(Box, { children: [leadingWidth > 0 ? _jsx(Text, { backgroundColor: TUI_THEME.rail, children: " ".repeat(leadingWidth) }) : null, children, trailingWidth > 0 ? _jsx(Text, { backgroundColor: TUI_THEME.rail, children: " ".repeat(trailingWidth) }) : null] }));
|
|
26
94
|
}
|
|
27
|
-
function
|
|
95
|
+
export function inputRailLayout(terminalWidth, textWidth, options = {}) {
|
|
28
96
|
const leadingWidth = terminalWidth > 1 ? 1 : 0;
|
|
97
|
+
if (options.fill === false) {
|
|
98
|
+
return { leadingWidth, trailingWidth: 0 };
|
|
99
|
+
}
|
|
29
100
|
const renderWidth = typeof process.stdout.columns === "number"
|
|
30
101
|
? Math.max(1, Math.min(terminalWidth, process.stdout.columns))
|
|
31
|
-
:
|
|
32
|
-
const barWidth =
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
: Math.max(0, barWidth - leadingWidth - textWidth)
|
|
36
|
-
|
|
102
|
+
: Math.max(1, terminalWidth);
|
|
103
|
+
const barWidth = Math.max(1, renderWidth - 1);
|
|
104
|
+
return {
|
|
105
|
+
leadingWidth,
|
|
106
|
+
trailingWidth: Math.max(0, barWidth - leadingWidth - Math.max(0, textWidth))
|
|
107
|
+
};
|
|
37
108
|
}
|
|
38
109
|
export function chatPlaceholderDisplayText(terminalWidth, options = {}, display = {}) {
|
|
39
110
|
const placeholder = chatPlaceholderDisplayValue(terminalWidth, options);
|
|
@@ -44,37 +115,211 @@ export function chatPlaceholderDisplayText(terminalWidth, options = {}, display
|
|
|
44
115
|
}
|
|
45
116
|
export function chatInputDisplayValue(value, terminalWidth) {
|
|
46
117
|
const valueWidth = Math.max(1, terminalWidth - 6);
|
|
47
|
-
return compactTailByDisplayWidth(value, valueWidth);
|
|
118
|
+
return compactTailByDisplayWidth(chatInputVisibleValue(value), valueWidth);
|
|
119
|
+
}
|
|
120
|
+
export function chatInputDisplayParts(value, cursor, terminalWidth) {
|
|
121
|
+
const sourceChars = Array.from(value);
|
|
122
|
+
const chars = sourceChars.map(chatInputVisibleCharacter);
|
|
123
|
+
const clampedCursor = Math.min(sourceChars.length, Math.max(0, Math.trunc(cursor)));
|
|
124
|
+
const valueWidth = Math.max(1, terminalWidth - 6);
|
|
125
|
+
if (displayWidth(chars.join("")) <= valueWidth) {
|
|
126
|
+
return {
|
|
127
|
+
before: chars.slice(0, clampedCursor).join(""),
|
|
128
|
+
after: chars.slice(clampedCursor).join("")
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const beforeCursor = chars.slice(0, clampedCursor).join("");
|
|
132
|
+
const afterCursor = chars.slice(clampedCursor).join("");
|
|
133
|
+
if (valueWidth < 6) {
|
|
134
|
+
return clampedCursor > 0
|
|
135
|
+
? { before: compactTailByDisplayWidth(beforeCursor, valueWidth), after: "" }
|
|
136
|
+
: { before: "", after: compactEndByDisplayWidth(afterCursor, valueWidth) };
|
|
137
|
+
}
|
|
138
|
+
let start = clampedCursor;
|
|
139
|
+
let end = clampedCursor;
|
|
140
|
+
const renderedWidth = (nextStart, nextEnd) => displayWidth([
|
|
141
|
+
nextStart > 0 ? "..." : "",
|
|
142
|
+
chars.slice(nextStart, nextEnd).join(""),
|
|
143
|
+
nextEnd < chars.length ? "..." : ""
|
|
144
|
+
].join(""));
|
|
145
|
+
while (true) {
|
|
146
|
+
const canExpandLeft = start > 0 && renderedWidth(start - 1, end) <= valueWidth;
|
|
147
|
+
const canExpandRight = end < chars.length && renderedWidth(start, end + 1) <= valueWidth;
|
|
148
|
+
if (!canExpandLeft && !canExpandRight) {
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
if (canExpandLeft && canExpandRight) {
|
|
152
|
+
const leftWidth = displayWidth(chars.slice(start, clampedCursor).join(""));
|
|
153
|
+
const rightWidth = displayWidth(chars.slice(clampedCursor, end).join(""));
|
|
154
|
+
if (leftWidth <= rightWidth) {
|
|
155
|
+
start -= 1;
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
end += 1;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
else if (canExpandLeft) {
|
|
162
|
+
start -= 1;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
end += 1;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
before: `${start > 0 ? "..." : ""}${chars.slice(start, clampedCursor).join("")}`,
|
|
170
|
+
after: `${chars.slice(clampedCursor, end).join("")}${end < chars.length ? "..." : ""}`
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function chatInputVisibleValue(value) {
|
|
174
|
+
return Array.from(value).map(chatInputVisibleCharacter).join("");
|
|
175
|
+
}
|
|
176
|
+
function chatInputVisibleCharacter(char) {
|
|
177
|
+
if (char === "\n" || char === "\r") {
|
|
178
|
+
return "↵";
|
|
179
|
+
}
|
|
180
|
+
if (char === "\t") {
|
|
181
|
+
return "⇥";
|
|
182
|
+
}
|
|
183
|
+
return char;
|
|
48
184
|
}
|
|
49
185
|
export function chatPlaceholderDisplayValue(terminalWidth, options = {}) {
|
|
50
|
-
if (options.
|
|
51
|
-
return
|
|
186
|
+
if (options.canRetry) {
|
|
187
|
+
return selectChatPlaceholder(terminalWidth, options.hasActiveTask
|
|
188
|
+
? ["message · ^R retry · ^N new", "^R retry · ^N", "^R retry", "retry"]
|
|
189
|
+
: ["message · ^R retry", "^R retry", "retry"]);
|
|
52
190
|
}
|
|
53
|
-
|
|
54
|
-
|
|
191
|
+
const maxScrollOffset = Math.max(0, options.maxScrollOffset ?? 0);
|
|
192
|
+
const scrollOffset = Math.min(Math.max(0, options.scrollOffset ?? 0), maxScrollOffset);
|
|
193
|
+
if (options.hasTaskResult) {
|
|
194
|
+
return chatTaskResultPlaceholderDisplayValue(terminalWidth, Boolean(options.taskResultExpanded), Boolean(options.hasWorkers), Boolean(options.hasActiveTask), scrollOffset, maxScrollOffset);
|
|
55
195
|
}
|
|
56
|
-
if (
|
|
57
|
-
return
|
|
196
|
+
if (scrollOffset > 0) {
|
|
197
|
+
return chatHistoryPlaceholderDisplayValue(terminalWidth, scrollOffset, maxScrollOffset);
|
|
58
198
|
}
|
|
59
|
-
|
|
199
|
+
if (options.hasActiveTask && !options.hasWorkers) {
|
|
200
|
+
return selectChatPlaceholder(terminalWidth, [
|
|
201
|
+
"message · ^N new · ^P project · ^T tasks · ^G routes",
|
|
202
|
+
"message · ^N new · ^P project · ^G routes",
|
|
203
|
+
"message · ^N new · ^P project",
|
|
204
|
+
"message · ^N new",
|
|
205
|
+
"msg · ^N",
|
|
206
|
+
"msg"
|
|
207
|
+
]);
|
|
208
|
+
}
|
|
209
|
+
if (options.hasWorkers) {
|
|
210
|
+
return chatTaskPlaceholderDisplayValue(terminalWidth, maxScrollOffset > 0, options.hasActiveTask);
|
|
211
|
+
}
|
|
212
|
+
if (maxScrollOffset > 0 && terminalWidth >= 22) {
|
|
213
|
+
return selectChatPlaceholder(terminalWidth, ["message · scroll", "message", "msg"]);
|
|
214
|
+
}
|
|
215
|
+
return selectChatPlaceholder(terminalWidth, [
|
|
216
|
+
"message · ^P project · ^T tasks · ^G routes",
|
|
217
|
+
"message · ^P project · ^G routes",
|
|
218
|
+
"message · ^P project",
|
|
219
|
+
"message",
|
|
220
|
+
"msg"
|
|
221
|
+
]);
|
|
222
|
+
}
|
|
223
|
+
function chatTaskResultPlaceholderDisplayValue(terminalWidth, expanded, hasWorkers, hasActiveTask, scrollOffset, maxScrollOffset) {
|
|
224
|
+
const toggle = expanded ? "^D compact" : "^D details";
|
|
225
|
+
const position = expanded && maxScrollOffset > 0
|
|
226
|
+
? scrollOffset > 0 ? `result ${scrollOffset}/${maxScrollOffset}` : "result · scroll"
|
|
227
|
+
: "message";
|
|
228
|
+
const candidates = hasWorkers
|
|
229
|
+
? [
|
|
230
|
+
`${position} · ${toggle} · ^N new · ^W logs · ^B workers · ^T tasks · Tab · ^O attach`,
|
|
231
|
+
`${position} · ${toggle} · ^N new · ^W logs · ^T tasks · Tab · ^O attach`,
|
|
232
|
+
`${position} · ${toggle} · ^W logs · ^B workers · ^T tasks · Tab · ^O attach`,
|
|
233
|
+
`${position} · ${toggle} · ^W logs · ^T tasks · Tab · ^O attach`,
|
|
234
|
+
`${position} · ${toggle} · ^W logs · Tab · ^O attach`,
|
|
235
|
+
`${position} · ${toggle} · ^W logs`,
|
|
236
|
+
`${toggle} · ^W logs`,
|
|
237
|
+
toggle,
|
|
238
|
+
"^D"
|
|
239
|
+
]
|
|
240
|
+
: [
|
|
241
|
+
`${position} · ${toggle}${hasActiveTask ? " · ^N new" : ""}`,
|
|
242
|
+
`${position} · ${toggle}`,
|
|
243
|
+
toggle,
|
|
244
|
+
"^D"
|
|
245
|
+
];
|
|
246
|
+
return selectChatPlaceholder(terminalWidth, candidates);
|
|
60
247
|
}
|
|
61
|
-
function
|
|
248
|
+
function chatHistoryPlaceholderDisplayValue(terminalWidth, offset, maxOffset) {
|
|
62
249
|
if (terminalWidth < 14) {
|
|
63
|
-
return "
|
|
250
|
+
return "back";
|
|
64
251
|
}
|
|
65
|
-
if (terminalWidth <
|
|
66
|
-
return
|
|
67
|
-
}
|
|
68
|
-
if (terminalWidth < 24) {
|
|
69
|
-
return "msg · ^W · ^O";
|
|
252
|
+
if (terminalWidth < 20) {
|
|
253
|
+
return `back ${offset}`;
|
|
70
254
|
}
|
|
71
255
|
if (terminalWidth < 38) {
|
|
72
|
-
return
|
|
256
|
+
return selectChatPlaceholder(terminalWidth, [
|
|
257
|
+
`back ${offset}/${maxOffset} · PgDn`,
|
|
258
|
+
`back ${offset}/${maxOffset}`,
|
|
259
|
+
`back ${offset}`,
|
|
260
|
+
"back"
|
|
261
|
+
]);
|
|
73
262
|
}
|
|
74
|
-
|
|
75
|
-
|
|
263
|
+
return selectChatPlaceholder(terminalWidth, [
|
|
264
|
+
`message · back ${offset}/${maxOffset} · PgDn latest`,
|
|
265
|
+
`back ${offset}/${maxOffset} · PgDn latest`,
|
|
266
|
+
`back ${offset}/${maxOffset} · PgDn`,
|
|
267
|
+
`back ${offset}/${maxOffset}`,
|
|
268
|
+
`back ${offset}`,
|
|
269
|
+
"back"
|
|
270
|
+
]);
|
|
271
|
+
}
|
|
272
|
+
function chatTaskPlaceholderDisplayValue(terminalWidth, scrollable = false, activeTask = false) {
|
|
273
|
+
if (activeTask && terminalWidth >= 72) {
|
|
274
|
+
const activeCandidates = scrollable
|
|
275
|
+
? [
|
|
276
|
+
"message · scroll · ^N new · ^W logs · ^B workers · ^T tasks · Tab · ^O attach · ^G routes",
|
|
277
|
+
"message · scroll · ^N new · ^W logs · ^B workers · Tab · ^O attach · ^G routes"
|
|
278
|
+
]
|
|
279
|
+
: [
|
|
280
|
+
"message · ^N new · ^W logs · ^B workers · ^T tasks · Tab · ^O attach · ^G routes",
|
|
281
|
+
"message · ^N new · ^W logs · ^B workers · Tab · ^O attach · ^G routes"
|
|
282
|
+
];
|
|
283
|
+
const active = activeCandidates.find((candidate) => displayWidth(candidate) <= chatPlaceholderValueWidth(terminalWidth));
|
|
284
|
+
if (active) {
|
|
285
|
+
return active;
|
|
286
|
+
}
|
|
76
287
|
}
|
|
77
|
-
return
|
|
288
|
+
return selectChatPlaceholder(terminalWidth, scrollable
|
|
289
|
+
? [
|
|
290
|
+
"message · scroll · ^W logs · ^B workers · ^T tasks · Tab · ^O attach · ^G routes",
|
|
291
|
+
"message · scroll · ^W logs · ^B workers · Tab · ^O attach · ^G routes",
|
|
292
|
+
"message · scroll · ^W logs · Tab · ^O attach · ^G routes",
|
|
293
|
+
"message · scroll · ^W logs · Tab · ^O attach",
|
|
294
|
+
"scroll · ^W logs · Tab · ^O attach",
|
|
295
|
+
"scroll · ^W logs · ^O attach",
|
|
296
|
+
"^W logs · ^O attach",
|
|
297
|
+
"message · ^W logs",
|
|
298
|
+
"msg · ^W logs",
|
|
299
|
+
"^W logs",
|
|
300
|
+
"msg"
|
|
301
|
+
]
|
|
302
|
+
: [
|
|
303
|
+
"message · ^W logs · ^B workers · ^T tasks · Tab · ^O attach · ^G routes",
|
|
304
|
+
"message · ^W logs · ^B workers · Tab · ^O attach · ^G routes",
|
|
305
|
+
"message · ^W logs · Tab · ^O attach · ^G routes",
|
|
306
|
+
"message · ^W logs · Tab · ^O attach",
|
|
307
|
+
"message · ^W logs · ^O attach",
|
|
308
|
+
"^W logs · ^O attach",
|
|
309
|
+
"message · ^W logs",
|
|
310
|
+
"msg · ^W logs",
|
|
311
|
+
"^W logs",
|
|
312
|
+
"msg"
|
|
313
|
+
]);
|
|
314
|
+
}
|
|
315
|
+
function selectChatPlaceholder(terminalWidth, candidates) {
|
|
316
|
+
const valueWidth = chatPlaceholderValueWidth(terminalWidth);
|
|
317
|
+
return candidates.find((candidate) => displayWidth(candidate) <= valueWidth)
|
|
318
|
+
?? candidates.at(-1)
|
|
319
|
+
?? "";
|
|
320
|
+
}
|
|
321
|
+
function chatPlaceholderValueWidth(terminalWidth) {
|
|
322
|
+
return Math.max(1, terminalWidth - (terminalWidth >= 10 ? 6 : 4));
|
|
78
323
|
}
|
|
79
324
|
export function chatBusyDisplayValue(terminalWidth) {
|
|
80
325
|
if (terminalWidth < 14) {
|
|
@@ -83,28 +328,228 @@ export function chatBusyDisplayValue(terminalWidth) {
|
|
|
83
328
|
if (terminalWidth < 22) {
|
|
84
329
|
return "busy";
|
|
85
330
|
}
|
|
86
|
-
|
|
331
|
+
if (terminalWidth >= 34) {
|
|
332
|
+
return "working · Esc stop";
|
|
333
|
+
}
|
|
334
|
+
return "working";
|
|
335
|
+
}
|
|
336
|
+
function routeFallbackInputHints(width) {
|
|
337
|
+
if (width < 10) {
|
|
338
|
+
return { label: "route", detail: "" };
|
|
339
|
+
}
|
|
340
|
+
if (width < 14) {
|
|
341
|
+
return { label: "choose", detail: "" };
|
|
342
|
+
}
|
|
343
|
+
if (width < 20) {
|
|
344
|
+
return { label: "1M", detail: " · 2P" };
|
|
345
|
+
}
|
|
346
|
+
if (width < 28) {
|
|
347
|
+
return { label: "1 Main", detail: " · 2 Pair" };
|
|
348
|
+
}
|
|
349
|
+
if (width < 40) {
|
|
350
|
+
return { label: "1 Main", detail: " · 2 Parallel" };
|
|
351
|
+
}
|
|
352
|
+
if (width < 54) {
|
|
353
|
+
return { label: "route", detail: " · 1 Main · 2 Parallel · Esc" };
|
|
354
|
+
}
|
|
355
|
+
if (width < 75) {
|
|
356
|
+
return { label: "route failed", detail: " · 1 Main · 2 Parallel · R · Esc" };
|
|
357
|
+
}
|
|
358
|
+
return { label: "route failed", detail: " · 1 Main · 2 Parallel · R retry · Esc cancel" };
|
|
359
|
+
}
|
|
360
|
+
export function chatStartingDisplayValue(terminalWidth) {
|
|
361
|
+
if (terminalWidth < 8) {
|
|
362
|
+
return "";
|
|
363
|
+
}
|
|
364
|
+
return terminalWidth < 12 ? "start" : "starting";
|
|
87
365
|
}
|
|
88
366
|
function workerInputHints(width) {
|
|
89
|
-
if (width <
|
|
367
|
+
if (width < 10) {
|
|
90
368
|
return { label: "log", detail: "" };
|
|
91
369
|
}
|
|
92
|
-
if (width <
|
|
93
|
-
return { label: "
|
|
370
|
+
if (width < 16) {
|
|
371
|
+
return { label: "Esc chat", detail: "" };
|
|
372
|
+
}
|
|
373
|
+
if (width < 17) {
|
|
374
|
+
return { label: "log", detail: " · Esc chat" };
|
|
375
|
+
}
|
|
376
|
+
if (width < 22) {
|
|
377
|
+
return { label: "logs", detail: " · Esc chat" };
|
|
94
378
|
}
|
|
95
|
-
if (width <
|
|
96
|
-
return { label: "
|
|
379
|
+
if (width < 28) {
|
|
380
|
+
return { label: "logs", detail: " · Pg · Esc chat" };
|
|
381
|
+
}
|
|
382
|
+
if (width < 32) {
|
|
383
|
+
return { label: "logs", detail: " · Pg · Tab · Esc chat" };
|
|
384
|
+
}
|
|
385
|
+
if (width < 44) {
|
|
386
|
+
return { label: "logs", detail: " · scroll · Tab · Esc chat" };
|
|
387
|
+
}
|
|
388
|
+
if (width < 54) {
|
|
389
|
+
return { label: "logs", detail: " · scroll · Tab · ^O attach · Esc chat" };
|
|
390
|
+
}
|
|
391
|
+
if (width < 71) {
|
|
392
|
+
return { label: "logs", detail: " · scroll · ^F find · Tab · ^O attach · Esc chat" };
|
|
393
|
+
}
|
|
394
|
+
if (width < 84) {
|
|
395
|
+
return { label: "logs", detail: " · scroll · ^F find · E err · D diff · Tab · ^O attach · Esc chat" };
|
|
396
|
+
}
|
|
397
|
+
return { label: "logs", detail: " · scroll · ^F find · E err · D diff · Tab · ^B workers · ^O attach · Esc chat" };
|
|
398
|
+
}
|
|
399
|
+
function workerOverviewInputHints(width) {
|
|
400
|
+
if (width < 16) {
|
|
401
|
+
return { label: "wrk", detail: "" };
|
|
402
|
+
}
|
|
403
|
+
if (width < 20) {
|
|
404
|
+
return { label: "wrk", detail: " · Esc back" };
|
|
97
405
|
}
|
|
98
406
|
if (width < 28) {
|
|
99
|
-
return { label: "
|
|
407
|
+
return { label: "workers", detail: " · Esc back" };
|
|
100
408
|
}
|
|
101
|
-
if (width <
|
|
102
|
-
return { label: "
|
|
409
|
+
if (width < 41) {
|
|
410
|
+
return { label: "workers", detail: " · Up/Dn · Esc back" };
|
|
411
|
+
}
|
|
412
|
+
if (width < 53) {
|
|
413
|
+
return { label: "workers", detail: " · Up/Dn · Enter logs · Esc back" };
|
|
103
414
|
}
|
|
104
415
|
if (width < 72) {
|
|
105
|
-
return { label: "
|
|
416
|
+
return { label: "workers", detail: " · Up/Dn · Enter logs · ^O attach · Esc back" };
|
|
417
|
+
}
|
|
418
|
+
if (width < 86) {
|
|
419
|
+
return { label: "workers", detail: " · Up/Dn · Enter logs · F board · C flow · ^O attach · Esc back" };
|
|
106
420
|
}
|
|
107
|
-
return { label: "
|
|
421
|
+
return { label: "workers", detail: " · Up/Dn select · Enter logs · F features · C timeline · ^O attach · Esc back" };
|
|
422
|
+
}
|
|
423
|
+
function featureBoardInputHints(width, options) {
|
|
424
|
+
if (options.confirmCancel) {
|
|
425
|
+
return selectInputHints(width, [
|
|
426
|
+
{ label: "cancel feature?", detail: " · X confirm · Esc keep" },
|
|
427
|
+
{ label: "cancel?", detail: " · X confirm · Esc keep" },
|
|
428
|
+
{ label: "cancel?", detail: " · Esc keep" },
|
|
429
|
+
{ label: "Esc keep", detail: "" },
|
|
430
|
+
{ label: "stop?", detail: "" },
|
|
431
|
+
{ label: "?", detail: "" }
|
|
432
|
+
]);
|
|
433
|
+
}
|
|
434
|
+
if (options.canCancel) {
|
|
435
|
+
return selectInputHints(width, [
|
|
436
|
+
{ label: "features", detail: " · Up/Dn select · Enter timeline · X cancel · R refresh · Esc workers" },
|
|
437
|
+
{ label: "features", detail: " · Up/Dn select · X cancel · R refresh · Esc workers" },
|
|
438
|
+
{ label: "features", detail: " · Up/Dn select · X cancel · Esc workers" },
|
|
439
|
+
{ label: "features", detail: " · X cancel · Esc workers" },
|
|
440
|
+
{ label: "features", detail: " · Esc workers" },
|
|
441
|
+
{ label: "features", detail: "" },
|
|
442
|
+
{ label: "ft", detail: "" },
|
|
443
|
+
{ label: "f", detail: "" }
|
|
444
|
+
]);
|
|
445
|
+
}
|
|
446
|
+
if (options.canRetry) {
|
|
447
|
+
return selectInputHints(width, [
|
|
448
|
+
{ label: "features", detail: " · Up/Dn select · Enter timeline · ^R retry task · R refresh · Esc workers" },
|
|
449
|
+
{ label: "features", detail: " · Up/Dn select · ^R retry task · R refresh · Esc workers" },
|
|
450
|
+
{ label: "features", detail: " · Up/Dn select · ^R retry · R refresh · Esc workers" },
|
|
451
|
+
{ label: "features", detail: " · Up/Dn select · ^R retry · Esc workers" },
|
|
452
|
+
{ label: "features", detail: " · ^R retry · Esc workers" },
|
|
453
|
+
{ label: "features", detail: " · Esc workers" },
|
|
454
|
+
{ label: "features", detail: "" },
|
|
455
|
+
{ label: "ft", detail: "" },
|
|
456
|
+
{ label: "f", detail: "" }
|
|
457
|
+
]);
|
|
458
|
+
}
|
|
459
|
+
return selectInputHints(width, [
|
|
460
|
+
{ label: "features", detail: " · Up/Dn select · Enter timeline · R refresh · Esc workers" },
|
|
461
|
+
{ label: "features", detail: " · Up/Dn select · Enter timeline · Esc workers" },
|
|
462
|
+
{ label: "features", detail: " · Up/Dn select · Esc workers" },
|
|
463
|
+
{ label: "features", detail: " · Esc workers" },
|
|
464
|
+
{ label: "features", detail: "" },
|
|
465
|
+
{ label: "ft", detail: "" },
|
|
466
|
+
{ label: "f", detail: "" }
|
|
467
|
+
]);
|
|
468
|
+
}
|
|
469
|
+
function collaborationTimelineInputHints(width, unresolvedOnly, back) {
|
|
470
|
+
const backAction = `Esc ${back}`;
|
|
471
|
+
const filterAction = unresolvedOnly ? "U all" : "U unresolved";
|
|
472
|
+
const compactFilterAction = unresolvedOnly ? "U all" : "U open";
|
|
473
|
+
return selectInputHints(width, [
|
|
474
|
+
{
|
|
475
|
+
label: "timeline",
|
|
476
|
+
detail: ` · Up/Dn event · Enter detail · Tab feature · ${filterAction} · R refresh · ${backAction}`
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
label: "timeline",
|
|
480
|
+
detail: ` · Up/Dn event · Enter detail · Tab feature · ${compactFilterAction} · R refresh · ${backAction}`
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
label: "timeline",
|
|
484
|
+
detail: ` · Up/Dn event · Enter detail · Tab feature · ${compactFilterAction} · ${backAction}`
|
|
485
|
+
},
|
|
486
|
+
{ label: "timeline", detail: ` · Up/Dn event · Enter detail · Tab feature · ${backAction}` },
|
|
487
|
+
{ label: "timeline", detail: ` · Up/Dn event · Enter detail · ${backAction}` },
|
|
488
|
+
{ label: "timeline", detail: ` · Enter detail · ${backAction}` },
|
|
489
|
+
{ label: "timeline", detail: ` · ${backAction}` },
|
|
490
|
+
{ label: backAction, detail: "" },
|
|
491
|
+
{ label: "flow", detail: "" },
|
|
492
|
+
{ label: "tl", detail: "" },
|
|
493
|
+
{ label: "t", detail: "" }
|
|
494
|
+
]);
|
|
495
|
+
}
|
|
496
|
+
function collaborationDetailInputHints(width) {
|
|
497
|
+
return selectInputHints(width, [
|
|
498
|
+
{ label: "event detail", detail: " · scroll · Enter/Esc timeline" },
|
|
499
|
+
{ label: "event", detail: " · Pg scroll · Enter/Esc timeline" },
|
|
500
|
+
{ label: "event", detail: " · Pg scroll · Esc timeline" },
|
|
501
|
+
{ label: "event", detail: " · Esc timeline" },
|
|
502
|
+
{ label: "Esc timeline", detail: "" },
|
|
503
|
+
{ label: "event", detail: "" },
|
|
504
|
+
{ label: "e", detail: "" }
|
|
505
|
+
]);
|
|
506
|
+
}
|
|
507
|
+
function taskSessionsInputHints(width, includeArchived) {
|
|
508
|
+
const archivedAction = includeArchived ? "H hide archived" : "H archived";
|
|
509
|
+
return selectInputHints(width, [
|
|
510
|
+
{ label: "sessions", detail: ` · Up/Dn select · Enter restore · R rename · A archive · D delete · E export · ${archivedAction} · Esc back` },
|
|
511
|
+
{ label: "sessions", detail: " · Up/Dn select · Enter restore · R rename · A archive · D delete · E export · Esc back" },
|
|
512
|
+
{ label: "sessions", detail: " · Up/Dn select · Enter restore · R rename · A archive · D delete · Esc back" },
|
|
513
|
+
{ label: "sessions", detail: " · Up/Dn select · Enter restore · R rename · A archive · Esc back" },
|
|
514
|
+
{ label: "sessions", detail: " · Up/Dn select · Enter restore · R rename · Esc back" },
|
|
515
|
+
{ label: "sessions", detail: " · Up/Dn select · Enter restore · Esc back" },
|
|
516
|
+
{ label: "sessions", detail: " · Up/Dn select · Esc back" },
|
|
517
|
+
{ label: "sessions", detail: " · Esc back" },
|
|
518
|
+
{ label: "Esc back", detail: "" },
|
|
519
|
+
{ label: "sessions", detail: "" },
|
|
520
|
+
{ label: "ses", detail: "" },
|
|
521
|
+
{ label: "s", detail: "" }
|
|
522
|
+
]);
|
|
523
|
+
}
|
|
524
|
+
function taskSessionDeleteInputHints(width, title) {
|
|
525
|
+
const safeTitle = title.replace(/[\u0000-\u001f\u007f]/g, " ").replace(/\s+/g, " ").trim();
|
|
526
|
+
return selectInputHints(width, [
|
|
527
|
+
{ label: "delete", detail: ` · ${safeTitle} · D confirm · Esc cancel` },
|
|
528
|
+
{ label: "delete", detail: " · D confirm · Esc cancel" },
|
|
529
|
+
{ label: "D confirm", detail: " · Esc cancel" },
|
|
530
|
+
{ label: "D confirm", detail: "" },
|
|
531
|
+
{ label: "D", detail: "" }
|
|
532
|
+
]);
|
|
533
|
+
}
|
|
534
|
+
function workerSearchInputSuffix(width, matchIndex, matchCount) {
|
|
535
|
+
const count = Math.max(0, Math.trunc(matchCount));
|
|
536
|
+
const index = count > 0
|
|
537
|
+
? Math.min(count - 1, Math.max(0, Math.trunc(matchIndex))) + 1
|
|
538
|
+
: 0;
|
|
539
|
+
const position = `${index}/${count}`;
|
|
540
|
+
if (width < 16) {
|
|
541
|
+
return "";
|
|
542
|
+
}
|
|
543
|
+
if (width < 24) {
|
|
544
|
+
return ` · ${position}`;
|
|
545
|
+
}
|
|
546
|
+
if (width < 36) {
|
|
547
|
+
return ` · ${position} · Esc`;
|
|
548
|
+
}
|
|
549
|
+
if (width < 52) {
|
|
550
|
+
return ` · ${position} · Enter · Esc`;
|
|
551
|
+
}
|
|
552
|
+
return ` · ${position} · Enter next · Up/Dn · Esc logs`;
|
|
108
553
|
}
|
|
109
554
|
function nativeInputHints(width, closed = false) {
|
|
110
555
|
if (closed) {
|
|
@@ -117,13 +562,10 @@ function nativeInputHints(width, closed = false) {
|
|
|
117
562
|
if (width < 24) {
|
|
118
563
|
return { label: "closed", detail: " · ^]" };
|
|
119
564
|
}
|
|
120
|
-
if (width <
|
|
565
|
+
if (width < 27) {
|
|
121
566
|
return { label: "closed", detail: " · Pg · ^]" };
|
|
122
567
|
}
|
|
123
|
-
|
|
124
|
-
return { label: "closed", detail: " · Pg/wheel · ^]" };
|
|
125
|
-
}
|
|
126
|
-
return { label: "closed", detail: " · wheel/Pg · ^] back" };
|
|
568
|
+
return { label: "closed", detail: " · scroll · ^] logs" };
|
|
127
569
|
}
|
|
128
570
|
if (width < 12) {
|
|
129
571
|
return { label: "nat", detail: " ^]" };
|
|
@@ -131,11 +573,26 @@ function nativeInputHints(width, closed = false) {
|
|
|
131
573
|
if (width < 24) {
|
|
132
574
|
return { label: "native", detail: " · ^]" };
|
|
133
575
|
}
|
|
134
|
-
if (width <
|
|
576
|
+
if (width < 27) {
|
|
135
577
|
return { label: "native", detail: " · Pg · ^]" };
|
|
136
578
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
return
|
|
579
|
+
return { label: "native", detail: " · scroll · ^] logs" };
|
|
580
|
+
}
|
|
581
|
+
function routerInputHints(width) {
|
|
582
|
+
return selectInputHints(width, [
|
|
583
|
+
{ label: "routes", detail: " · scroll · Tab scope · ^G refresh · Esc chat" },
|
|
584
|
+
{ label: "routes", detail: " · scroll · ^G refresh · Esc chat" },
|
|
585
|
+
{ label: "routes", detail: " · Pg scroll · Esc chat" },
|
|
586
|
+
{ label: "routes", detail: " · Esc chat" },
|
|
587
|
+
{ label: "Esc chat", detail: "" },
|
|
588
|
+
{ label: "routes", detail: "" },
|
|
589
|
+
{ label: "rt", detail: "" },
|
|
590
|
+
{ label: "r", detail: "" }
|
|
591
|
+
]);
|
|
592
|
+
}
|
|
593
|
+
function selectInputHints(width, candidates) {
|
|
594
|
+
const contentWidth = Math.max(1, Math.trunc(width) - (width > 1 ? 2 : 0));
|
|
595
|
+
return candidates.find((candidate) => displayWidth(`${candidate.label}${candidate.detail}`) <= contentWidth)
|
|
596
|
+
?? candidates.at(-1)
|
|
597
|
+
?? { label: "", detail: "" };
|
|
141
598
|
}
|