@opentui/core 0.1.28 → 0.1.30
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/3d.js +1 -1
- package/3d.js.map +1 -1
- package/README.md +10 -0
- package/Renderable.d.ts +25 -24
- package/buffer.d.ts +4 -7
- package/edit-buffer.d.ts +80 -0
- package/editor-view.d.ts +53 -0
- package/{index-phjxdb6g.js → index-0qmm1k4p.js} +1709 -323
- package/{index-phjxdb6g.js.map → index-0qmm1k4p.js.map} +18 -17
- package/index.d.ts +4 -0
- package/index.js +1505 -65
- package/index.js.map +13 -6
- package/lib/hast-styled-text.d.ts +2 -3
- package/lib/index.d.ts +0 -1
- package/lib/keymapping.d.ts +10 -0
- package/lib/objects-in-viewport.d.ts +14 -0
- package/lib/tree-sitter/index.d.ts +0 -2
- package/lib/tree-sitter-styled-text.d.ts +1 -1
- package/lib/yoga.options.d.ts +6 -6
- package/package.json +8 -7
- package/renderables/Code.d.ts +1 -1
- package/renderables/EditBufferRenderable.d.ts +113 -0
- package/renderables/Text.d.ts +0 -3
- package/renderables/TextBufferRenderable.d.ts +8 -14
- package/renderables/Textarea.d.ts +87 -0
- package/renderables/index.d.ts +1 -0
- package/renderer.d.ts +6 -2
- package/{lib/syntax-style.d.ts → syntax-style.d.ts} +21 -5
- package/testing/mock-keys.d.ts +37 -2
- package/testing.js +52 -6
- package/testing.js.map +3 -3
- package/text-buffer-view.d.ts +31 -0
- package/text-buffer.d.ts +28 -21
- package/types.d.ts +10 -0
- package/zig-structs.d.ts +22 -0
- package/zig.d.ts +145 -23
- package/lib/word-jumps.d.ts +0 -2
package/index.js
CHANGED
|
@@ -30,7 +30,6 @@ import {
|
|
|
30
30
|
RootRenderable,
|
|
31
31
|
Selection,
|
|
32
32
|
StyledText,
|
|
33
|
-
SyntaxStyle,
|
|
34
33
|
TerminalConsole,
|
|
35
34
|
TextAttributes,
|
|
36
35
|
TextBuffer,
|
|
@@ -61,7 +60,6 @@ import {
|
|
|
61
60
|
capture,
|
|
62
61
|
clearEnvCache,
|
|
63
62
|
convertGlobalToLocalSelection,
|
|
64
|
-
convertThemeToStyles,
|
|
65
63
|
coordinateToCharacterIndex,
|
|
66
64
|
createCliRenderer,
|
|
67
65
|
createTextAttributes,
|
|
@@ -133,7 +131,701 @@ import {
|
|
|
133
131
|
white,
|
|
134
132
|
wrapWithDelegates,
|
|
135
133
|
yellow
|
|
136
|
-
} from "./index-
|
|
134
|
+
} from "./index-0qmm1k4p.js";
|
|
135
|
+
// src/text-buffer-view.ts
|
|
136
|
+
class TextBufferView {
|
|
137
|
+
lib;
|
|
138
|
+
viewPtr;
|
|
139
|
+
textBuffer;
|
|
140
|
+
_destroyed = false;
|
|
141
|
+
constructor(lib, ptr, textBuffer) {
|
|
142
|
+
this.lib = lib;
|
|
143
|
+
this.viewPtr = ptr;
|
|
144
|
+
this.textBuffer = textBuffer;
|
|
145
|
+
}
|
|
146
|
+
static create(textBuffer) {
|
|
147
|
+
const lib = resolveRenderLib();
|
|
148
|
+
const viewPtr = lib.createTextBufferView(textBuffer.ptr);
|
|
149
|
+
return new TextBufferView(lib, viewPtr, textBuffer);
|
|
150
|
+
}
|
|
151
|
+
guard() {
|
|
152
|
+
if (this._destroyed)
|
|
153
|
+
throw new Error("TextBufferView is destroyed");
|
|
154
|
+
}
|
|
155
|
+
get ptr() {
|
|
156
|
+
this.guard();
|
|
157
|
+
return this.viewPtr;
|
|
158
|
+
}
|
|
159
|
+
setSelection(start, end, bgColor, fgColor) {
|
|
160
|
+
this.guard();
|
|
161
|
+
this.lib.textBufferViewSetSelection(this.viewPtr, start, end, bgColor || null, fgColor || null);
|
|
162
|
+
}
|
|
163
|
+
resetSelection() {
|
|
164
|
+
this.guard();
|
|
165
|
+
this.lib.textBufferViewResetSelection(this.viewPtr);
|
|
166
|
+
}
|
|
167
|
+
getSelection() {
|
|
168
|
+
this.guard();
|
|
169
|
+
return this.lib.textBufferViewGetSelection(this.viewPtr);
|
|
170
|
+
}
|
|
171
|
+
hasSelection() {
|
|
172
|
+
this.guard();
|
|
173
|
+
return this.getSelection() !== null;
|
|
174
|
+
}
|
|
175
|
+
setLocalSelection(anchorX, anchorY, focusX, focusY, bgColor, fgColor) {
|
|
176
|
+
this.guard();
|
|
177
|
+
return this.lib.textBufferViewSetLocalSelection(this.viewPtr, anchorX, anchorY, focusX, focusY, bgColor || null, fgColor || null);
|
|
178
|
+
}
|
|
179
|
+
resetLocalSelection() {
|
|
180
|
+
this.guard();
|
|
181
|
+
this.lib.textBufferViewResetLocalSelection(this.viewPtr);
|
|
182
|
+
}
|
|
183
|
+
setWrapWidth(width) {
|
|
184
|
+
this.guard();
|
|
185
|
+
this.lib.textBufferViewSetWrapWidth(this.viewPtr, width ?? 0);
|
|
186
|
+
}
|
|
187
|
+
setWrapMode(mode) {
|
|
188
|
+
this.guard();
|
|
189
|
+
this.lib.textBufferViewSetWrapMode(this.viewPtr, mode);
|
|
190
|
+
}
|
|
191
|
+
setViewportSize(width, height) {
|
|
192
|
+
this.guard();
|
|
193
|
+
this.lib.textBufferViewSetViewportSize(this.viewPtr, width, height);
|
|
194
|
+
}
|
|
195
|
+
get lineInfo() {
|
|
196
|
+
this.guard();
|
|
197
|
+
return this.lib.textBufferViewGetLineInfo(this.viewPtr);
|
|
198
|
+
}
|
|
199
|
+
get logicalLineInfo() {
|
|
200
|
+
this.guard();
|
|
201
|
+
return this.lib.textBufferViewGetLogicalLineInfo(this.viewPtr);
|
|
202
|
+
}
|
|
203
|
+
getSelectedText() {
|
|
204
|
+
this.guard();
|
|
205
|
+
const byteSize = this.textBuffer.byteSize;
|
|
206
|
+
if (byteSize === 0)
|
|
207
|
+
return "";
|
|
208
|
+
const selectedBytes = this.lib.textBufferViewGetSelectedTextBytes(this.viewPtr, byteSize);
|
|
209
|
+
if (!selectedBytes)
|
|
210
|
+
return "";
|
|
211
|
+
return this.lib.decoder.decode(selectedBytes);
|
|
212
|
+
}
|
|
213
|
+
getPlainText() {
|
|
214
|
+
this.guard();
|
|
215
|
+
const byteSize = this.textBuffer.byteSize;
|
|
216
|
+
if (byteSize === 0)
|
|
217
|
+
return "";
|
|
218
|
+
const plainBytes = this.lib.textBufferViewGetPlainTextBytes(this.viewPtr, byteSize);
|
|
219
|
+
if (!plainBytes)
|
|
220
|
+
return "";
|
|
221
|
+
return this.lib.decoder.decode(plainBytes);
|
|
222
|
+
}
|
|
223
|
+
destroy() {
|
|
224
|
+
if (this._destroyed)
|
|
225
|
+
return;
|
|
226
|
+
this._destroyed = true;
|
|
227
|
+
this.lib.destroyTextBufferView(this.viewPtr);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// src/edit-buffer.ts
|
|
231
|
+
import { EventEmitter } from "events";
|
|
232
|
+
|
|
233
|
+
class EditBuffer extends EventEmitter {
|
|
234
|
+
static registry = new Map;
|
|
235
|
+
static nativeEventsSubscribed = false;
|
|
236
|
+
lib;
|
|
237
|
+
bufferPtr;
|
|
238
|
+
textBufferPtr;
|
|
239
|
+
id;
|
|
240
|
+
_destroyed = false;
|
|
241
|
+
_textBytes = [];
|
|
242
|
+
_singleTextBytes = null;
|
|
243
|
+
_singleTextMemId = null;
|
|
244
|
+
_syntaxStyle;
|
|
245
|
+
constructor(lib, ptr) {
|
|
246
|
+
super();
|
|
247
|
+
this.lib = lib;
|
|
248
|
+
this.bufferPtr = ptr;
|
|
249
|
+
this.textBufferPtr = lib.editBufferGetTextBuffer(ptr);
|
|
250
|
+
this.id = lib.editBufferGetId(ptr);
|
|
251
|
+
EditBuffer.registry.set(this.id, this);
|
|
252
|
+
EditBuffer.subscribeToNativeEvents(lib);
|
|
253
|
+
}
|
|
254
|
+
static create(widthMethod) {
|
|
255
|
+
const lib = resolveRenderLib();
|
|
256
|
+
const ptr = lib.createEditBuffer(widthMethod);
|
|
257
|
+
return new EditBuffer(lib, ptr);
|
|
258
|
+
}
|
|
259
|
+
static subscribeToNativeEvents(lib) {
|
|
260
|
+
if (EditBuffer.nativeEventsSubscribed)
|
|
261
|
+
return;
|
|
262
|
+
EditBuffer.nativeEventsSubscribed = true;
|
|
263
|
+
lib.onAnyNativeEvent((name, data) => {
|
|
264
|
+
const buffer = new Uint16Array(data);
|
|
265
|
+
if (name.startsWith("eb_") && buffer.length >= 1) {
|
|
266
|
+
const id = buffer[0];
|
|
267
|
+
const instance = EditBuffer.registry.get(id);
|
|
268
|
+
if (instance) {
|
|
269
|
+
const eventName = name.slice(3);
|
|
270
|
+
const eventData = data.slice(2);
|
|
271
|
+
instance.emit(eventName, eventData);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
guard() {
|
|
277
|
+
if (this._destroyed)
|
|
278
|
+
throw new Error("EditBuffer is destroyed");
|
|
279
|
+
}
|
|
280
|
+
get ptr() {
|
|
281
|
+
this.guard();
|
|
282
|
+
return this.bufferPtr;
|
|
283
|
+
}
|
|
284
|
+
setText(text, opts) {
|
|
285
|
+
this.guard();
|
|
286
|
+
const history = opts?.history ?? true;
|
|
287
|
+
const textBytes = this.lib.encoder.encode(text);
|
|
288
|
+
if (history) {
|
|
289
|
+
this._textBytes.push(textBytes);
|
|
290
|
+
const memId = this.lib.textBufferRegisterMemBuffer(this.textBufferPtr, textBytes, false);
|
|
291
|
+
this.lib.editBufferSetTextFromMem(this.bufferPtr, memId, true);
|
|
292
|
+
} else {
|
|
293
|
+
if (this._singleTextMemId !== null) {
|
|
294
|
+
this.lib.textBufferReplaceMemBuffer(this.textBufferPtr, this._singleTextMemId, textBytes, false);
|
|
295
|
+
} else {
|
|
296
|
+
this._singleTextMemId = this.lib.textBufferRegisterMemBuffer(this.textBufferPtr, textBytes, false);
|
|
297
|
+
}
|
|
298
|
+
this._singleTextBytes = textBytes;
|
|
299
|
+
this.lib.editBufferSetTextFromMem(this.bufferPtr, this._singleTextMemId, false);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
setTextOwned(text, opts) {
|
|
303
|
+
this.guard();
|
|
304
|
+
const history = opts?.history ?? true;
|
|
305
|
+
const textBytes = this.lib.encoder.encode(text);
|
|
306
|
+
this.lib.editBufferSetText(this.bufferPtr, textBytes, history);
|
|
307
|
+
}
|
|
308
|
+
getText() {
|
|
309
|
+
this.guard();
|
|
310
|
+
const maxSize = 1024 * 1024;
|
|
311
|
+
const textBytes = this.lib.editBufferGetText(this.bufferPtr, maxSize);
|
|
312
|
+
if (!textBytes)
|
|
313
|
+
return "";
|
|
314
|
+
return this.lib.decoder.decode(textBytes);
|
|
315
|
+
}
|
|
316
|
+
insertChar(char) {
|
|
317
|
+
this.guard();
|
|
318
|
+
this.lib.editBufferInsertChar(this.bufferPtr, char);
|
|
319
|
+
}
|
|
320
|
+
insertText(text) {
|
|
321
|
+
this.guard();
|
|
322
|
+
this.lib.editBufferInsertText(this.bufferPtr, text);
|
|
323
|
+
}
|
|
324
|
+
deleteChar() {
|
|
325
|
+
this.guard();
|
|
326
|
+
this.lib.editBufferDeleteChar(this.bufferPtr);
|
|
327
|
+
}
|
|
328
|
+
deleteCharBackward() {
|
|
329
|
+
this.guard();
|
|
330
|
+
this.lib.editBufferDeleteCharBackward(this.bufferPtr);
|
|
331
|
+
}
|
|
332
|
+
deleteRange(startLine, startCol, endLine, endCol) {
|
|
333
|
+
this.guard();
|
|
334
|
+
this.lib.editBufferDeleteRange(this.bufferPtr, startLine, startCol, endLine, endCol);
|
|
335
|
+
}
|
|
336
|
+
newLine() {
|
|
337
|
+
this.guard();
|
|
338
|
+
this.lib.editBufferNewLine(this.bufferPtr);
|
|
339
|
+
}
|
|
340
|
+
deleteLine() {
|
|
341
|
+
this.guard();
|
|
342
|
+
this.lib.editBufferDeleteLine(this.bufferPtr);
|
|
343
|
+
}
|
|
344
|
+
moveCursorLeft() {
|
|
345
|
+
this.guard();
|
|
346
|
+
this.lib.editBufferMoveCursorLeft(this.bufferPtr);
|
|
347
|
+
}
|
|
348
|
+
moveCursorRight() {
|
|
349
|
+
this.guard();
|
|
350
|
+
this.lib.editBufferMoveCursorRight(this.bufferPtr);
|
|
351
|
+
}
|
|
352
|
+
moveCursorUp() {
|
|
353
|
+
this.guard();
|
|
354
|
+
this.lib.editBufferMoveCursorUp(this.bufferPtr);
|
|
355
|
+
}
|
|
356
|
+
moveCursorDown() {
|
|
357
|
+
this.guard();
|
|
358
|
+
this.lib.editBufferMoveCursorDown(this.bufferPtr);
|
|
359
|
+
}
|
|
360
|
+
gotoLine(line) {
|
|
361
|
+
this.guard();
|
|
362
|
+
this.lib.editBufferGotoLine(this.bufferPtr, line);
|
|
363
|
+
}
|
|
364
|
+
setCursor(line, col) {
|
|
365
|
+
this.guard();
|
|
366
|
+
this.lib.editBufferSetCursor(this.bufferPtr, line, col);
|
|
367
|
+
}
|
|
368
|
+
setCursorToLineCol(line, col) {
|
|
369
|
+
this.guard();
|
|
370
|
+
this.lib.editBufferSetCursorToLineCol(this.bufferPtr, line, col);
|
|
371
|
+
}
|
|
372
|
+
setCursorByOffset(offset) {
|
|
373
|
+
this.guard();
|
|
374
|
+
this.lib.editBufferSetCursorByOffset(this.bufferPtr, offset);
|
|
375
|
+
}
|
|
376
|
+
getCursorPosition() {
|
|
377
|
+
this.guard();
|
|
378
|
+
return this.lib.editBufferGetCursorPosition(this.bufferPtr);
|
|
379
|
+
}
|
|
380
|
+
getNextWordBoundary() {
|
|
381
|
+
this.guard();
|
|
382
|
+
const boundary = this.lib.editBufferGetNextWordBoundary(this.bufferPtr);
|
|
383
|
+
return {
|
|
384
|
+
line: boundary.row,
|
|
385
|
+
visualColumn: boundary.col,
|
|
386
|
+
offset: boundary.offset
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
getPrevWordBoundary() {
|
|
390
|
+
this.guard();
|
|
391
|
+
const boundary = this.lib.editBufferGetPrevWordBoundary(this.bufferPtr);
|
|
392
|
+
return {
|
|
393
|
+
line: boundary.row,
|
|
394
|
+
visualColumn: boundary.col,
|
|
395
|
+
offset: boundary.offset
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
getEOL() {
|
|
399
|
+
this.guard();
|
|
400
|
+
const boundary = this.lib.editBufferGetEOL(this.bufferPtr);
|
|
401
|
+
return {
|
|
402
|
+
line: boundary.row,
|
|
403
|
+
visualColumn: boundary.col,
|
|
404
|
+
offset: boundary.offset
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
debugLogRope() {
|
|
408
|
+
this.guard();
|
|
409
|
+
this.lib.editBufferDebugLogRope(this.bufferPtr);
|
|
410
|
+
}
|
|
411
|
+
undo() {
|
|
412
|
+
this.guard();
|
|
413
|
+
const maxSize = 256;
|
|
414
|
+
const metaBytes = this.lib.editBufferUndo(this.bufferPtr, maxSize);
|
|
415
|
+
if (!metaBytes)
|
|
416
|
+
return null;
|
|
417
|
+
return this.lib.decoder.decode(metaBytes);
|
|
418
|
+
}
|
|
419
|
+
redo() {
|
|
420
|
+
this.guard();
|
|
421
|
+
const maxSize = 256;
|
|
422
|
+
const metaBytes = this.lib.editBufferRedo(this.bufferPtr, maxSize);
|
|
423
|
+
if (!metaBytes)
|
|
424
|
+
return null;
|
|
425
|
+
return this.lib.decoder.decode(metaBytes);
|
|
426
|
+
}
|
|
427
|
+
canUndo() {
|
|
428
|
+
this.guard();
|
|
429
|
+
return this.lib.editBufferCanUndo(this.bufferPtr);
|
|
430
|
+
}
|
|
431
|
+
canRedo() {
|
|
432
|
+
this.guard();
|
|
433
|
+
return this.lib.editBufferCanRedo(this.bufferPtr);
|
|
434
|
+
}
|
|
435
|
+
clearHistory() {
|
|
436
|
+
this.guard();
|
|
437
|
+
this.lib.editBufferClearHistory(this.bufferPtr);
|
|
438
|
+
}
|
|
439
|
+
setDefaultFg(fg2) {
|
|
440
|
+
this.guard();
|
|
441
|
+
this.lib.textBufferSetDefaultFg(this.textBufferPtr, fg2);
|
|
442
|
+
}
|
|
443
|
+
setDefaultBg(bg2) {
|
|
444
|
+
this.guard();
|
|
445
|
+
this.lib.textBufferSetDefaultBg(this.textBufferPtr, bg2);
|
|
446
|
+
}
|
|
447
|
+
setDefaultAttributes(attributes) {
|
|
448
|
+
this.guard();
|
|
449
|
+
this.lib.textBufferSetDefaultAttributes(this.textBufferPtr, attributes);
|
|
450
|
+
}
|
|
451
|
+
resetDefaults() {
|
|
452
|
+
this.guard();
|
|
453
|
+
this.lib.textBufferResetDefaults(this.textBufferPtr);
|
|
454
|
+
}
|
|
455
|
+
setPlaceholder(text) {
|
|
456
|
+
this.guard();
|
|
457
|
+
this.lib.editBufferSetPlaceholder(this.bufferPtr, text);
|
|
458
|
+
}
|
|
459
|
+
setPlaceholderColor(color) {
|
|
460
|
+
this.guard();
|
|
461
|
+
this.lib.editBufferSetPlaceholderColor(this.bufferPtr, color);
|
|
462
|
+
}
|
|
463
|
+
setSyntaxStyle(style) {
|
|
464
|
+
this.guard();
|
|
465
|
+
this._syntaxStyle = style ?? undefined;
|
|
466
|
+
this.lib.textBufferSetSyntaxStyle(this.textBufferPtr, style?.ptr ?? null);
|
|
467
|
+
}
|
|
468
|
+
getSyntaxStyle() {
|
|
469
|
+
this.guard();
|
|
470
|
+
return this._syntaxStyle ?? null;
|
|
471
|
+
}
|
|
472
|
+
addHighlight(lineIdx, highlight) {
|
|
473
|
+
this.guard();
|
|
474
|
+
this.lib.textBufferAddHighlight(this.textBufferPtr, lineIdx, highlight);
|
|
475
|
+
}
|
|
476
|
+
addHighlightByCharRange(highlight) {
|
|
477
|
+
this.guard();
|
|
478
|
+
this.lib.textBufferAddHighlightByCharRange(this.textBufferPtr, highlight);
|
|
479
|
+
}
|
|
480
|
+
removeHighlightsByRef(hlRef) {
|
|
481
|
+
this.guard();
|
|
482
|
+
this.lib.textBufferRemoveHighlightsByRef(this.textBufferPtr, hlRef);
|
|
483
|
+
}
|
|
484
|
+
clearLineHighlights(lineIdx) {
|
|
485
|
+
this.guard();
|
|
486
|
+
this.lib.textBufferClearLineHighlights(this.textBufferPtr, lineIdx);
|
|
487
|
+
}
|
|
488
|
+
clearAllHighlights() {
|
|
489
|
+
this.guard();
|
|
490
|
+
this.lib.textBufferClearAllHighlights(this.textBufferPtr);
|
|
491
|
+
}
|
|
492
|
+
getLineHighlights(lineIdx) {
|
|
493
|
+
this.guard();
|
|
494
|
+
return this.lib.textBufferGetLineHighlights(this.textBufferPtr, lineIdx);
|
|
495
|
+
}
|
|
496
|
+
destroy() {
|
|
497
|
+
if (this._destroyed)
|
|
498
|
+
return;
|
|
499
|
+
this._destroyed = true;
|
|
500
|
+
EditBuffer.registry.delete(this.id);
|
|
501
|
+
this.lib.destroyEditBuffer(this.bufferPtr);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
// src/editor-view.ts
|
|
505
|
+
class EditorView {
|
|
506
|
+
lib;
|
|
507
|
+
viewPtr;
|
|
508
|
+
editBuffer;
|
|
509
|
+
_destroyed = false;
|
|
510
|
+
constructor(lib, ptr, editBuffer) {
|
|
511
|
+
this.lib = lib;
|
|
512
|
+
this.viewPtr = ptr;
|
|
513
|
+
this.editBuffer = editBuffer;
|
|
514
|
+
}
|
|
515
|
+
static create(editBuffer, viewportWidth, viewportHeight) {
|
|
516
|
+
const lib = resolveRenderLib();
|
|
517
|
+
const viewPtr = lib.createEditorView(editBuffer.ptr, viewportWidth, viewportHeight);
|
|
518
|
+
return new EditorView(lib, viewPtr, editBuffer);
|
|
519
|
+
}
|
|
520
|
+
guard() {
|
|
521
|
+
if (this._destroyed)
|
|
522
|
+
throw new Error("EditorView is destroyed");
|
|
523
|
+
}
|
|
524
|
+
get ptr() {
|
|
525
|
+
this.guard();
|
|
526
|
+
return this.viewPtr;
|
|
527
|
+
}
|
|
528
|
+
setViewportSize(width, height) {
|
|
529
|
+
this.guard();
|
|
530
|
+
this.lib.editorViewSetViewportSize(this.viewPtr, width, height);
|
|
531
|
+
}
|
|
532
|
+
getViewport() {
|
|
533
|
+
this.guard();
|
|
534
|
+
return this.lib.editorViewGetViewport(this.viewPtr);
|
|
535
|
+
}
|
|
536
|
+
setScrollMargin(margin) {
|
|
537
|
+
this.guard();
|
|
538
|
+
this.lib.editorViewSetScrollMargin(this.viewPtr, margin);
|
|
539
|
+
}
|
|
540
|
+
setWrapMode(mode) {
|
|
541
|
+
this.guard();
|
|
542
|
+
this.lib.editorViewSetWrapMode(this.viewPtr, mode);
|
|
543
|
+
}
|
|
544
|
+
getVirtualLineCount() {
|
|
545
|
+
this.guard();
|
|
546
|
+
return this.lib.editorViewGetVirtualLineCount(this.viewPtr);
|
|
547
|
+
}
|
|
548
|
+
getTotalVirtualLineCount() {
|
|
549
|
+
this.guard();
|
|
550
|
+
return this.lib.editorViewGetTotalVirtualLineCount(this.viewPtr);
|
|
551
|
+
}
|
|
552
|
+
setSelection(start, end, bgColor, fgColor) {
|
|
553
|
+
this.guard();
|
|
554
|
+
this.lib.editorViewSetSelection(this.viewPtr, start, end, bgColor || null, fgColor || null);
|
|
555
|
+
}
|
|
556
|
+
resetSelection() {
|
|
557
|
+
this.guard();
|
|
558
|
+
this.lib.editorViewResetSelection(this.viewPtr);
|
|
559
|
+
}
|
|
560
|
+
getSelection() {
|
|
561
|
+
this.guard();
|
|
562
|
+
return this.lib.editorViewGetSelection(this.viewPtr);
|
|
563
|
+
}
|
|
564
|
+
hasSelection() {
|
|
565
|
+
this.guard();
|
|
566
|
+
return this.getSelection() !== null;
|
|
567
|
+
}
|
|
568
|
+
setLocalSelection(anchorX, anchorY, focusX, focusY, bgColor, fgColor) {
|
|
569
|
+
this.guard();
|
|
570
|
+
return this.lib.editorViewSetLocalSelection(this.viewPtr, anchorX, anchorY, focusX, focusY, bgColor || null, fgColor || null);
|
|
571
|
+
}
|
|
572
|
+
resetLocalSelection() {
|
|
573
|
+
this.guard();
|
|
574
|
+
this.lib.editorViewResetLocalSelection(this.viewPtr);
|
|
575
|
+
}
|
|
576
|
+
getSelectedText() {
|
|
577
|
+
this.guard();
|
|
578
|
+
const maxLength = 1024 * 1024;
|
|
579
|
+
const selectedBytes = this.lib.editorViewGetSelectedTextBytes(this.viewPtr, maxLength);
|
|
580
|
+
if (!selectedBytes)
|
|
581
|
+
return "";
|
|
582
|
+
return this.lib.decoder.decode(selectedBytes);
|
|
583
|
+
}
|
|
584
|
+
getCursor() {
|
|
585
|
+
this.guard();
|
|
586
|
+
return this.lib.editorViewGetCursor(this.viewPtr);
|
|
587
|
+
}
|
|
588
|
+
getText() {
|
|
589
|
+
this.guard();
|
|
590
|
+
const maxLength = 1024 * 1024;
|
|
591
|
+
const textBytes = this.lib.editorViewGetText(this.viewPtr, maxLength);
|
|
592
|
+
if (!textBytes)
|
|
593
|
+
return "";
|
|
594
|
+
return this.lib.decoder.decode(textBytes);
|
|
595
|
+
}
|
|
596
|
+
getVisualCursor() {
|
|
597
|
+
this.guard();
|
|
598
|
+
return this.lib.editorViewGetVisualCursor(this.viewPtr);
|
|
599
|
+
}
|
|
600
|
+
moveUpVisual() {
|
|
601
|
+
this.guard();
|
|
602
|
+
this.lib.editorViewMoveUpVisual(this.viewPtr);
|
|
603
|
+
}
|
|
604
|
+
moveDownVisual() {
|
|
605
|
+
this.guard();
|
|
606
|
+
this.lib.editorViewMoveDownVisual(this.viewPtr);
|
|
607
|
+
}
|
|
608
|
+
deleteSelectedText() {
|
|
609
|
+
this.guard();
|
|
610
|
+
this.lib.editorViewDeleteSelectedText(this.viewPtr);
|
|
611
|
+
}
|
|
612
|
+
setCursorByOffset(offset) {
|
|
613
|
+
this.guard();
|
|
614
|
+
this.lib.editorViewSetCursorByOffset(this.viewPtr, offset);
|
|
615
|
+
}
|
|
616
|
+
getNextWordBoundary() {
|
|
617
|
+
this.guard();
|
|
618
|
+
return this.lib.editorViewGetNextWordBoundary(this.viewPtr);
|
|
619
|
+
}
|
|
620
|
+
getPrevWordBoundary() {
|
|
621
|
+
this.guard();
|
|
622
|
+
return this.lib.editorViewGetPrevWordBoundary(this.viewPtr);
|
|
623
|
+
}
|
|
624
|
+
getEOL() {
|
|
625
|
+
this.guard();
|
|
626
|
+
return this.lib.editorViewGetEOL(this.viewPtr);
|
|
627
|
+
}
|
|
628
|
+
getLineInfo() {
|
|
629
|
+
this.guard();
|
|
630
|
+
const textBufferViewPtr = this.lib.editorViewGetTextBufferView(this.viewPtr);
|
|
631
|
+
return this.lib.textBufferViewGetLineInfo(textBufferViewPtr);
|
|
632
|
+
}
|
|
633
|
+
getLogicalLineInfo() {
|
|
634
|
+
this.guard();
|
|
635
|
+
const textBufferViewPtr = this.lib.editorViewGetTextBufferView(this.viewPtr);
|
|
636
|
+
return this.lib.textBufferViewGetLogicalLineInfo(textBufferViewPtr);
|
|
637
|
+
}
|
|
638
|
+
destroy() {
|
|
639
|
+
if (this._destroyed)
|
|
640
|
+
return;
|
|
641
|
+
this._destroyed = true;
|
|
642
|
+
this.lib.destroyEditorView(this.viewPtr);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
// src/syntax-style.ts
|
|
646
|
+
function convertThemeToStyles(theme) {
|
|
647
|
+
const flatStyles = {};
|
|
648
|
+
for (const tokenStyle of theme) {
|
|
649
|
+
const styleDefinition = {};
|
|
650
|
+
if (tokenStyle.style.foreground) {
|
|
651
|
+
styleDefinition.fg = parseColor(tokenStyle.style.foreground);
|
|
652
|
+
}
|
|
653
|
+
if (tokenStyle.style.background) {
|
|
654
|
+
styleDefinition.bg = parseColor(tokenStyle.style.background);
|
|
655
|
+
}
|
|
656
|
+
if (tokenStyle.style.bold !== undefined) {
|
|
657
|
+
styleDefinition.bold = tokenStyle.style.bold;
|
|
658
|
+
}
|
|
659
|
+
if (tokenStyle.style.italic !== undefined) {
|
|
660
|
+
styleDefinition.italic = tokenStyle.style.italic;
|
|
661
|
+
}
|
|
662
|
+
if (tokenStyle.style.underline !== undefined) {
|
|
663
|
+
styleDefinition.underline = tokenStyle.style.underline;
|
|
664
|
+
}
|
|
665
|
+
if (tokenStyle.style.dim !== undefined) {
|
|
666
|
+
styleDefinition.dim = tokenStyle.style.dim;
|
|
667
|
+
}
|
|
668
|
+
for (const scope of tokenStyle.scope) {
|
|
669
|
+
flatStyles[scope] = styleDefinition;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
return flatStyles;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
class SyntaxStyle {
|
|
676
|
+
lib;
|
|
677
|
+
stylePtr;
|
|
678
|
+
_destroyed = false;
|
|
679
|
+
nameCache = new Map;
|
|
680
|
+
styleDefs = new Map;
|
|
681
|
+
mergedCache = new Map;
|
|
682
|
+
constructor(lib, ptr) {
|
|
683
|
+
this.lib = lib;
|
|
684
|
+
this.stylePtr = ptr;
|
|
685
|
+
}
|
|
686
|
+
static create() {
|
|
687
|
+
const lib = resolveRenderLib();
|
|
688
|
+
const ptr = lib.createSyntaxStyle();
|
|
689
|
+
return new SyntaxStyle(lib, ptr);
|
|
690
|
+
}
|
|
691
|
+
static fromTheme(theme) {
|
|
692
|
+
const style = SyntaxStyle.create();
|
|
693
|
+
const flatStyles = convertThemeToStyles(theme);
|
|
694
|
+
for (const [name, styleDef] of Object.entries(flatStyles)) {
|
|
695
|
+
style.registerStyle(name, styleDef);
|
|
696
|
+
}
|
|
697
|
+
return style;
|
|
698
|
+
}
|
|
699
|
+
static fromStyles(styles) {
|
|
700
|
+
const style = SyntaxStyle.create();
|
|
701
|
+
for (const [name, styleDef] of Object.entries(styles)) {
|
|
702
|
+
style.registerStyle(name, styleDef);
|
|
703
|
+
}
|
|
704
|
+
return style;
|
|
705
|
+
}
|
|
706
|
+
guard() {
|
|
707
|
+
if (this._destroyed)
|
|
708
|
+
throw new Error("NativeSyntaxStyle is destroyed");
|
|
709
|
+
}
|
|
710
|
+
registerStyle(name, style) {
|
|
711
|
+
this.guard();
|
|
712
|
+
const attributes = createTextAttributes({
|
|
713
|
+
bold: style.bold,
|
|
714
|
+
italic: style.italic,
|
|
715
|
+
underline: style.underline,
|
|
716
|
+
dim: style.dim
|
|
717
|
+
});
|
|
718
|
+
const id = this.lib.syntaxStyleRegister(this.stylePtr, name, style.fg || null, style.bg || null, attributes);
|
|
719
|
+
this.nameCache.set(name, id);
|
|
720
|
+
this.styleDefs.set(name, style);
|
|
721
|
+
return id;
|
|
722
|
+
}
|
|
723
|
+
resolveStyleId(name) {
|
|
724
|
+
this.guard();
|
|
725
|
+
const cached = this.nameCache.get(name);
|
|
726
|
+
if (cached !== undefined)
|
|
727
|
+
return cached;
|
|
728
|
+
const id = this.lib.syntaxStyleResolveByName(this.stylePtr, name);
|
|
729
|
+
if (id !== null) {
|
|
730
|
+
this.nameCache.set(name, id);
|
|
731
|
+
}
|
|
732
|
+
return id;
|
|
733
|
+
}
|
|
734
|
+
getStyleId(name) {
|
|
735
|
+
this.guard();
|
|
736
|
+
const id = this.resolveStyleId(name);
|
|
737
|
+
if (id !== null)
|
|
738
|
+
return id;
|
|
739
|
+
if (name.includes(".")) {
|
|
740
|
+
const baseName = name.split(".")[0];
|
|
741
|
+
return this.resolveStyleId(baseName);
|
|
742
|
+
}
|
|
743
|
+
return null;
|
|
744
|
+
}
|
|
745
|
+
get ptr() {
|
|
746
|
+
this.guard();
|
|
747
|
+
return this.stylePtr;
|
|
748
|
+
}
|
|
749
|
+
getStyleCount() {
|
|
750
|
+
this.guard();
|
|
751
|
+
return this.lib.syntaxStyleGetStyleCount(this.stylePtr);
|
|
752
|
+
}
|
|
753
|
+
clearNameCache() {
|
|
754
|
+
this.nameCache.clear();
|
|
755
|
+
}
|
|
756
|
+
getStyle(name) {
|
|
757
|
+
this.guard();
|
|
758
|
+
if (Object.prototype.hasOwnProperty.call(this.styleDefs, name)) {
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
const style = this.styleDefs.get(name);
|
|
762
|
+
if (style)
|
|
763
|
+
return style;
|
|
764
|
+
if (name.includes(".")) {
|
|
765
|
+
const baseName = name.split(".")[0];
|
|
766
|
+
if (Object.prototype.hasOwnProperty.call(this.styleDefs, baseName)) {
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
return this.styleDefs.get(baseName);
|
|
770
|
+
}
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
mergeStyles(...styleNames) {
|
|
774
|
+
this.guard();
|
|
775
|
+
const cacheKey = styleNames.join(":");
|
|
776
|
+
const cached = this.mergedCache.get(cacheKey);
|
|
777
|
+
if (cached)
|
|
778
|
+
return cached;
|
|
779
|
+
const styleDefinition = {};
|
|
780
|
+
for (const name of styleNames) {
|
|
781
|
+
const style = this.getStyle(name);
|
|
782
|
+
if (!style)
|
|
783
|
+
continue;
|
|
784
|
+
if (style.fg)
|
|
785
|
+
styleDefinition.fg = style.fg;
|
|
786
|
+
if (style.bg)
|
|
787
|
+
styleDefinition.bg = style.bg;
|
|
788
|
+
if (style.bold !== undefined)
|
|
789
|
+
styleDefinition.bold = style.bold;
|
|
790
|
+
if (style.italic !== undefined)
|
|
791
|
+
styleDefinition.italic = style.italic;
|
|
792
|
+
if (style.underline !== undefined)
|
|
793
|
+
styleDefinition.underline = style.underline;
|
|
794
|
+
if (style.dim !== undefined)
|
|
795
|
+
styleDefinition.dim = style.dim;
|
|
796
|
+
}
|
|
797
|
+
const attributes = createTextAttributes({
|
|
798
|
+
bold: styleDefinition.bold,
|
|
799
|
+
italic: styleDefinition.italic,
|
|
800
|
+
underline: styleDefinition.underline,
|
|
801
|
+
dim: styleDefinition.dim
|
|
802
|
+
});
|
|
803
|
+
const merged = {
|
|
804
|
+
fg: styleDefinition.fg,
|
|
805
|
+
bg: styleDefinition.bg,
|
|
806
|
+
attributes
|
|
807
|
+
};
|
|
808
|
+
this.mergedCache.set(cacheKey, merged);
|
|
809
|
+
return merged;
|
|
810
|
+
}
|
|
811
|
+
clearCache() {
|
|
812
|
+
this.guard();
|
|
813
|
+
this.mergedCache.clear();
|
|
814
|
+
}
|
|
815
|
+
getCacheSize() {
|
|
816
|
+
this.guard();
|
|
817
|
+
return this.mergedCache.size;
|
|
818
|
+
}
|
|
819
|
+
destroy() {
|
|
820
|
+
if (this._destroyed)
|
|
821
|
+
return;
|
|
822
|
+
this._destroyed = true;
|
|
823
|
+
this.nameCache.clear();
|
|
824
|
+
this.styleDefs.clear();
|
|
825
|
+
this.mergedCache.clear();
|
|
826
|
+
this.lib.destroySyntaxStyle(this.stylePtr);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
137
829
|
// src/post/filters.ts
|
|
138
830
|
function applyScanlines(buffer, strength = 0.8, step = 2) {
|
|
139
831
|
const width = buffer.width;
|
|
@@ -1618,10 +2310,10 @@ class TextBufferRenderable extends Renderable {
|
|
|
1618
2310
|
_defaultAttributes;
|
|
1619
2311
|
_selectionBg;
|
|
1620
2312
|
_selectionFg;
|
|
1621
|
-
_wrap = false;
|
|
1622
2313
|
_wrapMode = "word";
|
|
1623
2314
|
lastLocalSelection = null;
|
|
1624
2315
|
textBuffer;
|
|
2316
|
+
textBufferView;
|
|
1625
2317
|
_lineInfo = { lineStarts: [], lineWidths: [], maxLineWidth: 0 };
|
|
1626
2318
|
_defaultOptions = {
|
|
1627
2319
|
fg: RGBA.fromValues(1, 1, 1, 1),
|
|
@@ -1630,7 +2322,6 @@ class TextBufferRenderable extends Renderable {
|
|
|
1630
2322
|
selectionFg: undefined,
|
|
1631
2323
|
selectable: true,
|
|
1632
2324
|
attributes: 0,
|
|
1633
|
-
wrap: true,
|
|
1634
2325
|
wrapMode: "word"
|
|
1635
2326
|
};
|
|
1636
2327
|
constructor(ctx, options) {
|
|
@@ -1641,15 +2332,17 @@ class TextBufferRenderable extends Renderable {
|
|
|
1641
2332
|
this._selectionBg = options.selectionBg ? parseColor(options.selectionBg) : this._defaultOptions.selectionBg;
|
|
1642
2333
|
this._selectionFg = options.selectionFg ? parseColor(options.selectionFg) : this._defaultOptions.selectionFg;
|
|
1643
2334
|
this.selectable = options.selectable ?? this._defaultOptions.selectable;
|
|
1644
|
-
this._wrap = options.wrap ?? this._defaultOptions.wrap;
|
|
1645
2335
|
this._wrapMode = options.wrapMode ?? this._defaultOptions.wrapMode;
|
|
1646
2336
|
this.textBuffer = TextBuffer.create(this._ctx.widthMethod);
|
|
1647
|
-
this.
|
|
2337
|
+
this.textBufferView = TextBufferView.create(this.textBuffer);
|
|
2338
|
+
const style = SyntaxStyle.create();
|
|
2339
|
+
this.textBuffer.setSyntaxStyle(style);
|
|
2340
|
+
this.textBufferView.setWrapMode(this._wrapMode);
|
|
1648
2341
|
this.setupMeasureFunc();
|
|
1649
2342
|
this.textBuffer.setDefaultFg(this._defaultFg);
|
|
1650
2343
|
this.textBuffer.setDefaultBg(this._defaultBg);
|
|
1651
2344
|
this.textBuffer.setDefaultAttributes(this._defaultAttributes);
|
|
1652
|
-
if (this.
|
|
2345
|
+
if (this._wrapMode !== "none" && this.width > 0) {
|
|
1653
2346
|
this.updateWrapWidth(this.width);
|
|
1654
2347
|
}
|
|
1655
2348
|
this.updateTextInfo();
|
|
@@ -1721,27 +2414,22 @@ class TextBufferRenderable extends Renderable {
|
|
|
1721
2414
|
this.requestRender();
|
|
1722
2415
|
}
|
|
1723
2416
|
}
|
|
1724
|
-
get wrap() {
|
|
1725
|
-
return this._wrap;
|
|
1726
|
-
}
|
|
1727
|
-
set wrap(value) {
|
|
1728
|
-
if (this._wrap !== value) {
|
|
1729
|
-
this._wrap = value;
|
|
1730
|
-
this.textBuffer.setWrapWidth(this._wrap ? this.width : null);
|
|
1731
|
-
this.requestRender();
|
|
1732
|
-
}
|
|
1733
|
-
}
|
|
1734
2417
|
get wrapMode() {
|
|
1735
2418
|
return this._wrapMode;
|
|
1736
2419
|
}
|
|
1737
2420
|
set wrapMode(value) {
|
|
1738
2421
|
if (this._wrapMode !== value) {
|
|
1739
2422
|
this._wrapMode = value;
|
|
1740
|
-
this.
|
|
2423
|
+
this.textBufferView.setWrapMode(this._wrapMode);
|
|
2424
|
+
if (value !== "none" && this.width > 0) {
|
|
2425
|
+
this.updateWrapWidth(this.width);
|
|
2426
|
+
}
|
|
2427
|
+
this.yogaNode.markDirty();
|
|
1741
2428
|
this.requestRender();
|
|
1742
2429
|
}
|
|
1743
2430
|
}
|
|
1744
2431
|
onResize(width, height) {
|
|
2432
|
+
this.textBufferView.setViewportSize(width, height);
|
|
1745
2433
|
if (this.lastLocalSelection) {
|
|
1746
2434
|
const changed = this.updateLocalSelection(this.lastLocalSelection);
|
|
1747
2435
|
if (changed) {
|
|
@@ -1757,10 +2445,10 @@ class TextBufferRenderable extends Renderable {
|
|
|
1757
2445
|
}
|
|
1758
2446
|
updateLocalSelection(localSelection) {
|
|
1759
2447
|
if (!localSelection?.isActive) {
|
|
1760
|
-
this.
|
|
2448
|
+
this.textBufferView.resetLocalSelection();
|
|
1761
2449
|
return true;
|
|
1762
2450
|
}
|
|
1763
|
-
return this.
|
|
2451
|
+
return this.textBufferView.setLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg);
|
|
1764
2452
|
}
|
|
1765
2453
|
updateTextInfo() {
|
|
1766
2454
|
if (this.lastLocalSelection) {
|
|
@@ -1773,18 +2461,18 @@ class TextBufferRenderable extends Renderable {
|
|
|
1773
2461
|
this.requestRender();
|
|
1774
2462
|
}
|
|
1775
2463
|
updateLineInfo() {
|
|
1776
|
-
const lineInfo = this.
|
|
2464
|
+
const lineInfo = this.textBufferView.logicalLineInfo;
|
|
1777
2465
|
this._lineInfo.lineStarts = lineInfo.lineStarts;
|
|
1778
2466
|
this._lineInfo.lineWidths = lineInfo.lineWidths;
|
|
1779
2467
|
this._lineInfo.maxLineWidth = lineInfo.maxLineWidth;
|
|
1780
2468
|
}
|
|
1781
2469
|
updateWrapWidth(width) {
|
|
1782
|
-
this.
|
|
2470
|
+
this.textBufferView.setWrapWidth(width);
|
|
1783
2471
|
this.updateLineInfo();
|
|
1784
2472
|
}
|
|
1785
2473
|
setupMeasureFunc() {
|
|
1786
2474
|
const measureFunc = (width, widthMode, height, heightMode) => {
|
|
1787
|
-
if (this.
|
|
2475
|
+
if (this._wrapMode !== "none" && this.width !== width) {
|
|
1788
2476
|
this.updateWrapWidth(width);
|
|
1789
2477
|
} else {
|
|
1790
2478
|
this.updateLineInfo();
|
|
@@ -1798,18 +2486,6 @@ class TextBufferRenderable extends Renderable {
|
|
|
1798
2486
|
};
|
|
1799
2487
|
this.yogaNode.setMeasureFunc(measureFunc);
|
|
1800
2488
|
}
|
|
1801
|
-
insertChunk(chunk, index) {
|
|
1802
|
-
this.textBuffer.insertChunkGroup(index ?? this.textBuffer.chunkGroupCount, chunk.text, chunk.fg, chunk.bg, chunk.attributes);
|
|
1803
|
-
this.updateTextInfo();
|
|
1804
|
-
}
|
|
1805
|
-
removeChunk(index) {
|
|
1806
|
-
this.textBuffer.removeChunkGroup(index);
|
|
1807
|
-
this.updateTextInfo();
|
|
1808
|
-
}
|
|
1809
|
-
replaceChunk(index, chunk) {
|
|
1810
|
-
this.textBuffer.replaceChunkGroup(index, chunk.text, chunk.fg, chunk.bg, chunk.attributes);
|
|
1811
|
-
this.updateTextInfo();
|
|
1812
|
-
}
|
|
1813
2489
|
shouldStartSelection(x, y) {
|
|
1814
2490
|
if (!this.selectable)
|
|
1815
2491
|
return false;
|
|
@@ -1827,13 +2503,13 @@ class TextBufferRenderable extends Renderable {
|
|
|
1827
2503
|
return this.hasSelection();
|
|
1828
2504
|
}
|
|
1829
2505
|
getSelectedText() {
|
|
1830
|
-
return this.
|
|
2506
|
+
return this.textBufferView.getSelectedText();
|
|
1831
2507
|
}
|
|
1832
2508
|
hasSelection() {
|
|
1833
|
-
return this.
|
|
2509
|
+
return this.textBufferView.hasSelection();
|
|
1834
2510
|
}
|
|
1835
2511
|
getSelection() {
|
|
1836
|
-
return this.
|
|
2512
|
+
return this.textBufferView.getSelection();
|
|
1837
2513
|
}
|
|
1838
2514
|
render(buffer, deltaTime) {
|
|
1839
2515
|
if (!this.visible)
|
|
@@ -1844,16 +2520,11 @@ class TextBufferRenderable extends Renderable {
|
|
|
1844
2520
|
}
|
|
1845
2521
|
renderSelf(buffer) {
|
|
1846
2522
|
if (this.textBuffer.ptr) {
|
|
1847
|
-
|
|
1848
|
-
x: this.x,
|
|
1849
|
-
y: this.y,
|
|
1850
|
-
width: this.width,
|
|
1851
|
-
height: this.height
|
|
1852
|
-
};
|
|
1853
|
-
buffer.drawTextBuffer(this.textBuffer, this.x, this.y, clipRect);
|
|
2523
|
+
buffer.drawTextBuffer(this.textBufferView, this.x, this.y);
|
|
1854
2524
|
}
|
|
1855
2525
|
}
|
|
1856
2526
|
destroy() {
|
|
2527
|
+
this.textBufferView.destroy();
|
|
1857
2528
|
this.textBuffer.destroy();
|
|
1858
2529
|
super.destroy();
|
|
1859
2530
|
}
|
|
@@ -4264,24 +4935,6 @@ class TextRenderable extends TextBufferRenderable {
|
|
|
4264
4935
|
this.updateTextInfo();
|
|
4265
4936
|
}
|
|
4266
4937
|
}
|
|
4267
|
-
insertChunk(chunk, index) {
|
|
4268
|
-
super.insertChunk(chunk, index);
|
|
4269
|
-
this.clearChunks(this._text);
|
|
4270
|
-
}
|
|
4271
|
-
removeChunkByObject(chunk) {
|
|
4272
|
-
const index = this._text.chunks.indexOf(chunk);
|
|
4273
|
-
if (index === -1)
|
|
4274
|
-
return;
|
|
4275
|
-
super.removeChunk(index);
|
|
4276
|
-
this.clearChunks(this._text);
|
|
4277
|
-
}
|
|
4278
|
-
replaceChunkByObject(chunk, oldChunk) {
|
|
4279
|
-
const index = this._text.chunks.indexOf(oldChunk);
|
|
4280
|
-
if (index === -1)
|
|
4281
|
-
return;
|
|
4282
|
-
super.replaceChunk(index, chunk);
|
|
4283
|
-
this.clearChunks(this._text);
|
|
4284
|
-
}
|
|
4285
4938
|
updateTextFromNodes() {
|
|
4286
4939
|
if (this.rootTextNode.isDirty && !this._hasManualStyledText) {
|
|
4287
4940
|
const chunks = this.rootTextNode.gatherWithInheritedStyle({
|
|
@@ -4332,6 +4985,789 @@ class TextRenderable extends TextBufferRenderable {
|
|
|
4332
4985
|
super.destroy();
|
|
4333
4986
|
}
|
|
4334
4987
|
}
|
|
4988
|
+
// src/renderables/EditBufferRenderable.ts
|
|
4989
|
+
class EditBufferRenderable extends Renderable {
|
|
4990
|
+
_focusable = true;
|
|
4991
|
+
selectable = true;
|
|
4992
|
+
_textColor;
|
|
4993
|
+
_backgroundColor;
|
|
4994
|
+
_defaultAttributes;
|
|
4995
|
+
_selectionBg;
|
|
4996
|
+
_selectionFg;
|
|
4997
|
+
_wrapMode = "word";
|
|
4998
|
+
_scrollMargin = 0.2;
|
|
4999
|
+
_showCursor = true;
|
|
5000
|
+
_cursorColor;
|
|
5001
|
+
lastLocalSelection = null;
|
|
5002
|
+
_cursorChangeListener = undefined;
|
|
5003
|
+
_contentChangeListener = undefined;
|
|
5004
|
+
editBuffer;
|
|
5005
|
+
editorView;
|
|
5006
|
+
_defaultOptions = {
|
|
5007
|
+
textColor: RGBA.fromValues(1, 1, 1, 1),
|
|
5008
|
+
backgroundColor: "transparent",
|
|
5009
|
+
selectionBg: undefined,
|
|
5010
|
+
selectionFg: undefined,
|
|
5011
|
+
selectable: true,
|
|
5012
|
+
attributes: 0,
|
|
5013
|
+
wrapMode: "word",
|
|
5014
|
+
scrollMargin: 0.2,
|
|
5015
|
+
showCursor: true,
|
|
5016
|
+
cursorColor: RGBA.fromValues(1, 1, 1, 1)
|
|
5017
|
+
};
|
|
5018
|
+
constructor(ctx, options) {
|
|
5019
|
+
super(ctx, options);
|
|
5020
|
+
this._textColor = parseColor(options.textColor ?? this._defaultOptions.textColor);
|
|
5021
|
+
this._backgroundColor = parseColor(options.backgroundColor ?? this._defaultOptions.backgroundColor);
|
|
5022
|
+
this._defaultAttributes = options.attributes ?? this._defaultOptions.attributes;
|
|
5023
|
+
this._selectionBg = options.selectionBg ? parseColor(options.selectionBg) : this._defaultOptions.selectionBg;
|
|
5024
|
+
this._selectionFg = options.selectionFg ? parseColor(options.selectionFg) : this._defaultOptions.selectionFg;
|
|
5025
|
+
this.selectable = options.selectable ?? this._defaultOptions.selectable;
|
|
5026
|
+
this._wrapMode = options.wrapMode ?? this._defaultOptions.wrapMode;
|
|
5027
|
+
this._scrollMargin = options.scrollMargin ?? this._defaultOptions.scrollMargin;
|
|
5028
|
+
this._showCursor = options.showCursor ?? this._defaultOptions.showCursor;
|
|
5029
|
+
this._cursorColor = parseColor(options.cursorColor ?? this._defaultOptions.cursorColor);
|
|
5030
|
+
this.editBuffer = EditBuffer.create(this._ctx.widthMethod);
|
|
5031
|
+
this.editorView = EditorView.create(this.editBuffer, this.width || 80, this.height || 24);
|
|
5032
|
+
this.editorView.setWrapMode(this._wrapMode);
|
|
5033
|
+
this.editorView.setScrollMargin(this._scrollMargin);
|
|
5034
|
+
this.editBuffer.setDefaultFg(this._textColor);
|
|
5035
|
+
this.editBuffer.setDefaultBg(this._backgroundColor);
|
|
5036
|
+
this.editBuffer.setDefaultAttributes(this._defaultAttributes);
|
|
5037
|
+
if (options.syntaxStyle) {
|
|
5038
|
+
this.editBuffer.setSyntaxStyle(options.syntaxStyle);
|
|
5039
|
+
}
|
|
5040
|
+
this.setupMeasureFunc();
|
|
5041
|
+
this.setupEventListeners(options);
|
|
5042
|
+
}
|
|
5043
|
+
setupEventListeners(options) {
|
|
5044
|
+
this._cursorChangeListener = options.onCursorChange;
|
|
5045
|
+
this._contentChangeListener = options.onContentChange;
|
|
5046
|
+
this.editBuffer.on("cursor-changed", () => {
|
|
5047
|
+
if (this._cursorChangeListener) {
|
|
5048
|
+
const cursor = this.editBuffer.getCursorPosition();
|
|
5049
|
+
this._cursorChangeListener({
|
|
5050
|
+
line: cursor.line,
|
|
5051
|
+
visualColumn: cursor.visualColumn
|
|
5052
|
+
});
|
|
5053
|
+
}
|
|
5054
|
+
});
|
|
5055
|
+
this.editBuffer.on("content-changed", () => {
|
|
5056
|
+
this.yogaNode.markDirty();
|
|
5057
|
+
this.requestRender();
|
|
5058
|
+
if (this._contentChangeListener) {
|
|
5059
|
+
this._contentChangeListener({});
|
|
5060
|
+
}
|
|
5061
|
+
});
|
|
5062
|
+
}
|
|
5063
|
+
get plainText() {
|
|
5064
|
+
return this.editBuffer.getText();
|
|
5065
|
+
}
|
|
5066
|
+
get cursor() {
|
|
5067
|
+
return this.editBuffer.getCursorPosition();
|
|
5068
|
+
}
|
|
5069
|
+
get visualCursor() {
|
|
5070
|
+
return this.editorView.getVisualCursor();
|
|
5071
|
+
}
|
|
5072
|
+
get cursorOffset() {
|
|
5073
|
+
return this.editorView.getVisualCursor().offset;
|
|
5074
|
+
}
|
|
5075
|
+
set cursorOffset(offset) {
|
|
5076
|
+
this.editorView.setCursorByOffset(offset);
|
|
5077
|
+
this.requestRender();
|
|
5078
|
+
}
|
|
5079
|
+
get textColor() {
|
|
5080
|
+
return this._textColor;
|
|
5081
|
+
}
|
|
5082
|
+
set textColor(value) {
|
|
5083
|
+
const newColor = parseColor(value ?? this._defaultOptions.textColor);
|
|
5084
|
+
if (this._textColor !== newColor) {
|
|
5085
|
+
this._textColor = newColor;
|
|
5086
|
+
this.editBuffer.setDefaultFg(newColor);
|
|
5087
|
+
this.requestRender();
|
|
5088
|
+
}
|
|
5089
|
+
}
|
|
5090
|
+
get selectionBg() {
|
|
5091
|
+
return this._selectionBg;
|
|
5092
|
+
}
|
|
5093
|
+
set selectionBg(value) {
|
|
5094
|
+
const newColor = value ? parseColor(value) : this._defaultOptions.selectionBg;
|
|
5095
|
+
if (this._selectionBg !== newColor) {
|
|
5096
|
+
this._selectionBg = newColor;
|
|
5097
|
+
if (this.lastLocalSelection) {
|
|
5098
|
+
this.updateLocalSelection(this.lastLocalSelection);
|
|
5099
|
+
}
|
|
5100
|
+
this.requestRender();
|
|
5101
|
+
}
|
|
5102
|
+
}
|
|
5103
|
+
get selectionFg() {
|
|
5104
|
+
return this._selectionFg;
|
|
5105
|
+
}
|
|
5106
|
+
set selectionFg(value) {
|
|
5107
|
+
const newColor = value ? parseColor(value) : this._defaultOptions.selectionFg;
|
|
5108
|
+
if (this._selectionFg !== newColor) {
|
|
5109
|
+
this._selectionFg = newColor;
|
|
5110
|
+
if (this.lastLocalSelection) {
|
|
5111
|
+
this.updateLocalSelection(this.lastLocalSelection);
|
|
5112
|
+
}
|
|
5113
|
+
this.requestRender();
|
|
5114
|
+
}
|
|
5115
|
+
}
|
|
5116
|
+
get backgroundColor() {
|
|
5117
|
+
return this._backgroundColor;
|
|
5118
|
+
}
|
|
5119
|
+
set backgroundColor(value) {
|
|
5120
|
+
const newColor = parseColor(value ?? this._defaultOptions.backgroundColor);
|
|
5121
|
+
if (this._backgroundColor !== newColor) {
|
|
5122
|
+
this._backgroundColor = newColor;
|
|
5123
|
+
this.editBuffer.setDefaultBg(newColor);
|
|
5124
|
+
this.requestRender();
|
|
5125
|
+
}
|
|
5126
|
+
}
|
|
5127
|
+
get attributes() {
|
|
5128
|
+
return this._defaultAttributes;
|
|
5129
|
+
}
|
|
5130
|
+
set attributes(value) {
|
|
5131
|
+
if (this._defaultAttributes !== value) {
|
|
5132
|
+
this._defaultAttributes = value;
|
|
5133
|
+
this.editBuffer.setDefaultAttributes(value);
|
|
5134
|
+
this.requestRender();
|
|
5135
|
+
}
|
|
5136
|
+
}
|
|
5137
|
+
get wrapMode() {
|
|
5138
|
+
return this._wrapMode;
|
|
5139
|
+
}
|
|
5140
|
+
set wrapMode(value) {
|
|
5141
|
+
if (this._wrapMode !== value) {
|
|
5142
|
+
this._wrapMode = value;
|
|
5143
|
+
this.editorView.setWrapMode(value);
|
|
5144
|
+
this.yogaNode.markDirty();
|
|
5145
|
+
this.requestRender();
|
|
5146
|
+
}
|
|
5147
|
+
}
|
|
5148
|
+
get showCursor() {
|
|
5149
|
+
return this._showCursor;
|
|
5150
|
+
}
|
|
5151
|
+
set showCursor(value) {
|
|
5152
|
+
if (this._showCursor !== value) {
|
|
5153
|
+
this._showCursor = value;
|
|
5154
|
+
this.requestRender();
|
|
5155
|
+
}
|
|
5156
|
+
}
|
|
5157
|
+
get cursorColor() {
|
|
5158
|
+
return this._cursorColor;
|
|
5159
|
+
}
|
|
5160
|
+
set cursorColor(value) {
|
|
5161
|
+
const newColor = parseColor(value);
|
|
5162
|
+
if (this._cursorColor !== newColor) {
|
|
5163
|
+
this._cursorColor = newColor;
|
|
5164
|
+
this.requestRender();
|
|
5165
|
+
}
|
|
5166
|
+
}
|
|
5167
|
+
onResize(width, height) {
|
|
5168
|
+
this.editorView.setViewportSize(width, height);
|
|
5169
|
+
if (this.lastLocalSelection) {
|
|
5170
|
+
const changed = this.updateLocalSelection(this.lastLocalSelection);
|
|
5171
|
+
if (changed) {
|
|
5172
|
+
this.requestRender();
|
|
5173
|
+
}
|
|
5174
|
+
}
|
|
5175
|
+
}
|
|
5176
|
+
refreshLocalSelection() {
|
|
5177
|
+
if (this.lastLocalSelection) {
|
|
5178
|
+
return this.updateLocalSelection(this.lastLocalSelection);
|
|
5179
|
+
}
|
|
5180
|
+
return false;
|
|
5181
|
+
}
|
|
5182
|
+
updateLocalSelection(localSelection) {
|
|
5183
|
+
if (!localSelection?.isActive) {
|
|
5184
|
+
this.editorView.resetLocalSelection();
|
|
5185
|
+
return true;
|
|
5186
|
+
}
|
|
5187
|
+
return this.editorView.setLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg);
|
|
5188
|
+
}
|
|
5189
|
+
shouldStartSelection(x, y) {
|
|
5190
|
+
if (!this.selectable)
|
|
5191
|
+
return false;
|
|
5192
|
+
const localX = x - this.x;
|
|
5193
|
+
const localY = y - this.y;
|
|
5194
|
+
return localX >= 0 && localX < this.width && localY >= 0 && localY < this.height;
|
|
5195
|
+
}
|
|
5196
|
+
onSelectionChanged(selection) {
|
|
5197
|
+
const localSelection = convertGlobalToLocalSelection(selection, this.x, this.y);
|
|
5198
|
+
this.lastLocalSelection = localSelection;
|
|
5199
|
+
const changed = this.updateLocalSelection(localSelection);
|
|
5200
|
+
if (changed) {
|
|
5201
|
+
this.requestRender();
|
|
5202
|
+
}
|
|
5203
|
+
return this.hasSelection();
|
|
5204
|
+
}
|
|
5205
|
+
getSelectedText() {
|
|
5206
|
+
return this.editorView.getSelectedText();
|
|
5207
|
+
}
|
|
5208
|
+
hasSelection() {
|
|
5209
|
+
return this.editorView.hasSelection();
|
|
5210
|
+
}
|
|
5211
|
+
getSelection() {
|
|
5212
|
+
return this.editorView.getSelection();
|
|
5213
|
+
}
|
|
5214
|
+
setupMeasureFunc() {
|
|
5215
|
+
const measureFunc = (width, widthMode, height, heightMode) => {
|
|
5216
|
+
if (this._wrapMode !== "none" && this.width !== width) {
|
|
5217
|
+
this.editorView.setViewportSize(width, height);
|
|
5218
|
+
} else {
|
|
5219
|
+
this.editorView.setViewportSize(width, height);
|
|
5220
|
+
}
|
|
5221
|
+
const lineInfo = this.editorView.getLogicalLineInfo();
|
|
5222
|
+
const measuredWidth = lineInfo.maxLineWidth;
|
|
5223
|
+
const measuredHeight = lineInfo.lineStarts.length;
|
|
5224
|
+
return {
|
|
5225
|
+
width: Math.max(1, measuredWidth),
|
|
5226
|
+
height: Math.max(1, measuredHeight)
|
|
5227
|
+
};
|
|
5228
|
+
};
|
|
5229
|
+
this.yogaNode.setMeasureFunc(measureFunc);
|
|
5230
|
+
}
|
|
5231
|
+
render(buffer, deltaTime) {
|
|
5232
|
+
if (!this.visible)
|
|
5233
|
+
return;
|
|
5234
|
+
if (this.isDestroyed)
|
|
5235
|
+
return;
|
|
5236
|
+
this.markClean();
|
|
5237
|
+
this._ctx.addToHitGrid(this.x, this.y, this.width, this.height, this.num);
|
|
5238
|
+
this.renderSelf(buffer);
|
|
5239
|
+
this.renderCursor(buffer);
|
|
5240
|
+
}
|
|
5241
|
+
renderSelf(buffer) {
|
|
5242
|
+
buffer.drawEditorView(this.editorView, this.x, this.y);
|
|
5243
|
+
}
|
|
5244
|
+
renderCursor(buffer) {
|
|
5245
|
+
if (!this._showCursor || !this._focused)
|
|
5246
|
+
return;
|
|
5247
|
+
const visualCursor = this.editorView.getVisualCursor();
|
|
5248
|
+
const cursorX = this.x + visualCursor.visualCol + 1;
|
|
5249
|
+
const cursorY = this.y + visualCursor.visualRow + 1;
|
|
5250
|
+
this._ctx.setCursorPosition(cursorX, cursorY, true);
|
|
5251
|
+
this._ctx.setCursorColor(this._cursorColor);
|
|
5252
|
+
this._ctx.setCursorStyle("block", true);
|
|
5253
|
+
}
|
|
5254
|
+
focus() {
|
|
5255
|
+
super.focus();
|
|
5256
|
+
this._ctx.setCursorStyle("block", true);
|
|
5257
|
+
this._ctx.setCursorColor(this._cursorColor);
|
|
5258
|
+
this.requestRender();
|
|
5259
|
+
}
|
|
5260
|
+
blur() {
|
|
5261
|
+
super.blur();
|
|
5262
|
+
this._ctx.setCursorPosition(0, 0, false);
|
|
5263
|
+
this.requestRender();
|
|
5264
|
+
}
|
|
5265
|
+
onRemove() {
|
|
5266
|
+
if (this._focused) {
|
|
5267
|
+
this._ctx.setCursorPosition(0, 0, false);
|
|
5268
|
+
}
|
|
5269
|
+
}
|
|
5270
|
+
destroy() {
|
|
5271
|
+
if (this._focused) {
|
|
5272
|
+
this._ctx.setCursorPosition(0, 0, false);
|
|
5273
|
+
}
|
|
5274
|
+
super.destroy();
|
|
5275
|
+
this.editorView.destroy();
|
|
5276
|
+
this.editBuffer.destroy();
|
|
5277
|
+
}
|
|
5278
|
+
set onCursorChange(handler) {
|
|
5279
|
+
this._cursorChangeListener = handler;
|
|
5280
|
+
}
|
|
5281
|
+
get onCursorChange() {
|
|
5282
|
+
return this._cursorChangeListener;
|
|
5283
|
+
}
|
|
5284
|
+
set onContentChange(handler) {
|
|
5285
|
+
this._contentChangeListener = handler;
|
|
5286
|
+
}
|
|
5287
|
+
get onContentChange() {
|
|
5288
|
+
return this._contentChangeListener;
|
|
5289
|
+
}
|
|
5290
|
+
get syntaxStyle() {
|
|
5291
|
+
return this.editBuffer.getSyntaxStyle();
|
|
5292
|
+
}
|
|
5293
|
+
set syntaxStyle(style) {
|
|
5294
|
+
this.editBuffer.setSyntaxStyle(style);
|
|
5295
|
+
this.requestRender();
|
|
5296
|
+
}
|
|
5297
|
+
addHighlight(lineIdx, highlight) {
|
|
5298
|
+
this.editBuffer.addHighlight(lineIdx, highlight);
|
|
5299
|
+
this.requestRender();
|
|
5300
|
+
}
|
|
5301
|
+
addHighlightByCharRange(highlight) {
|
|
5302
|
+
this.editBuffer.addHighlightByCharRange(highlight);
|
|
5303
|
+
this.requestRender();
|
|
5304
|
+
}
|
|
5305
|
+
removeHighlightsByRef(hlRef) {
|
|
5306
|
+
this.editBuffer.removeHighlightsByRef(hlRef);
|
|
5307
|
+
this.requestRender();
|
|
5308
|
+
}
|
|
5309
|
+
clearLineHighlights(lineIdx) {
|
|
5310
|
+
this.editBuffer.clearLineHighlights(lineIdx);
|
|
5311
|
+
this.requestRender();
|
|
5312
|
+
}
|
|
5313
|
+
clearAllHighlights() {
|
|
5314
|
+
this.editBuffer.clearAllHighlights();
|
|
5315
|
+
this.requestRender();
|
|
5316
|
+
}
|
|
5317
|
+
getLineHighlights(lineIdx) {
|
|
5318
|
+
return this.editBuffer.getLineHighlights(lineIdx);
|
|
5319
|
+
}
|
|
5320
|
+
}
|
|
5321
|
+
|
|
5322
|
+
// src/lib/keymapping.ts
|
|
5323
|
+
function mergeKeyBindings(defaults, custom) {
|
|
5324
|
+
const map = new Map;
|
|
5325
|
+
for (const binding of defaults) {
|
|
5326
|
+
const key = getKeyBindingKey(binding);
|
|
5327
|
+
map.set(key, binding);
|
|
5328
|
+
}
|
|
5329
|
+
for (const binding of custom) {
|
|
5330
|
+
const key = getKeyBindingKey(binding);
|
|
5331
|
+
map.set(key, binding);
|
|
5332
|
+
}
|
|
5333
|
+
return Array.from(map.values());
|
|
5334
|
+
}
|
|
5335
|
+
function getKeyBindingKey(binding) {
|
|
5336
|
+
return `${binding.name}:${!!binding.ctrl}:${!!binding.shift}:${!!binding.meta}`;
|
|
5337
|
+
}
|
|
5338
|
+
function buildKeyBindingsMap(bindings) {
|
|
5339
|
+
const map = new Map;
|
|
5340
|
+
for (const binding of bindings) {
|
|
5341
|
+
const key = getKeyBindingKey(binding);
|
|
5342
|
+
map.set(key, binding.action);
|
|
5343
|
+
}
|
|
5344
|
+
return map;
|
|
5345
|
+
}
|
|
5346
|
+
|
|
5347
|
+
// src/renderables/Textarea.ts
|
|
5348
|
+
var defaultTextareaKeybindings = [
|
|
5349
|
+
{ name: "left", action: "move-left" },
|
|
5350
|
+
{ name: "right", action: "move-right" },
|
|
5351
|
+
{ name: "up", action: "move-up" },
|
|
5352
|
+
{ name: "down", action: "move-down" },
|
|
5353
|
+
{ name: "left", shift: true, action: "select-left" },
|
|
5354
|
+
{ name: "right", shift: true, action: "select-right" },
|
|
5355
|
+
{ name: "up", shift: true, action: "select-up" },
|
|
5356
|
+
{ name: "down", shift: true, action: "select-down" },
|
|
5357
|
+
{ name: "home", action: "line-home" },
|
|
5358
|
+
{ name: "end", action: "line-end" },
|
|
5359
|
+
{ name: "home", shift: true, action: "select-line-home" },
|
|
5360
|
+
{ name: "end", shift: true, action: "select-line-end" },
|
|
5361
|
+
{ name: "a", ctrl: true, action: "buffer-home" },
|
|
5362
|
+
{ name: "e", ctrl: true, action: "buffer-end" },
|
|
5363
|
+
{ name: "d", ctrl: true, action: "delete-line" },
|
|
5364
|
+
{ name: "k", ctrl: true, action: "delete-to-line-end" },
|
|
5365
|
+
{ name: "backspace", action: "backspace" },
|
|
5366
|
+
{ name: "delete", action: "delete" },
|
|
5367
|
+
{ name: "return", action: "newline" },
|
|
5368
|
+
{ name: "enter", action: "newline" },
|
|
5369
|
+
{ name: "z", ctrl: true, action: "undo" },
|
|
5370
|
+
{ name: "Z", ctrl: true, shift: true, action: "redo" },
|
|
5371
|
+
{ name: "y", ctrl: true, action: "redo" },
|
|
5372
|
+
{ name: "f", meta: true, action: "word-forward" },
|
|
5373
|
+
{ name: "b", meta: true, action: "word-backward" },
|
|
5374
|
+
{ name: "right", meta: true, action: "word-forward" },
|
|
5375
|
+
{ name: "left", meta: true, action: "word-backward" },
|
|
5376
|
+
{ name: "F", meta: true, shift: true, action: "select-word-forward" },
|
|
5377
|
+
{ name: "B", meta: true, shift: true, action: "select-word-backward" },
|
|
5378
|
+
{ name: "right", meta: true, shift: true, action: "select-word-forward" },
|
|
5379
|
+
{ name: "left", meta: true, shift: true, action: "select-word-backward" },
|
|
5380
|
+
{ name: "d", meta: true, action: "delete-word-forward" },
|
|
5381
|
+
{ name: "backspace", meta: true, action: "delete-word-backward" },
|
|
5382
|
+
{ name: "w", ctrl: true, action: "delete-word-backward" }
|
|
5383
|
+
];
|
|
5384
|
+
|
|
5385
|
+
class TextareaRenderable extends EditBufferRenderable {
|
|
5386
|
+
_placeholder;
|
|
5387
|
+
_unfocusedBackgroundColor;
|
|
5388
|
+
_unfocusedTextColor;
|
|
5389
|
+
_focusedBackgroundColor;
|
|
5390
|
+
_focusedTextColor;
|
|
5391
|
+
_placeholderColor;
|
|
5392
|
+
_keyBindingsMap;
|
|
5393
|
+
_actionHandlers;
|
|
5394
|
+
static defaults = {
|
|
5395
|
+
value: "",
|
|
5396
|
+
backgroundColor: "transparent",
|
|
5397
|
+
textColor: "#FFFFFF",
|
|
5398
|
+
focusedBackgroundColor: "transparent",
|
|
5399
|
+
focusedTextColor: "#FFFFFF",
|
|
5400
|
+
placeholder: null,
|
|
5401
|
+
placeholderColor: "#666666"
|
|
5402
|
+
};
|
|
5403
|
+
constructor(ctx, options) {
|
|
5404
|
+
const defaults = TextareaRenderable.defaults;
|
|
5405
|
+
const baseOptions = {
|
|
5406
|
+
...options,
|
|
5407
|
+
backgroundColor: options.backgroundColor || defaults.backgroundColor,
|
|
5408
|
+
textColor: options.textColor || defaults.textColor
|
|
5409
|
+
};
|
|
5410
|
+
super(ctx, baseOptions);
|
|
5411
|
+
this._unfocusedBackgroundColor = parseColor(options.backgroundColor || defaults.backgroundColor);
|
|
5412
|
+
this._unfocusedTextColor = parseColor(options.textColor || defaults.textColor);
|
|
5413
|
+
this._focusedBackgroundColor = parseColor(options.focusedBackgroundColor || options.backgroundColor || defaults.focusedBackgroundColor);
|
|
5414
|
+
this._focusedTextColor = parseColor(options.focusedTextColor || options.textColor || defaults.focusedTextColor);
|
|
5415
|
+
this._placeholder = options.placeholder ?? defaults.placeholder;
|
|
5416
|
+
this._placeholderColor = parseColor(options.placeholderColor || defaults.placeholderColor);
|
|
5417
|
+
const mergedBindings = mergeKeyBindings(defaultTextareaKeybindings, options.keyBindings || []);
|
|
5418
|
+
this._keyBindingsMap = buildKeyBindingsMap(mergedBindings);
|
|
5419
|
+
this._actionHandlers = this.buildActionHandlers();
|
|
5420
|
+
this.updateValue(options.value ?? defaults.value);
|
|
5421
|
+
this.updateColors();
|
|
5422
|
+
this.editBuffer.setPlaceholder(this._placeholder);
|
|
5423
|
+
this.editBuffer.setPlaceholderColor(this._placeholderColor);
|
|
5424
|
+
}
|
|
5425
|
+
buildActionHandlers() {
|
|
5426
|
+
return new Map([
|
|
5427
|
+
["move-left", () => this.moveCursorLeft()],
|
|
5428
|
+
["move-right", () => this.moveCursorRight()],
|
|
5429
|
+
["move-up", () => this.moveCursorUp()],
|
|
5430
|
+
["move-down", () => this.moveCursorDown()],
|
|
5431
|
+
["select-left", () => this.moveCursorLeft({ select: true })],
|
|
5432
|
+
["select-right", () => this.moveCursorRight({ select: true })],
|
|
5433
|
+
["select-up", () => this.moveCursorUp({ select: true })],
|
|
5434
|
+
["select-down", () => this.moveCursorDown({ select: true })],
|
|
5435
|
+
["line-home", () => this.gotoLineHome()],
|
|
5436
|
+
["line-end", () => this.gotoLineEnd()],
|
|
5437
|
+
["select-line-home", () => this.gotoLineHome({ select: true })],
|
|
5438
|
+
["select-line-end", () => this.gotoLineEnd({ select: true })],
|
|
5439
|
+
["buffer-home", () => this.gotoBufferHome()],
|
|
5440
|
+
["buffer-end", () => this.gotoBufferEnd()],
|
|
5441
|
+
["delete-line", () => this.deleteLine()],
|
|
5442
|
+
["delete-to-line-end", () => this.deleteToLineEnd()],
|
|
5443
|
+
["backspace", () => this.deleteCharBackward()],
|
|
5444
|
+
["delete", () => this.deleteChar()],
|
|
5445
|
+
["newline", () => this.newLine()],
|
|
5446
|
+
["undo", () => this.undo()],
|
|
5447
|
+
["redo", () => this.redo()],
|
|
5448
|
+
["word-forward", () => this.moveWordForward()],
|
|
5449
|
+
["word-backward", () => this.moveWordBackward()],
|
|
5450
|
+
["select-word-forward", () => this.moveWordForward({ select: true })],
|
|
5451
|
+
["select-word-backward", () => this.moveWordBackward({ select: true })],
|
|
5452
|
+
["delete-word-forward", () => this.deleteWordForward()],
|
|
5453
|
+
["delete-word-backward", () => this.deleteWordBackward()]
|
|
5454
|
+
]);
|
|
5455
|
+
}
|
|
5456
|
+
handlePaste(text) {
|
|
5457
|
+
this.insertText(text);
|
|
5458
|
+
}
|
|
5459
|
+
handleKeyPress(key) {
|
|
5460
|
+
const keyName = typeof key === "string" ? key : key.name;
|
|
5461
|
+
const keySequence = typeof key === "string" ? key : key.sequence;
|
|
5462
|
+
const keyCtrl = typeof key === "string" ? false : key.ctrl;
|
|
5463
|
+
const keyShift = typeof key === "string" ? false : key.shift;
|
|
5464
|
+
const keyMeta = typeof key === "string" ? false : key.meta;
|
|
5465
|
+
const bindingKey = getKeyBindingKey({
|
|
5466
|
+
name: keyName,
|
|
5467
|
+
ctrl: keyCtrl,
|
|
5468
|
+
shift: keyShift,
|
|
5469
|
+
meta: keyMeta,
|
|
5470
|
+
action: "move-left"
|
|
5471
|
+
});
|
|
5472
|
+
const action = this._keyBindingsMap.get(bindingKey);
|
|
5473
|
+
if (action) {
|
|
5474
|
+
const handler = this._actionHandlers.get(action);
|
|
5475
|
+
if (handler) {
|
|
5476
|
+
return handler();
|
|
5477
|
+
}
|
|
5478
|
+
}
|
|
5479
|
+
if (keySequence && !keyCtrl && !keyMeta) {
|
|
5480
|
+
const firstCharCode = keySequence.charCodeAt(0);
|
|
5481
|
+
if (firstCharCode < 32) {
|
|
5482
|
+
return false;
|
|
5483
|
+
}
|
|
5484
|
+
if (firstCharCode === 127) {
|
|
5485
|
+
return false;
|
|
5486
|
+
}
|
|
5487
|
+
this.insertText(keySequence);
|
|
5488
|
+
return true;
|
|
5489
|
+
}
|
|
5490
|
+
return false;
|
|
5491
|
+
}
|
|
5492
|
+
get value() {
|
|
5493
|
+
return this.editBuffer.getText();
|
|
5494
|
+
}
|
|
5495
|
+
set value(value) {
|
|
5496
|
+
this.updateValue(value);
|
|
5497
|
+
}
|
|
5498
|
+
updateValue(value) {
|
|
5499
|
+
this.editBuffer.setText(value, { history: false });
|
|
5500
|
+
this.yogaNode.markDirty();
|
|
5501
|
+
this.requestRender();
|
|
5502
|
+
}
|
|
5503
|
+
updateColors() {
|
|
5504
|
+
const effectiveBg = this._focused ? this._focusedBackgroundColor : this._unfocusedBackgroundColor;
|
|
5505
|
+
const effectiveFg = this._focused ? this._focusedTextColor : this._unfocusedTextColor;
|
|
5506
|
+
super.backgroundColor = effectiveBg;
|
|
5507
|
+
super.textColor = effectiveFg;
|
|
5508
|
+
}
|
|
5509
|
+
insertChar(char) {
|
|
5510
|
+
if (this.hasSelection()) {
|
|
5511
|
+
this.deleteSelectedText();
|
|
5512
|
+
}
|
|
5513
|
+
this.editBuffer.insertChar(char);
|
|
5514
|
+
this.requestRender();
|
|
5515
|
+
}
|
|
5516
|
+
insertText(text) {
|
|
5517
|
+
if (this.hasSelection()) {
|
|
5518
|
+
this.deleteSelectedText();
|
|
5519
|
+
}
|
|
5520
|
+
this.editBuffer.insertText(text);
|
|
5521
|
+
this.requestRender();
|
|
5522
|
+
}
|
|
5523
|
+
deleteChar() {
|
|
5524
|
+
if (this.hasSelection()) {
|
|
5525
|
+
this.deleteSelectedText();
|
|
5526
|
+
return true;
|
|
5527
|
+
}
|
|
5528
|
+
this._ctx.clearSelection();
|
|
5529
|
+
this.editBuffer.deleteChar();
|
|
5530
|
+
this.requestRender();
|
|
5531
|
+
return true;
|
|
5532
|
+
}
|
|
5533
|
+
deleteCharBackward() {
|
|
5534
|
+
if (this.hasSelection()) {
|
|
5535
|
+
this.deleteSelectedText();
|
|
5536
|
+
return true;
|
|
5537
|
+
}
|
|
5538
|
+
this._ctx.clearSelection();
|
|
5539
|
+
this.editBuffer.deleteCharBackward();
|
|
5540
|
+
this.requestRender();
|
|
5541
|
+
return true;
|
|
5542
|
+
}
|
|
5543
|
+
deleteSelectedText() {
|
|
5544
|
+
this.editorView.deleteSelectedText();
|
|
5545
|
+
this._ctx.clearSelection();
|
|
5546
|
+
this.requestRender();
|
|
5547
|
+
}
|
|
5548
|
+
newLine() {
|
|
5549
|
+
this._ctx.clearSelection();
|
|
5550
|
+
this.editBuffer.newLine();
|
|
5551
|
+
this.requestRender();
|
|
5552
|
+
return true;
|
|
5553
|
+
}
|
|
5554
|
+
deleteLine() {
|
|
5555
|
+
this._ctx.clearSelection();
|
|
5556
|
+
this.editBuffer.deleteLine();
|
|
5557
|
+
this.requestRender();
|
|
5558
|
+
return true;
|
|
5559
|
+
}
|
|
5560
|
+
moveCursorLeft(options) {
|
|
5561
|
+
const select = options?.select ?? false;
|
|
5562
|
+
this.handleShiftSelection(select, true);
|
|
5563
|
+
this.editBuffer.moveCursorLeft();
|
|
5564
|
+
this.handleShiftSelection(select, false);
|
|
5565
|
+
this.requestRender();
|
|
5566
|
+
return true;
|
|
5567
|
+
}
|
|
5568
|
+
moveCursorRight(options) {
|
|
5569
|
+
const select = options?.select ?? false;
|
|
5570
|
+
this.handleShiftSelection(select, true);
|
|
5571
|
+
this.editBuffer.moveCursorRight();
|
|
5572
|
+
this.handleShiftSelection(select, false);
|
|
5573
|
+
this.requestRender();
|
|
5574
|
+
return true;
|
|
5575
|
+
}
|
|
5576
|
+
moveCursorUp(options) {
|
|
5577
|
+
const select = options?.select ?? false;
|
|
5578
|
+
this.handleShiftSelection(select, true);
|
|
5579
|
+
this.editorView.moveUpVisual();
|
|
5580
|
+
this.handleShiftSelection(select, false);
|
|
5581
|
+
this.requestRender();
|
|
5582
|
+
return true;
|
|
5583
|
+
}
|
|
5584
|
+
moveCursorDown(options) {
|
|
5585
|
+
const select = options?.select ?? false;
|
|
5586
|
+
this.handleShiftSelection(select, true);
|
|
5587
|
+
this.editorView.moveDownVisual();
|
|
5588
|
+
this.handleShiftSelection(select, false);
|
|
5589
|
+
this.requestRender();
|
|
5590
|
+
return true;
|
|
5591
|
+
}
|
|
5592
|
+
gotoLine(line) {
|
|
5593
|
+
this.editBuffer.gotoLine(line);
|
|
5594
|
+
this.requestRender();
|
|
5595
|
+
}
|
|
5596
|
+
gotoLineHome(options) {
|
|
5597
|
+
const select = options?.select ?? false;
|
|
5598
|
+
this.handleShiftSelection(select, true);
|
|
5599
|
+
const cursor = this.editorView.getCursor();
|
|
5600
|
+
this.editBuffer.setCursor(cursor.row, 0);
|
|
5601
|
+
this.handleShiftSelection(select, false);
|
|
5602
|
+
this.requestRender();
|
|
5603
|
+
return true;
|
|
5604
|
+
}
|
|
5605
|
+
gotoLineEnd(options) {
|
|
5606
|
+
const select = options?.select ?? false;
|
|
5607
|
+
this.handleShiftSelection(select, true);
|
|
5608
|
+
const eol = this.editBuffer.getEOL();
|
|
5609
|
+
this.editBuffer.setCursor(eol.line, eol.visualColumn);
|
|
5610
|
+
this.handleShiftSelection(select, false);
|
|
5611
|
+
this.requestRender();
|
|
5612
|
+
return true;
|
|
5613
|
+
}
|
|
5614
|
+
gotoBufferHome() {
|
|
5615
|
+
this.editBuffer.setCursor(0, 0);
|
|
5616
|
+
this.requestRender();
|
|
5617
|
+
return true;
|
|
5618
|
+
}
|
|
5619
|
+
gotoBufferEnd() {
|
|
5620
|
+
this.editBuffer.gotoLine(999999);
|
|
5621
|
+
this.requestRender();
|
|
5622
|
+
return true;
|
|
5623
|
+
}
|
|
5624
|
+
deleteToLineEnd() {
|
|
5625
|
+
const cursor = this.editorView.getCursor();
|
|
5626
|
+
const eol = this.editBuffer.getEOL();
|
|
5627
|
+
if (eol.visualColumn > cursor.col) {
|
|
5628
|
+
this.editBuffer.deleteRange(cursor.row, cursor.col, eol.line, eol.visualColumn);
|
|
5629
|
+
}
|
|
5630
|
+
this.requestRender();
|
|
5631
|
+
return true;
|
|
5632
|
+
}
|
|
5633
|
+
undo() {
|
|
5634
|
+
this._ctx.clearSelection();
|
|
5635
|
+
this.editBuffer.undo();
|
|
5636
|
+
this.requestRender();
|
|
5637
|
+
return true;
|
|
5638
|
+
}
|
|
5639
|
+
redo() {
|
|
5640
|
+
this._ctx.clearSelection();
|
|
5641
|
+
this.editBuffer.redo();
|
|
5642
|
+
this.requestRender();
|
|
5643
|
+
return true;
|
|
5644
|
+
}
|
|
5645
|
+
moveWordForward(options) {
|
|
5646
|
+
const select = options?.select ?? false;
|
|
5647
|
+
this.handleShiftSelection(select, true);
|
|
5648
|
+
const nextWord = this.editBuffer.getNextWordBoundary();
|
|
5649
|
+
this.editBuffer.setCursorByOffset(nextWord.offset);
|
|
5650
|
+
this.handleShiftSelection(select, false);
|
|
5651
|
+
this.requestRender();
|
|
5652
|
+
return true;
|
|
5653
|
+
}
|
|
5654
|
+
moveWordBackward(options) {
|
|
5655
|
+
const select = options?.select ?? false;
|
|
5656
|
+
this.handleShiftSelection(select, true);
|
|
5657
|
+
const prevWord = this.editBuffer.getPrevWordBoundary();
|
|
5658
|
+
this.editBuffer.setCursorByOffset(prevWord.offset);
|
|
5659
|
+
this.handleShiftSelection(select, false);
|
|
5660
|
+
this.requestRender();
|
|
5661
|
+
return true;
|
|
5662
|
+
}
|
|
5663
|
+
deleteWordForward() {
|
|
5664
|
+
if (this.hasSelection()) {
|
|
5665
|
+
this.deleteSelectedText();
|
|
5666
|
+
return true;
|
|
5667
|
+
}
|
|
5668
|
+
const currentCursor = this.editBuffer.getCursorPosition();
|
|
5669
|
+
const nextWord = this.editBuffer.getNextWordBoundary();
|
|
5670
|
+
if (nextWord.offset > currentCursor.offset) {
|
|
5671
|
+
this.editBuffer.deleteRange(currentCursor.line, currentCursor.visualColumn, nextWord.line, nextWord.visualColumn);
|
|
5672
|
+
}
|
|
5673
|
+
this._ctx.clearSelection();
|
|
5674
|
+
this.requestRender();
|
|
5675
|
+
return true;
|
|
5676
|
+
}
|
|
5677
|
+
deleteWordBackward() {
|
|
5678
|
+
if (this.hasSelection()) {
|
|
5679
|
+
this.deleteSelectedText();
|
|
5680
|
+
return true;
|
|
5681
|
+
}
|
|
5682
|
+
const currentCursor = this.editBuffer.getCursorPosition();
|
|
5683
|
+
const prevWord = this.editBuffer.getPrevWordBoundary();
|
|
5684
|
+
if (prevWord.offset < currentCursor.offset) {
|
|
5685
|
+
this.editBuffer.deleteRange(prevWord.line, prevWord.visualColumn, currentCursor.line, currentCursor.visualColumn);
|
|
5686
|
+
}
|
|
5687
|
+
this._ctx.clearSelection();
|
|
5688
|
+
this.requestRender();
|
|
5689
|
+
return true;
|
|
5690
|
+
}
|
|
5691
|
+
handleShiftSelection(shiftPressed, isBeforeMovement) {
|
|
5692
|
+
if (!this.selectable)
|
|
5693
|
+
return;
|
|
5694
|
+
if (!shiftPressed) {
|
|
5695
|
+
this._ctx.clearSelection();
|
|
5696
|
+
return;
|
|
5697
|
+
}
|
|
5698
|
+
const visualCursor = this.editorView.getVisualCursor();
|
|
5699
|
+
const viewport = this.editorView.getViewport();
|
|
5700
|
+
const cursorX = this.x + visualCursor.visualCol;
|
|
5701
|
+
const cursorY = this.y + (visualCursor.visualRow - viewport.offsetY);
|
|
5702
|
+
if (isBeforeMovement) {
|
|
5703
|
+
if (!this._ctx.hasSelection) {
|
|
5704
|
+
this._ctx.startSelection(this, cursorX, cursorY);
|
|
5705
|
+
}
|
|
5706
|
+
} else {
|
|
5707
|
+
this._ctx.updateSelection(this, cursorX, cursorY);
|
|
5708
|
+
}
|
|
5709
|
+
}
|
|
5710
|
+
focus() {
|
|
5711
|
+
super.focus();
|
|
5712
|
+
this.updateColors();
|
|
5713
|
+
}
|
|
5714
|
+
blur() {
|
|
5715
|
+
super.blur();
|
|
5716
|
+
this.updateColors();
|
|
5717
|
+
}
|
|
5718
|
+
get placeholder() {
|
|
5719
|
+
return this._placeholder;
|
|
5720
|
+
}
|
|
5721
|
+
set placeholder(value) {
|
|
5722
|
+
if (this._placeholder !== value) {
|
|
5723
|
+
this._placeholder = value;
|
|
5724
|
+
this.editBuffer.setPlaceholder(value);
|
|
5725
|
+
this.requestRender();
|
|
5726
|
+
}
|
|
5727
|
+
}
|
|
5728
|
+
get backgroundColor() {
|
|
5729
|
+
return this._unfocusedBackgroundColor;
|
|
5730
|
+
}
|
|
5731
|
+
set backgroundColor(value) {
|
|
5732
|
+
const newColor = parseColor(value ?? TextareaRenderable.defaults.backgroundColor);
|
|
5733
|
+
if (this._unfocusedBackgroundColor !== newColor) {
|
|
5734
|
+
this._unfocusedBackgroundColor = newColor;
|
|
5735
|
+
this.updateColors();
|
|
5736
|
+
}
|
|
5737
|
+
}
|
|
5738
|
+
get textColor() {
|
|
5739
|
+
return this._unfocusedTextColor;
|
|
5740
|
+
}
|
|
5741
|
+
set textColor(value) {
|
|
5742
|
+
const newColor = parseColor(value ?? TextareaRenderable.defaults.textColor);
|
|
5743
|
+
if (this._unfocusedTextColor !== newColor) {
|
|
5744
|
+
this._unfocusedTextColor = newColor;
|
|
5745
|
+
this.updateColors();
|
|
5746
|
+
}
|
|
5747
|
+
}
|
|
5748
|
+
set focusedBackgroundColor(value) {
|
|
5749
|
+
const newColor = parseColor(value ?? TextareaRenderable.defaults.focusedBackgroundColor);
|
|
5750
|
+
if (this._focusedBackgroundColor !== newColor) {
|
|
5751
|
+
this._focusedBackgroundColor = newColor;
|
|
5752
|
+
this.updateColors();
|
|
5753
|
+
}
|
|
5754
|
+
}
|
|
5755
|
+
set focusedTextColor(value) {
|
|
5756
|
+
const newColor = parseColor(value ?? TextareaRenderable.defaults.focusedTextColor);
|
|
5757
|
+
if (this._focusedTextColor !== newColor) {
|
|
5758
|
+
this._focusedTextColor = newColor;
|
|
5759
|
+
this.updateColors();
|
|
5760
|
+
}
|
|
5761
|
+
}
|
|
5762
|
+
set placeholderColor(value) {
|
|
5763
|
+
const newColor = parseColor(value ?? TextareaRenderable.defaults.placeholderColor);
|
|
5764
|
+
if (this._placeholderColor !== newColor) {
|
|
5765
|
+
this._placeholderColor = newColor;
|
|
5766
|
+
this.editBuffer.setPlaceholderColor(newColor);
|
|
5767
|
+
this.requestRender();
|
|
5768
|
+
}
|
|
5769
|
+
}
|
|
5770
|
+
}
|
|
4335
5771
|
export {
|
|
4336
5772
|
yellow,
|
|
4337
5773
|
wrapWithDelegates,
|
|
@@ -4444,8 +5880,10 @@ export {
|
|
|
4444
5880
|
VRenderable,
|
|
4445
5881
|
TreeSitterClient,
|
|
4446
5882
|
Timeline,
|
|
5883
|
+
TextareaRenderable,
|
|
4447
5884
|
TextRenderable,
|
|
4448
5885
|
TextNodeRenderable,
|
|
5886
|
+
TextBufferView,
|
|
4449
5887
|
TextBufferRenderable,
|
|
4450
5888
|
TextBuffer,
|
|
4451
5889
|
TextAttributes,
|
|
@@ -4487,6 +5925,8 @@ export {
|
|
|
4487
5925
|
Generic,
|
|
4488
5926
|
FrameBufferRenderable,
|
|
4489
5927
|
FrameBuffer,
|
|
5928
|
+
EditorView,
|
|
5929
|
+
EditBuffer,
|
|
4490
5930
|
DistortionEffect,
|
|
4491
5931
|
DebugOverlayCorner,
|
|
4492
5932
|
DataPathsManager,
|
|
@@ -4508,5 +5948,5 @@ export {
|
|
|
4508
5948
|
ASCIIFont
|
|
4509
5949
|
};
|
|
4510
5950
|
|
|
4511
|
-
//# debugId=
|
|
5951
|
+
//# debugId=C45C47BFE87C68C464756E2164756E21
|
|
4512
5952
|
//# sourceMappingURL=index.js.map
|