swarm-code 0.1.21 → 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 +78 -37
- package/package.json +1 -1
package/dist/ui/text-input.js
CHANGED
|
@@ -44,51 +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
|
-
//
|
|
47
|
+
// Tracks cursor position relative to top border after each drawBox()
|
|
48
48
|
let cursorRowFromTop = 0;
|
|
49
|
-
let
|
|
50
|
-
function
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
out.write(`\x1b[${cursorRowFromTop}A`);
|
|
57
|
-
}
|
|
58
|
-
out.write("\x1b[0G"); // go to column 0
|
|
59
|
-
out.write("\x1b[J"); // erase from cursor to end of screen
|
|
60
|
-
}
|
|
61
|
-
hasDrawn = true;
|
|
62
|
-
// Top border — thin dim line
|
|
63
|
-
const topLine = `${BORDER_COLOR}${"─".repeat(w)}${RESET}`;
|
|
64
|
-
out.write(`${topLine}\n`);
|
|
65
|
-
// Content rows — dark background, full width
|
|
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
|
|
66
56
|
const promptChar = `${ACCENT_COLOR}❯${RESET} `;
|
|
67
57
|
for (let i = 0; i < linesBuf.length; i++) {
|
|
68
58
|
const lineText = linesBuf[i];
|
|
69
59
|
const prefix = i === 0 ? promptChar : `${dim("·")} `;
|
|
70
|
-
// How much space for text content
|
|
71
60
|
const contentWidth = w - promptVisibleLen;
|
|
72
|
-
// Truncate display if line is too long
|
|
73
61
|
const displayText = lineText.length > contentWidth ? lineText.slice(0, contentWidth - 1) + "…" : lineText;
|
|
74
62
|
const padding = Math.max(0, contentWidth - displayText.length);
|
|
75
|
-
|
|
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).
|
|
76
119
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
//
|
|
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
|
|
88
131
|
const col = promptVisibleLen + cursorPos + 1;
|
|
89
132
|
out.write(`\x1b[${col}G`);
|
|
90
|
-
|
|
91
|
-
cursorRowFromTop = 1 + currentLineIdx;
|
|
133
|
+
cursorRowFromTop = targetRow;
|
|
92
134
|
}
|
|
93
135
|
// Initial draw
|
|
94
136
|
process.stderr.write(HIDE_CURSOR);
|
|
@@ -203,12 +245,11 @@ export function readTextInput(_prompt) {
|
|
|
203
245
|
if (origRawMode !== undefined) {
|
|
204
246
|
process.stdin.setRawMode(origRawMode);
|
|
205
247
|
}
|
|
206
|
-
// Move cursor to top of box
|
|
248
|
+
// Move cursor to top of box
|
|
207
249
|
if (cursorRowFromTop > 0) {
|
|
208
250
|
process.stderr.write(`\x1b[${cursorRowFromTop}A`);
|
|
209
251
|
}
|
|
210
|
-
process.stderr.write("\x1b[
|
|
211
|
-
process.stderr.write("\x1b[J"); // erase to end of screen
|
|
252
|
+
process.stderr.write("\r\x1b[J"); // erase from here to end of screen
|
|
212
253
|
// Write the submitted text as a clean line (so it's visible in scrollback)
|
|
213
254
|
const fullText = linesBuf.join("\n").trim();
|
|
214
255
|
if (fullText) {
|
package/package.json
CHANGED