@lvce-editor/editor-worker 2.1.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/editorWorkerMain.js +1441 -1393
  2. package/package.json +1 -1
@@ -57,7 +57,6 @@ const boolean = value => {
57
57
  }
58
58
  };
59
59
 
60
- // @ts-ignore
61
60
  const clamp = (num, min, max) => {
62
61
  number$1(num);
63
62
  number$1(min);
@@ -212,10 +211,10 @@ const renderColorPickerDom = {
212
211
  return ['Viewlet.setDom2', dom];
213
212
  }
214
213
  };
215
- const render$3 = [renderColorPickerDom, renderColor, renderOffsetX];
214
+ const render$4 = [renderColorPickerDom, renderColor, renderOffsetX];
216
215
  const renderColorPicker = async (oldState, newState) => {
217
216
  const commands = [];
218
- for (const item of render$3) {
217
+ for (const item of render$4) {
219
218
  if (!item.isEqual(oldState, newState)) {
220
219
  commands.push(item.apply(oldState, newState));
221
220
  }
@@ -226,7 +225,7 @@ const renderColorPicker = async (oldState, newState) => {
226
225
  // TODO use numeric enum
227
226
  const CompositionUpdate = 'compositionUpdate';
228
227
  const ContentEditableInput = 'contentEditableInput';
229
- const Delete = 'delete';
228
+ const DeleteLeft = 'deleteLeft';
230
229
  const DeleteHorizontalRight = 'deleteHorizontalRight';
231
230
  const EditorCut = 'editorCut';
232
231
  const EditorPasteText = 'editorPasteText';
@@ -239,161 +238,1169 @@ const IndentMore = 'indentMore';
239
238
  const InsertLineBreak = 'insertLineBreak';
240
239
  const ToggleBlockComment = 'toggleBlockComment';
241
240
 
242
- const splitLines$2 = lines => {
243
- if (!lines) {
244
- return [];
245
- }
246
- return lines.split('\n');
247
- };
241
+ const Dash = '-';
242
+ const Dot = '.';
243
+ const EmptyString = '';
244
+ const Space = ' ';
245
+ const Tab = '\t';
246
+ const Underline = '_';
247
+ const T = 't';
248
248
 
249
- /**
250
- *
251
- * @param {number} size
252
- * @param {number} contentSize
253
- * @param {number} minimumSliderSize
254
- * @returns
255
- */
256
- const getScrollBarSize = (size, contentSize, minimumSliderSize) => {
257
- if (size >= contentSize) {
258
- return 0;
259
- }
260
- return Math.max(Math.round(size ** 2 / contentSize), minimumSliderSize);
249
+ const getFontString = (fontWeight, fontSize, fontFamily) => {
250
+ return `${fontWeight} ${fontSize}px ${fontFamily}`;
261
251
  };
262
- const getScrollBarOffset = (delta, finalDelta, size, scrollBarSize) => {
263
- const scrollBarOffset = delta / finalDelta * (size - scrollBarSize);
264
- return scrollBarOffset;
252
+
253
+ const getLetterSpacingString = letterSpacing => {
254
+ return `${letterSpacing}px`;
265
255
  };
266
- const getScrollBarY = getScrollBarOffset;
267
- const getScrollBarWidth = (width, longestLineWidth) => {
268
- if (width > longestLineWidth) {
269
- return 0;
256
+
257
+ const createMeasureContext = () => {
258
+ const canvas = new OffscreenCanvas(0, 0);
259
+ const ctx = /** @type {OffscreenCanvasRenderingContext2D} */canvas.getContext('2d');
260
+ if (!ctx) {
261
+ throw new Error('Failed to get canvas context 2d');
270
262
  }
271
- return width ** 2 / longestLineWidth;
263
+ return ctx;
272
264
  };
273
- const getNewDeltaPercent = (height, scrollBarHeight, relativeY) => {
274
- const halfScrollBarHeight = scrollBarHeight / 2;
275
- if (relativeY <= halfScrollBarHeight) {
276
- // clicked at top
277
- return {
278
- percent: 0,
279
- handleOffset: relativeY
280
- };
281
- }
282
- if (relativeY <= height - halfScrollBarHeight) {
283
- // clicked in middle
284
- return {
285
- percent: (relativeY - halfScrollBarHeight) / (height - scrollBarHeight),
286
- handleOffset: halfScrollBarHeight
287
- };
265
+
266
+ const state$b = {
267
+ ctx: undefined
268
+ };
269
+ const getOrCreate = createCtx => {
270
+ if (state$b.ctx) {
271
+ return state$b.ctx;
288
272
  }
289
- // clicked at bottom
290
- return {
291
- percent: 1,
292
- handleOffset: scrollBarHeight - height + relativeY
293
- };
273
+ state$b.ctx = createCtx();
274
+ return state$b.ctx;
294
275
  };
295
276
 
296
- // based on https://github.com/microsoft/vscode/blob/c0769274fa136b45799edeccc0d0a2f645b75caf/src/vs/base/common/arrays.ts#L625 (License MIT)
277
+ const getContext = () => {
278
+ const ctx = getOrCreate(createMeasureContext);
279
+ return ctx;
280
+ };
297
281
 
298
- // @ts-ignore
299
- const insertInto = (array, start, newItems) => {
300
- const originalLength = array.length;
301
- const newItemsLength = newItems.length;
302
- array.length = originalLength + newItemsLength;
303
- // Move the items after the start index, start from the end so that we don't overwrite any value.
304
- for (let i = originalLength - 1; i >= start; i--) {
305
- array[i + newItemsLength] = array[i];
282
+ const measureTextWidth = (text, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth) => {
283
+ string(text);
284
+ number$1(fontWeight);
285
+ number$1(fontSize);
286
+ string(fontFamily);
287
+ boolean(isMonoSpaceFont);
288
+ number$1(charWidth);
289
+ if (isMonoSpaceFont) {
290
+ return text.length * charWidth;
306
291
  }
307
- for (let i = 0; i < newItemsLength; i++) {
308
- array[i + start] = newItems[i];
292
+ if (typeof letterSpacing !== 'number') {
293
+ throw new TypeError('letterSpacing must be of type number');
309
294
  }
295
+ const letterSpacingString = getLetterSpacingString(letterSpacing);
296
+ const fontString = getFontString(fontWeight, fontSize, fontFamily);
297
+ const ctx = getContext();
298
+ // @ts-ignore
299
+ ctx.letterSpacing = letterSpacingString;
300
+ // @ts-ignore
301
+ ctx.font = fontString;
302
+ // @ts-ignore
303
+ const metrics = ctx.measureText(text);
304
+ const width = metrics.width;
305
+ return width;
310
306
  };
311
307
 
312
- /**
313
- * Alternative to the native Array.splice method, it
314
- * can only support limited number of items due to the maximum call stack size limit.
315
- */
308
+ const getAccurateColumnIndexAscii = (
316
309
  // @ts-ignore
317
- const spliceLargeArray = (array, start, deleteCount, newItems) => {
318
- const result = array.splice(start, deleteCount);
319
- insertInto(array, start, newItems);
320
- return result;
310
+ line,
311
+ // @ts-ignore
312
+ guess,
313
+ // @ts-ignore
314
+ averageCharWidth,
315
+ // @ts-ignore
316
+ eventX,
317
+ // @ts-ignore
318
+ fontWeight,
319
+ // @ts-ignore
320
+ fontSize,
321
+ // @ts-ignore
322
+ fontFamily,
323
+ // @ts-ignore
324
+ letterSpacing,
325
+ // @ts-ignore
326
+ isMonospaceFont,
327
+ // @ts-ignore
328
+ charWidth) => {
329
+ for (let i = guess; i < line.length; i++) {
330
+ const width = measureTextWidth(line.slice(0, i), fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
331
+ if (eventX - width < averageCharWidth / 2) {
332
+ return i;
333
+ }
334
+ }
335
+ return line.length;
321
336
  };
322
337
 
323
- const joinLines$2 = lines => {
324
- return lines.join('\n');
338
+ const supported = () => {
339
+ return 'Segmenter' in Intl;
325
340
  };
326
-
327
- // TODO have function for single edit (most common, avoid one array)
328
- const applyEdits = (textDocument, changes) => {
329
- object(textDocument);
330
- array(changes);
331
- // TODO don't copy all lines (can be expensive, e.g. 10000 lines = 10000 * 64bit = 64kB on every keystroke)
332
- const newLines = [...textDocument.lines];
333
- let linesDelta = 0;
334
- for (const change of changes) {
335
- const startRowIndex = change.start.rowIndex + linesDelta;
336
- const endRowIndex = change.end.rowIndex + linesDelta;
337
- const startColumnIndex = change.start.columnIndex;
338
- const endColumnIndex = change.end.columnIndex;
339
- const inserted = change.inserted;
340
- const deleted = change.deleted;
341
- number$1(startRowIndex);
342
- number$1(endRowIndex);
343
- number$1(startColumnIndex);
344
- number$1(endColumnIndex);
345
- array(inserted);
346
- array(deleted);
347
- if (startRowIndex === endRowIndex) {
348
- if (inserted.length === 0) {
349
- const line = newLines[startRowIndex];
350
- const before = line.slice(0, startColumnIndex);
351
- const after = line.slice(endColumnIndex);
352
- newLines[startRowIndex] = before + after;
353
- } else if (inserted.length === 1) {
354
- const line = newLines[startRowIndex];
355
- let before = line.slice(0, startColumnIndex);
356
- if (startColumnIndex > line.length) {
357
- before += ' '.repeat(startColumnIndex - line.length);
341
+ const create$5 = () => {
342
+ // @ts-ignore
343
+ const segmenter = new Intl.Segmenter();
344
+ return {
345
+ at(line, index) {
346
+ const segments = segmenter.segment(line);
347
+ return segments.containing(index);
348
+ },
349
+ visualIndex(line, index) {
350
+ const segments = segmenter.segment(line);
351
+ let currentVisualIndex = 0;
352
+ for (const segment of segments) {
353
+ if (segment.index >= index) {
354
+ return currentVisualIndex;
358
355
  }
359
- const after = line.slice(endColumnIndex);
360
- const text = inserted[0];
361
- newLines[startRowIndex] = before + text + after;
362
- } else {
363
- const line = newLines[startRowIndex];
364
- const before = line.slice(0, startColumnIndex) + inserted[0];
365
- const after = inserted.at(-1) + line.slice(endColumnIndex);
366
- spliceLargeArray(newLines, startRowIndex, deleted.length, [before, ...inserted.slice(1, -1), after]);
367
- // TODO only do this once after all edits, not inside loop
368
- textDocument.maxLineY = Math.min(textDocument.numberOfVisibleLines, newLines.length);
356
+ currentVisualIndex++;
369
357
  }
370
- } else {
371
- if (inserted.length === 1) {
372
- const before = newLines[startRowIndex].slice(0, startColumnIndex) + inserted[0];
373
- const after = endRowIndex >= newLines.length ? '' : newLines[endRowIndex].slice(endColumnIndex);
374
- spliceLargeArray(newLines, startRowIndex, deleted.length, [before + after]);
375
- } else {
376
- const before = newLines[startRowIndex].slice(0, startColumnIndex) + inserted[0];
377
- const middle = inserted.slice(1, -1);
378
- const after = inserted.at(-1) + (endRowIndex >= newLines.length ? '' : newLines[endRowIndex].slice(endColumnIndex));
379
- spliceLargeArray(newLines, startRowIndex, deleted.length, [before, ...middle, after]);
358
+ return currentVisualIndex;
359
+ },
360
+ modelIndex(line, visualIndex) {
361
+ const segments = segmenter.segment(line);
362
+ let currentVisualIndex = 0;
363
+ for (const segment of segments) {
364
+ if (currentVisualIndex >= visualIndex) {
365
+ return segment.index;
366
+ }
367
+ currentVisualIndex++;
380
368
  }
381
- // TODO only do this once after all edits, not inside loop
382
- textDocument.maxLineY = Math.min(textDocument.numberOfVisibleLines, textDocument.lines.length);
369
+ return line.length;
370
+ },
371
+ getSegments(line) {
372
+ return segmenter.segment(line);
383
373
  }
384
- linesDelta += Math.max(inserted.length - deleted.length, 0);
385
- }
386
- return newLines;
387
- };
388
- const getLine = (textDocument, index) => {
389
- return textDocument.lines[index];
374
+ };
390
375
  };
391
- const getText$1 = state => {
392
- return joinLines$2(state.lines);
376
+
377
+ // @ts-ignore
378
+ const getAccurateColumnIndexUnicode = (line, guess, averageCharWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing) => {
379
+ const segmenter = create$5();
380
+ const segments = segmenter.getSegments(line);
381
+ const isMonospaceFont = false;
382
+ const charWidth = 0;
383
+ for (const segment of segments) {
384
+ const width = measureTextWidth(line.slice(0, segment.index), fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
385
+ if (eventX - width < averageCharWidth) {
386
+ return segment.index;
387
+ }
388
+ }
389
+ return line.length;
393
390
  };
394
- const RE_WHITESPACE = /^\s+/;
395
391
 
396
- // TODO this doesn't belong here
392
+ const RE_ASCII = /^[\p{ASCII}]*$/u;
393
+ const isAscii = line => {
394
+ return RE_ASCII.test(line);
395
+ };
396
+
397
+ const normalizeText = (text, normalize, tabSize) => {
398
+ if (normalize) {
399
+ return text.replaceAll(Tab, Space.repeat(tabSize));
400
+ }
401
+ return text;
402
+ };
403
+ const shouldNormalizeText = text => {
404
+ return text.includes(Tab);
405
+ };
406
+
407
+ // @ts-ignore
408
+ const guessOffset = (eventX, averageCharWidth) => {
409
+ const guess = Math.round(eventX / averageCharWidth);
410
+ return guess;
411
+ };
412
+
413
+ // @ts-ignore
414
+ const normalizeGuess = (line, guess, tabSize) => {
415
+ let normalizedGuess = guess;
416
+ for (let i = 0; i < guess; i++) {
417
+ if (line[i] === Tab) {
418
+ normalizedGuess -= tabSize - 1;
419
+ }
420
+ }
421
+ return normalizedGuess;
422
+ };
423
+
424
+ // @ts-ignore
425
+ const getAccurateColumnIndex = (line, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth, tabSize, eventX) => {
426
+ string(line);
427
+ number$1(fontWeight);
428
+ number$1(fontSize);
429
+ string(fontFamily);
430
+ number$1(letterSpacing);
431
+ boolean(isMonospaceFont);
432
+ number$1(charWidth);
433
+ number$1(tabSize);
434
+ number$1(eventX);
435
+ // Assert.greaterZero(charWidth)
436
+ const guess = guessOffset(eventX, charWidth);
437
+ const normalize = shouldNormalizeText(line);
438
+ const normalizedGuess = normalizeGuess(line, guess, tabSize);
439
+ const text = line.slice(0, normalizedGuess);
440
+ const normalizedText = normalizeText(text, normalize, tabSize);
441
+ const actual = measureTextWidth(normalizedText, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
442
+ const isAscii$1 = isAscii(line);
443
+ if (isAscii$1) {
444
+ if (Math.abs(eventX - actual) < charWidth / 2) {
445
+ return normalizedGuess;
446
+ }
447
+ return getAccurateColumnIndexAscii(line, normalizedGuess, charWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
448
+ }
449
+ return getAccurateColumnIndexUnicode(line, normalizedGuess, charWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing);
450
+ };
451
+
452
+ const at = (editor, eventX, eventY) => {
453
+ object(editor);
454
+ number$1(eventX);
455
+ number$1(eventY);
456
+ const {
457
+ y,
458
+ deltaY,
459
+ rowHeight,
460
+ fontSize,
461
+ fontWeight,
462
+ fontFamily,
463
+ letterSpacing,
464
+ lines,
465
+ tabSize,
466
+ differences,
467
+ isMonospaceFont,
468
+ charWidth
469
+ } = editor;
470
+ const rowIndex = Math.floor((eventY - y + deltaY) / rowHeight);
471
+ if (rowIndex < 0) {
472
+ return {
473
+ rowIndex: 0,
474
+ columnIndex: 0
475
+ };
476
+ }
477
+ const clampedRowIndex = clamp(rowIndex, 0, lines.length - 1);
478
+ const line = lines[clampedRowIndex];
479
+ const columnIndex = getAccurateColumnIndex(line, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth, tabSize, eventX);
480
+ return {
481
+ rowIndex: clampedRowIndex,
482
+ columnIndex
483
+ };
484
+ };
485
+
486
+ /**
487
+ * @deprecated this doesn't work for variable width characters (unicode/emoji).
488
+ * Use position computation in renderer process instead
489
+ *
490
+ * @param {object} editor
491
+ * @param {number} rowIndex
492
+ * @param {number} columnIndex
493
+ * @returns
494
+ */
495
+ const x = (editor, rowIndex, columnIndex) => {
496
+ const {
497
+ columnWidth,
498
+ x
499
+ } = editor;
500
+ const offsetX = columnIndex * columnWidth + x;
501
+ return offsetX;
502
+ };
503
+ const y = (editor, rowIndex) => {
504
+ const {
505
+ rowHeight,
506
+ y
507
+ } = editor;
508
+ const offsetY = (rowIndex + 1) * rowHeight + y;
509
+ return offsetY;
510
+ };
511
+
512
+ const emptyObject = {};
513
+ const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
514
+ const i18nString = (key, placeholders = emptyObject) => {
515
+ if (placeholders === emptyObject) {
516
+ return key;
517
+ }
518
+ const replacer = (match, rest) => {
519
+ return placeholders[rest];
520
+ };
521
+ return key.replaceAll(RE_PLACEHOLDER, replacer);
522
+ };
523
+
524
+ /**
525
+ * @enum {string}
526
+ */
527
+ const UiStrings = {
528
+ OrganizeImports: 'Organize Imports',
529
+ Copy: 'Copy',
530
+ CopyLineDown: 'Copy Line Down',
531
+ CopyLineUp: 'Copy Line Up',
532
+ Cut: 'Cut',
533
+ DuplicateSelection: 'Duplicate Selection',
534
+ FindAllImplementations: 'Find All Implementations',
535
+ FindAllReferences: 'Find All References',
536
+ GoToDefinition: 'Go to Definition',
537
+ GoToTypeDefinition: 'Go to Type Definition',
538
+ MoveLineDown: 'Move Line Down',
539
+ MoveLineUp: 'Move Line Up',
540
+ NoDefinitionFound: 'No definition found',
541
+ NoDefinitionFoundFor: "No definition found for '{PH1}'",
542
+ NoTypeDefinitionFound: 'No type definition found',
543
+ NoTypeDefinitionFoundFor: "No type definition found for '{PH1}'",
544
+ Paste: 'Paste',
545
+ Redo: 'Redo',
546
+ SelectAll: 'Select All',
547
+ Separator: 'Separator',
548
+ ToggleBlockComment: 'Toggle Block Comment',
549
+ ToggleLineComment: 'Toggle Line Comment',
550
+ Undo: 'Undo',
551
+ FormatDocument: 'Format Document',
552
+ SourceActions: 'Source Actions',
553
+ EditorShowHover: 'Show Hover',
554
+ EditorFormatDocumentForced: 'Editor: Format Document (forced)',
555
+ EditorSelectNextOccurrence: 'Editor: Select Next Occurrence',
556
+ EditorSelectAllOccurrences: 'Editor: Select All Occurrences',
557
+ EditorGoToDefinition: 'Editor: Go To Definition',
558
+ EditorGoToTypeDefinition: 'Editor: Go To Type Definition',
559
+ EditorSelectInsideString: 'Editor: Select Inside String',
560
+ EditorIndent: 'Editor: Indent',
561
+ EditorUnindent: 'Editor: Unindent',
562
+ EditorSortLinesAscending: 'Editor: Sort Lines Ascending',
563
+ EditorToggleComment: 'Editor: Toggle Comment',
564
+ EditorSelectUp: 'Editor: Select Up',
565
+ EditorSelectDown: 'Editor: Select Down',
566
+ EditorToggleBlockComment: 'Editor: Toggle Block Comment',
567
+ EditorOpenColorPicker: 'Editor: Open Color Picker',
568
+ EditorCloseColorPicker: 'Editor: Close Color Picker',
569
+ EditorCopyLineDown: 'Editor: Copy Line Down',
570
+ EditorCopyLineUp: 'Editor: Copy Line Up',
571
+ Replace: 'replace',
572
+ NoResults: 'No Results'
573
+ };
574
+ const noDefinitionFound = () => {
575
+ return i18nString(UiStrings.NoDefinitionFound);
576
+ };
577
+
578
+ // @ts-ignore
579
+ const noDefinitionFoundFor = word => {
580
+ return i18nString(UiStrings.NoDefinitionFoundFor, {
581
+ PH1: word
582
+ });
583
+ };
584
+
585
+ // @ts-ignore
586
+ const noTypeDefinitionFoundFor = word => {
587
+ return i18nString(UiStrings.NoTypeDefinitionFoundFor, {
588
+ PH1: word
589
+ });
590
+ };
591
+ const noTypeDefinitionFound = () => {
592
+ return i18nString(UiStrings.NoTypeDefinitionFound);
593
+ };
594
+ const noResults = () => {
595
+ return i18nString(UiStrings.NoResults);
596
+ };
597
+
598
+ const None$1 = 'none';
599
+ const Option = 'option';
600
+
601
+ const getFileIconVirtualDom = icon => {
602
+ return {
603
+ type: Img,
604
+ className: FileIcon,
605
+ src: icon,
606
+ role: None$1,
607
+ childCount: 0
608
+ };
609
+ };
610
+
611
+ const getIconDom = (fileIcon, symbolName) => {
612
+ if (fileIcon) {
613
+ return getFileIconVirtualDom(fileIcon);
614
+ }
615
+ return {
616
+ type: Div,
617
+ className: `${ColoredMaskIcon} ${symbolName}`,
618
+ childCount: 0
619
+ };
620
+ };
621
+
622
+ const text = data => {
623
+ return {
624
+ type: Text,
625
+ text: data,
626
+ childCount: 0
627
+ };
628
+ };
629
+
630
+ const label1 = {
631
+ type: Div,
632
+ className: Label,
633
+ childCount: 1
634
+ };
635
+ const completionHighlight = {
636
+ type: Span,
637
+ className: EditorCompletionItemHighlight,
638
+ childCount: 1
639
+ };
640
+ const getHighlightedLabelDom = (label, highlights) => {
641
+ if (highlights.length === 0) {
642
+ return [label1, text(label)];
643
+ }
644
+ const dom = [];
645
+ const labelDom = {
646
+ type: Div,
647
+ className: Label,
648
+ childCount: 0
649
+ };
650
+ dom.push(labelDom);
651
+ let position = 0;
652
+ for (let i = 0; i < highlights.length; i += 2) {
653
+ const highlightStart = highlights[i];
654
+ const highlightEnd = highlights[i + 1];
655
+ if (position < highlightStart) {
656
+ const beforeText = label.slice(position, highlightStart);
657
+ labelDom.childCount++;
658
+ dom.push(text(beforeText));
659
+ }
660
+ const highlightText = label.slice(highlightStart, highlightEnd);
661
+ labelDom.childCount++;
662
+ dom.push(completionHighlight, text(highlightText));
663
+ position = highlightEnd;
664
+ }
665
+ if (position < label.length) {
666
+ const afterText = label.slice(position);
667
+ labelDom.childCount++;
668
+ dom.push(text(afterText));
669
+ }
670
+ return dom;
671
+ };
672
+
673
+ const getCompletionItemVirtualDom = visibleItem => {
674
+ const {
675
+ top,
676
+ label,
677
+ symbolName,
678
+ highlights,
679
+ focused,
680
+ deprecated,
681
+ fileIcon
682
+ } = visibleItem;
683
+ let className = EditorCompletionItem;
684
+ if (focused) {
685
+ className += ' ' + EditorCompletionItemFocused;
686
+ }
687
+ if (deprecated) {
688
+ className += ' ' + EditorCompletionItemDeprecated;
689
+ }
690
+ return [{
691
+ type: Div,
692
+ role: Option,
693
+ className,
694
+ top,
695
+ childCount: 2
696
+ }, getIconDom(fileIcon, symbolName), ...getHighlightedLabelDom(label, highlights)];
697
+ };
698
+
699
+ const getCompletionItemsVirtualDom = visibleItems => {
700
+ if (visibleItems.length === 0) {
701
+ return [{
702
+ type: Div,
703
+ childCount: 1
704
+ }, text(noResults())];
705
+ }
706
+ const root = {
707
+ type: Div,
708
+ childCount: visibleItems.length
709
+ };
710
+ const dom = [root, ...visibleItems.flatMap(getCompletionItemVirtualDom)];
711
+ return dom;
712
+ };
713
+
714
+ const Deprecated = 1 << 0;
715
+
716
+ const Property = 1;
717
+ const Value = 2;
718
+ const Function$1 = 3;
719
+ const Variable = 4;
720
+ const Keyword = 5;
721
+ const Folder = 6;
722
+ const File = 7;
723
+ const Field = 8;
724
+
725
+ const SymbolProperty = 'SymbolProperty';
726
+ const SymbolValue = 'SymbolValue';
727
+ const SymbolFunction = 'SymbolFunction';
728
+ const SymbolVariable = 'SymbolVariable';
729
+ const SymbolKeyword = 'SymbolKeyword';
730
+ const SymbolDefault = 'SymbolDefault';
731
+ const SymbolField = 'SymbolField';
732
+ const SymbolNone = '';
733
+
734
+ const getSymbolName = kind => {
735
+ switch (kind) {
736
+ case Property:
737
+ return SymbolProperty;
738
+ case Value:
739
+ return SymbolValue;
740
+ case Function$1:
741
+ return SymbolFunction;
742
+ case Variable:
743
+ return SymbolVariable;
744
+ case Keyword:
745
+ return SymbolKeyword;
746
+ case Field:
747
+ return SymbolField;
748
+ case File:
749
+ return SymbolNone;
750
+ default:
751
+ return SymbolDefault;
752
+ }
753
+ };
754
+
755
+ const getHighlights = item => {
756
+ const {
757
+ matches
758
+ } = item;
759
+ return matches.slice(1);
760
+ };
761
+
762
+ // import * as IconTheme from '../IconTheme/IconTheme.ts'
763
+
764
+ const getLabel = item => {
765
+ return item.label;
766
+ };
767
+ const getFileIcon = item => {
768
+ switch (item.kind) {
769
+ case File:
770
+ // TODO IconTheme.getFileNameIcon(item.label)
771
+ return '';
772
+ case Folder:
773
+ // TODO IconTheme.getFolderNameIcon(item.label)
774
+ return '';
775
+ default:
776
+ return '';
777
+ }
778
+ };
779
+ const getVisibleIem = (item, itemHeight, leadingWord, i, focusedIndex) => {
780
+ return {
781
+ label: getLabel(item),
782
+ symbolName: getSymbolName(item.kind),
783
+ top: i * itemHeight,
784
+ highlights: getHighlights(item),
785
+ focused: i === focusedIndex,
786
+ deprecated: item.flags & Deprecated,
787
+ fileIcon: getFileIcon(item)
788
+ };
789
+ };
790
+
791
+ const getVisibleItems = (filteredItems, itemHeight, leadingWord, minLineY, maxLineY, focusedIndex) => {
792
+ const visibleItems = [];
793
+ for (let i = minLineY; i < maxLineY; i++) {
794
+ const filteredItem = filteredItems[i];
795
+ visibleItems.push(getVisibleIem(filteredItem, itemHeight, leadingWord, i, focusedIndex));
796
+ }
797
+ return visibleItems;
798
+ };
799
+
800
+ /**
801
+ *
802
+ * @param {number} size
803
+ * @param {number} contentSize
804
+ * @param {number} minimumSliderSize
805
+ * @returns
806
+ */
807
+ const getScrollBarSize = (size, contentSize, minimumSliderSize) => {
808
+ if (size >= contentSize) {
809
+ return 0;
810
+ }
811
+ return Math.max(Math.round(size ** 2 / contentSize), minimumSliderSize);
812
+ };
813
+ const getScrollBarOffset = (delta, finalDelta, size, scrollBarSize) => {
814
+ const scrollBarOffset = delta / finalDelta * (size - scrollBarSize);
815
+ return scrollBarOffset;
816
+ };
817
+ const getScrollBarY = getScrollBarOffset;
818
+ const getScrollBarWidth = (width, longestLineWidth) => {
819
+ if (width > longestLineWidth) {
820
+ return 0;
821
+ }
822
+ return width ** 2 / longestLineWidth;
823
+ };
824
+ const getNewDeltaPercent = (height, scrollBarHeight, relativeY) => {
825
+ const halfScrollBarHeight = scrollBarHeight / 2;
826
+ if (relativeY <= halfScrollBarHeight) {
827
+ // clicked at top
828
+ return {
829
+ percent: 0,
830
+ handleOffset: relativeY
831
+ };
832
+ }
833
+ if (relativeY <= height - halfScrollBarHeight) {
834
+ // clicked in middle
835
+ return {
836
+ percent: (relativeY - halfScrollBarHeight) / (height - scrollBarHeight),
837
+ handleOffset: halfScrollBarHeight
838
+ };
839
+ }
840
+ // clicked at bottom
841
+ return {
842
+ percent: 1,
843
+ handleOffset: scrollBarHeight - height + relativeY
844
+ };
845
+ };
846
+
847
+ const renderItems = {
848
+ isEqual(oldState, newState) {
849
+ return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.focusedIndex === newState.focusedIndex;
850
+ },
851
+ apply(oldState, newState) {
852
+ const visibleItems = getVisibleItems(newState.items, newState.itemHeight, newState.leadingWord, newState.minLineY, newState.maxLineY, newState.focusedIndex);
853
+ const dom = getCompletionItemsVirtualDom(visibleItems);
854
+ return ['setDom', dom];
855
+ }
856
+ };
857
+ const renderBounds$1 = {
858
+ isEqual(oldState, newState) {
859
+ return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.x === newState.x && oldState.y === newState.y;
860
+ },
861
+ apply(oldState, newState) {
862
+ const {
863
+ x,
864
+ y,
865
+ width,
866
+ height
867
+ } = newState;
868
+ return [/* method */SetBounds, /* x */x, /* y */y, /* width */width, /* height */height];
869
+ }
870
+ };
871
+ const renderHeight = {
872
+ isEqual(oldState, newState) {
873
+ return oldState.items.length === newState.items.length;
874
+ },
875
+ apply(oldState, newState) {
876
+ const {
877
+ itemHeight
878
+ } = newState;
879
+ const contentHeight = newState.items.length * itemHeight;
880
+ return [/* method */SetContentHeight, /* contentHeight */contentHeight];
881
+ }
882
+ };
883
+ const renderNegativeMargin = {
884
+ isEqual(oldState, newState) {
885
+ return oldState.deltaY === newState.deltaY;
886
+ },
887
+ apply(oldState, newState) {
888
+ return [/* method */SetNegativeMargin, /* negativeMargin */-newState.deltaY];
889
+ }
890
+ };
891
+ const renderScrollBar = {
892
+ isEqual(oldState, newState) {
893
+ return oldState.negativeMargin === newState.negativeMargin && oldState.deltaY === newState.deltaY && oldState.height === newState.height && oldState.finalDeltaY === newState.finalDeltaY && oldState.items.length === newState.items.length;
894
+ },
895
+ apply(oldState, newState) {
896
+ const total = newState.items.length;
897
+ const contentHeight = total * newState.itemHeight;
898
+ const scrollBarHeight = getScrollBarSize(newState.height, contentHeight, newState.minimumSliderSize);
899
+ const scrollBarY = getScrollBarY(newState.deltaY, newState.finalDeltaY, newState.height - newState.headerHeight, scrollBarHeight);
900
+ return [/* method */SetScrollBar, /* scrollBarY */scrollBarY, /* scrollBarHeight */scrollBarHeight];
901
+ }
902
+ };
903
+ const render$3 = [renderItems, renderBounds$1, renderHeight, renderNegativeMargin, renderScrollBar];
904
+ const renderCompletion = (oldState, newState) => {
905
+ const commands = [];
906
+ for (const item of render$3) {
907
+ if (!item.isEqual(oldState, newState)) {
908
+ commands.push(item.apply(oldState, newState));
909
+ }
910
+ }
911
+ return commands;
912
+ };
913
+
914
+ const EmptyMatches = [];
915
+
916
+ const Diagonal = 1;
917
+ const Left = 2;
918
+
919
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
920
+
921
+ const createTable = size => {
922
+ const table = [];
923
+ for (let i = 0; i < size; i++) {
924
+ const row = new Uint8Array(size);
925
+ table.push(row);
926
+ }
927
+ return table;
928
+ };
929
+
930
+ const isLowerCase = char => {
931
+ return char === char.toLowerCase();
932
+ };
933
+
934
+ const isUpperCase = char => {
935
+ return char === char.toUpperCase();
936
+ };
937
+
938
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
939
+ const isGap = (columnCharBefore, columnChar) => {
940
+ switch (columnCharBefore) {
941
+ case Dash:
942
+ case Underline:
943
+ case EmptyString:
944
+ case T:
945
+ case Space:
946
+ case Dot:
947
+ return true;
948
+ }
949
+ if (isLowerCase(columnCharBefore) && isUpperCase(columnChar)) {
950
+ return true;
951
+ }
952
+ return false;
953
+ };
954
+
955
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
956
+ const getScore = (rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, column, wordLength, isDiagonalMatch) => {
957
+ if (rowCharLow !== columnCharLow) {
958
+ return -1;
959
+ }
960
+ const isMatch = rowChar === columnChar;
961
+ if (isMatch) {
962
+ if (isDiagonalMatch) {
963
+ return 8;
964
+ }
965
+ if (isGap(columnCharBefore, columnChar)) {
966
+ return 8;
967
+ }
968
+ return 5;
969
+ }
970
+ if (isGap(columnCharBefore, columnChar)) {
971
+ return 8;
972
+ }
973
+ return 5;
974
+ };
975
+
976
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
977
+
978
+ const isPatternInWord = (patternLow, patternPos, patternLen, wordLow, wordPos, wordLen) => {
979
+ while (patternPos < patternLen && wordPos < wordLen) {
980
+ if (patternLow[patternPos] === wordLow[wordPos]) {
981
+ patternPos += 1;
982
+ }
983
+ wordPos += 1;
984
+ }
985
+ return patternPos === patternLen; // pattern must be exhausted
986
+ };
987
+
988
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
989
+ const traceHighlights = (table, arrows, patternLength, wordLength) => {
990
+ let row = patternLength;
991
+ let column = wordLength;
992
+ const matches = [];
993
+ while (row >= 1 && column >= 1) {
994
+ const arrow = arrows[row][column];
995
+ if (arrow === Left) {
996
+ column--;
997
+ } else if (arrow === Diagonal) {
998
+ row--;
999
+ column--;
1000
+ const start = column + 1;
1001
+ while (row >= 1 && column >= 1) {
1002
+ const arrow = arrows[row][column];
1003
+ if (arrow === Left) {
1004
+ break;
1005
+ }
1006
+ if (arrow === Diagonal) {
1007
+ row--;
1008
+ column--;
1009
+ }
1010
+ }
1011
+ const end = column;
1012
+ matches.unshift(end, start);
1013
+ }
1014
+ }
1015
+ matches.unshift(table[patternLength][wordLength - 1]);
1016
+ return matches;
1017
+ };
1018
+
1019
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
1020
+ const gridSize = 128;
1021
+ const table = createTable(gridSize);
1022
+ const arrows = createTable(gridSize);
1023
+ const filterCompletionItem = (pattern, word) => {
1024
+ const patternLength = Math.min(pattern.length, gridSize - 1);
1025
+ const wordLength = Math.min(word.length, gridSize - 1);
1026
+ const patternLower = pattern.toLowerCase();
1027
+ const wordLower = word.toLowerCase();
1028
+ if (!isPatternInWord(patternLower, 0, patternLength, wordLower, 0, wordLength)) {
1029
+ return EmptyMatches;
1030
+ }
1031
+ let strongMatch = false;
1032
+ for (let row = 1; row < patternLength + 1; row++) {
1033
+ const rowChar = pattern[row - 1];
1034
+ const rowCharLow = patternLower[row - 1];
1035
+ for (let column = 1; column < wordLength + 1; column++) {
1036
+ const columnChar = word[column - 1];
1037
+ const columnCharLow = wordLower[column - 1];
1038
+ const columnCharBefore = word[column - 2] || '';
1039
+ const isDiagonalMatch = arrows[row - 1][column - 1] === Diagonal;
1040
+ const score = getScore(rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, column, wordLength, isDiagonalMatch);
1041
+ if (row === 1 && score > 5) {
1042
+ strongMatch = true;
1043
+ }
1044
+ let diagonalScore = score + table[row - 1][column - 1];
1045
+ if (isDiagonalMatch && score !== -1) {
1046
+ diagonalScore += 2;
1047
+ }
1048
+ const leftScore = table[row][column - 1];
1049
+ if (leftScore > diagonalScore) {
1050
+ table[row][column] = leftScore;
1051
+ arrows[row][column] = Left;
1052
+ } else {
1053
+ table[row][column] = diagonalScore;
1054
+ arrows[row][column] = Diagonal;
1055
+ }
1056
+ }
1057
+ }
1058
+ if (!strongMatch) {
1059
+ return EmptyMatches;
1060
+ }
1061
+ const highlights = traceHighlights(table, arrows, patternLength, wordLength);
1062
+ return highlights;
1063
+ };
1064
+
1065
+ const addEmptyMatch = item => {
1066
+ return {
1067
+ ...item,
1068
+ matches: EmptyMatches
1069
+ };
1070
+ };
1071
+ const filterCompletionItems = (completionItems, word) => {
1072
+ if (word === EmptyString) {
1073
+ return completionItems.map(addEmptyMatch);
1074
+ }
1075
+ const filteredCompletions = [];
1076
+ const deprecated = [];
1077
+ for (const completionItem of completionItems) {
1078
+ const {
1079
+ label,
1080
+ flags
1081
+ } = completionItem;
1082
+ const result = filterCompletionItem(word, label);
1083
+ if (result !== EmptyMatches) {
1084
+ if (flags & Deprecated) {
1085
+ // TODO avoid mutation
1086
+ completionItem.matches = EmptyMatches;
1087
+ deprecated.push(completionItem);
1088
+ } else {
1089
+ // TODO avoid mutation
1090
+ completionItem.matches = result;
1091
+ filteredCompletions.push(completionItem);
1092
+ }
1093
+ }
1094
+ }
1095
+ if (deprecated.length > 0) {
1096
+ filteredCompletions.push(...deprecated);
1097
+ }
1098
+ return filteredCompletions;
1099
+ };
1100
+
1101
+ const getListHeight = (itemsLength, itemHeight, maxHeight) => {
1102
+ number$1(itemsLength);
1103
+ number$1(itemHeight);
1104
+ number$1(maxHeight);
1105
+ if (itemsLength === 0) {
1106
+ return itemHeight;
1107
+ }
1108
+ const totalHeight = itemsLength * itemHeight;
1109
+ return Math.min(totalHeight, maxHeight);
1110
+ };
1111
+
1112
+ const RE_WORD_START$1 = /^[\w\-]+/;
1113
+ const RE_WORD_END$1 = /[\w\-]+$/;
1114
+ const getWordAt$1 = (line, columnIndex) => {
1115
+ const before = line.slice(0, columnIndex);
1116
+ const matchBefore = before.match(RE_WORD_END$1);
1117
+ const after = line.slice(columnIndex);
1118
+ const matchAfter = after.match(RE_WORD_START$1);
1119
+ let word = EmptyString;
1120
+ if (matchBefore) {
1121
+ word += matchBefore[0];
1122
+ }
1123
+ if (matchAfter) {
1124
+ word += matchAfter[0];
1125
+ }
1126
+ return {
1127
+ word
1128
+ };
1129
+ };
1130
+ const getWordBefore$1 = (line, columnIndex) => {
1131
+ const before = line.slice(0, columnIndex);
1132
+ const matchBefore = before.match(RE_WORD_END$1);
1133
+ if (matchBefore) {
1134
+ return matchBefore[0];
1135
+ }
1136
+ return EmptyString;
1137
+ };
1138
+
1139
+ const getWordAt = (editor, rowIndex, columnIndex) => {
1140
+ const {
1141
+ lines
1142
+ } = editor;
1143
+ const line = lines[rowIndex];
1144
+ return getWordAt$1(line, columnIndex);
1145
+ };
1146
+ const getWordBefore = (editor, rowIndex, columnIndex) => {
1147
+ const {
1148
+ lines
1149
+ } = editor;
1150
+ const line = lines[rowIndex];
1151
+ return getWordBefore$1(line, columnIndex);
1152
+ };
1153
+
1154
+ const render$2 = (oldState, newState) => {
1155
+ const commands = renderCompletion(oldState, newState);
1156
+ const wrappedCommands = [];
1157
+ const uid = newState.uid;
1158
+ for (const command of commands) {
1159
+ wrappedCommands.push(['Viewlet.send', uid, ...command]);
1160
+ }
1161
+ return wrappedCommands;
1162
+ };
1163
+ const add = widget => {
1164
+ const commands = render$2(widget.oldState, widget.newState);
1165
+ const id = 'EditorCompletion';
1166
+ // TODO how to generate a unique integer id
1167
+ // that doesn't collide with ids created in renderer worker?
1168
+ const uid = widget.newState.uid;
1169
+ const allCommands = [];
1170
+ allCommands.push(['Viewlet.create', id, uid]);
1171
+ allCommands.push(...commands);
1172
+ return allCommands;
1173
+ };
1174
+ const remove$1 = widget => {
1175
+ return [['Viewlet.send', widget.newState.uid, 'dispose']];
1176
+ };
1177
+ const handleEditorType$1 = (editor, state) => {
1178
+ const {
1179
+ unfilteredItems,
1180
+ itemHeight,
1181
+ maxHeight
1182
+ } = state;
1183
+ const {
1184
+ selections
1185
+ } = editor;
1186
+ const rowIndex = selections[0];
1187
+ const columnIndex = selections[1];
1188
+ const x$1 = x(editor, rowIndex, columnIndex);
1189
+ const y$1 = y(editor, rowIndex);
1190
+ const wordAtOffset = getWordBefore(editor, rowIndex, columnIndex);
1191
+ const items = filterCompletionItems(unfilteredItems, wordAtOffset);
1192
+ const newMinLineY = 0;
1193
+ const newMaxLineY = Math.min(items.length, 8);
1194
+ const height = getListHeight(items.length, itemHeight, maxHeight);
1195
+ const finalDeltaY = items.length * itemHeight - height;
1196
+ return {
1197
+ ...state,
1198
+ items,
1199
+ x: x$1,
1200
+ y: y$1,
1201
+ minLineY: newMinLineY,
1202
+ maxLineY: newMaxLineY,
1203
+ leadingWord: wordAtOffset,
1204
+ height,
1205
+ finalDeltaY
1206
+ };
1207
+ };
1208
+ const handleEditorDeleteLeft$1 = (editor, state) => {
1209
+ const {
1210
+ unfilteredItems,
1211
+ itemHeight,
1212
+ maxHeight
1213
+ } = state;
1214
+ const {
1215
+ selections
1216
+ } = editor;
1217
+ const rowIndex = selections[0];
1218
+ const columnIndex = selections[1];
1219
+ const x$1 = x(editor, rowIndex, columnIndex);
1220
+ const y$1 = y(editor, rowIndex);
1221
+ const wordAtOffset = getWordBefore(editor, rowIndex, columnIndex);
1222
+ if (!wordAtOffset) {
1223
+ return undefined;
1224
+ }
1225
+ const items = filterCompletionItems(unfilteredItems, wordAtOffset);
1226
+ const newMaxLineY = Math.min(items.length, 8);
1227
+ const height = getListHeight(items.length, itemHeight, maxHeight);
1228
+ return {
1229
+ ...state,
1230
+ items,
1231
+ x: x$1,
1232
+ y: y$1,
1233
+ maxLineY: newMaxLineY,
1234
+ leadingWord: wordAtOffset,
1235
+ height
1236
+ };
1237
+ };
1238
+
1239
+ const EditorCompletionWidget = {
1240
+ __proto__: null,
1241
+ add,
1242
+ handleEditorDeleteLeft: handleEditorDeleteLeft$1,
1243
+ handleEditorType: handleEditorType$1,
1244
+ remove: remove$1,
1245
+ render: render$2
1246
+ };
1247
+
1248
+ const Completion = 'completion';
1249
+
1250
+ const modules = Object.create(null);
1251
+ const register = (id, value) => {
1252
+ modules[id] = value;
1253
+ };
1254
+ const get$7 = id => {
1255
+ return modules[id];
1256
+ };
1257
+
1258
+ const getModule$2 = id => {
1259
+ return get$7(id);
1260
+ };
1261
+
1262
+ const applyWidgetChange = (editor, widget, changes) => {
1263
+ const module = getModule$2(widget.id);
1264
+ if (changes.length === 1 && changes[0].origin === EditorType && module.handleEditorType) {
1265
+ const newState = module.handleEditorType(editor, widget.newState);
1266
+ return {
1267
+ ...widget,
1268
+ newState
1269
+ };
1270
+ }
1271
+ if (changes.length === 1 && changes[0].origin === DeleteLeft && module.handleEditorDeleteLeft) {
1272
+ const newState = module.handleEditorDeleteLeft(editor, widget.newState);
1273
+ return {
1274
+ ...widget,
1275
+ newState
1276
+ };
1277
+ }
1278
+ return widget;
1279
+ };
1280
+
1281
+ const applyWidgetChanges = (editor, changes) => {
1282
+ const widgets = editor.widgets || [];
1283
+ if (widgets.length === 0) {
1284
+ return widgets;
1285
+ }
1286
+ const newWidgets = [];
1287
+ for (const widget of widgets) {
1288
+ const newWidget = applyWidgetChange(editor, widget, changes);
1289
+ if (newWidget.newState) {
1290
+ newWidgets.push(newWidget);
1291
+ }
1292
+ }
1293
+ return newWidgets;
1294
+ };
1295
+
1296
+ const splitLines$2 = lines => {
1297
+ if (!lines) {
1298
+ return [];
1299
+ }
1300
+ return lines.split('\n');
1301
+ };
1302
+
1303
+ // based on https://github.com/microsoft/vscode/blob/c0769274fa136b45799edeccc0d0a2f645b75caf/src/vs/base/common/arrays.ts#L625 (License MIT)
1304
+
1305
+ // @ts-ignore
1306
+ const insertInto = (array, start, newItems) => {
1307
+ const originalLength = array.length;
1308
+ const newItemsLength = newItems.length;
1309
+ array.length = originalLength + newItemsLength;
1310
+ // Move the items after the start index, start from the end so that we don't overwrite any value.
1311
+ for (let i = originalLength - 1; i >= start; i--) {
1312
+ array[i + newItemsLength] = array[i];
1313
+ }
1314
+ for (let i = 0; i < newItemsLength; i++) {
1315
+ array[i + start] = newItems[i];
1316
+ }
1317
+ };
1318
+
1319
+ /**
1320
+ * Alternative to the native Array.splice method, it
1321
+ * can only support limited number of items due to the maximum call stack size limit.
1322
+ */
1323
+ // @ts-ignore
1324
+ const spliceLargeArray = (array, start, deleteCount, newItems) => {
1325
+ const result = array.splice(start, deleteCount);
1326
+ insertInto(array, start, newItems);
1327
+ return result;
1328
+ };
1329
+
1330
+ const joinLines$2 = lines => {
1331
+ return lines.join('\n');
1332
+ };
1333
+
1334
+ // TODO have function for single edit (most common, avoid one array)
1335
+ const applyEdits = (textDocument, changes) => {
1336
+ object(textDocument);
1337
+ array(changes);
1338
+ // TODO don't copy all lines (can be expensive, e.g. 10000 lines = 10000 * 64bit = 64kB on every keystroke)
1339
+ const newLines = [...textDocument.lines];
1340
+ let linesDelta = 0;
1341
+ for (const change of changes) {
1342
+ const startRowIndex = change.start.rowIndex + linesDelta;
1343
+ const endRowIndex = change.end.rowIndex + linesDelta;
1344
+ const startColumnIndex = change.start.columnIndex;
1345
+ const endColumnIndex = change.end.columnIndex;
1346
+ const inserted = change.inserted;
1347
+ const deleted = change.deleted;
1348
+ number$1(startRowIndex);
1349
+ number$1(endRowIndex);
1350
+ number$1(startColumnIndex);
1351
+ number$1(endColumnIndex);
1352
+ array(inserted);
1353
+ array(deleted);
1354
+ if (startRowIndex === endRowIndex) {
1355
+ if (inserted.length === 0) {
1356
+ const line = newLines[startRowIndex];
1357
+ const before = line.slice(0, startColumnIndex);
1358
+ const after = line.slice(endColumnIndex);
1359
+ newLines[startRowIndex] = before + after;
1360
+ } else if (inserted.length === 1) {
1361
+ const line = newLines[startRowIndex];
1362
+ let before = line.slice(0, startColumnIndex);
1363
+ if (startColumnIndex > line.length) {
1364
+ before += ' '.repeat(startColumnIndex - line.length);
1365
+ }
1366
+ const after = line.slice(endColumnIndex);
1367
+ const text = inserted[0];
1368
+ newLines[startRowIndex] = before + text + after;
1369
+ } else {
1370
+ const line = newLines[startRowIndex];
1371
+ const before = line.slice(0, startColumnIndex) + inserted[0];
1372
+ const after = inserted.at(-1) + line.slice(endColumnIndex);
1373
+ spliceLargeArray(newLines, startRowIndex, deleted.length, [before, ...inserted.slice(1, -1), after]);
1374
+ // TODO only do this once after all edits, not inside loop
1375
+ textDocument.maxLineY = Math.min(textDocument.numberOfVisibleLines, newLines.length);
1376
+ }
1377
+ } else {
1378
+ if (inserted.length === 1) {
1379
+ const before = newLines[startRowIndex].slice(0, startColumnIndex) + inserted[0];
1380
+ const after = endRowIndex >= newLines.length ? '' : newLines[endRowIndex].slice(endColumnIndex);
1381
+ spliceLargeArray(newLines, startRowIndex, deleted.length, [before + after]);
1382
+ } else {
1383
+ const before = newLines[startRowIndex].slice(0, startColumnIndex) + inserted[0];
1384
+ const middle = inserted.slice(1, -1);
1385
+ const after = inserted.at(-1) + (endRowIndex >= newLines.length ? '' : newLines[endRowIndex].slice(endColumnIndex));
1386
+ spliceLargeArray(newLines, startRowIndex, deleted.length, [before, ...middle, after]);
1387
+ }
1388
+ // TODO only do this once after all edits, not inside loop
1389
+ textDocument.maxLineY = Math.min(textDocument.numberOfVisibleLines, textDocument.lines.length);
1390
+ }
1391
+ linesDelta += Math.max(inserted.length - deleted.length, 0);
1392
+ }
1393
+ return newLines;
1394
+ };
1395
+ const getLine = (textDocument, index) => {
1396
+ return textDocument.lines[index];
1397
+ };
1398
+ const getText$1 = state => {
1399
+ return joinLines$2(state.lines);
1400
+ };
1401
+ const RE_WHITESPACE = /^\s+/;
1402
+
1403
+ // TODO this doesn't belong here
397
1404
  const getIndent = line => {
398
1405
  const whitespaceMatch = line.match(RE_WHITESPACE);
399
1406
  if (!whitespaceMatch) {
@@ -476,8 +1483,7 @@ const positionAt = (textDocument, offset) => {
476
1483
  };
477
1484
 
478
1485
  // TODO this should be in a separate scrolling module
479
- // @ts-ignore
480
- const setDeltaY$3 = (state, value) => {
1486
+ const setDeltaY$2 = (state, value) => {
481
1487
  object(state);
482
1488
  number$1(value);
483
1489
  const {
@@ -515,98 +1521,19 @@ const getSelectionPairs = (selections, i) => {
515
1521
  return [first, second, third, fourth, 0];
516
1522
  };
517
1523
 
518
- const state$b = {
519
- ctx: undefined
520
- };
521
-
522
- /**
523
- * @param {()=>OffscreenCanvasRenderingContext2D} createCtx
524
- * @returns {OffscreenCanvasRenderingContext2D}
525
- */
526
- const getOrCreate = createCtx => {
527
- if (state$b.ctx) {
528
- return state$b.ctx;
529
- }
530
- state$b.ctx = createCtx();
531
- return state$b.ctx;
532
- };
533
-
534
- const createCtx = () => {
535
- const canvas = new OffscreenCanvas(0, 0);
536
- const ctx = /** @type {OffscreenCanvasRenderingContext2D} */canvas.getContext('2d');
537
- if (!ctx) {
538
- throw new Error('Failed to get canvas context 2d');
539
- }
540
- return ctx;
541
- };
542
- const getContext = () => {
543
- const ctx = getOrCreate(createCtx);
544
- return ctx;
545
- };
546
-
547
- // @ts-ignore
548
- const getFontString = (fontWeight, fontSize, fontFamily) => {
549
- return `${fontWeight} ${fontSize}px ${fontFamily}`;
550
- };
551
-
552
- const getLetterSpacingString = letterSpacing => {
553
- return `${letterSpacing}px`;
554
- };
555
- const measureTextWidth = (text, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth) => {
556
- string(text);
557
- number$1(fontWeight);
558
- number$1(fontSize);
559
- string(fontFamily);
560
- boolean(isMonoSpaceFont);
561
- number$1(charWidth);
562
- if (isMonoSpaceFont) {
563
- return text.length * charWidth;
564
- }
565
- if (typeof letterSpacing !== 'number') {
566
- throw new TypeError('letterSpacing must be of type number');
567
- }
568
- const letterSpacingString = getLetterSpacingString(letterSpacing);
569
- const fontString = getFontString(fontWeight, fontSize, fontFamily);
570
- const ctx = getContext();
571
- // @ts-ignore
572
- ctx.letterSpacing = letterSpacingString;
573
- // @ts-ignore
574
- ctx.font = fontString;
575
- // @ts-ignore
576
- const metrics = ctx.measureText(text);
577
- const width = metrics.width;
578
- return width;
579
- };
580
-
581
- const Dash = '-';
582
- const Dot = '.';
583
- const EmptyString = '';
584
- const Space = ' ';
585
- const Tab = '\t';
586
- const Underline = '_';
587
- const T = 't';
588
-
589
- const normalizeText = (text, normalize, tabSize) => {
590
- if (normalize) {
591
- return text.replaceAll(Tab, Space.repeat(tabSize));
592
- }
593
- return text;
594
- };
595
- const shouldNormalizeText = text => {
596
- return text.includes(Tab);
597
- };
598
-
599
- // TODO visible selections could also be uint16array
600
- // [top1, left1, width1, height1, top2, left2, width2, height2...]
601
1524
  const getTabCount = string => {
602
1525
  let count = 0;
603
1526
  for (const element of string) {
604
- if (element === '\t') {
1527
+ if (element === Tab) {
605
1528
  count++;
606
1529
  }
607
1530
  }
608
1531
  return count;
609
1532
  };
1533
+
1534
+ // TODO visible selections could also be uint16array
1535
+ // [top1, left1, width1, height1, top2, left2, width2, height2...]
1536
+
610
1537
  const getX = (line, column, fontWeight, fontSize, fontFamily, isMonospaceFont, letterSpacing, tabSize, halfCursorWidth, width, averageCharWidth, difference = 0) => {
611
1538
  if (!line) {
612
1539
  return 0;
@@ -718,6 +1645,9 @@ const push = (selections, startRowIndex, startColumnIndex, endRowIndex, endColum
718
1645
  newSelections[oldLength + 4] = endColumnIndex;
719
1646
  return newSelections;
720
1647
  };
1648
+
1649
+ // TODO maybe only accept sorted selection edits in the first place
1650
+
721
1651
  const emptyCursors = [];
722
1652
  const getCursorArray = (visibleCursors, isFocused) => {
723
1653
  if (!isFocused) {
@@ -882,22 +1812,15 @@ const applyEdit$1 = (editor, changes) => {
882
1812
  };
883
1813
 
884
1814
  // TODO
885
- // @ts-ignore
886
1815
  const setDeltaYFixedValue$1 = (editor, value) => {
887
- return setDeltaY$3(editor, value);
1816
+ return setDeltaY$2(editor, value);
888
1817
  };
889
-
890
- // @ts-ignore
891
- const setDeltaY$2 = (editor, value) => {
1818
+ const setDeltaY$1 = (editor, value) => {
892
1819
  return setDeltaYFixedValue$1(editor, editor.deltaY + value);
893
1820
  };
894
-
895
- // @ts-ignore
896
1821
  const isAutoClosingChange = change => {
897
1822
  return change.origin === EditorTypeWithAutoClosing;
898
1823
  };
899
-
900
- // @ts-ignore
901
1824
  const applyAutoClosingRangesEdit = (editor, changes) => {
902
1825
  const {
903
1826
  autoClosingRanges = []
@@ -937,7 +1860,6 @@ const scheduleSelections = (editor, selectionEdits) => {
937
1860
  * @param {Uint32Array|undefined} selectionChanges
938
1861
  * @returns
939
1862
  */
940
- // @ts-ignore
941
1863
  const scheduleDocumentAndCursorsSelections = (editor, changes, selectionChanges = undefined) => {
942
1864
  object(editor);
943
1865
  array(changes);
@@ -967,7 +1889,12 @@ const scheduleDocumentAndCursorsSelections = (editor, changes, selectionChanges
967
1889
  invalidStartIndex,
968
1890
  autoClosingRanges
969
1891
  };
970
- return newEditor;
1892
+ const newWidgets = applyWidgetChanges(newEditor, changes);
1893
+ const newEditor2 = {
1894
+ ...newEditor,
1895
+ widgets: newWidgets
1896
+ };
1897
+ return newEditor2;
971
1898
  };
972
1899
  // @ts-ignore
973
1900
  const scheduleDocumentAndCursorsSelectionIsUndo = (editor, changes) => {
@@ -1032,8 +1959,6 @@ const scheduleDocument = async (editor, changes) => {
1032
1959
  // /* selectionInfos */ selectionInfos,
1033
1960
  // ])
1034
1961
  };
1035
-
1036
- // @ts-ignore
1037
1962
  const hasSelection = editor => {
1038
1963
  // TODO editor.selections should always be defined
1039
1964
  return editor.selections && editor.selections.length > 0;
@@ -1074,55 +1999,27 @@ const setText = (editor, text) => {
1074
1999
  const contentHeight = lines.length * editor.rowHeight;
1075
2000
  const scrollBarHeight = getScrollBarSize(editor.height, contentHeight, minimumSliderSize);
1076
2001
  return {
1077
- ...editor,
1078
- lines,
1079
- maxLineY,
1080
- finalY,
1081
- finalDeltaY,
1082
- scrollBarHeight
1083
- };
1084
- };
1085
-
1086
- const editors = Object.create(null);
1087
- const get$6 = id => {
1088
- number$1(id);
1089
- return editors[id];
1090
- };
1091
- const set$6 = (id, oldEditor, newEditor) => {
1092
- number$1(id);
1093
- object(oldEditor);
1094
- object(newEditor);
1095
- editors[id] = {
1096
- oldState: oldEditor,
1097
- newState: newEditor
1098
- };
1099
- };
1100
-
1101
- // TODO this should be in a separate scrolling module
1102
- const setDeltaY$1 = (state, value) => {
1103
- object(state);
1104
- number$1(value);
1105
- const {
1106
- finalDeltaY,
1107
- deltaY,
1108
- numberOfVisibleLines,
1109
- height,
1110
- scrollBarHeight,
1111
- itemHeight
1112
- } = state;
1113
- const newDeltaY = clamp(value, 0, finalDeltaY);
1114
- if (deltaY === newDeltaY) {
1115
- return state;
1116
- }
1117
- const newMinLineY = Math.floor(newDeltaY / itemHeight);
1118
- const newMaxLineY = newMinLineY + numberOfVisibleLines;
1119
- const scrollBarY = getScrollBarY(newDeltaY, finalDeltaY, height, scrollBarHeight);
1120
- return {
1121
- ...state,
1122
- minLineY: newMinLineY,
1123
- maxLineY: newMaxLineY,
1124
- deltaY: newDeltaY,
1125
- scrollBarY
2002
+ ...editor,
2003
+ lines,
2004
+ maxLineY,
2005
+ finalY,
2006
+ finalDeltaY,
2007
+ scrollBarHeight
2008
+ };
2009
+ };
2010
+
2011
+ const editors = Object.create(null);
2012
+ const get$6 = id => {
2013
+ number$1(id);
2014
+ return editors[id];
2015
+ };
2016
+ const set$6 = (id, oldEditor, newEditor) => {
2017
+ number$1(id);
2018
+ object(oldEditor);
2019
+ object(newEditor);
2020
+ editors[id] = {
2021
+ oldState: oldEditor,
2022
+ newState: newEditor
1126
2023
  };
1127
2024
  };
1128
2025
 
@@ -1240,7 +2137,7 @@ class JsonRpcError extends Error {
1240
2137
  this.name = 'JsonRpcError';
1241
2138
  }
1242
2139
  }
1243
- const NewLine$2 = '\n';
2140
+ const NewLine$3 = '\n';
1244
2141
  const DomException = 'DOMException';
1245
2142
  const ReferenceError$1 = 'ReferenceError';
1246
2143
  const SyntaxError$1 = 'SyntaxError';
@@ -1288,20 +2185,20 @@ const constructError = (message, type, name) => {
1288
2185
  return new ErrorConstructor(message);
1289
2186
  };
1290
2187
  const getNewLineIndex$2 = (string, startIndex = undefined) => {
1291
- return string.indexOf(NewLine$2, startIndex);
2188
+ return string.indexOf(NewLine$3, startIndex);
1292
2189
  };
1293
2190
  const joinLines$1 = lines => {
1294
- return lines.join(NewLine$2);
2191
+ return lines.join(NewLine$3);
1295
2192
  };
1296
2193
  const MethodNotFound = -32601;
1297
2194
  const Custom = -32001;
1298
2195
  const splitLines$1 = lines => {
1299
- return lines.split(NewLine$2);
2196
+ return lines.split(NewLine$3);
1300
2197
  };
1301
2198
  const getParentStack = error => {
1302
2199
  let parentStack = error.stack || error.data || error.message || '';
1303
2200
  if (parentStack.startsWith(' at')) {
1304
- parentStack = error.message + NewLine$2 + parentStack;
2201
+ parentStack = error.message + NewLine$3 + parentStack;
1305
2202
  }
1306
2203
  return parentStack;
1307
2204
  };
@@ -1313,14 +2210,14 @@ const restoreJsonRpcError = error => {
1313
2210
  if (error && error.code && error.code === MethodNotFound) {
1314
2211
  const restoredError = new JsonRpcError(error.message);
1315
2212
  const parentStack = getParentStack(error);
1316
- restoredError.stack = parentStack + NewLine$2 + currentStack;
2213
+ restoredError.stack = parentStack + NewLine$3 + currentStack;
1317
2214
  return restoredError;
1318
2215
  }
1319
2216
  if (error && error.message) {
1320
2217
  const restoredError = constructError(error.message, error.type, error.name);
1321
2218
  if (error.data) {
1322
2219
  if (error.data.stack && error.data.type && error.message) {
1323
- restoredError.stack = error.data.type + ': ' + error.message + NewLine$2 + error.data.stack + NewLine$2 + currentStack;
2220
+ restoredError.stack = error.data.type + ': ' + error.message + NewLine$3 + error.data.stack + NewLine$3 + currentStack;
1324
2221
  } else if (error.data.stack) {
1325
2222
  restoredError.stack = error.data.stack;
1326
2223
  }
@@ -1401,7 +2298,7 @@ const getErrorResponse = (message, error, preparePrettyError, logError) => {
1401
2298
  const errorProperty = getErrorProperty(error, prettyError);
1402
2299
  return create$1$1(message, errorProperty);
1403
2300
  };
1404
- const create$5 = (message, result) => {
2301
+ const create$4 = (message, result) => {
1405
2302
  return {
1406
2303
  jsonrpc: Two,
1407
2304
  id: message.id,
@@ -1410,7 +2307,7 @@ const create$5 = (message, result) => {
1410
2307
  };
1411
2308
  const getSuccessResponse = (message, result) => {
1412
2309
  const resultProperty = result ?? null;
1413
- return create$5(message, resultProperty);
2310
+ return create$4(message, resultProperty);
1414
2311
  };
1415
2312
  const getResponse = async (message, ipc, execute, preparePrettyError, logError, requiresSocket) => {
1416
2313
  try {
@@ -1607,7 +2504,7 @@ const waitForFirstMessage$1 = async port => {
1607
2504
  return event;
1608
2505
  };
1609
2506
 
1610
- const create$4 = async () => {
2507
+ const create$3 = async () => {
1611
2508
  const {
1612
2509
  port1,
1613
2510
  port2
@@ -1652,7 +2549,7 @@ const wrap$3 = port => {
1652
2549
 
1653
2550
  const IpcParentWithExtensionHostWorker = {
1654
2551
  __proto__: null,
1655
- create: create$4,
2552
+ create: create$3,
1656
2553
  wrap: wrap$3
1657
2554
  };
1658
2555
 
@@ -1660,7 +2557,7 @@ const sendMessagePortToSyntaxHighlightingWorker = async port => {
1660
2557
  await invokeAndTransfer([port], 'SendMessagePortToSyntaxHighlightingWorker.sendMessagePortToSyntaxHighlightingWorker', port, 'HandleMessagePort.handleMessagePort');
1661
2558
  };
1662
2559
 
1663
- const create$3 = async () => {
2560
+ const create$2 = async () => {
1664
2561
  const {
1665
2562
  port1,
1666
2563
  port2
@@ -1705,7 +2602,7 @@ const wrap$1 = port => {
1705
2602
 
1706
2603
  const IpcParentWithSyntaxHighlightingWorker = {
1707
2604
  __proto__: null,
1708
- create: create$3,
2605
+ create: create$2,
1709
2606
  wrap: wrap$1
1710
2607
  };
1711
2608
 
@@ -1713,7 +2610,7 @@ const sendMessagePortToRendererProcess = async port => {
1713
2610
  await invokeAndTransfer([port], 'SendMessagePortToRendererProcess.sendMessagePortToRendererProcess', port, 'HandleMessagePort.handleMessagePort');
1714
2611
  };
1715
2612
 
1716
- const create$2 = async () => {
2613
+ const create$1 = async () => {
1717
2614
  const {
1718
2615
  port1,
1719
2616
  port2
@@ -1758,7 +2655,7 @@ const wrap = port => {
1758
2655
 
1759
2656
  const IpcParentWithRendererProcess = {
1760
2657
  __proto__: null,
1761
- create: create$2,
2658
+ create: create$1,
1762
2659
  wrap
1763
2660
  };
1764
2661
 
@@ -1775,7 +2672,7 @@ const getModule$1 = method => {
1775
2672
  }
1776
2673
  };
1777
2674
 
1778
- const create$1 = async ({
2675
+ const create = async ({
1779
2676
  method,
1780
2677
  ...options
1781
2678
  }) => {
@@ -1793,7 +2690,7 @@ const create$1 = async ({
1793
2690
  const createRpc = method => {
1794
2691
  let _ipc;
1795
2692
  const listen = async () => {
1796
- const ipc = await create$1({
2693
+ const ipc = await create({
1797
2694
  method
1798
2695
  });
1799
2696
  handleIpc(ipc);
@@ -1936,7 +2833,7 @@ const createEditor = async ({
1936
2833
  // TODO avoid creating intermediate editors here
1937
2834
  const newEditor1 = setBounds(editor, x, y, width, height, 9);
1938
2835
  const newEditor2 = setText(newEditor1, content);
1939
- const newEditor3 = setDeltaY$1(newEditor2, 0);
2836
+ const newEditor3 = setDeltaY$2(newEditor2, 0);
1940
2837
  const newEditor4 = {
1941
2838
  ...newEditor3,
1942
2839
  focused: true
@@ -2003,260 +2900,58 @@ const addCursorBelow = editor => {
2003
2900
  };
2004
2901
  };
2005
2902
 
2006
- // @ts-ignore
2007
-
2008
- // @ts-ignore
2009
2903
  const applyEdit = async (editor, changes) => {
2010
2904
  object(editor);
2011
- array(changes);
2012
- return scheduleDocumentAndCursorsSelections(editor, changes);
2013
- };
2014
-
2015
- const handleBlur = editor => {
2016
- // for (const listener of state.blurListeners) {
2017
- // listener(editor)
2018
- // }
2019
- // TODO save on blur
2020
- // Command.execute(/* Main.save */ 89)
2021
- const newEditor = {
2022
- ...editor,
2023
- focused: false
2024
- };
2025
- return newEditor;
2026
- };
2027
-
2028
- const replaceRange = (editor, ranges, replacement, origin) => {
2029
- const changes = [];
2030
- const rangesLength = ranges.length;
2031
- for (let i = 0; i < rangesLength; i += 4) {
2032
- const [selectionStartRow, selectionStartColumn, selectionEndRow, selectionEndColumn] = getSelectionPairs(ranges, i);
2033
- const start = {
2034
- rowIndex: selectionStartRow,
2035
- columnIndex: selectionStartColumn
2036
- };
2037
- const end = {
2038
- rowIndex: selectionEndRow,
2039
- columnIndex: selectionEndColumn
2040
- };
2041
- const selection = {
2042
- start,
2043
- end
2044
- };
2045
- changes.push({
2046
- start: start,
2047
- end: end,
2048
- inserted: replacement,
2049
- deleted: getSelectionText(editor, selection),
2050
- origin
2051
- });
2052
- }
2053
- return changes;
2054
- };
2055
-
2056
- // @ts-ignore
2057
- const editorReplaceSelections = (editor, replacement, origin) => {
2058
- const {
2059
- selections
2060
- } = editor;
2061
- return replaceRange(editor, selections, replacement, origin);
2062
- };
2063
-
2064
- const getAccurateColumnIndexAscii = (
2065
- // @ts-ignore
2066
- line,
2067
- // @ts-ignore
2068
- guess,
2069
- // @ts-ignore
2070
- averageCharWidth,
2071
- // @ts-ignore
2072
- eventX,
2073
- // @ts-ignore
2074
- fontWeight,
2075
- // @ts-ignore
2076
- fontSize,
2077
- // @ts-ignore
2078
- fontFamily,
2079
- // @ts-ignore
2080
- letterSpacing,
2081
- // @ts-ignore
2082
- isMonospaceFont,
2083
- // @ts-ignore
2084
- charWidth) => {
2085
- for (let i = guess; i < line.length; i++) {
2086
- const width = measureTextWidth(line.slice(0, i), fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
2087
- if (eventX - width < averageCharWidth / 2) {
2088
- return i;
2089
- }
2090
- }
2091
- return line.length;
2092
- };
2093
-
2094
- const supported = () => {
2095
- return 'Segmenter' in Intl;
2096
- };
2097
- const create = () => {
2098
- // @ts-ignore
2099
- const segmenter = new Intl.Segmenter();
2100
- return {
2101
- at(line, index) {
2102
- const segments = segmenter.segment(line);
2103
- return segments.containing(index);
2104
- },
2105
- visualIndex(line, index) {
2106
- const segments = segmenter.segment(line);
2107
- let currentVisualIndex = 0;
2108
- for (const segment of segments) {
2109
- if (segment.index >= index) {
2110
- return currentVisualIndex;
2111
- }
2112
- currentVisualIndex++;
2113
- }
2114
- return currentVisualIndex;
2115
- },
2116
- modelIndex(line, visualIndex) {
2117
- const segments = segmenter.segment(line);
2118
- let currentVisualIndex = 0;
2119
- for (const segment of segments) {
2120
- if (currentVisualIndex >= visualIndex) {
2121
- return segment.index;
2122
- }
2123
- currentVisualIndex++;
2124
- }
2125
- return line.length;
2126
- },
2127
- getSegments(line) {
2128
- return segmenter.segment(line);
2129
- }
2130
- };
2131
- };
2132
-
2133
- // @ts-ignore
2134
- const getAccurateColumnIndexUnicode = (line, guess, averageCharWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing) => {
2135
- const segmenter = create();
2136
- const segments = segmenter.getSegments(line);
2137
- const isMonospaceFont = false;
2138
- const charWidth = 0;
2139
- for (const segment of segments) {
2140
- const width = measureTextWidth(line.slice(0, segment.index), fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
2141
- if (eventX - width < averageCharWidth) {
2142
- return segment.index;
2143
- }
2144
- }
2145
- return line.length;
2146
- };
2147
-
2148
- const RE_ASCII = /^[\p{ASCII}]*$/u;
2149
- const isAscii = line => {
2150
- return RE_ASCII.test(line);
2151
- };
2152
-
2153
- // @ts-ignore
2154
- const guessOffset = (eventX, averageCharWidth) => {
2155
- const guess = Math.round(eventX / averageCharWidth);
2156
- return guess;
2157
- };
2158
-
2159
- // @ts-ignore
2160
- const normalizeGuess = (line, guess, tabSize) => {
2161
- let normalizedGuess = guess;
2162
- for (let i = 0; i < guess; i++) {
2163
- if (line[i] === Tab) {
2164
- normalizedGuess -= tabSize - 1;
2165
- }
2166
- }
2167
- return normalizedGuess;
2168
- };
2169
-
2170
- // @ts-ignore
2171
- const getAccurateColumnIndex = (line, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth, tabSize, eventX) => {
2172
- string(line);
2173
- number$1(fontWeight);
2174
- number$1(fontSize);
2175
- string(fontFamily);
2176
- number$1(letterSpacing);
2177
- boolean(isMonospaceFont);
2178
- number$1(charWidth);
2179
- number$1(tabSize);
2180
- number$1(eventX);
2181
- // Assert.greaterZero(charWidth)
2182
- const guess = guessOffset(eventX, charWidth);
2183
- const normalize = shouldNormalizeText(line);
2184
- const normalizedGuess = normalizeGuess(line, guess, tabSize);
2185
- const text = line.slice(0, normalizedGuess);
2186
- const normalizedText = normalizeText(text, normalize, tabSize);
2187
- const actual = measureTextWidth(normalizedText, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
2188
- const isAscii$1 = isAscii(line);
2189
- if (isAscii$1) {
2190
- if (Math.abs(eventX - actual) < charWidth / 2) {
2191
- return normalizedGuess;
2192
- }
2193
- return getAccurateColumnIndexAscii(line, normalizedGuess, charWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
2194
- }
2195
- return getAccurateColumnIndexUnicode(line, normalizedGuess, charWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing);
2196
- };
2197
-
2198
- // @ts-ignore
2199
- const at = (editor, eventX, eventY) => {
2200
- object(editor);
2201
- number$1(eventX);
2202
- number$1(eventY);
2203
- const {
2204
- y,
2205
- deltaY,
2206
- rowHeight,
2207
- fontSize,
2208
- fontWeight,
2209
- fontFamily,
2210
- letterSpacing,
2211
- lines,
2212
- tabSize,
2213
- differences,
2214
- isMonospaceFont,
2215
- charWidth
2216
- } = editor;
2217
- const rowIndex = Math.floor((eventY - y + deltaY) / rowHeight);
2218
- if (rowIndex < 0) {
2219
- return {
2220
- rowIndex: 0,
2221
- columnIndex: 0
2222
- };
2223
- }
2224
- const clampedRowIndex = clamp(rowIndex, 0, lines.length - 1);
2225
- const line = lines[clampedRowIndex];
2226
- const columnIndex = getAccurateColumnIndex(line, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth, tabSize, eventX);
2227
- return {
2228
- rowIndex: clampedRowIndex,
2229
- columnIndex
2905
+ array(changes);
2906
+ return scheduleDocumentAndCursorsSelections(editor, changes);
2907
+ };
2908
+
2909
+ const handleBlur = editor => {
2910
+ // for (const listener of state.blurListeners) {
2911
+ // listener(editor)
2912
+ // }
2913
+ // TODO save on blur
2914
+ // Command.execute(/* Main.save */ 89)
2915
+ const newEditor = {
2916
+ ...editor,
2917
+ focused: false
2230
2918
  };
2919
+ return newEditor;
2231
2920
  };
2232
2921
 
2233
- /**
2234
- * @deprecated this doesn't work for variable width characters (unicode/emoji).
2235
- * Use position computation in renderer process instead
2236
- *
2237
- * @param {object} editor
2238
- * @param {number} rowIndex
2239
- * @param {number} columnIndex
2240
- * @returns
2241
- */
2242
- // @ts-ignore
2243
- const x = (editor, rowIndex, columnIndex) => {
2244
- const {
2245
- columnWidth,
2246
- x
2247
- } = editor;
2248
- const offsetX = columnIndex * columnWidth + x;
2249
- return offsetX;
2922
+ const replaceRange = (editor, ranges, replacement, origin) => {
2923
+ const changes = [];
2924
+ const rangesLength = ranges.length;
2925
+ for (let i = 0; i < rangesLength; i += 4) {
2926
+ const [selectionStartRow, selectionStartColumn, selectionEndRow, selectionEndColumn] = getSelectionPairs(ranges, i);
2927
+ const start = {
2928
+ rowIndex: selectionStartRow,
2929
+ columnIndex: selectionStartColumn
2930
+ };
2931
+ const end = {
2932
+ rowIndex: selectionEndRow,
2933
+ columnIndex: selectionEndColumn
2934
+ };
2935
+ const selection = {
2936
+ start,
2937
+ end
2938
+ };
2939
+ changes.push({
2940
+ start: start,
2941
+ end: end,
2942
+ inserted: replacement,
2943
+ deleted: getSelectionText(editor, selection),
2944
+ origin
2945
+ });
2946
+ }
2947
+ return changes;
2250
2948
  };
2251
2949
 
2252
- // @ts-ignore
2253
- const y = (editor, rowIndex) => {
2950
+ const editorReplaceSelections = (editor, replacement, origin) => {
2254
2951
  const {
2255
- rowHeight,
2256
- y
2952
+ selections
2257
2953
  } = editor;
2258
- const offsetY = (rowIndex + 1) * rowHeight + y;
2259
- return offsetY;
2954
+ return replaceRange(editor, selections, replacement, origin);
2260
2955
  };
2261
2956
 
2262
2957
  const state$7 = {
@@ -2366,7 +3061,7 @@ const cancelSelection = editor => {
2366
3061
  };
2367
3062
 
2368
3063
  const isCompletionWidget = widget => {
2369
- return widget.id === 'completion';
3064
+ return widget.id === Completion;
2370
3065
  };
2371
3066
  const closeCompletion = editor => {
2372
3067
  const {
@@ -2438,17 +3133,6 @@ const compositionEnd = (editor, data) => {
2438
3133
  return scheduleDocumentAndCursorsSelections(editor, changes);
2439
3134
  };
2440
3135
 
2441
- /**
2442
- *
2443
- * @param {string} string
2444
- * @param {number|undefined} startIndex
2445
- * @returns
2446
- */
2447
- // @ts-ignore
2448
- const getNewLineIndex$1 = (string, startIndex = undefined) => {
2449
- return string.indexOf('\n', startIndex);
2450
- };
2451
-
2452
3136
  const normalizeLine$1 = line => {
2453
3137
  if (line.startsWith('Error: ')) {
2454
3138
  return line.slice(`Error: `.length);
@@ -2458,7 +3142,17 @@ const normalizeLine$1 = line => {
2458
3142
  }
2459
3143
  return line;
2460
3144
  };
2461
-
3145
+ const getCombinedMessage$1 = (error, message) => {
3146
+ const stringifiedError = normalizeLine$1(`${error}`);
3147
+ if (message) {
3148
+ return `${message}: ${stringifiedError}`;
3149
+ }
3150
+ return stringifiedError;
3151
+ };
3152
+ const NewLine$2 = '\n';
3153
+ const getNewLineIndex$1 = (string, startIndex = undefined) => {
3154
+ return string.indexOf(NewLine$2, startIndex);
3155
+ };
2462
3156
  const mergeStacks$1 = (parent, child) => {
2463
3157
  if (!child) {
2464
3158
  return parent;
@@ -2476,28 +3170,6 @@ const mergeStacks$1 = (parent, child) => {
2476
3170
  }
2477
3171
  return child;
2478
3172
  };
2479
-
2480
- // @ts-nocheck
2481
- const stringifyError = error => {
2482
- if (error instanceof DOMException && error.message) {
2483
- return `DOMException: ${error.message}`;
2484
- }
2485
- const errorPrefixes = ['Error: ', 'VError: '];
2486
- const stringifiedError = `${error}`;
2487
- for (const errorPrefix of errorPrefixes) {
2488
- if (stringifiedError.startsWith(errorPrefix)) {
2489
- return stringifiedError.slice(errorPrefix.length);
2490
- }
2491
- }
2492
- return stringifiedError;
2493
- };
2494
- const getCombinedMessage$1 = (error, message) => {
2495
- const stringifiedError = stringifyError(error);
2496
- if (message) {
2497
- return `${message}: ${stringifiedError}`;
2498
- }
2499
- return `${stringifiedError}`;
2500
- };
2501
3173
  let VError$1 = class VError extends Error {
2502
3174
  constructor(error, message) {
2503
3175
  const combinedMessage = getCombinedMessage$1(error, message);
@@ -2507,12 +3179,16 @@ let VError$1 = class VError extends Error {
2507
3179
  this.stack = mergeStacks$1(this.stack, error.stack);
2508
3180
  }
2509
3181
  if (error.codeFrame) {
3182
+ // @ts-ignore
2510
3183
  this.codeFrame = error.codeFrame;
2511
3184
  }
3185
+ if (error.code) {
3186
+ // @ts-ignore
3187
+ this.code = error.code;
3188
+ }
2512
3189
  }
2513
3190
  };
2514
3191
 
2515
- // @ts-ignore
2516
3192
  const writeText = async text => {
2517
3193
  try {
2518
3194
  string(text);
@@ -2712,7 +3388,7 @@ const characterLeft = (line, columnIndex) => {
2712
3388
  if (!supported()) {
2713
3389
  return 1;
2714
3390
  }
2715
- const segmenter = create();
3391
+ const segmenter = create$5();
2716
3392
  const last = segmenter.at(line, columnIndex - 1);
2717
3393
  return columnIndex - last.index;
2718
3394
  };
@@ -2725,7 +3401,7 @@ const characterRight = (line, columnIndex) => {
2725
3401
  if (!supported()) {
2726
3402
  return 1;
2727
3403
  }
2728
- const segmenter = create();
3404
+ const segmenter = create$5();
2729
3405
  const next = segmenter.at(line, columnIndex);
2730
3406
  return next.segment.length;
2731
3407
  };
@@ -2929,9 +3605,6 @@ const cursorSet = (editor, rowIndex, columnIndex) => {
2929
3605
  return scheduleSelections(editor, selectionEdits);
2930
3606
  };
2931
3607
 
2932
- // @ts-ignore
2933
-
2934
- // @ts-ignore
2935
3608
  const moveSelectionWithoutIntlSegmenter = (selections, i, selectionStartRow, selectionStartColumn, selectionEndRow, selectionEndColumn) => {
2936
3609
  if (selectionStartRow === 0) {
2937
3610
  moveRangeToPosition$1(selections, i, 0, 0);
@@ -2939,13 +3612,9 @@ const moveSelectionWithoutIntlSegmenter = (selections, i, selectionStartRow, sel
2939
3612
  moveRangeToPosition$1(selections, i, selectionStartRow - 1, selectionStartColumn);
2940
3613
  }
2941
3614
  };
2942
-
2943
- // @ts-ignore
2944
3615
  const getNewSelections$8 = selections => {
2945
3616
  return map(selections, moveSelectionWithoutIntlSegmenter);
2946
3617
  };
2947
-
2948
- // @ts-ignore
2949
3618
  const cursorVertical = (editor, getPosition, getEdgePosition, delta) => {
2950
3619
  // if (TextSegmenter.supported()) {
2951
3620
  // return editorCursorsVerticalWithIntlSegmenter(
@@ -2961,7 +3630,6 @@ const cursorVertical = (editor, getPosition, getEdgePosition, delta) => {
2961
3630
  return scheduleSelections(editor, newSelections);
2962
3631
  };
2963
3632
 
2964
- // @ts-ignore
2965
3633
  const cursorUp = editor => {
2966
3634
  return cursorVertical(editor);
2967
3635
  };
@@ -2989,7 +3657,6 @@ const cursorWordRight = editor => {
2989
3657
  return editorCursorHorizontalRight(editor, wordRight);
2990
3658
  };
2991
3659
 
2992
- // @ts-ignore
2993
3660
  const cutLine = async editor => {
2994
3661
  const {
2995
3662
  lines,
@@ -3001,7 +3668,6 @@ const cutLine = async editor => {
3001
3668
  const changes = replaceRange(editor, replaceRange$1, [''], EditorCut);
3002
3669
  const selectionChanges = new Uint32Array([startRowIndex, 0, startRowIndex, 0]);
3003
3670
  await writeText(line);
3004
- // @ts-ignore
3005
3671
  return scheduleDocumentAndCursorsSelections(editor, changes, selectionChanges);
3006
3672
  };
3007
3673
 
@@ -3021,7 +3687,6 @@ const cutSelectedText = async editor => {
3021
3687
  return scheduleDocumentAndCursorsSelections(editor, changes, selectionChanges);
3022
3688
  };
3023
3689
 
3024
- // @ts-ignore
3025
3690
  const cut = editor => {
3026
3691
  const {
3027
3692
  selections
@@ -3037,7 +3702,7 @@ const cut = editor => {
3037
3702
  // @ts-ignore
3038
3703
  const getChanges$6 = (lines, selections, getDelta) => {
3039
3704
  const changes = [];
3040
- // @ts-ignore
3705
+ // TODO avoid closure
3041
3706
  const deleteSelection = (selectionStartRow, selectionStartColumn, selectionEndRow, selectionEndColumn) => {
3042
3707
  const positionLeft = editorGetPositionLeft(selectionStartRow, selectionStartColumn, lines, getDelta);
3043
3708
  const selectionEnd = {
@@ -3054,7 +3719,7 @@ const getChanges$6 = (lines, selections, getDelta) => {
3054
3719
  start: positionLeft,
3055
3720
  end: selectionEnd
3056
3721
  }),
3057
- origin: Delete
3722
+ origin: DeleteLeft
3058
3723
  });
3059
3724
  };
3060
3725
  forEach(selections, deleteSelection);
@@ -3090,9 +3755,6 @@ const isAllAutoClosingPairDelete = (autoClosingRanges, selections) => {
3090
3755
  return true;
3091
3756
  };
3092
3757
 
3093
- // @ts-ignore
3094
-
3095
- // @ts-ignore
3096
3758
  const deleteLeftWithAutoClose = editor => {
3097
3759
  const {
3098
3760
  selections,
@@ -3105,8 +3767,6 @@ const deleteLeftWithAutoClose = editor => {
3105
3767
  const changes = getChanges$6(lines, selections, twoCharactersLeft);
3106
3768
  return scheduleDocumentAndCursorsSelections(editor, changes);
3107
3769
  };
3108
-
3109
- // @ts-ignore
3110
3770
  const editorDeleteHorizontalLeft = (editor, getDelta) => {
3111
3771
  const {
3112
3772
  autoClosingRanges = [],
@@ -3120,7 +3780,7 @@ const editorDeleteHorizontalLeft = (editor, getDelta) => {
3120
3780
  const changes = getChanges$6(lines, selections, getDelta);
3121
3781
  return scheduleDocumentAndCursorsSelections(editor, changes);
3122
3782
  }
3123
- const changes = editorReplaceSelections(editor, [''], Delete);
3783
+ const changes = editorReplaceSelections(editor, [''], DeleteLeft);
3124
3784
  return scheduleDocumentAndCursorsSelections(editor, changes);
3125
3785
  };
3126
3786
 
@@ -3257,170 +3917,39 @@ const applyDocumentEdits = (editor, edits) => {
3257
3917
  }
3258
3918
  if (edits.length === 0) {
3259
3919
  return editor;
3260
- }
3261
- const documentEdits = getDocumentEdits(editor, edits);
3262
- return scheduleDocumentAndCursorsSelections(editor, documentEdits);
3263
- };
3264
-
3265
- const expectedErrorMessage = 'Failed to execute formatting provider: FormattingError:';
3266
- const isFormattingError = error => {
3267
- return error && error instanceof Error && error.message.startsWith(expectedErrorMessage);
3268
- };
3269
-
3270
- // TODO also format with cursor
3271
- const format = async editor => {
3272
- try {
3273
- const edits = await format$1(editor);
3274
- return applyDocumentEdits(editor, edits);
3275
- } catch (error) {
3276
- if (isFormattingError(error)) {
3277
- console.error('Formatting Error:',
3278
- // @ts-ignore
3279
- error.message.slice(expectedErrorMessage.length));
3280
- return editor;
3281
- }
3282
- console.error(error);
3283
- const displayErrorMessage = `${error}`;
3284
- await editorShowMessage(editor, 0, 0, displayErrorMessage, true);
3285
- return editor;
3286
- }
3287
- };
3288
-
3289
- const RE_WORD_START$1 = /^\w+/;
3290
- const RE_WORD_END$1 = /\w+$/;
3291
- const getWordAt = (editor, rowIndex, columnIndex) => {
3292
- const {
3293
- lines
3294
- } = editor;
3295
- const line = lines[rowIndex];
3296
- const before = line.slice(0, columnIndex);
3297
- const matchBefore = before.match(RE_WORD_END$1);
3298
- const after = line.slice(columnIndex);
3299
- const matchAfter = after.match(RE_WORD_START$1);
3300
- let word = EmptyString;
3301
- if (matchBefore) {
3302
- word += matchBefore[0];
3303
- }
3304
- if (matchAfter) {
3305
- word += matchAfter[0];
3306
- }
3307
- return {
3308
- word
3309
- };
3310
- };
3311
- const getWordBefore = (editor, rowIndex, columnIndex) => {
3312
- const {
3313
- lines
3314
- } = editor;
3315
- const line = lines[rowIndex];
3316
- const before = line.slice(0, columnIndex);
3317
- const matchBefore = before.match(RE_WORD_END$1);
3318
- if (matchBefore) {
3319
- return matchBefore[0];
3320
- }
3321
- return EmptyString;
3322
- };
3323
-
3324
- // @ts-ignore
3325
- const getDefinition = async (editor, offset) => {
3326
- const definition = await invoke$3('ExtensionHostDefinition.executeDefinitionProvider', editor, offset);
3327
- return definition;
3328
- };
3329
-
3330
- const emptyObject = {};
3331
- const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
3332
-
3333
- /**
3334
- *
3335
- * @param {string} key
3336
- * @param {any} placeholders
3337
- * @returns {string}
3338
- */
3339
- // @ts-ignore
3340
- const i18nString = (key, placeholders = emptyObject) => {
3341
- if (placeholders === emptyObject) {
3342
- return key;
3343
- }
3344
- // @ts-ignore
3345
- const replacer = (match, rest) => {
3346
- // @ts-ignore
3347
- return placeholders[rest];
3348
- };
3349
- return key.replaceAll(RE_PLACEHOLDER, replacer);
3350
- };
3351
-
3352
- /**
3353
- * @enum {string}
3354
- */
3355
- const UiStrings = {
3356
- OrganizeImports: 'Organize Imports',
3357
- Copy: 'Copy',
3358
- CopyLineDown: 'Copy Line Down',
3359
- CopyLineUp: 'Copy Line Up',
3360
- Cut: 'Cut',
3361
- DuplicateSelection: 'Duplicate Selection',
3362
- FindAllImplementations: 'Find All Implementations',
3363
- FindAllReferences: 'Find All References',
3364
- GoToDefinition: 'Go to Definition',
3365
- GoToTypeDefinition: 'Go to Type Definition',
3366
- MoveLineDown: 'Move Line Down',
3367
- MoveLineUp: 'Move Line Up',
3368
- NoDefinitionFound: 'No definition found',
3369
- NoDefinitionFoundFor: "No definition found for '{PH1}'",
3370
- NoTypeDefinitionFound: 'No type definition found',
3371
- NoTypeDefinitionFoundFor: "No type definition found for '{PH1}'",
3372
- Paste: 'Paste',
3373
- Redo: 'Redo',
3374
- SelectAll: 'Select All',
3375
- Separator: 'Separator',
3376
- ToggleBlockComment: 'Toggle Block Comment',
3377
- ToggleLineComment: 'Toggle Line Comment',
3378
- Undo: 'Undo',
3379
- FormatDocument: 'Format Document',
3380
- SourceActions: 'Source Actions',
3381
- EditorShowHover: 'Show Hover',
3382
- EditorFormatDocumentForced: 'Editor: Format Document (forced)',
3383
- EditorSelectNextOccurrence: 'Editor: Select Next Occurrence',
3384
- EditorSelectAllOccurrences: 'Editor: Select All Occurrences',
3385
- EditorGoToDefinition: 'Editor: Go To Definition',
3386
- EditorGoToTypeDefinition: 'Editor: Go To Type Definition',
3387
- EditorSelectInsideString: 'Editor: Select Inside String',
3388
- EditorIndent: 'Editor: Indent',
3389
- EditorUnindent: 'Editor: Unindent',
3390
- EditorSortLinesAscending: 'Editor: Sort Lines Ascending',
3391
- EditorToggleComment: 'Editor: Toggle Comment',
3392
- EditorSelectUp: 'Editor: Select Up',
3393
- EditorSelectDown: 'Editor: Select Down',
3394
- EditorToggleBlockComment: 'Editor: Toggle Block Comment',
3395
- EditorOpenColorPicker: 'Editor: Open Color Picker',
3396
- EditorCloseColorPicker: 'Editor: Close Color Picker',
3397
- EditorCopyLineDown: 'Editor: Copy Line Down',
3398
- EditorCopyLineUp: 'Editor: Copy Line Up',
3399
- Replace: 'replace',
3400
- NoResults: 'No Results'
3920
+ }
3921
+ const documentEdits = getDocumentEdits(editor, edits);
3922
+ return scheduleDocumentAndCursorsSelections(editor, documentEdits);
3401
3923
  };
3402
- const noDefinitionFound = () => {
3403
- return i18nString(UiStrings.NoDefinitionFound);
3924
+
3925
+ const expectedErrorMessage = 'Failed to execute formatting provider: FormattingError:';
3926
+ const isFormattingError = error => {
3927
+ return error && error instanceof Error && error.message.startsWith(expectedErrorMessage);
3404
3928
  };
3405
3929
 
3406
- // @ts-ignore
3407
- const noDefinitionFoundFor = word => {
3408
- return i18nString(UiStrings.NoDefinitionFoundFor, {
3409
- PH1: word
3410
- });
3930
+ // TODO also format with cursor
3931
+ const format = async editor => {
3932
+ try {
3933
+ const edits = await format$1(editor);
3934
+ return applyDocumentEdits(editor, edits);
3935
+ } catch (error) {
3936
+ if (isFormattingError(error)) {
3937
+ console.error('Formatting Error:',
3938
+ // @ts-ignore
3939
+ error.message.slice(expectedErrorMessage.length));
3940
+ return editor;
3941
+ }
3942
+ console.error(error);
3943
+ const displayErrorMessage = `${error}`;
3944
+ await editorShowMessage(editor, 0, 0, displayErrorMessage, true);
3945
+ return editor;
3946
+ }
3411
3947
  };
3412
3948
 
3413
3949
  // @ts-ignore
3414
- const noTypeDefinitionFoundFor = word => {
3415
- return i18nString(UiStrings.NoTypeDefinitionFoundFor, {
3416
- PH1: word
3417
- });
3418
- };
3419
- const noTypeDefinitionFound = () => {
3420
- return i18nString(UiStrings.NoTypeDefinitionFound);
3421
- };
3422
- const noResults = () => {
3423
- return i18nString(UiStrings.NoResults);
3950
+ const getDefinition = async (editor, offset) => {
3951
+ const definition = await invoke$3('ExtensionHostDefinition.executeDefinitionProvider', editor, offset);
3952
+ return definition;
3424
3953
  };
3425
3954
 
3426
3955
  // @ts-ignore
@@ -4252,7 +4781,7 @@ const handleTouchEnd = (editor, touchEvent) => {
4252
4781
 
4253
4782
  // @ts-ignore
4254
4783
  const setDeltaY = (editor, deltaY) => {
4255
- return setDeltaY$2(editor, deltaY);
4784
+ return setDeltaY$1(editor, deltaY);
4256
4785
  };
4257
4786
 
4258
4787
  // @ts-ignore
@@ -4649,226 +5178,17 @@ const resolveCompletion = async (editor, name, completionItem) => {
4649
5178
  object(completionItem);
4650
5179
  const rowIndex = editor.selections[0];
4651
5180
  const columnIndex = editor.selections[1];
4652
- const offset = await offsetAt(editor, rowIndex, columnIndex);
4653
- // @ts-ignore
4654
- const resolvedCompletionItem = await executeResolveCompletionItem(editor, offset, name, completionItem);
4655
- return resolvedCompletionItem;
4656
- } catch {
4657
- return undefined;
4658
- }
4659
- };
4660
-
4661
- const None$1 = 1;
4662
-
4663
- const EmptyMatches = [];
4664
-
4665
- const Diagonal = 1;
4666
- const Left = 2;
4667
-
4668
- // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
4669
-
4670
- const createTable = size => {
4671
- const table = [];
4672
- for (let i = 0; i < size; i++) {
4673
- const row = new Uint8Array(size);
4674
- table.push(row);
4675
- }
4676
- return table;
4677
- };
4678
-
4679
- const isLowerCase = char => {
4680
- return char === char.toLowerCase();
4681
- };
4682
-
4683
- const isUpperCase = char => {
4684
- return char === char.toUpperCase();
4685
- };
4686
-
4687
- // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
4688
- const isGap = (columnCharBefore, columnChar) => {
4689
- switch (columnCharBefore) {
4690
- case Dash:
4691
- case Underline:
4692
- case EmptyString:
4693
- case T:
4694
- case Space:
4695
- case Dot:
4696
- return true;
4697
- }
4698
- if (isLowerCase(columnCharBefore) && isUpperCase(columnChar)) {
4699
- return true;
4700
- }
4701
- return false;
4702
- };
4703
-
4704
- // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
4705
- const getScore = (rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, column, wordLength, isDiagonalMatch) => {
4706
- if (rowCharLow !== columnCharLow) {
4707
- return -1;
4708
- }
4709
- const isMatch = rowChar === columnChar;
4710
- if (isMatch) {
4711
- if (isDiagonalMatch) {
4712
- return 8;
4713
- }
4714
- if (isGap(columnCharBefore, columnChar)) {
4715
- return 8;
4716
- }
4717
- return 5;
4718
- }
4719
- if (isGap(columnCharBefore, columnChar)) {
4720
- return 8;
4721
- }
4722
- return 5;
4723
- };
4724
-
4725
- // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
4726
-
4727
- const isPatternInWord = (patternLow, patternPos, patternLen, wordLow, wordPos, wordLen) => {
4728
- while (patternPos < patternLen && wordPos < wordLen) {
4729
- if (patternLow[patternPos] === wordLow[wordPos]) {
4730
- patternPos += 1;
4731
- }
4732
- wordPos += 1;
4733
- }
4734
- return patternPos === patternLen; // pattern must be exhausted
4735
- };
4736
-
4737
- // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
4738
- const traceHighlights = (table, arrows, patternLength, wordLength) => {
4739
- let row = patternLength;
4740
- let column = wordLength;
4741
- const matches = [];
4742
- while (row >= 1 && column >= 1) {
4743
- const arrow = arrows[row][column];
4744
- if (arrow === Left) {
4745
- column--;
4746
- } else if (arrow === Diagonal) {
4747
- row--;
4748
- column--;
4749
- const start = column + 1;
4750
- while (row >= 1 && column >= 1) {
4751
- const arrow = arrows[row][column];
4752
- if (arrow === Left) {
4753
- break;
4754
- }
4755
- if (arrow === Diagonal) {
4756
- row--;
4757
- column--;
4758
- }
4759
- }
4760
- const end = column;
4761
- matches.unshift(end, start);
4762
- }
4763
- }
4764
- matches.unshift(table[patternLength][wordLength - 1]);
4765
- return matches;
4766
- };
4767
-
4768
- // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
4769
- const gridSize = 128;
4770
- const table = createTable(gridSize);
4771
- const arrows = createTable(gridSize);
4772
- // @ts-ignore
4773
- createTable(gridSize);
4774
- const filterCompletionItem = (pattern, word) => {
4775
- const patternLength = Math.min(pattern.length, gridSize - 1);
4776
- const wordLength = Math.min(word.length, gridSize - 1);
4777
- const patternLower = pattern.toLowerCase();
4778
- const wordLower = word.toLowerCase();
4779
- if (!isPatternInWord(patternLower, 0, patternLength, wordLower, 0, wordLength)) {
4780
- return EmptyMatches;
4781
- }
4782
- let strongMatch = false;
4783
- for (let row = 1; row < patternLength + 1; row++) {
4784
- const rowChar = pattern[row - 1];
4785
- const rowCharLow = patternLower[row - 1];
4786
- for (let column = 1; column < wordLength + 1; column++) {
4787
- const columnChar = word[column - 1];
4788
- const columnCharLow = wordLower[column - 1];
4789
- const columnCharBefore = word[column - 2] || '';
4790
- const isDiagonalMatch = arrows[row - 1][column - 1] === Diagonal;
4791
- const score = getScore(rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, column, wordLength, isDiagonalMatch);
4792
- if (row === 1 && score > 5) {
4793
- strongMatch = true;
4794
- }
4795
- let diagonalScore = score + table[row - 1][column - 1];
4796
- if (isDiagonalMatch && score !== -1) {
4797
- diagonalScore += 2;
4798
- }
4799
- const leftScore = table[row][column - 1];
4800
- if (leftScore > diagonalScore) {
4801
- table[row][column] = leftScore;
4802
- arrows[row][column] = Left;
4803
- } else {
4804
- table[row][column] = diagonalScore;
4805
- arrows[row][column] = Diagonal;
4806
- }
4807
- }
4808
- }
4809
- if (!strongMatch) {
4810
- return EmptyMatches;
4811
- }
4812
- // printTables(pattern, 0, word, 0)
4813
- const highlights = traceHighlights(table, arrows, patternLength, wordLength);
4814
- return highlights;
4815
- };
4816
-
4817
- const Deprecated = 1 << 0;
4818
-
4819
- const addEmptyMatch = item => {
4820
- return {
4821
- ...item,
4822
- matches: EmptyMatches
4823
- };
4824
- };
4825
- const filterCompletionItems = (completionItems, word) => {
4826
- if (word === EmptyString) {
4827
- return completionItems.map(addEmptyMatch);
4828
- }
4829
- const filteredCompletions = [];
4830
- const deprecated = [];
4831
- for (const completionItem of completionItems) {
4832
- const {
4833
- label,
4834
- flags
4835
- } = completionItem;
4836
- const result = filterCompletionItem(word, label);
4837
- if (result !== EmptyMatches) {
4838
- if (flags & Deprecated) {
4839
- // TODO avoid mutation
4840
- completionItem.matches = EmptyMatches;
4841
- deprecated.push(completionItem);
4842
- } else {
4843
- // TODO avoid mutation
4844
- completionItem.matches = result;
4845
- filteredCompletions.push(completionItem);
4846
- }
4847
- }
4848
- }
4849
- if (deprecated.length > 0) {
4850
- filteredCompletions.push(...deprecated);
4851
- }
4852
- return filteredCompletions;
4853
- };
4854
-
4855
- const getFinalDeltaY = (height, itemHeight, itemsLength) => {
4856
- const contentHeight = itemsLength * itemHeight;
4857
- const finalDeltaY = Math.max(contentHeight - height, 0);
4858
- return finalDeltaY;
4859
- };
4860
-
4861
- const getListHeight = (itemsLength, itemHeight, maxHeight) => {
4862
- number$1(itemsLength);
4863
- number$1(itemHeight);
4864
- number$1(maxHeight);
4865
- if (itemsLength === 0) {
4866
- return itemHeight;
5181
+ const offset = await offsetAt(editor, rowIndex, columnIndex);
5182
+ // @ts-ignore
5183
+ const resolvedCompletionItem = await executeResolveCompletionItem(editor, offset, name, completionItem);
5184
+ return resolvedCompletionItem;
5185
+ } catch {
5186
+ return undefined;
4867
5187
  }
4868
- const totalHeight = itemsLength * itemHeight;
4869
- return Math.min(totalHeight, maxHeight);
4870
5188
  };
4871
5189
 
5190
+ const None = 1;
5191
+
4872
5192
  const getEditor = editorUid => {
4873
5193
  const instance = get$6(editorUid);
4874
5194
  if (!instance) {
@@ -4880,6 +5200,12 @@ const getEditor = editorUid => {
4880
5200
  return newState;
4881
5201
  };
4882
5202
 
5203
+ const getFinalDeltaY = (height, itemHeight, itemsLength) => {
5204
+ const contentHeight = itemsLength * itemHeight;
5205
+ const finalDeltaY = Math.max(contentHeight - height, 0);
5206
+ return finalDeltaY;
5207
+ };
5208
+
4883
5209
  const RE_WORD = /[\w\-]+$/;
4884
5210
  const getWordAtOffset = editor => {
4885
5211
  const {
@@ -4940,7 +5266,7 @@ const handleEditorDeleteLeft = (editorUid, state) => {
4940
5266
  const y$1 = y(editor, rowIndex);
4941
5267
  const wordAtOffset = getWordAtOffset(editor);
4942
5268
  if (!wordAtOffset) {
4943
- editor.completionState = None$1;
5269
+ editor.completionState = None;
4944
5270
  return {
4945
5271
  ...state,
4946
5272
  disposed: true
@@ -4966,7 +5292,7 @@ const dispose = state => {
4966
5292
  };
4967
5293
  };
4968
5294
  const disposeWithEditor = (state, editor) => {
4969
- editor.completionState = None$1;
5295
+ editor.completionState = None;
4970
5296
  editor.completionUid = 0;
4971
5297
  // Focus.removeAdditionalFocus(FocusKey.EditorCompletion)
4972
5298
  return dispose(state);
@@ -5020,14 +5346,26 @@ const advance = (state, word) => {
5020
5346
  };
5021
5347
  };
5022
5348
 
5349
+ const hasWidget = (widgets, id) => {
5350
+ for (const widget of widgets) {
5351
+ if (widget.id === id) {
5352
+ return true;
5353
+ }
5354
+ }
5355
+ return false;
5356
+ };
5357
+
5023
5358
  const openCompletion = async editor => {
5024
5359
  const {
5025
5360
  widgets,
5026
5361
  uid
5027
5362
  } = editor;
5363
+ if (hasWidget(widgets, Completion)) {
5364
+ return editor;
5365
+ }
5028
5366
  const completionUid = Math.random();
5029
5367
  const completionWidget = {
5030
- id: 'completion',
5368
+ id: Completion,
5031
5369
  oldState: {
5032
5370
  items: [],
5033
5371
  itemHeight: 20,
@@ -5998,7 +6336,6 @@ const showSourceActions = async editor => {
5998
6336
  return editor;
5999
6337
  };
6000
6338
 
6001
- // @ts-ignore
6002
6339
  const compareString = (a, b) => {
6003
6340
  return a.localeCompare(b);
6004
6341
  };
@@ -6783,7 +7120,7 @@ const editorUnindent = editor => {
6783
7120
  // editor.lines //?
6784
7121
 
6785
7122
  const isCompletion$2 = widget => {
6786
- return widget.id === 'completion';
7123
+ return widget.id === Completion;
6787
7124
  };
6788
7125
  const getCompletionState = editor => {
6789
7126
  const {
@@ -6794,7 +7131,7 @@ const getCompletionState = editor => {
6794
7131
  };
6795
7132
 
6796
7133
  const isCompletion$1 = widget => {
6797
- return widget.id === 'completion';
7134
+ return widget.id === Completion;
6798
7135
  };
6799
7136
  const focusIndex$1 = (editor, index) => {
6800
7137
  const child = getCompletionState(editor);
@@ -6857,7 +7194,7 @@ const getEdits = async (editor, completionItem) => {
6857
7194
  return changes;
6858
7195
  };
6859
7196
  const isCompletion = widget => {
6860
- return widget.id === 'completion';
7197
+ return widget.id === Completion;
6861
7198
  };
6862
7199
  const select = async (editor, completionItem) => {
6863
7200
  const changes = await getEdits(editor, completionItem);
@@ -6866,7 +7203,7 @@ const select = async (editor, completionItem) => {
6866
7203
  ();
6867
7204
  if (index !== -1) {
6868
7205
  editor.widgets.splice(index, 1);
6869
- editor.completionState = None$1;
7206
+ editor.completionState = None;
6870
7207
  editor.completionUid = 0;
6871
7208
  }
6872
7209
  // TODO dispose completion widget
@@ -6929,7 +7266,7 @@ const getHover = async (editor, offset) => {
6929
7266
 
6930
7267
  let _ipc;
6931
7268
  const listen$5 = async () => {
6932
- const ipc = await create$1({
7269
+ const ipc = await create({
6933
7270
  method: RendererProcess
6934
7271
  });
6935
7272
  handleIpc(ipc);
@@ -7158,14 +7495,6 @@ const handleSashPointerUp = (state, eventX, eventY) => {
7158
7495
  return state;
7159
7496
  };
7160
7497
 
7161
- const text = data => {
7162
- return {
7163
- type: Text,
7164
- text: data,
7165
- childCount: 0
7166
- };
7167
- };
7168
-
7169
7498
  const getLineInfoVirtualDom = lineInfo => {
7170
7499
  const dom = [{
7171
7500
  type: Div,
@@ -7253,7 +7582,7 @@ const renderHoverDom = {
7253
7582
  return [/* method */'Viewlet.setDom2', dom];
7254
7583
  }
7255
7584
  };
7256
- const renderBounds$1 = {
7585
+ const renderBounds = {
7257
7586
  isEqual(oldState, newState) {
7258
7587
  return oldState.x === newState.x && oldState.y === newState.y && oldState.resizedWidth === newState.resizedWidth;
7259
7588
  },
@@ -7271,10 +7600,10 @@ const renderBounds$1 = {
7271
7600
  return [SetBounds, x, y, resizedWidth, height];
7272
7601
  }
7273
7602
  };
7274
- const render$2 = [renderHoverDom, renderBounds$1];
7603
+ const render$1 = [renderHoverDom, renderBounds];
7275
7604
  const renderHover = async (oldState, newState) => {
7276
7605
  const commands = [];
7277
- for (const item of render$2) {
7606
+ for (const item of render$1) {
7278
7607
  if (!item.isEqual(oldState, newState)) {
7279
7608
  commands.push(item.apply(oldState, newState));
7280
7609
  }
@@ -7580,7 +7909,7 @@ const moveLineUp = editor => {
7580
7909
  };
7581
7910
 
7582
7911
  const Link$1 = 'Link';
7583
- const Function$1 = 'Function';
7912
+ const Function = 'Function';
7584
7913
  const Parameter = 'Parameter';
7585
7914
  const Type = 'Type';
7586
7915
  const VariableName = 'VariableName';
@@ -7639,7 +7968,7 @@ const getDecorationClassName = type => {
7639
7968
  case Ts3073:
7640
7969
  case Ts3077:
7641
7970
  case Ts3088:
7642
- return Function$1;
7971
+ return Function;
7643
7972
  case Ts1792:
7644
7973
  case Ts1793:
7645
7974
  return Parameter;
@@ -8060,424 +8389,145 @@ const getVisible = async (editor, syncIncremental) => {
8060
8389
  loadTokenizers(tokenizersToLoad);
8061
8390
  }
8062
8391
  return {
8063
- textInfos: result,
8064
- differences
8065
- };
8066
- };
8067
-
8068
- const getCursorsVirtualDom = cursors => {
8069
- const dom = [];
8070
- for (const translate of cursors) {
8071
- dom.push({
8072
- type: Div,
8073
- className: EditorCursor,
8074
- translate
8075
- });
8076
- }
8077
- return dom;
8078
- };
8079
-
8080
- const Error$1 = 'error';
8081
- const Warning = 'warning';
8082
-
8083
- const getDiagnosticClassName = type => {
8084
- // TODO use classnames enum
8085
- switch (type) {
8086
- case Error$1:
8087
- return 'DiagnosticError';
8088
- case Warning:
8089
- return 'DiagnosticWarning';
8090
- default:
8091
- return 'DiagnosticError';
8092
- }
8093
- };
8094
- const getDiagnosticVirtualDom = diagnostic => {
8095
- const {
8096
- x,
8097
- y,
8098
- width,
8099
- height,
8100
- type
8101
- } = diagnostic;
8102
- const extraClassName = getDiagnosticClassName(type);
8103
- return [{
8104
- type: Div,
8105
- className: `${Diagnostic} ${extraClassName}`,
8106
- width,
8107
- height,
8108
- top: y,
8109
- left: x,
8110
- childCount: 0
8111
- }];
8112
- };
8113
-
8114
- const getDiagnosticsVirtualDom = diagnostics => {
8115
- const dom = diagnostics.flatMap(getDiagnosticVirtualDom);
8116
- return dom;
8117
- };
8118
-
8119
- const getGutterInfoVirtualDom = gutterInfo => {
8120
- return [{
8121
- type: Span,
8122
- className: 'LineNumber',
8123
- childCount: 1
8124
- }, text(gutterInfo)];
8125
- };
8126
- const getEditorGutterVirtualDom = gutterInfos => {
8127
- const dom = gutterInfos.flatMap(getGutterInfoVirtualDom);
8128
- return dom;
8129
- };
8130
-
8131
- const getEditorRowsVirtualDom = (textInfos, differences, lineNumbers = true) => {
8132
- const dom = [];
8133
- for (let i = 0; i < textInfos.length; i++) {
8134
- const textInfo = textInfos[i];
8135
- const difference = differences[i];
8136
- dom.push({
8137
- type: Div,
8138
- className: EditorRow,
8139
- translate: px(difference),
8140
- childCount: textInfo.length / 2
8141
- });
8142
- for (let j = 0; j < textInfo.length; j += 2) {
8143
- const tokenText = textInfo[j];
8144
- const className = textInfo[j + 1];
8145
- dom.push({
8146
- type: Span,
8147
- className,
8148
- childCount: 1
8149
- }, text(tokenText));
8150
- }
8151
- }
8152
- return dom;
8153
- };
8154
-
8155
- const getIncrementalEdits = async (oldState, newState) => {
8156
- if (!newState.undoStack) {
8157
- return undefined;
8158
- }
8159
- const lastChanges = newState.undoStack.at(-1);
8160
- if (lastChanges && lastChanges.length === 1) {
8161
- const lastChange = lastChanges[0];
8162
- if (lastChange.origin === EditorType) {
8163
- const rowIndex = lastChange.start.rowIndex;
8164
- const lines = newState.lines;
8165
- const oldLine = oldState.lines[rowIndex];
8166
- const newLine = lines[rowIndex];
8167
- const incrementalEdits = await invoke$1('TokenizeIncremental.tokenizeIncremental', newState.uid, newState.languageId, oldLine, newLine, rowIndex, newState.minLineY);
8168
- if (incrementalEdits && incrementalEdits.length === 1) {
8169
- return incrementalEdits;
8170
- }
8171
- }
8172
- }
8173
- return undefined;
8174
- };
8175
-
8176
- const getSelectionsVirtualDom = selections => {
8177
- const dom = [];
8178
- for (let i = 0; i < selections.length; i += 4) {
8179
- const x = selections[i];
8180
- const y = selections[i + 1];
8181
- const width = selections[i + 2];
8182
- const height = selections[i + 3];
8183
- dom.push({
8184
- type: Div,
8185
- className: EditorSelection,
8186
- left: x,
8187
- top: y,
8188
- width,
8189
- height
8190
- });
8191
- }
8192
- return dom;
8193
- };
8194
-
8195
- const None = 'none';
8196
- const Option = 'option';
8197
-
8198
- const getFileIconVirtualDom = icon => {
8199
- return {
8200
- type: Img,
8201
- className: FileIcon,
8202
- src: icon,
8203
- role: None,
8204
- childCount: 0
8205
- };
8206
- };
8207
-
8208
- const getIconDom = (fileIcon, symbolName) => {
8209
- if (fileIcon) {
8210
- return getFileIconVirtualDom(fileIcon);
8211
- }
8212
- return {
8213
- type: Div,
8214
- className: `${ColoredMaskIcon} ${symbolName}`,
8215
- childCount: 0
8216
- };
8217
- };
8218
-
8219
- const label1 = {
8220
- type: Div,
8221
- className: Label,
8222
- childCount: 1
8223
- };
8224
- const completionHighlight = {
8225
- type: Span,
8226
- className: EditorCompletionItemHighlight,
8227
- childCount: 1
8228
- };
8229
- const getHighlightedLabelDom = (label, highlights) => {
8230
- if (highlights.length === 0) {
8231
- return [label1, text(label)];
8232
- }
8233
- const dom = [];
8234
- const labelDom = {
8235
- type: Div,
8236
- className: Label,
8237
- childCount: 0
8238
- };
8239
- dom.push(labelDom);
8240
- let position = 0;
8241
- for (let i = 0; i < highlights.length; i += 2) {
8242
- const highlightStart = highlights[i];
8243
- const highlightEnd = highlights[i + 1];
8244
- if (position < highlightStart) {
8245
- const beforeText = label.slice(position, highlightStart);
8246
- labelDom.childCount++;
8247
- dom.push(text(beforeText));
8248
- }
8249
- const highlightText = label.slice(highlightStart, highlightEnd);
8250
- labelDom.childCount++;
8251
- dom.push(completionHighlight, text(highlightText));
8252
- position = highlightEnd;
8253
- }
8254
- if (position < label.length) {
8255
- const afterText = label.slice(position);
8256
- labelDom.childCount++;
8257
- dom.push(text(afterText));
8258
- }
8259
- return dom;
8260
- };
8261
-
8262
- const getCompletionItemVirtualDom = visibleItem => {
8263
- const {
8264
- top,
8265
- label,
8266
- symbolName,
8267
- highlights,
8268
- focused,
8269
- deprecated,
8270
- fileIcon
8271
- } = visibleItem;
8272
- let className = EditorCompletionItem;
8273
- if (focused) {
8274
- className += ' ' + EditorCompletionItemFocused;
8275
- }
8276
- if (deprecated) {
8277
- className += ' ' + EditorCompletionItemDeprecated;
8278
- }
8279
- return [{
8280
- type: Div,
8281
- role: Option,
8282
- className,
8283
- top,
8284
- childCount: 2
8285
- }, getIconDom(fileIcon, symbolName), ...getHighlightedLabelDom(label, highlights)];
8392
+ textInfos: result,
8393
+ differences
8394
+ };
8286
8395
  };
8287
8396
 
8288
- const getCompletionItemsVirtualDom = visibleItems => {
8289
- if (visibleItems.length === 0) {
8290
- return [{
8397
+ const getCursorsVirtualDom = cursors => {
8398
+ const dom = [];
8399
+ for (const translate of cursors) {
8400
+ dom.push({
8291
8401
  type: Div,
8292
- childCount: 1
8293
- }, text(noResults())];
8402
+ className: EditorCursor,
8403
+ translate
8404
+ });
8294
8405
  }
8295
- const root = {
8296
- type: Div,
8297
- childCount: visibleItems.length
8298
- };
8299
- const dom = [root, ...visibleItems.flatMap(getCompletionItemVirtualDom)];
8300
8406
  return dom;
8301
8407
  };
8302
8408
 
8303
- const Property = 1;
8304
- const Value = 2;
8305
- const Function = 3;
8306
- const Variable = 4;
8307
- const Keyword = 5;
8308
- const Folder = 6;
8309
- const File = 7;
8310
- const Field = 8;
8311
-
8312
- const SymbolProperty = 'SymbolProperty';
8313
- const SymbolValue = 'SymbolValue';
8314
- const SymbolFunction = 'SymbolFunction';
8315
- const SymbolVariable = 'SymbolVariable';
8316
- const SymbolKeyword = 'SymbolKeyword';
8317
- const SymbolDefault = 'SymbolDefault';
8318
- const SymbolField = 'SymbolField';
8319
- const SymbolNone = '';
8409
+ const Error$1 = 'error';
8410
+ const Warning = 'warning';
8320
8411
 
8321
- const getSymbolName = item => {
8322
- switch (item.kind) {
8323
- case Property:
8324
- return SymbolProperty;
8325
- case Value:
8326
- return SymbolValue;
8327
- case Function:
8328
- return SymbolFunction;
8329
- case Variable:
8330
- return SymbolVariable;
8331
- case Keyword:
8332
- return SymbolKeyword;
8333
- case Field:
8334
- return SymbolField;
8335
- case File:
8336
- return SymbolNone;
8412
+ const getDiagnosticClassName = type => {
8413
+ // TODO use classnames enum
8414
+ switch (type) {
8415
+ case Error$1:
8416
+ return 'DiagnosticError';
8417
+ case Warning:
8418
+ return 'DiagnosticWarning';
8337
8419
  default:
8338
- return SymbolDefault;
8420
+ return 'DiagnosticError';
8339
8421
  }
8340
8422
  };
8341
-
8342
- const getHighlights = (item, leadingWord) => {
8423
+ const getDiagnosticVirtualDom = diagnostic => {
8343
8424
  const {
8344
- matches
8345
- } = item;
8346
- return matches.slice(1);
8425
+ x,
8426
+ y,
8427
+ width,
8428
+ height,
8429
+ type
8430
+ } = diagnostic;
8431
+ const extraClassName = getDiagnosticClassName(type);
8432
+ return [{
8433
+ type: Div,
8434
+ className: `${Diagnostic} ${extraClassName}`,
8435
+ width,
8436
+ height,
8437
+ top: y,
8438
+ left: x,
8439
+ childCount: 0
8440
+ }];
8347
8441
  };
8348
8442
 
8349
- // import * as IconTheme from '../IconTheme/IconTheme.ts'
8350
-
8351
- const getLabel = item => {
8352
- return item.label;
8443
+ const getDiagnosticsVirtualDom = diagnostics => {
8444
+ const dom = diagnostics.flatMap(getDiagnosticVirtualDom);
8445
+ return dom;
8353
8446
  };
8354
- const getFileIcon = item => {
8355
- switch (item.kind) {
8356
- case File:
8357
- // TODO IconTheme.getFileNameIcon(item.label)
8358
- return '';
8359
- case Folder:
8360
- // TODO IconTheme.getFolderNameIcon(item.label)
8361
- return '';
8362
- default:
8363
- return '';
8364
- }
8447
+
8448
+ const getGutterInfoVirtualDom = gutterInfo => {
8449
+ return [{
8450
+ type: Span,
8451
+ className: 'LineNumber',
8452
+ childCount: 1
8453
+ }, text(gutterInfo)];
8365
8454
  };
8366
- const getVisibleIem = (item, itemHeight, leadingWord, i, focusedIndex) => {
8367
- return {
8368
- label: getLabel(item),
8369
- symbolName: getSymbolName(item),
8370
- top: i * itemHeight,
8371
- highlights: getHighlights(item),
8372
- focused: i === focusedIndex,
8373
- deprecated: item.flags & Deprecated,
8374
- fileIcon: getFileIcon(item)
8375
- };
8455
+ const getEditorGutterVirtualDom = gutterInfos => {
8456
+ const dom = gutterInfos.flatMap(getGutterInfoVirtualDom);
8457
+ return dom;
8376
8458
  };
8377
8459
 
8378
- const getVisibleItems = (filteredItems, itemHeight, leadingWord, minLineY, maxLineY, focusedIndex) => {
8379
- const visibleItems = [];
8380
- for (let i = minLineY; i < maxLineY; i++) {
8381
- const filteredItem = filteredItems[i];
8382
- visibleItems.push(getVisibleIem(filteredItem, itemHeight, leadingWord, i, focusedIndex));
8460
+ const getEditorRowsVirtualDom = (textInfos, differences, lineNumbers = true) => {
8461
+ const dom = [];
8462
+ for (let i = 0; i < textInfos.length; i++) {
8463
+ const textInfo = textInfos[i];
8464
+ const difference = differences[i];
8465
+ dom.push({
8466
+ type: Div,
8467
+ className: EditorRow,
8468
+ translate: px(difference),
8469
+ childCount: textInfo.length / 2
8470
+ });
8471
+ for (let j = 0; j < textInfo.length; j += 2) {
8472
+ const tokenText = textInfo[j];
8473
+ const className = textInfo[j + 1];
8474
+ dom.push({
8475
+ type: Span,
8476
+ className,
8477
+ childCount: 1
8478
+ }, text(tokenText));
8479
+ }
8383
8480
  }
8384
- return visibleItems;
8481
+ return dom;
8385
8482
  };
8386
8483
 
8387
- const renderItems = {
8388
- isEqual(oldState, newState) {
8389
- return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.focusedIndex === newState.focusedIndex;
8390
- },
8391
- apply(oldState, newState) {
8392
- const visibleItems = getVisibleItems(newState.items, newState.itemHeight, newState.leadingWord, newState.minLineY, newState.maxLineY, newState.focusedIndex);
8393
- const dom = getCompletionItemsVirtualDom(visibleItems);
8394
- return ['setDom', dom];
8395
- }
8396
- };
8397
- const renderBounds = {
8398
- isEqual(oldState, newState) {
8399
- return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.x === newState.x && oldState.y === newState.y;
8400
- },
8401
- apply(oldState, newState) {
8402
- const {
8403
- x,
8404
- y,
8405
- width,
8406
- height
8407
- } = newState;
8408
- return [/* method */SetBounds, /* x */x, /* y */y, /* width */width, /* height */height];
8409
- }
8410
- };
8411
- const renderHeight = {
8412
- isEqual(oldState, newState) {
8413
- return oldState.items.length === newState.items.length;
8414
- },
8415
- apply(oldState, newState) {
8416
- const {
8417
- itemHeight
8418
- } = newState;
8419
- const contentHeight = newState.items.length * itemHeight;
8420
- return [/* method */SetContentHeight, /* contentHeight */contentHeight];
8421
- }
8422
- };
8423
- const renderNegativeMargin = {
8424
- isEqual(oldState, newState) {
8425
- return oldState.deltaY === newState.deltaY;
8426
- },
8427
- apply(oldState, newState) {
8428
- return [/* method */SetNegativeMargin, /* negativeMargin */-newState.deltaY];
8429
- }
8430
- };
8431
- const renderScrollBar = {
8432
- isEqual(oldState, newState) {
8433
- return oldState.negativeMargin === newState.negativeMargin && oldState.deltaY === newState.deltaY && oldState.height === newState.height && oldState.finalDeltaY === newState.finalDeltaY && oldState.items.length === newState.items.length;
8434
- },
8435
- apply(oldState, newState) {
8436
- const total = newState.items.length;
8437
- const contentHeight = total * newState.itemHeight;
8438
- const scrollBarHeight = getScrollBarSize(newState.height, contentHeight, newState.minimumSliderSize);
8439
- const scrollBarY = getScrollBarY(newState.deltaY, newState.finalDeltaY, newState.height - newState.headerHeight, scrollBarHeight);
8440
- return [/* method */SetScrollBar, /* scrollBarY */scrollBarY, /* scrollBarHeight */scrollBarHeight];
8484
+ const getIncrementalEdits = async (oldState, newState) => {
8485
+ if (!newState.undoStack) {
8486
+ return undefined;
8441
8487
  }
8442
- };
8443
- const render$1 = [renderItems, renderBounds, renderHeight, renderNegativeMargin, renderScrollBar];
8444
- const renderCompletion$1 = (oldState, newState) => {
8445
- const commands = [];
8446
- for (const item of render$1) {
8447
- if (!item.isEqual(oldState, newState)) {
8448
- commands.push(item.apply(oldState, newState));
8488
+ const lastChanges = newState.undoStack.at(-1);
8489
+ if (lastChanges && lastChanges.length === 1) {
8490
+ const lastChange = lastChanges[0];
8491
+ if (lastChange.origin === EditorType) {
8492
+ const rowIndex = lastChange.start.rowIndex;
8493
+ const lines = newState.lines;
8494
+ const oldLine = oldState.lines[rowIndex];
8495
+ const newLine = lines[rowIndex];
8496
+ const incrementalEdits = await invoke$1('TokenizeIncremental.tokenizeIncremental', newState.uid, newState.languageId, oldLine, newLine, rowIndex, newState.minLineY);
8497
+ if (incrementalEdits && incrementalEdits.length === 1) {
8498
+ return incrementalEdits;
8499
+ }
8449
8500
  }
8450
8501
  }
8451
- return commands;
8502
+ return undefined;
8452
8503
  };
8453
8504
 
8454
- const renderCompletion = (oldState, newState) => {
8455
- const commands = renderCompletion$1(oldState, newState);
8456
- const wrappedCommands = [];
8457
- const uid = newState.uid;
8458
- for (const command of commands) {
8459
- wrappedCommands.push(['Viewlet.send', uid, ...command]);
8505
+ const getSelectionsVirtualDom = selections => {
8506
+ const dom = [];
8507
+ for (let i = 0; i < selections.length; i += 4) {
8508
+ const x = selections[i];
8509
+ const y = selections[i + 1];
8510
+ const width = selections[i + 2];
8511
+ const height = selections[i + 3];
8512
+ dom.push({
8513
+ type: Div,
8514
+ className: EditorSelection,
8515
+ left: x,
8516
+ top: y,
8517
+ width,
8518
+ height
8519
+ });
8460
8520
  }
8461
- return wrappedCommands;
8462
- };
8463
- const addWidgetCompletion = widget => {
8464
- const commands = renderCompletion(widget.oldState, widget.newState);
8465
- const id = 'EditorCompletion';
8466
- // TODO how to generate a unique integer id
8467
- // that doesn't collide with ids created in renderer worker?
8468
- const uid = widget.newState.uid;
8469
- const allCommands = [];
8470
- allCommands.push(['Viewlet.create', id, uid]);
8471
- allCommands.push(...commands);
8472
- return allCommands;
8521
+ return dom;
8473
8522
  };
8523
+
8474
8524
  const addWidget = widget => {
8475
8525
  const {
8476
8526
  id
8477
8527
  } = widget;
8478
8528
  switch (id) {
8479
- case 'completion':
8480
- return addWidgetCompletion(widget);
8529
+ case Completion:
8530
+ return add(widget);
8481
8531
  default:
8482
8532
  throw new Error('unsupported widget');
8483
8533
  }
@@ -8487,22 +8537,19 @@ const renderWidget = widget => {
8487
8537
  id
8488
8538
  } = widget;
8489
8539
  switch (id) {
8490
- case 'completion':
8491
- return renderCompletion(widget.oldState, widget.newState);
8540
+ case Completion:
8541
+ return render$2(widget.oldState, widget.newState);
8492
8542
  default:
8493
8543
  throw new Error(`unsupported widget`);
8494
8544
  }
8495
8545
  };
8496
- const removeCompletion = widget => {
8497
- return [['Viewlet.send', widget.newState.uid, 'dispose']];
8498
- };
8499
8546
  const removeWidget = widget => {
8500
8547
  const {
8501
8548
  id
8502
8549
  } = widget;
8503
8550
  switch (id) {
8504
- case 'completion':
8505
- return removeCompletion(widget);
8551
+ case Completion:
8552
+ return remove$1(widget);
8506
8553
  default:
8507
8554
  throw new Error('unsupported widget');
8508
8555
  }
@@ -9292,6 +9339,7 @@ const listen$1 = async ({
9292
9339
 
9293
9340
  const listen = async () => {
9294
9341
  registerCommands(commandMap);
9342
+ register(Completion, EditorCompletionWidget);
9295
9343
  const ipc = await listen$1({
9296
9344
  method: Auto()
9297
9345
  });