@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/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-phjxdb6g.js";
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.textBuffer.setWrapMode(this._wrapMode);
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._wrap && this.width > 0) {
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.textBuffer.setWrapMode(this._wrapMode);
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.textBuffer.resetLocalSelection();
2448
+ this.textBufferView.resetLocalSelection();
1761
2449
  return true;
1762
2450
  }
1763
- return this.textBuffer.setLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg);
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.textBuffer.lineInfo;
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.textBuffer.setWrapWidth(width);
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._wrap && this.width !== width) {
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.textBuffer.getSelectedText();
2506
+ return this.textBufferView.getSelectedText();
1831
2507
  }
1832
2508
  hasSelection() {
1833
- return this.textBuffer.hasSelection();
2509
+ return this.textBufferView.hasSelection();
1834
2510
  }
1835
2511
  getSelection() {
1836
- return this.textBuffer.getSelection();
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
- const clipRect = {
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=6F0864CECE58138064756E2164756E21
5951
+ //# debugId=C45C47BFE87C68C464756E2164756E21
4512
5952
  //# sourceMappingURL=index.js.map