zames_pro 2.49.1 → 2.49.2
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/input.js +68 -12
- package/package.json +1 -1
package/dist/input.js
CHANGED
|
@@ -93,7 +93,12 @@ export function visRows(s, cols) {
|
|
|
93
93
|
const len = visLen(s);
|
|
94
94
|
return Math.max(1, Math.ceil(len / width));
|
|
95
95
|
}
|
|
96
|
-
// Visible length of a line without ANSI sequences.
|
|
96
|
+
// Visible length of a line without ANSI sequences. WIDE characters (emoji,
|
|
97
|
+
// CJK) count as 2 columns — a plain code-point count made the status-line
|
|
98
|
+
// arithmetic (right-align, wrapping, block erase) disagree with the real
|
|
99
|
+
// screen, so a status containing an emoji/CJK could wrap past the edge and
|
|
100
|
+
// make the block erase miss (status "stacking"). Combining marks and the
|
|
101
|
+
// zero-width joiner/space/variation selectors count as 0.
|
|
97
102
|
export function visLen(s) {
|
|
98
103
|
s = String(s);
|
|
99
104
|
let n = 0;
|
|
@@ -109,11 +114,48 @@ export function visLen(s) {
|
|
|
109
114
|
}
|
|
110
115
|
continue;
|
|
111
116
|
}
|
|
112
|
-
|
|
113
|
-
|
|
117
|
+
const cp = s.codePointAt(i);
|
|
118
|
+
n += charWidth(cp);
|
|
119
|
+
i += cp > 0xffff ? 2 : 1;
|
|
114
120
|
}
|
|
115
121
|
return n;
|
|
116
122
|
}
|
|
123
|
+
// Display width of one code point in columns (0, 1 or 2). Based on the
|
|
124
|
+
// conventional wcwidth ranges — good enough for terminal layout, and it makes
|
|
125
|
+
// the emoji used in the status line (🧠🌐) count as 2, while math symbols like
|
|
126
|
+
// ⧗ (U+29D7) stay 1, matching a real terminal.
|
|
127
|
+
export function charWidth(cp) {
|
|
128
|
+
// Zero width: combining marks, ZWJ/ZWNJ, variation selectors.
|
|
129
|
+
if (cp === 0x200b ||
|
|
130
|
+
cp === 0x200c ||
|
|
131
|
+
cp === 0x200d ||
|
|
132
|
+
(cp >= 0x0300 && cp <= 0x036f) ||
|
|
133
|
+
(cp >= 0x1ab0 && cp <= 0x1aff) ||
|
|
134
|
+
(cp >= 0x1dc0 && cp <= 0x1dff) ||
|
|
135
|
+
(cp >= 0x20d0 && cp <= 0x20ff) ||
|
|
136
|
+
(cp >= 0xfe00 && cp <= 0xfe0f) ||
|
|
137
|
+
(cp >= 0xfe20 && cp <= 0xfe2f)) {
|
|
138
|
+
return 0;
|
|
139
|
+
}
|
|
140
|
+
// Wide: CJK, Hangul, fullwidth forms, emoji.
|
|
141
|
+
if ((cp >= 0x1100 && cp <= 0x115f) ||
|
|
142
|
+
(cp >= 0x2e80 && cp <= 0x303e) ||
|
|
143
|
+
(cp >= 0x3041 && cp <= 0x33ff) ||
|
|
144
|
+
(cp >= 0x3400 && cp <= 0x4dbf) ||
|
|
145
|
+
(cp >= 0x4e00 && cp <= 0x9fff) ||
|
|
146
|
+
(cp >= 0xa000 && cp <= 0xa4cf) ||
|
|
147
|
+
(cp >= 0xac00 && cp <= 0xd7a3) ||
|
|
148
|
+
(cp >= 0xf900 && cp <= 0xfaff) ||
|
|
149
|
+
(cp >= 0xfe30 && cp <= 0xfe4f) ||
|
|
150
|
+
(cp >= 0xff00 && cp <= 0xff60) ||
|
|
151
|
+
(cp >= 0xffe0 && cp <= 0xffe6) ||
|
|
152
|
+
(cp >= 0x1f000 && cp <= 0x1f02f) ||
|
|
153
|
+
(cp >= 0x1f300 && cp <= 0x1faff) ||
|
|
154
|
+
(cp >= 0x20000 && cp <= 0x3fffd)) {
|
|
155
|
+
return 2;
|
|
156
|
+
}
|
|
157
|
+
return 1;
|
|
158
|
+
}
|
|
117
159
|
export function layoutInput(promptStr, buf, cursor, cols) {
|
|
118
160
|
const width = Math.max(20, Number(cols) || 80);
|
|
119
161
|
const promptW = visLen(promptStr);
|
|
@@ -128,21 +170,29 @@ export function layoutInput(promptStr, buf, cursor, cols) {
|
|
|
128
170
|
const avail = Math.max(1, width - promptW);
|
|
129
171
|
const start = i;
|
|
130
172
|
// Build the next visual line. First we take as many
|
|
131
|
-
// characters as fit (
|
|
173
|
+
// characters as fit (columns < avail). If we hit the width
|
|
132
174
|
// and the next character is not the end of the line, we roll back to the
|
|
133
175
|
// last space so we don't split a word in the middle (word-wrap).
|
|
176
|
+
// Wrapping and the cursor column are measured in COLUMNS (charWidth),
|
|
177
|
+
// not code points — otherwise a CJK/emoji input would overflow the row
|
|
178
|
+
// and put the cursor on the wrong cell.
|
|
134
179
|
let text = '';
|
|
135
|
-
let
|
|
136
|
-
let
|
|
137
|
-
|
|
180
|
+
let widthUsed = 0;
|
|
181
|
+
let charIdx = 0;
|
|
182
|
+
let lastSpace = -1; // char index of the space within text
|
|
183
|
+
while (i < chars.length && chars[i] !== NL) {
|
|
184
|
+
const w = charWidth(chars[i].codePointAt(0));
|
|
185
|
+
if (widthUsed + w > avail)
|
|
186
|
+
break;
|
|
138
187
|
if (chars[i] === ' ')
|
|
139
|
-
lastSpace =
|
|
188
|
+
lastSpace = charIdx;
|
|
140
189
|
text += chars[i];
|
|
141
190
|
i++;
|
|
142
|
-
|
|
191
|
+
charIdx++;
|
|
192
|
+
widthUsed += w;
|
|
143
193
|
}
|
|
144
194
|
const atLineEnd = i >= chars.length || chars[i] === NL;
|
|
145
|
-
if (!atLineEnd &&
|
|
195
|
+
if (!atLineEnd && widthUsed >= avail && lastSpace > 0) {
|
|
146
196
|
// Move the "tail" of the line to the next visual line.
|
|
147
197
|
const textChars = Array.from(text);
|
|
148
198
|
const tailLen = textChars.length - lastSpace;
|
|
@@ -162,7 +212,8 @@ export function layoutInput(promptStr, buf, cursor, cols) {
|
|
|
162
212
|
let cursorCol = promptW;
|
|
163
213
|
for (let r = 0; r < rows.length; r++) {
|
|
164
214
|
const row = rows[r];
|
|
165
|
-
const
|
|
215
|
+
const rowChars = Array.from(row.text);
|
|
216
|
+
const len = rowChars.length;
|
|
166
217
|
const from = row.start;
|
|
167
218
|
const to = row.start + len;
|
|
168
219
|
if (cur >= from && cur <= to) {
|
|
@@ -170,7 +221,12 @@ export function layoutInput(promptStr, buf, cursor, cols) {
|
|
|
170
221
|
if (cur === to && next && next.start === to)
|
|
171
222
|
continue;
|
|
172
223
|
cursorRow = r;
|
|
173
|
-
|
|
224
|
+
// Cursor column in COLUMNS (wide chars count as 2).
|
|
225
|
+
let w = 0;
|
|
226
|
+
for (let k = 0; k < cur - from; k++) {
|
|
227
|
+
w += charWidth(rowChars[k].codePointAt(0));
|
|
228
|
+
}
|
|
229
|
+
cursorCol = promptW + w;
|
|
174
230
|
break;
|
|
175
231
|
}
|
|
176
232
|
}
|