bunmicro 0.8.3 → 0.9.0
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/CHANGELOG.md +9 -0
- package/README.md +16 -1
- package/package.json +1 -1
- package/runtime/help/defaultkeys.md +7 -0
- package/runtime/help/help.md +14 -9
- package/runtime/help/keybindings.md +32 -437
- package/runtime/syntax/javascript.yaml +49 -1
- package/runtime/syntax/python3.yaml +18 -0
- package/src/highlight/parser.js +77 -9
- package/src/index.js +157 -26
- package/src/plugins/js-bridge.js +5 -0
- package/src/screen/screen.js +13 -1
- package/src/screen/vt100.js +98 -9
- package/todo.txt +4 -0
package/src/screen/vt100.js
CHANGED
|
@@ -8,7 +8,7 @@ const ANSI_COLORS = [
|
|
|
8
8
|
];
|
|
9
9
|
|
|
10
10
|
function blankCell() {
|
|
11
|
-
return { ch: " ", fg: "default", bg: "default", bold: false, italic: false, underline: false, reverse: false };
|
|
11
|
+
return { ch: " ", combining: [], filler: false, fg: "default", bg: "default", bold: false, italic: false, underline: false, reverse: false };
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
function findCSIEnd(str, start) {
|
|
@@ -24,6 +24,52 @@ function toHex2(n) {
|
|
|
24
24
|
return ((n ?? 0) & 0xFF).toString(16).padStart(2, "0");
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
function isZeroWidthCodePoint(cp) {
|
|
28
|
+
return (
|
|
29
|
+
cp === 0x200D ||
|
|
30
|
+
(cp >= 0x0300 && cp <= 0x036F) ||
|
|
31
|
+
(cp >= 0x1AB0 && cp <= 0x1AFF) ||
|
|
32
|
+
(cp >= 0x1DC0 && cp <= 0x1DFF) ||
|
|
33
|
+
(cp >= 0x20D0 && cp <= 0x20FF) ||
|
|
34
|
+
(cp >= 0xFE00 && cp <= 0xFE0F) ||
|
|
35
|
+
(cp >= 0xFE20 && cp <= 0xFE2F) ||
|
|
36
|
+
(cp >= 0xE0100 && cp <= 0xE01EF)
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function isWideCodePoint(cp) {
|
|
41
|
+
if (cp < 0x1100) return false;
|
|
42
|
+
return (
|
|
43
|
+
cp <= 0x115F ||
|
|
44
|
+
cp === 0x2329 || cp === 0x232A ||
|
|
45
|
+
(cp >= 0x2E80 && cp <= 0x303E) ||
|
|
46
|
+
(cp >= 0x3040 && cp <= 0x33FF) ||
|
|
47
|
+
(cp >= 0x3400 && cp <= 0x4DBF) ||
|
|
48
|
+
(cp >= 0x4E00 && cp <= 0xA4C6) ||
|
|
49
|
+
(cp >= 0xA960 && cp <= 0xA97C) ||
|
|
50
|
+
(cp >= 0xAC00 && cp <= 0xD7A3) ||
|
|
51
|
+
(cp >= 0xF900 && cp <= 0xFAFF) ||
|
|
52
|
+
(cp >= 0xFE10 && cp <= 0xFE19) ||
|
|
53
|
+
(cp >= 0xFE30 && cp <= 0xFE4F) ||
|
|
54
|
+
(cp >= 0xFF01 && cp <= 0xFF60) ||
|
|
55
|
+
(cp >= 0xFFE0 && cp <= 0xFFE6) ||
|
|
56
|
+
(cp >= 0x1B000 && cp <= 0x1B0FF) ||
|
|
57
|
+
(cp >= 0x1F004 && cp <= 0x1F0CF) ||
|
|
58
|
+
(cp >= 0x1F18F && cp <= 0x1F19A) ||
|
|
59
|
+
(cp >= 0x1F200 && cp <= 0x1F2FF) ||
|
|
60
|
+
(cp >= 0x1F300 && cp <= 0x1FAFF) ||
|
|
61
|
+
(cp >= 0x20000 && cp <= 0x2FFFD) ||
|
|
62
|
+
(cp >= 0x30000 && cp <= 0x3FFFD)
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function charWidth(ch) {
|
|
67
|
+
if (!ch) return 0;
|
|
68
|
+
const cp = ch.codePointAt(0);
|
|
69
|
+
if (cp < 32 || (cp >= 0x7f && cp < 0xa0) || isZeroWidthCodePoint(cp)) return 0;
|
|
70
|
+
return isWideCodePoint(cp) ? 2 : 1;
|
|
71
|
+
}
|
|
72
|
+
|
|
27
73
|
export class VT100 {
|
|
28
74
|
constructor(cols, rows) {
|
|
29
75
|
this.cols = Math.max(1, cols);
|
|
@@ -56,10 +102,7 @@ export class VT100 {
|
|
|
56
102
|
return this.cells[this._idx(x, y)];
|
|
57
103
|
}
|
|
58
104
|
|
|
59
|
-
|
|
60
|
-
const cell = this._cell(x, y);
|
|
61
|
-
if (!cell) return;
|
|
62
|
-
cell.ch = ch;
|
|
105
|
+
_copyStyleTo(cell) {
|
|
63
106
|
cell.fg = this.sgr.fg;
|
|
64
107
|
cell.bg = this.sgr.bg;
|
|
65
108
|
cell.bold = this.sgr.bold;
|
|
@@ -68,11 +111,54 @@ export class VT100 {
|
|
|
68
111
|
cell.reverse = this.sgr.reverse;
|
|
69
112
|
}
|
|
70
113
|
|
|
71
|
-
|
|
114
|
+
_clearCellRaw(x, y) {
|
|
72
115
|
const cell = this._cell(x, y);
|
|
73
116
|
if (cell) Object.assign(cell, blankCell());
|
|
74
117
|
}
|
|
75
118
|
|
|
119
|
+
_breakWideAt(x, y) {
|
|
120
|
+
const cell = this._cell(x, y);
|
|
121
|
+
if (!cell) return;
|
|
122
|
+
if (cell.filler) this._clearCellRaw(x - 1, y);
|
|
123
|
+
if (x + 1 < this.cols && this._cell(x + 1, y)?.filler) this._clearCellRaw(x + 1, y);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
_setCell(x, y, ch, width = 1) {
|
|
127
|
+
if (width === 0) {
|
|
128
|
+
const targetX = this.cx > 0 ? this.cx - 1 : 0;
|
|
129
|
+
const cell = this._cell(targetX, this.cy);
|
|
130
|
+
if (cell && !cell.filler) cell.combining.push(ch);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (width > 1 && x >= this.cols - 1) {
|
|
134
|
+
this.cx = 0;
|
|
135
|
+
this._lineFeed();
|
|
136
|
+
x = this.cx;
|
|
137
|
+
y = this.cy;
|
|
138
|
+
}
|
|
139
|
+
this._breakWideAt(x, y);
|
|
140
|
+
if (width > 1) this._breakWideAt(x + 1, y);
|
|
141
|
+
const cell = this._cell(x, y);
|
|
142
|
+
if (!cell) return;
|
|
143
|
+
cell.ch = ch;
|
|
144
|
+
cell.combining = [];
|
|
145
|
+
cell.filler = false;
|
|
146
|
+
this._copyStyleTo(cell);
|
|
147
|
+
if (width > 1) {
|
|
148
|
+
const filler = this._cell(x + 1, y);
|
|
149
|
+
if (filler) {
|
|
150
|
+
Object.assign(filler, blankCell());
|
|
151
|
+
filler.filler = true;
|
|
152
|
+
this._copyStyleTo(filler);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
_clearCell(x, y) {
|
|
158
|
+
this._breakWideAt(x, y);
|
|
159
|
+
this._clearCellRaw(x, y);
|
|
160
|
+
}
|
|
161
|
+
|
|
76
162
|
_clearLineFrom(x, y) {
|
|
77
163
|
for (let i = x; i < this.cols; i++) this._clearCell(i, y);
|
|
78
164
|
}
|
|
@@ -198,12 +284,15 @@ export class VT100 {
|
|
|
198
284
|
i++; // SO/SI charset switch, ignore
|
|
199
285
|
} else if (code >= 0x20) {
|
|
200
286
|
// Printable
|
|
201
|
-
|
|
202
|
-
|
|
287
|
+
const cp = data.codePointAt(i);
|
|
288
|
+
const rune = String.fromCodePoint(cp);
|
|
289
|
+
const width = charWidth(rune);
|
|
290
|
+
this._setCell(this.cx, this.cy, rune, width);
|
|
291
|
+
this.cx += width;
|
|
203
292
|
if (this.cx >= this.cols) {
|
|
204
293
|
this.cx = 0; this._lineFeed();
|
|
205
294
|
}
|
|
206
|
-
i
|
|
295
|
+
i += cp > 0xFFFF ? 2 : 1;
|
|
207
296
|
} else {
|
|
208
297
|
i++; // other control: skip
|
|
209
298
|
}
|
package/todo.txt
CHANGED
|
@@ -30,6 +30,10 @@ Current handoff notes
|
|
|
30
30
|
- Matchbrace highlights (), {}, [] and statusline column click cycles between matched braces when cursor is on a matched brace.
|
|
31
31
|
- Ctrl-C/Ctrl-X/Ctrl-V/Ctrl-Y work for line and selection clipboard flows; external clipboard failures fall back to the internal register.
|
|
32
32
|
- Copy/cut/paste and similar status messages render on a standalone info row above the statusline.
|
|
33
|
+
[x] term pane Unicode input/output support:
|
|
34
|
+
- PTY output now uses a streaming UTF-8 decoder so multi-byte Unicode split across chunks is preserved.
|
|
35
|
+
- VT100 printable handling iterates by code point, stores combining marks on the base cell, and uses filler cells for wide CJK/emoji output.
|
|
36
|
+
- Terminal pane rendering skips filler cells and emits combining marks through Screen.SetContent.
|
|
33
37
|
[x] replace/replaceall commands aligned with Go behavior:
|
|
34
38
|
- Flags: -a (replace all at once), -l (literal/no-regex, uses RegExp.escape).
|
|
35
39
|
- replace without -a shows interactive Y/N prompt per match (Perform replacement (y,n,esc)).
|