swarm-code 0.1.20 → 0.1.22
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/ui/text-input.js +83 -57
- package/package.json +1 -1
package/dist/ui/text-input.js
CHANGED
|
@@ -44,47 +44,93 @@ export function readTextInput(_prompt) {
|
|
|
44
44
|
process.stdin.setRawMode(true);
|
|
45
45
|
process.stdin.resume();
|
|
46
46
|
process.stdin.setEncoding("utf-8");
|
|
47
|
-
//
|
|
48
|
-
let
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
// Top border — thin dim line
|
|
58
|
-
const topLine = `${BORDER_COLOR}${"─".repeat(w)}${RESET}`;
|
|
59
|
-
out.write(`${topLine}\n`);
|
|
60
|
-
// Content rows — dark background, full width
|
|
47
|
+
// Tracks cursor position relative to top border after each drawBox()
|
|
48
|
+
let cursorRowFromTop = 0;
|
|
49
|
+
let prevTotalRows = 0;
|
|
50
|
+
function buildRows() {
|
|
51
|
+
const promptVisibleLen = 2;
|
|
52
|
+
const rows = [];
|
|
53
|
+
// Top border
|
|
54
|
+
rows.push(`${BORDER_COLOR}${"─".repeat(w)}${RESET}`);
|
|
55
|
+
// Content rows
|
|
61
56
|
const promptChar = `${ACCENT_COLOR}❯${RESET} `;
|
|
62
|
-
const promptVisibleLen = 2; // "❯ "
|
|
63
57
|
for (let i = 0; i < linesBuf.length; i++) {
|
|
64
58
|
const lineText = linesBuf[i];
|
|
65
59
|
const prefix = i === 0 ? promptChar : `${dim("·")} `;
|
|
66
|
-
const
|
|
67
|
-
// How much space for text content
|
|
68
|
-
const contentWidth = w - prefixVisibleLen;
|
|
69
|
-
// Truncate display if line is too long
|
|
60
|
+
const contentWidth = w - promptVisibleLen;
|
|
70
61
|
const displayText = lineText.length > contentWidth ? lineText.slice(0, contentWidth - 1) + "…" : lineText;
|
|
71
62
|
const padding = Math.max(0, contentWidth - displayText.length);
|
|
72
|
-
|
|
63
|
+
rows.push(`${BG_DARK}${prefix}${displayText}${" ".repeat(padding)}${RESET}`);
|
|
64
|
+
}
|
|
65
|
+
// Bottom border
|
|
66
|
+
rows.push(`${ACCENT_COLOR}${"─".repeat(w)}${RESET}`);
|
|
67
|
+
// Hints — pad to full width so it fully overwrites old content
|
|
68
|
+
const hintsText = " enter submit esc exit";
|
|
69
|
+
const hintsPad = Math.max(0, w - hintsText.length);
|
|
70
|
+
rows.push(`${dim(hintsText)}${" ".repeat(hintsPad)}`);
|
|
71
|
+
return rows;
|
|
72
|
+
}
|
|
73
|
+
function drawBox() {
|
|
74
|
+
const out = process.stderr;
|
|
75
|
+
const promptVisibleLen = 2;
|
|
76
|
+
const rows = buildRows();
|
|
77
|
+
const totalRows = rows.length;
|
|
78
|
+
if (prevTotalRows > 0) {
|
|
79
|
+
// ── Redraw: overwrite rows in place (no \n, no scrolling) ──
|
|
80
|
+
// Move cursor to top border row
|
|
81
|
+
if (cursorRowFromTop > 0) {
|
|
82
|
+
out.write(`\x1b[${cursorRowFromTop}A`);
|
|
83
|
+
}
|
|
84
|
+
out.write("\r");
|
|
85
|
+
// Overwrite each row in place
|
|
86
|
+
const commonRows = Math.min(totalRows, prevTotalRows);
|
|
87
|
+
for (let i = 0; i < commonRows; i++) {
|
|
88
|
+
out.write(`\x1b[2K${rows[i]}`);
|
|
89
|
+
if (i < commonRows - 1) {
|
|
90
|
+
out.write("\x1b[1B\r"); // cursor down 1 (no scroll), start of line
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (totalRows > prevTotalRows) {
|
|
94
|
+
// More rows than before (multi-line paste) — append with \n
|
|
95
|
+
for (let i = commonRows; i < totalRows; i++) {
|
|
96
|
+
out.write(`\n\x1b[2K${rows[i]}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else if (prevTotalRows > totalRows) {
|
|
100
|
+
// Fewer rows than before — erase leftover old rows
|
|
101
|
+
for (let i = totalRows; i < prevTotalRows; i++) {
|
|
102
|
+
out.write("\x1b[1B\r\x1b[2K");
|
|
103
|
+
}
|
|
104
|
+
// Move back to last new row
|
|
105
|
+
const extra = prevTotalRows - totalRows;
|
|
106
|
+
if (extra > 0)
|
|
107
|
+
out.write(`\x1b[${extra}A`);
|
|
108
|
+
}
|
|
109
|
+
// Cursor is now on the last row (hints).
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// ── Initial draw: use \n between rows, no trailing \n ──
|
|
113
|
+
for (let i = 0; i < totalRows; i++) {
|
|
114
|
+
if (i > 0)
|
|
115
|
+
out.write("\n");
|
|
116
|
+
out.write(rows[i]);
|
|
117
|
+
}
|
|
118
|
+
// Cursor is on the hints line (last row).
|
|
73
119
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
//
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
// Move to correct column: prefix width + cursor position
|
|
120
|
+
prevTotalRows = totalRows;
|
|
121
|
+
// Position cursor at the active content row
|
|
122
|
+
// Cursor is currently on the hints line (last row = index totalRows-1).
|
|
123
|
+
// Content cursor is on row (1 + currentLineIdx).
|
|
124
|
+
const currentLineIdx = linesBuf.length - 1;
|
|
125
|
+
const targetRow = 1 + currentLineIdx;
|
|
126
|
+
const hintsRow = totalRows - 1;
|
|
127
|
+
const rowsUp = hintsRow - targetRow;
|
|
128
|
+
if (rowsUp > 0)
|
|
129
|
+
out.write(`\x1b[${rowsUp}A`);
|
|
130
|
+
// Set column
|
|
86
131
|
const col = promptVisibleLen + cursorPos + 1;
|
|
87
132
|
out.write(`\x1b[${col}G`);
|
|
133
|
+
cursorRowFromTop = targetRow;
|
|
88
134
|
}
|
|
89
135
|
// Initial draw
|
|
90
136
|
process.stderr.write(HIDE_CURSOR);
|
|
@@ -106,8 +152,6 @@ export function readTextInput(_prompt) {
|
|
|
106
152
|
linesBuf.push(line);
|
|
107
153
|
cursorPos = line.length;
|
|
108
154
|
}
|
|
109
|
-
// Move cursor back to top of box before redraw
|
|
110
|
-
moveCursorToBoxTop();
|
|
111
155
|
drawBox();
|
|
112
156
|
return;
|
|
113
157
|
}
|
|
@@ -120,28 +164,24 @@ export function readTextInput(_prompt) {
|
|
|
120
164
|
if (code === "C" && cursorPos < linesBuf[linesBuf.length - 1].length) {
|
|
121
165
|
cursorPos++;
|
|
122
166
|
i += 2;
|
|
123
|
-
moveCursorToBoxTop();
|
|
124
167
|
drawBox();
|
|
125
168
|
continue;
|
|
126
169
|
}
|
|
127
170
|
if (code === "D" && cursorPos > 0) {
|
|
128
171
|
cursorPos--;
|
|
129
172
|
i += 2;
|
|
130
|
-
moveCursorToBoxTop();
|
|
131
173
|
drawBox();
|
|
132
174
|
continue;
|
|
133
175
|
}
|
|
134
176
|
if (code === "H") {
|
|
135
177
|
cursorPos = 0;
|
|
136
178
|
i += 2;
|
|
137
|
-
moveCursorToBoxTop();
|
|
138
179
|
drawBox();
|
|
139
180
|
continue;
|
|
140
181
|
}
|
|
141
182
|
if (code === "F") {
|
|
142
183
|
cursorPos = linesBuf[linesBuf.length - 1].length;
|
|
143
184
|
i += 2;
|
|
144
|
-
moveCursorToBoxTop();
|
|
145
185
|
drawBox();
|
|
146
186
|
continue;
|
|
147
187
|
}
|
|
@@ -179,7 +219,6 @@ export function readTextInput(_prompt) {
|
|
|
179
219
|
const line = linesBuf[linesBuf.length - 1];
|
|
180
220
|
linesBuf[linesBuf.length - 1] = line.slice(0, cursorPos - 1) + line.slice(cursorPos);
|
|
181
221
|
cursorPos--;
|
|
182
|
-
moveCursorToBoxTop();
|
|
183
222
|
drawBox();
|
|
184
223
|
}
|
|
185
224
|
continue;
|
|
@@ -189,7 +228,6 @@ export function readTextInput(_prompt) {
|
|
|
189
228
|
const line = linesBuf[linesBuf.length - 1];
|
|
190
229
|
linesBuf[linesBuf.length - 1] = line.slice(0, cursorPos) + " " + line.slice(cursorPos);
|
|
191
230
|
cursorPos += 2;
|
|
192
|
-
moveCursorToBoxTop();
|
|
193
231
|
drawBox();
|
|
194
232
|
continue;
|
|
195
233
|
}
|
|
@@ -198,32 +236,20 @@ export function readTextInput(_prompt) {
|
|
|
198
236
|
const line = linesBuf[linesBuf.length - 1];
|
|
199
237
|
linesBuf[linesBuf.length - 1] = line.slice(0, cursorPos) + ch + line.slice(cursorPos);
|
|
200
238
|
cursorPos++;
|
|
201
|
-
moveCursorToBoxTop();
|
|
202
239
|
drawBox();
|
|
203
240
|
}
|
|
204
241
|
}
|
|
205
242
|
};
|
|
206
|
-
function moveCursorToBoxTop() {
|
|
207
|
-
// From current cursor position (inside the text area), move to the line
|
|
208
|
-
// before the top border so drawBox() can clear and redraw from there.
|
|
209
|
-
// Current cursor is at content row (linesBuf.length - 1 from top border)
|
|
210
|
-
// We need to go up past: content rows above cursor + top border
|
|
211
|
-
// But drawBox handles clearing with drawnRows, so just go up to start
|
|
212
|
-
const currentLineIdx = linesBuf.length - 1;
|
|
213
|
-
const rowsUp = currentLineIdx + 1; // content lines above + top border
|
|
214
|
-
if (rowsUp > 0) {
|
|
215
|
-
process.stderr.write(`\x1b[${rowsUp}A`);
|
|
216
|
-
}
|
|
217
|
-
process.stderr.write("\x1b[0G");
|
|
218
|
-
}
|
|
219
243
|
function finishAndClear() {
|
|
220
244
|
process.stdin.removeListener("data", onData);
|
|
221
245
|
if (origRawMode !== undefined) {
|
|
222
246
|
process.stdin.setRawMode(origRawMode);
|
|
223
247
|
}
|
|
224
|
-
// Move cursor to top of box
|
|
225
|
-
|
|
226
|
-
|
|
248
|
+
// Move cursor to top of box
|
|
249
|
+
if (cursorRowFromTop > 0) {
|
|
250
|
+
process.stderr.write(`\x1b[${cursorRowFromTop}A`);
|
|
251
|
+
}
|
|
252
|
+
process.stderr.write("\r\x1b[J"); // erase from here to end of screen
|
|
227
253
|
// Write the submitted text as a clean line (so it's visible in scrollback)
|
|
228
254
|
const fullText = linesBuf.join("\n").trim();
|
|
229
255
|
if (fullText) {
|
package/package.json
CHANGED