@lvce-editor/editor-worker 2.1.0 → 2.2.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 +1808 -1719
  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,365 +238,1291 @@ 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');
241
+ const Dash = '-';
242
+ const Dot = '.';
243
+ const EmptyString = '';
244
+ const Space = ' ';
245
+ const Tab = '\t';
246
+ const Underline = '_';
247
+ const T = 't';
248
+
249
+ // @ts-ignore
250
+ const getFontString = (fontWeight, fontSize, fontFamily) => {
251
+ return `${fontWeight} ${fontSize}px ${fontFamily}`;
252
+ };
253
+
254
+ const getLetterSpacingString = letterSpacing => {
255
+ return `${letterSpacing}px`;
256
+ };
257
+
258
+ const state$b = {
259
+ ctx: undefined
247
260
  };
248
261
 
249
262
  /**
250
- *
251
- * @param {number} size
252
- * @param {number} contentSize
253
- * @param {number} minimumSliderSize
254
- * @returns
263
+ * @param {()=>OffscreenCanvasRenderingContext2D} createCtx
264
+ * @returns {OffscreenCanvasRenderingContext2D}
255
265
  */
256
- const getScrollBarSize = (size, contentSize, minimumSliderSize) => {
257
- if (size >= contentSize) {
258
- return 0;
266
+ const getOrCreate = createCtx => {
267
+ if (state$b.ctx) {
268
+ return state$b.ctx;
259
269
  }
260
- return Math.max(Math.round(size ** 2 / contentSize), minimumSliderSize);
261
- };
262
- const getScrollBarOffset = (delta, finalDelta, size, scrollBarSize) => {
263
- const scrollBarOffset = delta / finalDelta * (size - scrollBarSize);
264
- return scrollBarOffset;
270
+ state$b.ctx = createCtx();
271
+ return state$b.ctx;
265
272
  };
266
- const getScrollBarY = getScrollBarOffset;
267
- const getScrollBarWidth = (width, longestLineWidth) => {
268
- if (width > longestLineWidth) {
269
- return 0;
273
+
274
+ const createCtx = () => {
275
+ const canvas = new OffscreenCanvas(0, 0);
276
+ const ctx = /** @type {OffscreenCanvasRenderingContext2D} */canvas.getContext('2d');
277
+ if (!ctx) {
278
+ throw new Error('Failed to get canvas context 2d');
270
279
  }
271
- return width ** 2 / longestLineWidth;
280
+ return ctx;
272
281
  };
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
- };
288
- }
289
- // clicked at bottom
290
- return {
291
- percent: 1,
292
- handleOffset: scrollBarHeight - height + relativeY
293
- };
282
+ const getContext = () => {
283
+ const ctx = getOrCreate(createCtx);
284
+ return ctx;
294
285
  };
295
286
 
296
- // based on https://github.com/microsoft/vscode/blob/c0769274fa136b45799edeccc0d0a2f645b75caf/src/vs/base/common/arrays.ts#L625 (License MIT)
297
-
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];
287
+ const measureTextWidth = (text, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth) => {
288
+ string(text);
289
+ number$1(fontWeight);
290
+ number$1(fontSize);
291
+ string(fontFamily);
292
+ boolean(isMonoSpaceFont);
293
+ number$1(charWidth);
294
+ if (isMonoSpaceFont) {
295
+ return text.length * charWidth;
306
296
  }
307
- for (let i = 0; i < newItemsLength; i++) {
308
- array[i + start] = newItems[i];
297
+ if (typeof letterSpacing !== 'number') {
298
+ throw new TypeError('letterSpacing must be of type number');
309
299
  }
300
+ const letterSpacingString = getLetterSpacingString(letterSpacing);
301
+ const fontString = getFontString(fontWeight, fontSize, fontFamily);
302
+ const ctx = getContext();
303
+ // @ts-ignore
304
+ ctx.letterSpacing = letterSpacingString;
305
+ // @ts-ignore
306
+ ctx.font = fontString;
307
+ // @ts-ignore
308
+ const metrics = ctx.measureText(text);
309
+ const width = metrics.width;
310
+ return width;
310
311
  };
311
312
 
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
- */
313
+ const getAccurateColumnIndexAscii = (
316
314
  // @ts-ignore
317
- const spliceLargeArray = (array, start, deleteCount, newItems) => {
318
- const result = array.splice(start, deleteCount);
319
- insertInto(array, start, newItems);
320
- return result;
315
+ line,
316
+ // @ts-ignore
317
+ guess,
318
+ // @ts-ignore
319
+ averageCharWidth,
320
+ // @ts-ignore
321
+ eventX,
322
+ // @ts-ignore
323
+ fontWeight,
324
+ // @ts-ignore
325
+ fontSize,
326
+ // @ts-ignore
327
+ fontFamily,
328
+ // @ts-ignore
329
+ letterSpacing,
330
+ // @ts-ignore
331
+ isMonospaceFont,
332
+ // @ts-ignore
333
+ charWidth) => {
334
+ for (let i = guess; i < line.length; i++) {
335
+ const width = measureTextWidth(line.slice(0, i), fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
336
+ if (eventX - width < averageCharWidth / 2) {
337
+ return i;
338
+ }
339
+ }
340
+ return line.length;
321
341
  };
322
342
 
323
- const joinLines$2 = lines => {
324
- return lines.join('\n');
343
+ const supported = () => {
344
+ return 'Segmenter' in Intl;
325
345
  };
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);
346
+ const create$5 = () => {
347
+ // @ts-ignore
348
+ const segmenter = new Intl.Segmenter();
349
+ return {
350
+ at(line, index) {
351
+ const segments = segmenter.segment(line);
352
+ return segments.containing(index);
353
+ },
354
+ visualIndex(line, index) {
355
+ const segments = segmenter.segment(line);
356
+ let currentVisualIndex = 0;
357
+ for (const segment of segments) {
358
+ if (segment.index >= index) {
359
+ return currentVisualIndex;
358
360
  }
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);
361
+ currentVisualIndex++;
369
362
  }
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]);
363
+ return currentVisualIndex;
364
+ },
365
+ modelIndex(line, visualIndex) {
366
+ const segments = segmenter.segment(line);
367
+ let currentVisualIndex = 0;
368
+ for (const segment of segments) {
369
+ if (currentVisualIndex >= visualIndex) {
370
+ return segment.index;
371
+ }
372
+ currentVisualIndex++;
380
373
  }
381
- // TODO only do this once after all edits, not inside loop
382
- textDocument.maxLineY = Math.min(textDocument.numberOfVisibleLines, textDocument.lines.length);
374
+ return line.length;
375
+ },
376
+ getSegments(line) {
377
+ return segmenter.segment(line);
383
378
  }
384
- linesDelta += Math.max(inserted.length - deleted.length, 0);
385
- }
386
- return newLines;
387
- };
388
- const getLine = (textDocument, index) => {
389
- return textDocument.lines[index];
390
- };
391
- const getText$1 = state => {
392
- return joinLines$2(state.lines);
379
+ };
393
380
  };
394
- const RE_WHITESPACE = /^\s+/;
395
381
 
396
- // TODO this doesn't belong here
397
- const getIndent = line => {
398
- const whitespaceMatch = line.match(RE_WHITESPACE);
399
- if (!whitespaceMatch) {
400
- return '';
401
- }
402
- return whitespaceMatch[0];
403
- };
404
-
405
- // TDOO this doesn;t belong here
406
- const getSelectionText = (textDocument, range) => {
407
- object(textDocument);
408
- // console.log(range)
409
- // console.log(textDocument)
410
- const startRowIndex = range.start.rowIndex;
411
- const startColumnIndex = range.start.columnIndex;
412
- const endRowIndex = Math.min(range.end.rowIndex, textDocument.lines.length - 1);
413
- const endColumnIndex = range.end.columnIndex;
414
- if (startRowIndex === endRowIndex) {
415
- // console.log(startRowIndex)
416
- // console.log(textDocument.lines)
417
- return [textDocument.lines[startRowIndex].slice(startColumnIndex, endColumnIndex)];
418
- }
419
- const selectedLines = [textDocument.lines[startRowIndex].slice(startColumnIndex), ...textDocument.lines.slice(startRowIndex + 1, endRowIndex), textDocument.lines[endRowIndex].slice(0, endColumnIndex)];
420
- return selectedLines;
421
- };
422
- const offsetAtSync = async (textDocument, positionRowIndex, positionColumnIndex) => {
423
- object(textDocument);
424
- number$1(positionRowIndex);
425
- number$1(positionColumnIndex);
426
- let offset = 0;
427
- let rowIndex = 0;
428
- const lines = textDocument.lines;
429
- const max = Math.min(positionRowIndex, textDocument.lines.length);
430
- while (rowIndex < max) {
431
- offset += lines[rowIndex].length + 1;
432
- rowIndex++;
433
- }
434
- offset += positionColumnIndex;
435
- return offset;
436
- };
437
- const offsetAt = (textDocument, positionRowIndex, positionColumnIndex) => {
438
- object(textDocument);
439
- number$1(positionRowIndex);
440
- number$1(positionColumnIndex);
441
- let offset = 0;
442
- let rowIndex = 0;
443
- const lines = textDocument.lines;
444
- const max = Math.min(positionRowIndex, textDocument.lines.length);
445
- while (rowIndex < max) {
446
- offset += lines[rowIndex].length + 1;
447
- rowIndex++;
448
- }
449
- offset += positionColumnIndex;
450
- return offset;
451
- };
452
- const positionAt = (textDocument, offset) => {
453
- // console.log({ textDocument, offset })
454
- let rowIndex = 0;
455
- let columnIndex = 0;
456
- let currentOffset = 0;
457
- while (rowIndex < textDocument.lines.length && currentOffset < offset) {
458
- currentOffset += textDocument.lines[rowIndex].length + 1;
459
- rowIndex++;
460
- }
461
- if (currentOffset > offset) {
462
- rowIndex--;
463
- currentOffset -= textDocument.lines[rowIndex].length + 1;
464
- columnIndex = offset - currentOffset;
465
- } else {
466
- columnIndex = currentOffset - offset;
382
+ // @ts-ignore
383
+ const getAccurateColumnIndexUnicode = (line, guess, averageCharWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing) => {
384
+ const segmenter = create$5();
385
+ const segments = segmenter.getSegments(line);
386
+ const isMonospaceFont = false;
387
+ const charWidth = 0;
388
+ for (const segment of segments) {
389
+ const width = measureTextWidth(line.slice(0, segment.index), fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
390
+ if (eventX - width < averageCharWidth) {
391
+ return segment.index;
392
+ }
467
393
  }
468
- // for (let i = 0; i < textDocument.lines.length; i++) {
469
- // if(currentOffset)
470
- // }
471
- // TODO
472
- return {
473
- rowIndex,
474
- columnIndex
475
- };
394
+ return line.length;
476
395
  };
477
396
 
478
- // TODO this should be in a separate scrolling module
479
- // @ts-ignore
480
- const setDeltaY$3 = (state, value) => {
481
- object(state);
482
- number$1(value);
483
- const {
484
- finalDeltaY,
485
- deltaY,
486
- numberOfVisibleLines,
487
- height,
488
- scrollBarHeight,
489
- itemHeight
490
- } = state;
491
- const newDeltaY = clamp(value, 0, finalDeltaY);
492
- if (deltaY === newDeltaY) {
493
- return state;
494
- }
495
- const newMinLineY = Math.floor(newDeltaY / itemHeight);
496
- const newMaxLineY = newMinLineY + numberOfVisibleLines;
497
- const scrollBarY = getScrollBarY(newDeltaY, finalDeltaY, height, scrollBarHeight);
498
- return {
499
- ...state,
500
- minLineY: newMinLineY,
501
- maxLineY: newMaxLineY,
502
- deltaY: newDeltaY,
503
- scrollBarY
504
- };
397
+ const RE_ASCII = /^[\p{ASCII}]*$/u;
398
+ const isAscii = line => {
399
+ return RE_ASCII.test(line);
505
400
  };
506
401
 
507
- const getSelectionPairs = (selections, i) => {
508
- const first = selections[i];
509
- const second = selections[i + 1];
510
- const third = selections[i + 2];
511
- const fourth = selections[i + 3];
512
- if (first > third || first === third && second >= fourth) {
513
- return [third, fourth, first, second, 1];
402
+ const normalizeText = (text, normalize, tabSize) => {
403
+ if (normalize) {
404
+ return text.replaceAll(Tab, Space.repeat(tabSize));
514
405
  }
515
- return [first, second, third, fourth, 0];
406
+ return text;
516
407
  };
517
-
518
- const state$b = {
519
- ctx: undefined
408
+ const shouldNormalizeText = text => {
409
+ return text.includes(Tab);
520
410
  };
521
411
 
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;
412
+ // @ts-ignore
413
+ const guessOffset = (eventX, averageCharWidth) => {
414
+ const guess = Math.round(eventX / averageCharWidth);
415
+ return guess;
532
416
  };
533
417
 
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');
418
+ // @ts-ignore
419
+ const normalizeGuess = (line, guess, tabSize) => {
420
+ let normalizedGuess = guess;
421
+ for (let i = 0; i < guess; i++) {
422
+ if (line[i] === Tab) {
423
+ normalizedGuess -= tabSize - 1;
424
+ }
539
425
  }
540
- return ctx;
541
- };
542
- const getContext = () => {
543
- const ctx = getOrCreate(createCtx);
544
- return ctx;
426
+ return normalizedGuess;
545
427
  };
546
428
 
547
429
  // @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);
430
+ const getAccurateColumnIndex = (line, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth, tabSize, eventX) => {
431
+ string(line);
557
432
  number$1(fontWeight);
558
433
  number$1(fontSize);
559
434
  string(fontFamily);
560
- boolean(isMonoSpaceFont);
435
+ number$1(letterSpacing);
436
+ boolean(isMonospaceFont);
561
437
  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');
438
+ number$1(tabSize);
439
+ number$1(eventX);
440
+ // Assert.greaterZero(charWidth)
441
+ const guess = guessOffset(eventX, charWidth);
442
+ const normalize = shouldNormalizeText(line);
443
+ const normalizedGuess = normalizeGuess(line, guess, tabSize);
444
+ const text = line.slice(0, normalizedGuess);
445
+ const normalizedText = normalizeText(text, normalize, tabSize);
446
+ const actual = measureTextWidth(normalizedText, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
447
+ const isAscii$1 = isAscii(line);
448
+ if (isAscii$1) {
449
+ if (Math.abs(eventX - actual) < charWidth / 2) {
450
+ return normalizedGuess;
451
+ }
452
+ return getAccurateColumnIndexAscii(line, normalizedGuess, charWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
567
453
  }
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;
454
+ return getAccurateColumnIndexUnicode(line, normalizedGuess, charWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing);
579
455
  };
580
456
 
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));
457
+ // @ts-ignore
458
+ const at = (editor, eventX, eventY) => {
459
+ object(editor);
460
+ number$1(eventX);
461
+ number$1(eventY);
462
+ const {
463
+ y,
464
+ deltaY,
465
+ rowHeight,
466
+ fontSize,
467
+ fontWeight,
468
+ fontFamily,
469
+ letterSpacing,
470
+ lines,
471
+ tabSize,
472
+ differences,
473
+ isMonospaceFont,
474
+ charWidth
475
+ } = editor;
476
+ const rowIndex = Math.floor((eventY - y + deltaY) / rowHeight);
477
+ if (rowIndex < 0) {
478
+ return {
479
+ rowIndex: 0,
480
+ columnIndex: 0
481
+ };
592
482
  }
593
- return text;
594
- };
595
- const shouldNormalizeText = text => {
596
- return text.includes(Tab);
483
+ const clampedRowIndex = clamp(rowIndex, 0, lines.length - 1);
484
+ const line = lines[clampedRowIndex];
485
+ const columnIndex = getAccurateColumnIndex(line, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth, tabSize, eventX);
486
+ return {
487
+ rowIndex: clampedRowIndex,
488
+ columnIndex
489
+ };
597
490
  };
598
491
 
599
- // TODO visible selections could also be uint16array
600
- // [top1, left1, width1, height1, top2, left2, width2, height2...]
492
+ /**
493
+ * @deprecated this doesn't work for variable width characters (unicode/emoji).
494
+ * Use position computation in renderer process instead
495
+ *
496
+ * @param {object} editor
497
+ * @param {number} rowIndex
498
+ * @param {number} columnIndex
499
+ * @returns
500
+ */
501
+ // @ts-ignore
502
+ const x = (editor, rowIndex, columnIndex) => {
503
+ const {
504
+ columnWidth,
505
+ x
506
+ } = editor;
507
+ const offsetX = columnIndex * columnWidth + x;
508
+ return offsetX;
509
+ };
510
+
511
+ // @ts-ignore
512
+ const y = (editor, rowIndex) => {
513
+ const {
514
+ rowHeight,
515
+ y
516
+ } = editor;
517
+ const offsetY = (rowIndex + 1) * rowHeight + y;
518
+ return offsetY;
519
+ };
520
+
521
+ const emptyObject = {};
522
+ const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
523
+ const i18nString = (key, placeholders = emptyObject) => {
524
+ if (placeholders === emptyObject) {
525
+ return key;
526
+ }
527
+ const replacer = (match, rest) => {
528
+ return placeholders[rest];
529
+ };
530
+ return key.replaceAll(RE_PLACEHOLDER, replacer);
531
+ };
532
+
533
+ /**
534
+ * @enum {string}
535
+ */
536
+ const UiStrings = {
537
+ OrganizeImports: 'Organize Imports',
538
+ Copy: 'Copy',
539
+ CopyLineDown: 'Copy Line Down',
540
+ CopyLineUp: 'Copy Line Up',
541
+ Cut: 'Cut',
542
+ DuplicateSelection: 'Duplicate Selection',
543
+ FindAllImplementations: 'Find All Implementations',
544
+ FindAllReferences: 'Find All References',
545
+ GoToDefinition: 'Go to Definition',
546
+ GoToTypeDefinition: 'Go to Type Definition',
547
+ MoveLineDown: 'Move Line Down',
548
+ MoveLineUp: 'Move Line Up',
549
+ NoDefinitionFound: 'No definition found',
550
+ NoDefinitionFoundFor: "No definition found for '{PH1}'",
551
+ NoTypeDefinitionFound: 'No type definition found',
552
+ NoTypeDefinitionFoundFor: "No type definition found for '{PH1}'",
553
+ Paste: 'Paste',
554
+ Redo: 'Redo',
555
+ SelectAll: 'Select All',
556
+ Separator: 'Separator',
557
+ ToggleBlockComment: 'Toggle Block Comment',
558
+ ToggleLineComment: 'Toggle Line Comment',
559
+ Undo: 'Undo',
560
+ FormatDocument: 'Format Document',
561
+ SourceActions: 'Source Actions',
562
+ EditorShowHover: 'Show Hover',
563
+ EditorFormatDocumentForced: 'Editor: Format Document (forced)',
564
+ EditorSelectNextOccurrence: 'Editor: Select Next Occurrence',
565
+ EditorSelectAllOccurrences: 'Editor: Select All Occurrences',
566
+ EditorGoToDefinition: 'Editor: Go To Definition',
567
+ EditorGoToTypeDefinition: 'Editor: Go To Type Definition',
568
+ EditorSelectInsideString: 'Editor: Select Inside String',
569
+ EditorIndent: 'Editor: Indent',
570
+ EditorUnindent: 'Editor: Unindent',
571
+ EditorSortLinesAscending: 'Editor: Sort Lines Ascending',
572
+ EditorToggleComment: 'Editor: Toggle Comment',
573
+ EditorSelectUp: 'Editor: Select Up',
574
+ EditorSelectDown: 'Editor: Select Down',
575
+ EditorToggleBlockComment: 'Editor: Toggle Block Comment',
576
+ EditorOpenColorPicker: 'Editor: Open Color Picker',
577
+ EditorCloseColorPicker: 'Editor: Close Color Picker',
578
+ EditorCopyLineDown: 'Editor: Copy Line Down',
579
+ EditorCopyLineUp: 'Editor: Copy Line Up',
580
+ Replace: 'replace',
581
+ NoResults: 'No Results'
582
+ };
583
+ const noDefinitionFound = () => {
584
+ return i18nString(UiStrings.NoDefinitionFound);
585
+ };
586
+
587
+ // @ts-ignore
588
+ const noDefinitionFoundFor = word => {
589
+ return i18nString(UiStrings.NoDefinitionFoundFor, {
590
+ PH1: word
591
+ });
592
+ };
593
+
594
+ // @ts-ignore
595
+ const noTypeDefinitionFoundFor = word => {
596
+ return i18nString(UiStrings.NoTypeDefinitionFoundFor, {
597
+ PH1: word
598
+ });
599
+ };
600
+ const noTypeDefinitionFound = () => {
601
+ return i18nString(UiStrings.NoTypeDefinitionFound);
602
+ };
603
+ const noResults = () => {
604
+ return i18nString(UiStrings.NoResults);
605
+ };
606
+
607
+ const None$1 = 'none';
608
+ const Option = 'option';
609
+
610
+ const getFileIconVirtualDom = icon => {
611
+ return {
612
+ type: Img,
613
+ className: FileIcon,
614
+ src: icon,
615
+ role: None$1,
616
+ childCount: 0
617
+ };
618
+ };
619
+
620
+ const getIconDom = (fileIcon, symbolName) => {
621
+ if (fileIcon) {
622
+ return getFileIconVirtualDom(fileIcon);
623
+ }
624
+ return {
625
+ type: Div,
626
+ className: `${ColoredMaskIcon} ${symbolName}`,
627
+ childCount: 0
628
+ };
629
+ };
630
+
631
+ const text = data => {
632
+ return {
633
+ type: Text,
634
+ text: data,
635
+ childCount: 0
636
+ };
637
+ };
638
+
639
+ const label1 = {
640
+ type: Div,
641
+ className: Label,
642
+ childCount: 1
643
+ };
644
+ const completionHighlight = {
645
+ type: Span,
646
+ className: EditorCompletionItemHighlight,
647
+ childCount: 1
648
+ };
649
+ const getHighlightedLabelDom = (label, highlights) => {
650
+ if (highlights.length === 0) {
651
+ return [label1, text(label)];
652
+ }
653
+ const dom = [];
654
+ const labelDom = {
655
+ type: Div,
656
+ className: Label,
657
+ childCount: 0
658
+ };
659
+ dom.push(labelDom);
660
+ let position = 0;
661
+ for (let i = 0; i < highlights.length; i += 2) {
662
+ const highlightStart = highlights[i];
663
+ const highlightEnd = highlights[i + 1];
664
+ if (position < highlightStart) {
665
+ const beforeText = label.slice(position, highlightStart);
666
+ labelDom.childCount++;
667
+ dom.push(text(beforeText));
668
+ }
669
+ const highlightText = label.slice(highlightStart, highlightEnd);
670
+ labelDom.childCount++;
671
+ dom.push(completionHighlight, text(highlightText));
672
+ position = highlightEnd;
673
+ }
674
+ if (position < label.length) {
675
+ const afterText = label.slice(position);
676
+ labelDom.childCount++;
677
+ dom.push(text(afterText));
678
+ }
679
+ return dom;
680
+ };
681
+
682
+ const getCompletionItemVirtualDom = visibleItem => {
683
+ const {
684
+ top,
685
+ label,
686
+ symbolName,
687
+ highlights,
688
+ focused,
689
+ deprecated,
690
+ fileIcon
691
+ } = visibleItem;
692
+ let className = EditorCompletionItem;
693
+ if (focused) {
694
+ className += ' ' + EditorCompletionItemFocused;
695
+ }
696
+ if (deprecated) {
697
+ className += ' ' + EditorCompletionItemDeprecated;
698
+ }
699
+ return [{
700
+ type: Div,
701
+ role: Option,
702
+ className,
703
+ top,
704
+ childCount: 2
705
+ }, getIconDom(fileIcon, symbolName), ...getHighlightedLabelDom(label, highlights)];
706
+ };
707
+
708
+ const getCompletionItemsVirtualDom = visibleItems => {
709
+ if (visibleItems.length === 0) {
710
+ return [{
711
+ type: Div,
712
+ childCount: 1
713
+ }, text(noResults())];
714
+ }
715
+ const root = {
716
+ type: Div,
717
+ childCount: visibleItems.length
718
+ };
719
+ const dom = [root, ...visibleItems.flatMap(getCompletionItemVirtualDom)];
720
+ return dom;
721
+ };
722
+
723
+ const Deprecated = 1 << 0;
724
+
725
+ const Property = 1;
726
+ const Value = 2;
727
+ const Function$1 = 3;
728
+ const Variable = 4;
729
+ const Keyword = 5;
730
+ const Folder = 6;
731
+ const File = 7;
732
+ const Field = 8;
733
+
734
+ const SymbolProperty = 'SymbolProperty';
735
+ const SymbolValue = 'SymbolValue';
736
+ const SymbolFunction = 'SymbolFunction';
737
+ const SymbolVariable = 'SymbolVariable';
738
+ const SymbolKeyword = 'SymbolKeyword';
739
+ const SymbolDefault = 'SymbolDefault';
740
+ const SymbolField = 'SymbolField';
741
+ const SymbolNone = '';
742
+
743
+ const getSymbolName = item => {
744
+ switch (item.kind) {
745
+ case Property:
746
+ return SymbolProperty;
747
+ case Value:
748
+ return SymbolValue;
749
+ case Function$1:
750
+ return SymbolFunction;
751
+ case Variable:
752
+ return SymbolVariable;
753
+ case Keyword:
754
+ return SymbolKeyword;
755
+ case Field:
756
+ return SymbolField;
757
+ case File:
758
+ return SymbolNone;
759
+ default:
760
+ return SymbolDefault;
761
+ }
762
+ };
763
+
764
+ const getHighlights = item => {
765
+ const {
766
+ matches
767
+ } = item;
768
+ return matches.slice(1);
769
+ };
770
+
771
+ // import * as IconTheme from '../IconTheme/IconTheme.ts'
772
+
773
+ const getLabel = item => {
774
+ return item.label;
775
+ };
776
+ const getFileIcon = item => {
777
+ switch (item.kind) {
778
+ case File:
779
+ // TODO IconTheme.getFileNameIcon(item.label)
780
+ return '';
781
+ case Folder:
782
+ // TODO IconTheme.getFolderNameIcon(item.label)
783
+ return '';
784
+ default:
785
+ return '';
786
+ }
787
+ };
788
+ const getVisibleIem = (item, itemHeight, leadingWord, i, focusedIndex) => {
789
+ return {
790
+ label: getLabel(item),
791
+ symbolName: getSymbolName(item),
792
+ top: i * itemHeight,
793
+ highlights: getHighlights(item),
794
+ focused: i === focusedIndex,
795
+ deprecated: item.flags & Deprecated,
796
+ fileIcon: getFileIcon(item)
797
+ };
798
+ };
799
+
800
+ const getVisibleItems = (filteredItems, itemHeight, leadingWord, minLineY, maxLineY, focusedIndex) => {
801
+ const visibleItems = [];
802
+ for (let i = minLineY; i < maxLineY; i++) {
803
+ const filteredItem = filteredItems[i];
804
+ visibleItems.push(getVisibleIem(filteredItem, itemHeight, leadingWord, i, focusedIndex));
805
+ }
806
+ return visibleItems;
807
+ };
808
+
809
+ /**
810
+ *
811
+ * @param {number} size
812
+ * @param {number} contentSize
813
+ * @param {number} minimumSliderSize
814
+ * @returns
815
+ */
816
+ const getScrollBarSize = (size, contentSize, minimumSliderSize) => {
817
+ if (size >= contentSize) {
818
+ return 0;
819
+ }
820
+ return Math.max(Math.round(size ** 2 / contentSize), minimumSliderSize);
821
+ };
822
+ const getScrollBarOffset = (delta, finalDelta, size, scrollBarSize) => {
823
+ const scrollBarOffset = delta / finalDelta * (size - scrollBarSize);
824
+ return scrollBarOffset;
825
+ };
826
+ const getScrollBarY = getScrollBarOffset;
827
+ const getScrollBarWidth = (width, longestLineWidth) => {
828
+ if (width > longestLineWidth) {
829
+ return 0;
830
+ }
831
+ return width ** 2 / longestLineWidth;
832
+ };
833
+ const getNewDeltaPercent = (height, scrollBarHeight, relativeY) => {
834
+ const halfScrollBarHeight = scrollBarHeight / 2;
835
+ if (relativeY <= halfScrollBarHeight) {
836
+ // clicked at top
837
+ return {
838
+ percent: 0,
839
+ handleOffset: relativeY
840
+ };
841
+ }
842
+ if (relativeY <= height - halfScrollBarHeight) {
843
+ // clicked in middle
844
+ return {
845
+ percent: (relativeY - halfScrollBarHeight) / (height - scrollBarHeight),
846
+ handleOffset: halfScrollBarHeight
847
+ };
848
+ }
849
+ // clicked at bottom
850
+ return {
851
+ percent: 1,
852
+ handleOffset: scrollBarHeight - height + relativeY
853
+ };
854
+ };
855
+
856
+ const renderItems = {
857
+ isEqual(oldState, newState) {
858
+ return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.focusedIndex === newState.focusedIndex;
859
+ },
860
+ apply(oldState, newState) {
861
+ const visibleItems = getVisibleItems(newState.items, newState.itemHeight, newState.leadingWord, newState.minLineY, newState.maxLineY, newState.focusedIndex);
862
+ const dom = getCompletionItemsVirtualDom(visibleItems);
863
+ return ['setDom', dom];
864
+ }
865
+ };
866
+ const renderBounds$1 = {
867
+ isEqual(oldState, newState) {
868
+ return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.x === newState.x && oldState.y === newState.y;
869
+ },
870
+ apply(oldState, newState) {
871
+ const {
872
+ x,
873
+ y,
874
+ width,
875
+ height
876
+ } = newState;
877
+ return [/* method */SetBounds, /* x */x, /* y */y, /* width */width, /* height */height];
878
+ }
879
+ };
880
+ const renderHeight = {
881
+ isEqual(oldState, newState) {
882
+ return oldState.items.length === newState.items.length;
883
+ },
884
+ apply(oldState, newState) {
885
+ const {
886
+ itemHeight
887
+ } = newState;
888
+ const contentHeight = newState.items.length * itemHeight;
889
+ return [/* method */SetContentHeight, /* contentHeight */contentHeight];
890
+ }
891
+ };
892
+ const renderNegativeMargin = {
893
+ isEqual(oldState, newState) {
894
+ return oldState.deltaY === newState.deltaY;
895
+ },
896
+ apply(oldState, newState) {
897
+ return [/* method */SetNegativeMargin, /* negativeMargin */-newState.deltaY];
898
+ }
899
+ };
900
+ const renderScrollBar = {
901
+ isEqual(oldState, newState) {
902
+ return oldState.negativeMargin === newState.negativeMargin && oldState.deltaY === newState.deltaY && oldState.height === newState.height && oldState.finalDeltaY === newState.finalDeltaY && oldState.items.length === newState.items.length;
903
+ },
904
+ apply(oldState, newState) {
905
+ const total = newState.items.length;
906
+ const contentHeight = total * newState.itemHeight;
907
+ const scrollBarHeight = getScrollBarSize(newState.height, contentHeight, newState.minimumSliderSize);
908
+ const scrollBarY = getScrollBarY(newState.deltaY, newState.finalDeltaY, newState.height - newState.headerHeight, scrollBarHeight);
909
+ return [/* method */SetScrollBar, /* scrollBarY */scrollBarY, /* scrollBarHeight */scrollBarHeight];
910
+ }
911
+ };
912
+ const render$3 = [renderItems, renderBounds$1, renderHeight, renderNegativeMargin, renderScrollBar];
913
+ const renderCompletion = (oldState, newState) => {
914
+ const commands = [];
915
+ for (const item of render$3) {
916
+ if (!item.isEqual(oldState, newState)) {
917
+ commands.push(item.apply(oldState, newState));
918
+ }
919
+ }
920
+ return commands;
921
+ };
922
+
923
+ const EmptyMatches = [];
924
+
925
+ const Diagonal = 1;
926
+ const Left = 2;
927
+
928
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
929
+
930
+ const createTable = size => {
931
+ const table = [];
932
+ for (let i = 0; i < size; i++) {
933
+ const row = new Uint8Array(size);
934
+ table.push(row);
935
+ }
936
+ return table;
937
+ };
938
+
939
+ const isLowerCase = char => {
940
+ return char === char.toLowerCase();
941
+ };
942
+
943
+ const isUpperCase = char => {
944
+ return char === char.toUpperCase();
945
+ };
946
+
947
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
948
+ const isGap = (columnCharBefore, columnChar) => {
949
+ switch (columnCharBefore) {
950
+ case Dash:
951
+ case Underline:
952
+ case EmptyString:
953
+ case T:
954
+ case Space:
955
+ case Dot:
956
+ return true;
957
+ }
958
+ if (isLowerCase(columnCharBefore) && isUpperCase(columnChar)) {
959
+ return true;
960
+ }
961
+ return false;
962
+ };
963
+
964
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
965
+ const getScore = (rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, column, wordLength, isDiagonalMatch) => {
966
+ if (rowCharLow !== columnCharLow) {
967
+ return -1;
968
+ }
969
+ const isMatch = rowChar === columnChar;
970
+ if (isMatch) {
971
+ if (isDiagonalMatch) {
972
+ return 8;
973
+ }
974
+ if (isGap(columnCharBefore, columnChar)) {
975
+ return 8;
976
+ }
977
+ return 5;
978
+ }
979
+ if (isGap(columnCharBefore, columnChar)) {
980
+ return 8;
981
+ }
982
+ return 5;
983
+ };
984
+
985
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
986
+
987
+ const isPatternInWord = (patternLow, patternPos, patternLen, wordLow, wordPos, wordLen) => {
988
+ while (patternPos < patternLen && wordPos < wordLen) {
989
+ if (patternLow[patternPos] === wordLow[wordPos]) {
990
+ patternPos += 1;
991
+ }
992
+ wordPos += 1;
993
+ }
994
+ return patternPos === patternLen; // pattern must be exhausted
995
+ };
996
+
997
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
998
+ const traceHighlights = (table, arrows, patternLength, wordLength) => {
999
+ let row = patternLength;
1000
+ let column = wordLength;
1001
+ const matches = [];
1002
+ while (row >= 1 && column >= 1) {
1003
+ const arrow = arrows[row][column];
1004
+ if (arrow === Left) {
1005
+ column--;
1006
+ } else if (arrow === Diagonal) {
1007
+ row--;
1008
+ column--;
1009
+ const start = column + 1;
1010
+ while (row >= 1 && column >= 1) {
1011
+ const arrow = arrows[row][column];
1012
+ if (arrow === Left) {
1013
+ break;
1014
+ }
1015
+ if (arrow === Diagonal) {
1016
+ row--;
1017
+ column--;
1018
+ }
1019
+ }
1020
+ const end = column;
1021
+ matches.unshift(end, start);
1022
+ }
1023
+ }
1024
+ matches.unshift(table[patternLength][wordLength - 1]);
1025
+ return matches;
1026
+ };
1027
+
1028
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
1029
+ const gridSize = 128;
1030
+ const table = createTable(gridSize);
1031
+ const arrows = createTable(gridSize);
1032
+ // @ts-ignore
1033
+ createTable(gridSize);
1034
+ const filterCompletionItem = (pattern, word) => {
1035
+ const patternLength = Math.min(pattern.length, gridSize - 1);
1036
+ const wordLength = Math.min(word.length, gridSize - 1);
1037
+ const patternLower = pattern.toLowerCase();
1038
+ const wordLower = word.toLowerCase();
1039
+ if (!isPatternInWord(patternLower, 0, patternLength, wordLower, 0, wordLength)) {
1040
+ return EmptyMatches;
1041
+ }
1042
+ let strongMatch = false;
1043
+ for (let row = 1; row < patternLength + 1; row++) {
1044
+ const rowChar = pattern[row - 1];
1045
+ const rowCharLow = patternLower[row - 1];
1046
+ for (let column = 1; column < wordLength + 1; column++) {
1047
+ const columnChar = word[column - 1];
1048
+ const columnCharLow = wordLower[column - 1];
1049
+ const columnCharBefore = word[column - 2] || '';
1050
+ const isDiagonalMatch = arrows[row - 1][column - 1] === Diagonal;
1051
+ const score = getScore(rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, column, wordLength, isDiagonalMatch);
1052
+ if (row === 1 && score > 5) {
1053
+ strongMatch = true;
1054
+ }
1055
+ let diagonalScore = score + table[row - 1][column - 1];
1056
+ if (isDiagonalMatch && score !== -1) {
1057
+ diagonalScore += 2;
1058
+ }
1059
+ const leftScore = table[row][column - 1];
1060
+ if (leftScore > diagonalScore) {
1061
+ table[row][column] = leftScore;
1062
+ arrows[row][column] = Left;
1063
+ } else {
1064
+ table[row][column] = diagonalScore;
1065
+ arrows[row][column] = Diagonal;
1066
+ }
1067
+ }
1068
+ }
1069
+ if (!strongMatch) {
1070
+ return EmptyMatches;
1071
+ }
1072
+ // printTables(pattern, 0, word, 0)
1073
+ const highlights = traceHighlights(table, arrows, patternLength, wordLength);
1074
+ return highlights;
1075
+ };
1076
+
1077
+ const addEmptyMatch = item => {
1078
+ return {
1079
+ ...item,
1080
+ matches: EmptyMatches
1081
+ };
1082
+ };
1083
+ const filterCompletionItems = (completionItems, word) => {
1084
+ if (word === EmptyString) {
1085
+ return completionItems.map(addEmptyMatch);
1086
+ }
1087
+ const filteredCompletions = [];
1088
+ const deprecated = [];
1089
+ for (const completionItem of completionItems) {
1090
+ const {
1091
+ label,
1092
+ flags
1093
+ } = completionItem;
1094
+ const result = filterCompletionItem(word, label);
1095
+ if (result !== EmptyMatches) {
1096
+ if (flags & Deprecated) {
1097
+ // TODO avoid mutation
1098
+ completionItem.matches = EmptyMatches;
1099
+ deprecated.push(completionItem);
1100
+ } else {
1101
+ // TODO avoid mutation
1102
+ completionItem.matches = result;
1103
+ filteredCompletions.push(completionItem);
1104
+ }
1105
+ }
1106
+ }
1107
+ if (deprecated.length > 0) {
1108
+ filteredCompletions.push(...deprecated);
1109
+ }
1110
+ return filteredCompletions;
1111
+ };
1112
+
1113
+ const getListHeight = (itemsLength, itemHeight, maxHeight) => {
1114
+ number$1(itemsLength);
1115
+ number$1(itemHeight);
1116
+ number$1(maxHeight);
1117
+ if (itemsLength === 0) {
1118
+ return itemHeight;
1119
+ }
1120
+ const totalHeight = itemsLength * itemHeight;
1121
+ return Math.min(totalHeight, maxHeight);
1122
+ };
1123
+
1124
+ const RE_WORD_START$1 = /^\w+/;
1125
+ const RE_WORD_END$1 = /\w+$/;
1126
+ const getWordAt = (editor, rowIndex, columnIndex) => {
1127
+ const {
1128
+ lines
1129
+ } = editor;
1130
+ const line = lines[rowIndex];
1131
+ const before = line.slice(0, columnIndex);
1132
+ const matchBefore = before.match(RE_WORD_END$1);
1133
+ const after = line.slice(columnIndex);
1134
+ const matchAfter = after.match(RE_WORD_START$1);
1135
+ let word = EmptyString;
1136
+ if (matchBefore) {
1137
+ word += matchBefore[0];
1138
+ }
1139
+ if (matchAfter) {
1140
+ word += matchAfter[0];
1141
+ }
1142
+ return {
1143
+ word
1144
+ };
1145
+ };
1146
+ const getWordBefore = (editor, rowIndex, columnIndex) => {
1147
+ const {
1148
+ lines
1149
+ } = editor;
1150
+ const line = lines[rowIndex];
1151
+ const before = line.slice(0, columnIndex);
1152
+ const matchBefore = before.match(RE_WORD_END$1);
1153
+ if (matchBefore) {
1154
+ return matchBefore[0];
1155
+ }
1156
+ return EmptyString;
1157
+ };
1158
+
1159
+ const render$2 = (oldState, newState) => {
1160
+ const commands = renderCompletion(oldState, newState);
1161
+ const wrappedCommands = [];
1162
+ const uid = newState.uid;
1163
+ for (const command of commands) {
1164
+ wrappedCommands.push(['Viewlet.send', uid, ...command]);
1165
+ }
1166
+ return wrappedCommands;
1167
+ };
1168
+ const add = widget => {
1169
+ const commands = render$2(widget.oldState, widget.newState);
1170
+ const id = 'EditorCompletion';
1171
+ // TODO how to generate a unique integer id
1172
+ // that doesn't collide with ids created in renderer worker?
1173
+ const uid = widget.newState.uid;
1174
+ const allCommands = [];
1175
+ allCommands.push(['Viewlet.create', id, uid]);
1176
+ allCommands.push(...commands);
1177
+ return allCommands;
1178
+ };
1179
+ const remove$1 = widget => {
1180
+ return [['Viewlet.send', widget.newState.uid, 'dispose']];
1181
+ };
1182
+ const handleEditorType$1 = (editor, state) => {
1183
+ const {
1184
+ unfilteredItems,
1185
+ itemHeight,
1186
+ maxHeight
1187
+ } = state;
1188
+ const {
1189
+ selections
1190
+ } = editor;
1191
+ const rowIndex = selections[0];
1192
+ const columnIndex = selections[1];
1193
+ const x$1 = x(editor, rowIndex, columnIndex);
1194
+ const y$1 = y(editor, rowIndex);
1195
+ const wordAtOffset = getWordBefore(editor, rowIndex, columnIndex);
1196
+ const items = filterCompletionItems(unfilteredItems, wordAtOffset);
1197
+ const newMinLineY = 0;
1198
+ const newMaxLineY = Math.min(items.length, 8);
1199
+ const height = getListHeight(items.length, itemHeight, maxHeight);
1200
+ const finalDeltaY = items.length * itemHeight - height;
1201
+ return {
1202
+ ...state,
1203
+ items,
1204
+ x: x$1,
1205
+ y: y$1,
1206
+ minLineY: newMinLineY,
1207
+ maxLineY: newMaxLineY,
1208
+ leadingWord: wordAtOffset,
1209
+ height,
1210
+ finalDeltaY
1211
+ };
1212
+ };
1213
+ const handleEditorDeleteLeft$1 = (editor, state) => {
1214
+ const {
1215
+ unfilteredItems,
1216
+ itemHeight,
1217
+ maxHeight
1218
+ } = state;
1219
+ const {
1220
+ selections
1221
+ } = editor;
1222
+ const rowIndex = selections[0];
1223
+ const columnIndex = selections[1];
1224
+ const x$1 = x(editor, rowIndex, columnIndex);
1225
+ const y$1 = y(editor, rowIndex);
1226
+ const wordAtOffset = getWordBefore(editor, rowIndex, columnIndex);
1227
+ if (!wordAtOffset) {
1228
+ return state;
1229
+ }
1230
+ const items = filterCompletionItems(unfilteredItems, wordAtOffset);
1231
+ const newMaxLineY = Math.min(items.length, 8);
1232
+ const height = getListHeight(items.length, itemHeight, maxHeight);
1233
+ return {
1234
+ ...state,
1235
+ items,
1236
+ x: x$1,
1237
+ y: y$1,
1238
+ maxLineY: newMaxLineY,
1239
+ leadingWord: wordAtOffset,
1240
+ height
1241
+ };
1242
+ };
1243
+
1244
+ const EditorCompletionWidget = {
1245
+ __proto__: null,
1246
+ add,
1247
+ handleEditorDeleteLeft: handleEditorDeleteLeft$1,
1248
+ handleEditorType: handleEditorType$1,
1249
+ remove: remove$1,
1250
+ render: render$2
1251
+ };
1252
+
1253
+ const Completion = 'completion';
1254
+
1255
+ const getModule$2 = id => {
1256
+ switch (id) {
1257
+ case Completion:
1258
+ return EditorCompletionWidget;
1259
+ default:
1260
+ throw new Error('unsupported widget');
1261
+ }
1262
+ };
1263
+
1264
+ const applyWidgetChange = (editor, widget, changes) => {
1265
+ const module = getModule$2(widget.id);
1266
+ if (changes.length === 1 && changes[0].origin === EditorType && module.handleEditorType) {
1267
+ const newState = module.handleEditorType(editor, widget.newState);
1268
+ return {
1269
+ ...widget,
1270
+ newState
1271
+ };
1272
+ }
1273
+ if (changes.length === 1 && changes[0].origin === DeleteLeft && module.handleEditorDeleteLeft) {
1274
+ const newState = module.handleEditorDeleteLeft(editor, widget.newState);
1275
+ return {
1276
+ ...widget,
1277
+ newState
1278
+ };
1279
+ }
1280
+ return widget;
1281
+ };
1282
+
1283
+ const applyWidgetChanges = (editor, changes) => {
1284
+ const widgets = editor.widgets || [];
1285
+ if (widgets.length === 0) {
1286
+ return widgets;
1287
+ }
1288
+ const newWidgets = widgets.map(widget => {
1289
+ const newWidget = applyWidgetChange(editor, widget, changes);
1290
+ return newWidget;
1291
+ });
1292
+ return newWidgets;
1293
+ };
1294
+
1295
+ const splitLines$2 = lines => {
1296
+ if (!lines) {
1297
+ return [];
1298
+ }
1299
+ return lines.split('\n');
1300
+ };
1301
+
1302
+ // based on https://github.com/microsoft/vscode/blob/c0769274fa136b45799edeccc0d0a2f645b75caf/src/vs/base/common/arrays.ts#L625 (License MIT)
1303
+
1304
+ // @ts-ignore
1305
+ const insertInto = (array, start, newItems) => {
1306
+ const originalLength = array.length;
1307
+ const newItemsLength = newItems.length;
1308
+ array.length = originalLength + newItemsLength;
1309
+ // Move the items after the start index, start from the end so that we don't overwrite any value.
1310
+ for (let i = originalLength - 1; i >= start; i--) {
1311
+ array[i + newItemsLength] = array[i];
1312
+ }
1313
+ for (let i = 0; i < newItemsLength; i++) {
1314
+ array[i + start] = newItems[i];
1315
+ }
1316
+ };
1317
+
1318
+ /**
1319
+ * Alternative to the native Array.splice method, it
1320
+ * can only support limited number of items due to the maximum call stack size limit.
1321
+ */
1322
+ // @ts-ignore
1323
+ const spliceLargeArray = (array, start, deleteCount, newItems) => {
1324
+ const result = array.splice(start, deleteCount);
1325
+ insertInto(array, start, newItems);
1326
+ return result;
1327
+ };
1328
+
1329
+ const joinLines$2 = lines => {
1330
+ return lines.join('\n');
1331
+ };
1332
+
1333
+ // TODO have function for single edit (most common, avoid one array)
1334
+ const applyEdits = (textDocument, changes) => {
1335
+ object(textDocument);
1336
+ array(changes);
1337
+ // TODO don't copy all lines (can be expensive, e.g. 10000 lines = 10000 * 64bit = 64kB on every keystroke)
1338
+ const newLines = [...textDocument.lines];
1339
+ let linesDelta = 0;
1340
+ for (const change of changes) {
1341
+ const startRowIndex = change.start.rowIndex + linesDelta;
1342
+ const endRowIndex = change.end.rowIndex + linesDelta;
1343
+ const startColumnIndex = change.start.columnIndex;
1344
+ const endColumnIndex = change.end.columnIndex;
1345
+ const inserted = change.inserted;
1346
+ const deleted = change.deleted;
1347
+ number$1(startRowIndex);
1348
+ number$1(endRowIndex);
1349
+ number$1(startColumnIndex);
1350
+ number$1(endColumnIndex);
1351
+ array(inserted);
1352
+ array(deleted);
1353
+ if (startRowIndex === endRowIndex) {
1354
+ if (inserted.length === 0) {
1355
+ const line = newLines[startRowIndex];
1356
+ const before = line.slice(0, startColumnIndex);
1357
+ const after = line.slice(endColumnIndex);
1358
+ newLines[startRowIndex] = before + after;
1359
+ } else if (inserted.length === 1) {
1360
+ const line = newLines[startRowIndex];
1361
+ let before = line.slice(0, startColumnIndex);
1362
+ if (startColumnIndex > line.length) {
1363
+ before += ' '.repeat(startColumnIndex - line.length);
1364
+ }
1365
+ const after = line.slice(endColumnIndex);
1366
+ const text = inserted[0];
1367
+ newLines[startRowIndex] = before + text + after;
1368
+ } else {
1369
+ const line = newLines[startRowIndex];
1370
+ const before = line.slice(0, startColumnIndex) + inserted[0];
1371
+ const after = inserted.at(-1) + line.slice(endColumnIndex);
1372
+ spliceLargeArray(newLines, startRowIndex, deleted.length, [before, ...inserted.slice(1, -1), after]);
1373
+ // TODO only do this once after all edits, not inside loop
1374
+ textDocument.maxLineY = Math.min(textDocument.numberOfVisibleLines, newLines.length);
1375
+ }
1376
+ } else {
1377
+ if (inserted.length === 1) {
1378
+ const before = newLines[startRowIndex].slice(0, startColumnIndex) + inserted[0];
1379
+ const after = endRowIndex >= newLines.length ? '' : newLines[endRowIndex].slice(endColumnIndex);
1380
+ spliceLargeArray(newLines, startRowIndex, deleted.length, [before + after]);
1381
+ } else {
1382
+ const before = newLines[startRowIndex].slice(0, startColumnIndex) + inserted[0];
1383
+ const middle = inserted.slice(1, -1);
1384
+ const after = inserted.at(-1) + (endRowIndex >= newLines.length ? '' : newLines[endRowIndex].slice(endColumnIndex));
1385
+ spliceLargeArray(newLines, startRowIndex, deleted.length, [before, ...middle, after]);
1386
+ }
1387
+ // TODO only do this once after all edits, not inside loop
1388
+ textDocument.maxLineY = Math.min(textDocument.numberOfVisibleLines, textDocument.lines.length);
1389
+ }
1390
+ linesDelta += Math.max(inserted.length - deleted.length, 0);
1391
+ }
1392
+ return newLines;
1393
+ };
1394
+ const getLine = (textDocument, index) => {
1395
+ return textDocument.lines[index];
1396
+ };
1397
+ const getText$1 = state => {
1398
+ return joinLines$2(state.lines);
1399
+ };
1400
+ const RE_WHITESPACE = /^\s+/;
1401
+
1402
+ // TODO this doesn't belong here
1403
+ const getIndent = line => {
1404
+ const whitespaceMatch = line.match(RE_WHITESPACE);
1405
+ if (!whitespaceMatch) {
1406
+ return '';
1407
+ }
1408
+ return whitespaceMatch[0];
1409
+ };
1410
+
1411
+ // TDOO this doesn;t belong here
1412
+ const getSelectionText = (textDocument, range) => {
1413
+ object(textDocument);
1414
+ // console.log(range)
1415
+ // console.log(textDocument)
1416
+ const startRowIndex = range.start.rowIndex;
1417
+ const startColumnIndex = range.start.columnIndex;
1418
+ const endRowIndex = Math.min(range.end.rowIndex, textDocument.lines.length - 1);
1419
+ const endColumnIndex = range.end.columnIndex;
1420
+ if (startRowIndex === endRowIndex) {
1421
+ // console.log(startRowIndex)
1422
+ // console.log(textDocument.lines)
1423
+ return [textDocument.lines[startRowIndex].slice(startColumnIndex, endColumnIndex)];
1424
+ }
1425
+ const selectedLines = [textDocument.lines[startRowIndex].slice(startColumnIndex), ...textDocument.lines.slice(startRowIndex + 1, endRowIndex), textDocument.lines[endRowIndex].slice(0, endColumnIndex)];
1426
+ return selectedLines;
1427
+ };
1428
+ const offsetAtSync = async (textDocument, positionRowIndex, positionColumnIndex) => {
1429
+ object(textDocument);
1430
+ number$1(positionRowIndex);
1431
+ number$1(positionColumnIndex);
1432
+ let offset = 0;
1433
+ let rowIndex = 0;
1434
+ const lines = textDocument.lines;
1435
+ const max = Math.min(positionRowIndex, textDocument.lines.length);
1436
+ while (rowIndex < max) {
1437
+ offset += lines[rowIndex].length + 1;
1438
+ rowIndex++;
1439
+ }
1440
+ offset += positionColumnIndex;
1441
+ return offset;
1442
+ };
1443
+ const offsetAt = (textDocument, positionRowIndex, positionColumnIndex) => {
1444
+ object(textDocument);
1445
+ number$1(positionRowIndex);
1446
+ number$1(positionColumnIndex);
1447
+ let offset = 0;
1448
+ let rowIndex = 0;
1449
+ const lines = textDocument.lines;
1450
+ const max = Math.min(positionRowIndex, textDocument.lines.length);
1451
+ while (rowIndex < max) {
1452
+ offset += lines[rowIndex].length + 1;
1453
+ rowIndex++;
1454
+ }
1455
+ offset += positionColumnIndex;
1456
+ return offset;
1457
+ };
1458
+ const positionAt = (textDocument, offset) => {
1459
+ // console.log({ textDocument, offset })
1460
+ let rowIndex = 0;
1461
+ let columnIndex = 0;
1462
+ let currentOffset = 0;
1463
+ while (rowIndex < textDocument.lines.length && currentOffset < offset) {
1464
+ currentOffset += textDocument.lines[rowIndex].length + 1;
1465
+ rowIndex++;
1466
+ }
1467
+ if (currentOffset > offset) {
1468
+ rowIndex--;
1469
+ currentOffset -= textDocument.lines[rowIndex].length + 1;
1470
+ columnIndex = offset - currentOffset;
1471
+ } else {
1472
+ columnIndex = currentOffset - offset;
1473
+ }
1474
+ // for (let i = 0; i < textDocument.lines.length; i++) {
1475
+ // if(currentOffset)
1476
+ // }
1477
+ // TODO
1478
+ return {
1479
+ rowIndex,
1480
+ columnIndex
1481
+ };
1482
+ };
1483
+
1484
+ // TODO this should be in a separate scrolling module
1485
+ // @ts-ignore
1486
+ const setDeltaY$3 = (state, value) => {
1487
+ object(state);
1488
+ number$1(value);
1489
+ const {
1490
+ finalDeltaY,
1491
+ deltaY,
1492
+ numberOfVisibleLines,
1493
+ height,
1494
+ scrollBarHeight,
1495
+ itemHeight
1496
+ } = state;
1497
+ const newDeltaY = clamp(value, 0, finalDeltaY);
1498
+ if (deltaY === newDeltaY) {
1499
+ return state;
1500
+ }
1501
+ const newMinLineY = Math.floor(newDeltaY / itemHeight);
1502
+ const newMaxLineY = newMinLineY + numberOfVisibleLines;
1503
+ const scrollBarY = getScrollBarY(newDeltaY, finalDeltaY, height, scrollBarHeight);
1504
+ return {
1505
+ ...state,
1506
+ minLineY: newMinLineY,
1507
+ maxLineY: newMaxLineY,
1508
+ deltaY: newDeltaY,
1509
+ scrollBarY
1510
+ };
1511
+ };
1512
+
1513
+ const getSelectionPairs = (selections, i) => {
1514
+ const first = selections[i];
1515
+ const second = selections[i + 1];
1516
+ const third = selections[i + 2];
1517
+ const fourth = selections[i + 3];
1518
+ if (first > third || first === third && second >= fourth) {
1519
+ return [third, fourth, first, second, 1];
1520
+ }
1521
+ return [first, second, third, fourth, 0];
1522
+ };
1523
+
1524
+ // TODO visible selections could also be uint16array
1525
+ // [top1, left1, width1, height1, top2, left2, width2, height2...]
601
1526
  const getTabCount = string => {
602
1527
  let count = 0;
603
1528
  for (const element of string) {
@@ -882,22 +1807,15 @@ const applyEdit$1 = (editor, changes) => {
882
1807
  };
883
1808
 
884
1809
  // TODO
885
- // @ts-ignore
886
1810
  const setDeltaYFixedValue$1 = (editor, value) => {
887
1811
  return setDeltaY$3(editor, value);
888
1812
  };
889
-
890
- // @ts-ignore
891
1813
  const setDeltaY$2 = (editor, value) => {
892
1814
  return setDeltaYFixedValue$1(editor, editor.deltaY + value);
893
1815
  };
894
-
895
- // @ts-ignore
896
1816
  const isAutoClosingChange = change => {
897
1817
  return change.origin === EditorTypeWithAutoClosing;
898
1818
  };
899
-
900
- // @ts-ignore
901
1819
  const applyAutoClosingRangesEdit = (editor, changes) => {
902
1820
  const {
903
1821
  autoClosingRanges = []
@@ -937,7 +1855,6 @@ const scheduleSelections = (editor, selectionEdits) => {
937
1855
  * @param {Uint32Array|undefined} selectionChanges
938
1856
  * @returns
939
1857
  */
940
- // @ts-ignore
941
1858
  const scheduleDocumentAndCursorsSelections = (editor, changes, selectionChanges = undefined) => {
942
1859
  object(editor);
943
1860
  array(changes);
@@ -967,7 +1884,12 @@ const scheduleDocumentAndCursorsSelections = (editor, changes, selectionChanges
967
1884
  invalidStartIndex,
968
1885
  autoClosingRanges
969
1886
  };
970
- return newEditor;
1887
+ const newWidgets = applyWidgetChanges(newEditor, changes);
1888
+ const newEditor2 = {
1889
+ ...newEditor,
1890
+ widgets: newWidgets
1891
+ };
1892
+ return newEditor2;
971
1893
  };
972
1894
  // @ts-ignore
973
1895
  const scheduleDocumentAndCursorsSelectionIsUndo = (editor, changes) => {
@@ -1032,8 +1954,6 @@ const scheduleDocument = async (editor, changes) => {
1032
1954
  // /* selectionInfos */ selectionInfos,
1033
1955
  // ])
1034
1956
  };
1035
-
1036
- // @ts-ignore
1037
1957
  const hasSelection = editor => {
1038
1958
  // TODO editor.selections should always be defined
1039
1959
  return editor.selections && editor.selections.length > 0;
@@ -1401,7 +2321,7 @@ const getErrorResponse = (message, error, preparePrettyError, logError) => {
1401
2321
  const errorProperty = getErrorProperty(error, prettyError);
1402
2322
  return create$1$1(message, errorProperty);
1403
2323
  };
1404
- const create$5 = (message, result) => {
2324
+ const create$4 = (message, result) => {
1405
2325
  return {
1406
2326
  jsonrpc: Two,
1407
2327
  id: message.id,
@@ -1410,7 +2330,7 @@ const create$5 = (message, result) => {
1410
2330
  };
1411
2331
  const getSuccessResponse = (message, result) => {
1412
2332
  const resultProperty = result ?? null;
1413
- return create$5(message, resultProperty);
2333
+ return create$4(message, resultProperty);
1414
2334
  };
1415
2335
  const getResponse = async (message, ipc, execute, preparePrettyError, logError, requiresSocket) => {
1416
2336
  try {
@@ -1571,161 +2491,55 @@ const listen$8 = ipc => {
1571
2491
  const invoke$3 = async (method, ...params) => {
1572
2492
  return invoke$4(method, ...params);
1573
2493
  };
1574
- const invokeAndTransfer = async (transfer, method, ...params) => {
1575
- return invokeAndTransfer$1(transfer, method, ...params);
1576
- };
1577
-
1578
- const sendMessagePortToExtensionHostWorker = async port => {
1579
- await invokeAndTransfer([port], 'SendMessagePortToExtensionHostWorker.sendMessagePortToExtensionHostWorker', port, 'HandleMessagePort.handleMessagePort');
1580
- };
1581
-
1582
- const withResolvers$1 = () => {
1583
- let _resolve;
1584
- const promise = new Promise(resolve => {
1585
- _resolve = resolve;
1586
- });
1587
- return {
1588
- resolve: _resolve,
1589
- promise
1590
- };
1591
- };
1592
-
1593
- const waitForFirstMessage$1 = async port => {
1594
- const {
1595
- resolve,
1596
- promise
1597
- } = withResolvers$1();
1598
- const cleanup = value => {
1599
- port.onmessage = null;
1600
- resolve(value);
1601
- };
1602
- const handleMessage = event => {
1603
- cleanup(event);
1604
- };
1605
- port.onmessage = handleMessage;
1606
- const event = await promise;
1607
- return event;
1608
- };
1609
-
1610
- const create$4 = async () => {
1611
- const {
1612
- port1,
1613
- port2
1614
- } = getPortTuple();
1615
- await sendMessagePortToExtensionHostWorker(port1);
1616
- const event = await waitForFirstMessage$1(port2);
1617
- if (event.data !== 'ready') {
1618
- throw new IpcError$1('unexpected first message');
1619
- }
1620
- return port2;
1621
- };
1622
- const wrap$3 = port => {
1623
- return {
1624
- port,
1625
- /**
1626
- * @type {any}
1627
- */
1628
- listener: undefined,
1629
- get onmessage() {
1630
- return this.listener;
1631
- },
1632
- set onmessage(listener) {
1633
- this.listener = listener;
1634
- const wrappedListener = event => {
1635
- const data = getData(event);
1636
- // @ts-ignore
1637
- listener({
1638
- target: this,
1639
- data
1640
- });
1641
- };
1642
- this.port.onmessage = wrappedListener;
1643
- },
1644
- send(message) {
1645
- this.port.postMessage(message);
1646
- },
1647
- sendAndTransfer(message, transfer) {
1648
- this.port.postMessage(message, transfer);
1649
- }
1650
- };
1651
- };
1652
-
1653
- const IpcParentWithExtensionHostWorker = {
1654
- __proto__: null,
1655
- create: create$4,
1656
- wrap: wrap$3
1657
- };
1658
-
1659
- const sendMessagePortToSyntaxHighlightingWorker = async port => {
1660
- await invokeAndTransfer([port], 'SendMessagePortToSyntaxHighlightingWorker.sendMessagePortToSyntaxHighlightingWorker', port, 'HandleMessagePort.handleMessagePort');
1661
- };
1662
-
1663
- const create$3 = async () => {
1664
- const {
1665
- port1,
1666
- port2
1667
- } = getPortTuple();
1668
- await sendMessagePortToSyntaxHighlightingWorker(port1);
1669
- const event = await waitForFirstMessage$1(port2);
1670
- if (event.data !== 'ready') {
1671
- throw new IpcError$1('unexpected first message');
1672
- }
1673
- return port2;
1674
- };
1675
- const wrap$1 = port => {
1676
- return {
1677
- port,
1678
- /**
1679
- * @type {any}
1680
- */
1681
- listener: undefined,
1682
- get onmessage() {
1683
- return this.listener;
1684
- },
1685
- set onmessage(listener) {
1686
- this.listener = listener;
1687
- const wrappedListener = event => {
1688
- const data = getData(event);
1689
- // @ts-ignore
1690
- listener({
1691
- target: this,
1692
- data
1693
- });
1694
- };
1695
- this.port.onmessage = wrappedListener;
1696
- },
1697
- send(message) {
1698
- this.port.postMessage(message);
1699
- },
1700
- sendAndTransfer(message, transfer) {
1701
- this.port.postMessage(message, transfer);
1702
- }
1703
- };
2494
+ const invokeAndTransfer = async (transfer, method, ...params) => {
2495
+ return invokeAndTransfer$1(transfer, method, ...params);
1704
2496
  };
1705
2497
 
1706
- const IpcParentWithSyntaxHighlightingWorker = {
1707
- __proto__: null,
1708
- create: create$3,
1709
- wrap: wrap$1
2498
+ const sendMessagePortToExtensionHostWorker = async port => {
2499
+ await invokeAndTransfer([port], 'SendMessagePortToExtensionHostWorker.sendMessagePortToExtensionHostWorker', port, 'HandleMessagePort.handleMessagePort');
1710
2500
  };
1711
2501
 
1712
- const sendMessagePortToRendererProcess = async port => {
1713
- await invokeAndTransfer([port], 'SendMessagePortToRendererProcess.sendMessagePortToRendererProcess', port, 'HandleMessagePort.handleMessagePort');
2502
+ const withResolvers$1 = () => {
2503
+ let _resolve;
2504
+ const promise = new Promise(resolve => {
2505
+ _resolve = resolve;
2506
+ });
2507
+ return {
2508
+ resolve: _resolve,
2509
+ promise
2510
+ };
1714
2511
  };
1715
2512
 
1716
- const create$2 = async () => {
2513
+ const waitForFirstMessage$1 = async port => {
2514
+ const {
2515
+ resolve,
2516
+ promise
2517
+ } = withResolvers$1();
2518
+ const cleanup = value => {
2519
+ port.onmessage = null;
2520
+ resolve(value);
2521
+ };
2522
+ const handleMessage = event => {
2523
+ cleanup(event);
2524
+ };
2525
+ port.onmessage = handleMessage;
2526
+ const event = await promise;
2527
+ return event;
2528
+ };
2529
+
2530
+ const create$3 = async () => {
1717
2531
  const {
1718
2532
  port1,
1719
2533
  port2
1720
2534
  } = getPortTuple();
1721
- await sendMessagePortToRendererProcess(port1);
2535
+ await sendMessagePortToExtensionHostWorker(port1);
1722
2536
  const event = await waitForFirstMessage$1(port2);
1723
2537
  if (event.data !== 'ready') {
1724
2538
  throw new IpcError$1('unexpected first message');
1725
2539
  }
1726
2540
  return port2;
1727
2541
  };
1728
- const wrap = port => {
2542
+ const wrap$3 = port => {
1729
2543
  return {
1730
2544
  port,
1731
2545
  /**
@@ -1756,507 +2570,411 @@ const wrap = port => {
1756
2570
  };
1757
2571
  };
1758
2572
 
1759
- const IpcParentWithRendererProcess = {
1760
- __proto__: null,
1761
- create: create$2,
1762
- wrap
1763
- };
1764
-
1765
- const getModule$1 = method => {
1766
- switch (method) {
1767
- case RendererProcess:
1768
- return IpcParentWithRendererProcess;
1769
- case ExtensionHostWorker:
1770
- return IpcParentWithExtensionHostWorker;
1771
- case SyntaxHighlightingWorker:
1772
- return IpcParentWithSyntaxHighlightingWorker;
1773
- default:
1774
- throw new Error('unexpected ipc type');
1775
- }
1776
- };
1777
-
1778
- const create$1 = async ({
1779
- method,
1780
- ...options
1781
- }) => {
1782
- const module = await getModule$1(method);
1783
- // @ts-ignore
1784
- const rawIpc = await module.create(options);
1785
- // @ts-ignore
1786
- if (options.raw) {
1787
- return rawIpc;
1788
- }
1789
- const ipc = module.wrap(rawIpc);
1790
- return ipc;
1791
- };
1792
-
1793
- const createRpc = method => {
1794
- let _ipc;
1795
- const listen = async () => {
1796
- const ipc = await create$1({
1797
- method
1798
- });
1799
- handleIpc(ipc);
1800
- _ipc = ipc;
1801
- };
1802
- const invoke = (method, ...params) => {
1803
- return invoke$5(_ipc, method, ...params);
1804
- };
1805
- return {
1806
- listen,
1807
- invoke
1808
- };
1809
- };
1810
-
1811
- const {
1812
- listen: listen$7,
1813
- invoke: invoke$2
1814
- } = createRpc(ExtensionHostWorker);
1815
-
1816
- const CompletionExecute = 'ExtensionHostCompletion.execute';
1817
- const CompletionResolveExecute = 'ExtensionHostCompletion.executeResolve';
1818
- const HoverExecute = 'ExtensionHostHover.execute';
1819
- const TextDocumentSyncFull = 'ExtensionHostTextDocument.syncFull';
1820
-
1821
- const measureCharacterWidth = (fontWeight, fontSize, fontFamily, letterSpacing) => {
1822
- return measureTextWidth('a', fontWeight, fontSize, fontFamily, letterSpacing, false, 0);
1823
- };
1824
-
1825
- const emptyEditor = {
1826
- uri: '',
1827
- languageId: '',
1828
- // TODO use numeric language id?
1829
- lines: [],
1830
- x: 0,
1831
- y: 0,
1832
- width: 0,
1833
- height: 0,
1834
- tokenizerId: 0,
1835
- minLineY: 0,
1836
- decorations: [],
1837
- embeds: [],
1838
- deltaX: 0,
1839
- focused: false,
1840
- deltaY: 0,
1841
- scrollBarHeight: 0,
1842
- longestLineWidth: 0,
1843
- maxLineY: 0,
1844
- undoStack: [],
1845
- lineCache: [],
1846
- selections: new Uint32Array(),
1847
- diagnostics: []
1848
- };
1849
- const createEditor = async ({
1850
- id,
1851
- content,
1852
- savedDeltaY,
1853
- rowHeight,
1854
- fontSize,
1855
- hoverEnabled,
1856
- letterSpacing,
1857
- tabSize,
1858
- links,
1859
- lineNumbers,
1860
- formatOnSave,
1861
- isAutoClosingBracketsEnabled,
1862
- isAutoClosingTagsEnabled,
1863
- isAutoClosingQuotesEnabled,
1864
- isQuickSuggestionsEnabled,
1865
- completionTriggerCharacters,
1866
- savedSelections,
1867
- languageId,
1868
- x,
1869
- y,
1870
- width,
1871
- height,
1872
- fontWeight,
1873
- fontFamily,
1874
- isMonospaceFont,
1875
- uri
1876
- }) => {
1877
- number$1(id);
1878
- string(content);
1879
- const charWidth = measureCharacterWidth(fontWeight, fontSize, fontFamily, letterSpacing);
1880
- const editor = {
1881
- uri,
1882
- isAutoClosingBracketsEnabled,
1883
- isAutoClosingTagsEnabled,
1884
- isAutoClosingQuotesEnabled,
1885
- isQuickSuggestionsEnabled,
1886
- completionTriggerCharacters,
1887
- savedSelections,
1888
- languageId,
1889
- x,
1890
- y,
1891
- width,
1892
- height,
1893
- tokenizerId: 0,
1894
- minLineY: 0,
1895
- maxLineY: 0,
1896
- lines: [],
1897
- undoStack: [],
1898
- lineCache: [],
1899
- selections: new Uint32Array(),
1900
- diagnostics: [],
1901
- decorations: [],
1902
- primarySelectionIndex: 0,
1903
- deltaX: 0,
1904
- deltaY: 0,
1905
- numberOfVisiblelines: 0,
1906
- finalY: 0,
1907
- finalDeltaY: 0,
1908
- columnWidth: 0,
1909
- rowHeight,
1910
- scrollBarWidth: 0,
1911
- scrollBarHeight: 0,
1912
- validLines: [],
1913
- invalidStartIndex: 0,
1914
- focused: false,
1915
- handleOffsetX: 0,
1916
- itemHeight: 20,
1917
- fontFamily,
1918
- fontWeight,
1919
- tabSize,
1920
- fontSize,
1921
- cursorWidth: 2,
1922
- completionState: '',
1923
- longestLineWidth: 0,
1924
- minimumSliderSize: 20,
1925
- differences: [],
1926
- completionUid: 0,
1927
- lineNumbers,
1928
- numberOfVisibleLines: 0,
1929
- isMonospaceFont,
1930
- letterSpacing,
1931
- charWidth,
1932
- uid: id,
1933
- id,
1934
- widgets: []
1935
- };
1936
- // TODO avoid creating intermediate editors here
1937
- const newEditor1 = setBounds(editor, x, y, width, height, 9);
1938
- const newEditor2 = setText(newEditor1, content);
1939
- const newEditor3 = setDeltaY$1(newEditor2, 0);
1940
- const newEditor4 = {
1941
- ...newEditor3,
1942
- focused: true
1943
- };
1944
- // console.log({ newEditor })
1945
- set$6(id, emptyEditor, newEditor4);
1946
- await invoke$2(TextDocumentSyncFull, uri, id, languageId, content);
1947
- };
1948
-
1949
- // @ts-ignore
1950
- const getNewSelections$d = selections => {
1951
- const newSelections = [];
1952
- for (let i = 0; i < selections.length; i += 4) {
1953
- const startRowIndex = selections[i];
1954
- const startColumnIndex = selections[i + 1];
1955
- const endRowIndex = selections[i + 2];
1956
- const endColumnIndex = selections[i + 3];
1957
- if (i === 0 && startRowIndex !== 0) {
1958
- newSelections.push(startRowIndex - 1, startColumnIndex, startRowIndex - 1, startColumnIndex);
1959
- }
1960
- newSelections.push(startRowIndex, startColumnIndex, endRowIndex, endColumnIndex);
1961
- }
1962
- return new Uint32Array(newSelections);
2573
+ const IpcParentWithExtensionHostWorker = {
2574
+ __proto__: null,
2575
+ create: create$3,
2576
+ wrap: wrap$3
1963
2577
  };
1964
2578
 
1965
- // @ts-ignore
1966
- const addCursorAbove = editor => {
1967
- const {
1968
- selections
1969
- } = editor;
1970
- const newSelections = getNewSelections$d(selections);
1971
- return {
1972
- ...editor,
1973
- selections: newSelections
1974
- };
2579
+ const sendMessagePortToSyntaxHighlightingWorker = async port => {
2580
+ await invokeAndTransfer([port], 'SendMessagePortToSyntaxHighlightingWorker.sendMessagePortToSyntaxHighlightingWorker', port, 'HandleMessagePort.handleMessagePort');
1975
2581
  };
1976
2582
 
1977
- // @ts-ignore
1978
- const getNewSelections$c = (selections, linesLength) => {
1979
- const newSelections = [];
1980
- for (let i = 0; i < selections.length; i += 4) {
1981
- const startRowIndex = selections[i];
1982
- const startColumnIndex = selections[i + 1];
1983
- const endRowIndex = selections[i + 2];
1984
- const endColumnIndex = selections[i + 3];
1985
- newSelections.push(startRowIndex, startColumnIndex, endRowIndex, endColumnIndex);
1986
- if (i === selections.length - 4 && endRowIndex < linesLength) {
1987
- newSelections.push(endRowIndex + 1, endColumnIndex, endRowIndex + 1, endColumnIndex);
1988
- }
2583
+ const create$2 = async () => {
2584
+ const {
2585
+ port1,
2586
+ port2
2587
+ } = getPortTuple();
2588
+ await sendMessagePortToSyntaxHighlightingWorker(port1);
2589
+ const event = await waitForFirstMessage$1(port2);
2590
+ if (event.data !== 'ready') {
2591
+ throw new IpcError$1('unexpected first message');
1989
2592
  }
1990
- return new Uint32Array(newSelections);
2593
+ return port2;
1991
2594
  };
1992
-
1993
- // @ts-ignore
1994
- const addCursorBelow = editor => {
1995
- const {
1996
- selections,
1997
- lines
1998
- } = editor;
1999
- const newSelections = getNewSelections$c(selections, lines.length);
2595
+ const wrap$1 = port => {
2000
2596
  return {
2001
- ...editor,
2002
- selections: newSelections
2597
+ port,
2598
+ /**
2599
+ * @type {any}
2600
+ */
2601
+ listener: undefined,
2602
+ get onmessage() {
2603
+ return this.listener;
2604
+ },
2605
+ set onmessage(listener) {
2606
+ this.listener = listener;
2607
+ const wrappedListener = event => {
2608
+ const data = getData(event);
2609
+ // @ts-ignore
2610
+ listener({
2611
+ target: this,
2612
+ data
2613
+ });
2614
+ };
2615
+ this.port.onmessage = wrappedListener;
2616
+ },
2617
+ send(message) {
2618
+ this.port.postMessage(message);
2619
+ },
2620
+ sendAndTransfer(message, transfer) {
2621
+ this.port.postMessage(message, transfer);
2622
+ }
2003
2623
  };
2004
2624
  };
2005
2625
 
2006
- // @ts-ignore
2007
-
2008
- // @ts-ignore
2009
- const applyEdit = async (editor, changes) => {
2010
- 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;
2626
+ const IpcParentWithSyntaxHighlightingWorker = {
2627
+ __proto__: null,
2628
+ create: create$2,
2629
+ wrap: wrap$1
2026
2630
  };
2027
2631
 
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;
2632
+ const sendMessagePortToRendererProcess = async port => {
2633
+ await invokeAndTransfer([port], 'SendMessagePortToRendererProcess.sendMessagePortToRendererProcess', port, 'HandleMessagePort.handleMessagePort');
2054
2634
  };
2055
2635
 
2056
- // @ts-ignore
2057
- const editorReplaceSelections = (editor, replacement, origin) => {
2636
+ const create$1 = async () => {
2058
2637
  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
- }
2638
+ port1,
2639
+ port2
2640
+ } = getPortTuple();
2641
+ await sendMessagePortToRendererProcess(port1);
2642
+ const event = await waitForFirstMessage$1(port2);
2643
+ if (event.data !== 'ready') {
2644
+ throw new IpcError$1('unexpected first message');
2090
2645
  }
2091
- return line.length;
2092
- };
2093
-
2094
- const supported = () => {
2095
- return 'Segmenter' in Intl;
2646
+ return port2;
2096
2647
  };
2097
- const create = () => {
2098
- // @ts-ignore
2099
- const segmenter = new Intl.Segmenter();
2648
+ const wrap = port => {
2100
2649
  return {
2101
- at(line, index) {
2102
- const segments = segmenter.segment(line);
2103
- return segments.containing(index);
2650
+ port,
2651
+ /**
2652
+ * @type {any}
2653
+ */
2654
+ listener: undefined,
2655
+ get onmessage() {
2656
+ return this.listener;
2104
2657
  },
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;
2658
+ set onmessage(listener) {
2659
+ this.listener = listener;
2660
+ const wrappedListener = event => {
2661
+ const data = getData(event);
2662
+ // @ts-ignore
2663
+ listener({
2664
+ target: this,
2665
+ data
2666
+ });
2667
+ };
2668
+ this.port.onmessage = wrappedListener;
2115
2669
  },
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;
2670
+ send(message) {
2671
+ this.port.postMessage(message);
2126
2672
  },
2127
- getSegments(line) {
2128
- return segmenter.segment(line);
2673
+ sendAndTransfer(message, transfer) {
2674
+ this.port.postMessage(message, transfer);
2129
2675
  }
2130
2676
  };
2131
2677
  };
2132
2678
 
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
- }
2679
+ const IpcParentWithRendererProcess = {
2680
+ __proto__: null,
2681
+ create: create$1,
2682
+ wrap
2683
+ };
2684
+
2685
+ const getModule$1 = method => {
2686
+ switch (method) {
2687
+ case RendererProcess:
2688
+ return IpcParentWithRendererProcess;
2689
+ case ExtensionHostWorker:
2690
+ return IpcParentWithExtensionHostWorker;
2691
+ case SyntaxHighlightingWorker:
2692
+ return IpcParentWithSyntaxHighlightingWorker;
2693
+ default:
2694
+ throw new Error('unexpected ipc type');
2695
+ }
2696
+ };
2697
+
2698
+ const create = async ({
2699
+ method,
2700
+ ...options
2701
+ }) => {
2702
+ const module = await getModule$1(method);
2703
+ // @ts-ignore
2704
+ const rawIpc = await module.create(options);
2705
+ // @ts-ignore
2706
+ if (options.raw) {
2707
+ return rawIpc;
2144
2708
  }
2145
- return line.length;
2709
+ const ipc = module.wrap(rawIpc);
2710
+ return ipc;
2146
2711
  };
2147
2712
 
2148
- const RE_ASCII = /^[\p{ASCII}]*$/u;
2149
- const isAscii = line => {
2150
- return RE_ASCII.test(line);
2713
+ const createRpc = method => {
2714
+ let _ipc;
2715
+ const listen = async () => {
2716
+ const ipc = await create({
2717
+ method
2718
+ });
2719
+ handleIpc(ipc);
2720
+ _ipc = ipc;
2721
+ };
2722
+ const invoke = (method, ...params) => {
2723
+ return invoke$5(_ipc, method, ...params);
2724
+ };
2725
+ return {
2726
+ listen,
2727
+ invoke
2728
+ };
2151
2729
  };
2152
2730
 
2153
- // @ts-ignore
2154
- const guessOffset = (eventX, averageCharWidth) => {
2155
- const guess = Math.round(eventX / averageCharWidth);
2156
- return guess;
2731
+ const {
2732
+ listen: listen$7,
2733
+ invoke: invoke$2
2734
+ } = createRpc(ExtensionHostWorker);
2735
+
2736
+ const CompletionExecute = 'ExtensionHostCompletion.execute';
2737
+ const CompletionResolveExecute = 'ExtensionHostCompletion.executeResolve';
2738
+ const HoverExecute = 'ExtensionHostHover.execute';
2739
+ const TextDocumentSyncFull = 'ExtensionHostTextDocument.syncFull';
2740
+
2741
+ const measureCharacterWidth = (fontWeight, fontSize, fontFamily, letterSpacing) => {
2742
+ return measureTextWidth('a', fontWeight, fontSize, fontFamily, letterSpacing, false, 0);
2157
2743
  };
2158
2744
 
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;
2745
+ const emptyEditor = {
2746
+ uri: '',
2747
+ languageId: '',
2748
+ // TODO use numeric language id?
2749
+ lines: [],
2750
+ x: 0,
2751
+ y: 0,
2752
+ width: 0,
2753
+ height: 0,
2754
+ tokenizerId: 0,
2755
+ minLineY: 0,
2756
+ decorations: [],
2757
+ embeds: [],
2758
+ deltaX: 0,
2759
+ focused: false,
2760
+ deltaY: 0,
2761
+ scrollBarHeight: 0,
2762
+ longestLineWidth: 0,
2763
+ maxLineY: 0,
2764
+ undoStack: [],
2765
+ lineCache: [],
2766
+ selections: new Uint32Array(),
2767
+ diagnostics: []
2768
+ };
2769
+ const createEditor = async ({
2770
+ id,
2771
+ content,
2772
+ savedDeltaY,
2773
+ rowHeight,
2774
+ fontSize,
2775
+ hoverEnabled,
2776
+ letterSpacing,
2777
+ tabSize,
2778
+ links,
2779
+ lineNumbers,
2780
+ formatOnSave,
2781
+ isAutoClosingBracketsEnabled,
2782
+ isAutoClosingTagsEnabled,
2783
+ isAutoClosingQuotesEnabled,
2784
+ isQuickSuggestionsEnabled,
2785
+ completionTriggerCharacters,
2786
+ savedSelections,
2787
+ languageId,
2788
+ x,
2789
+ y,
2790
+ width,
2791
+ height,
2792
+ fontWeight,
2793
+ fontFamily,
2794
+ isMonospaceFont,
2795
+ uri
2796
+ }) => {
2797
+ number$1(id);
2798
+ string(content);
2799
+ const charWidth = measureCharacterWidth(fontWeight, fontSize, fontFamily, letterSpacing);
2800
+ const editor = {
2801
+ uri,
2802
+ isAutoClosingBracketsEnabled,
2803
+ isAutoClosingTagsEnabled,
2804
+ isAutoClosingQuotesEnabled,
2805
+ isQuickSuggestionsEnabled,
2806
+ completionTriggerCharacters,
2807
+ savedSelections,
2808
+ languageId,
2809
+ x,
2810
+ y,
2811
+ width,
2812
+ height,
2813
+ tokenizerId: 0,
2814
+ minLineY: 0,
2815
+ maxLineY: 0,
2816
+ lines: [],
2817
+ undoStack: [],
2818
+ lineCache: [],
2819
+ selections: new Uint32Array(),
2820
+ diagnostics: [],
2821
+ decorations: [],
2822
+ primarySelectionIndex: 0,
2823
+ deltaX: 0,
2824
+ deltaY: 0,
2825
+ numberOfVisiblelines: 0,
2826
+ finalY: 0,
2827
+ finalDeltaY: 0,
2828
+ columnWidth: 0,
2829
+ rowHeight,
2830
+ scrollBarWidth: 0,
2831
+ scrollBarHeight: 0,
2832
+ validLines: [],
2833
+ invalidStartIndex: 0,
2834
+ focused: false,
2835
+ handleOffsetX: 0,
2836
+ itemHeight: 20,
2837
+ fontFamily,
2838
+ fontWeight,
2839
+ tabSize,
2840
+ fontSize,
2841
+ cursorWidth: 2,
2842
+ completionState: '',
2843
+ longestLineWidth: 0,
2844
+ minimumSliderSize: 20,
2845
+ differences: [],
2846
+ completionUid: 0,
2847
+ lineNumbers,
2848
+ numberOfVisibleLines: 0,
2849
+ isMonospaceFont,
2850
+ letterSpacing,
2851
+ charWidth,
2852
+ uid: id,
2853
+ id,
2854
+ widgets: []
2855
+ };
2856
+ // TODO avoid creating intermediate editors here
2857
+ const newEditor1 = setBounds(editor, x, y, width, height, 9);
2858
+ const newEditor2 = setText(newEditor1, content);
2859
+ const newEditor3 = setDeltaY$1(newEditor2, 0);
2860
+ const newEditor4 = {
2861
+ ...newEditor3,
2862
+ focused: true
2863
+ };
2864
+ // console.log({ newEditor })
2865
+ set$6(id, emptyEditor, newEditor4);
2866
+ await invoke$2(TextDocumentSyncFull, uri, id, languageId, content);
2168
2867
  };
2169
2868
 
2170
2869
  // @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;
2870
+ const getNewSelections$d = selections => {
2871
+ const newSelections = [];
2872
+ for (let i = 0; i < selections.length; i += 4) {
2873
+ const startRowIndex = selections[i];
2874
+ const startColumnIndex = selections[i + 1];
2875
+ const endRowIndex = selections[i + 2];
2876
+ const endColumnIndex = selections[i + 3];
2877
+ if (i === 0 && startRowIndex !== 0) {
2878
+ newSelections.push(startRowIndex - 1, startColumnIndex, startRowIndex - 1, startColumnIndex);
2192
2879
  }
2193
- return getAccurateColumnIndexAscii(line, normalizedGuess, charWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
2880
+ newSelections.push(startRowIndex, startColumnIndex, endRowIndex, endColumnIndex);
2194
2881
  }
2195
- return getAccurateColumnIndexUnicode(line, normalizedGuess, charWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing);
2882
+ return new Uint32Array(newSelections);
2196
2883
  };
2197
2884
 
2198
2885
  // @ts-ignore
2199
- const at = (editor, eventX, eventY) => {
2200
- object(editor);
2201
- number$1(eventX);
2202
- number$1(eventY);
2886
+ const addCursorAbove = editor => {
2203
2887
  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
2888
+ selections
2216
2889
  } = 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
2890
+ const newSelections = getNewSelections$d(selections);
2891
+ return {
2892
+ ...editor,
2893
+ selections: newSelections
2230
2894
  };
2231
2895
  };
2232
2896
 
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
2897
  // @ts-ignore
2243
- const x = (editor, rowIndex, columnIndex) => {
2898
+ const getNewSelections$c = (selections, linesLength) => {
2899
+ const newSelections = [];
2900
+ for (let i = 0; i < selections.length; i += 4) {
2901
+ const startRowIndex = selections[i];
2902
+ const startColumnIndex = selections[i + 1];
2903
+ const endRowIndex = selections[i + 2];
2904
+ const endColumnIndex = selections[i + 3];
2905
+ newSelections.push(startRowIndex, startColumnIndex, endRowIndex, endColumnIndex);
2906
+ if (i === selections.length - 4 && endRowIndex < linesLength) {
2907
+ newSelections.push(endRowIndex + 1, endColumnIndex, endRowIndex + 1, endColumnIndex);
2908
+ }
2909
+ }
2910
+ return new Uint32Array(newSelections);
2911
+ };
2912
+
2913
+ // @ts-ignore
2914
+ const addCursorBelow = editor => {
2244
2915
  const {
2245
- columnWidth,
2246
- x
2916
+ selections,
2917
+ lines
2247
2918
  } = editor;
2248
- const offsetX = columnIndex * columnWidth + x;
2249
- return offsetX;
2919
+ const newSelections = getNewSelections$c(selections, lines.length);
2920
+ return {
2921
+ ...editor,
2922
+ selections: newSelections
2923
+ };
2250
2924
  };
2251
2925
 
2252
- // @ts-ignore
2253
- const y = (editor, rowIndex) => {
2926
+ const applyEdit = async (editor, changes) => {
2927
+ object(editor);
2928
+ array(changes);
2929
+ return scheduleDocumentAndCursorsSelections(editor, changes);
2930
+ };
2931
+
2932
+ const handleBlur = editor => {
2933
+ // for (const listener of state.blurListeners) {
2934
+ // listener(editor)
2935
+ // }
2936
+ // TODO save on blur
2937
+ // Command.execute(/* Main.save */ 89)
2938
+ const newEditor = {
2939
+ ...editor,
2940
+ focused: false
2941
+ };
2942
+ return newEditor;
2943
+ };
2944
+
2945
+ const replaceRange = (editor, ranges, replacement, origin) => {
2946
+ const changes = [];
2947
+ const rangesLength = ranges.length;
2948
+ for (let i = 0; i < rangesLength; i += 4) {
2949
+ const [selectionStartRow, selectionStartColumn, selectionEndRow, selectionEndColumn] = getSelectionPairs(ranges, i);
2950
+ const start = {
2951
+ rowIndex: selectionStartRow,
2952
+ columnIndex: selectionStartColumn
2953
+ };
2954
+ const end = {
2955
+ rowIndex: selectionEndRow,
2956
+ columnIndex: selectionEndColumn
2957
+ };
2958
+ const selection = {
2959
+ start,
2960
+ end
2961
+ };
2962
+ changes.push({
2963
+ start: start,
2964
+ end: end,
2965
+ inserted: replacement,
2966
+ deleted: getSelectionText(editor, selection),
2967
+ origin
2968
+ });
2969
+ }
2970
+ return changes;
2971
+ };
2972
+
2973
+ const editorReplaceSelections = (editor, replacement, origin) => {
2254
2974
  const {
2255
- rowHeight,
2256
- y
2975
+ selections
2257
2976
  } = editor;
2258
- const offsetY = (rowIndex + 1) * rowHeight + y;
2259
- return offsetY;
2977
+ return replaceRange(editor, selections, replacement, origin);
2260
2978
  };
2261
2979
 
2262
2980
  const state$7 = {
@@ -2712,7 +3430,7 @@ const characterLeft = (line, columnIndex) => {
2712
3430
  if (!supported()) {
2713
3431
  return 1;
2714
3432
  }
2715
- const segmenter = create();
3433
+ const segmenter = create$5();
2716
3434
  const last = segmenter.at(line, columnIndex - 1);
2717
3435
  return columnIndex - last.index;
2718
3436
  };
@@ -2725,7 +3443,7 @@ const characterRight = (line, columnIndex) => {
2725
3443
  if (!supported()) {
2726
3444
  return 1;
2727
3445
  }
2728
- const segmenter = create();
3446
+ const segmenter = create$5();
2729
3447
  const next = segmenter.at(line, columnIndex);
2730
3448
  return next.segment.length;
2731
3449
  };
@@ -3037,7 +3755,7 @@ const cut = editor => {
3037
3755
  // @ts-ignore
3038
3756
  const getChanges$6 = (lines, selections, getDelta) => {
3039
3757
  const changes = [];
3040
- // @ts-ignore
3758
+ // TODO avoid closure
3041
3759
  const deleteSelection = (selectionStartRow, selectionStartColumn, selectionEndRow, selectionEndColumn) => {
3042
3760
  const positionLeft = editorGetPositionLeft(selectionStartRow, selectionStartColumn, lines, getDelta);
3043
3761
  const selectionEnd = {
@@ -3054,7 +3772,7 @@ const getChanges$6 = (lines, selections, getDelta) => {
3054
3772
  start: positionLeft,
3055
3773
  end: selectionEnd
3056
3774
  }),
3057
- origin: Delete
3775
+ origin: DeleteLeft
3058
3776
  });
3059
3777
  };
3060
3778
  forEach(selections, deleteSelection);
@@ -3090,9 +3808,6 @@ const isAllAutoClosingPairDelete = (autoClosingRanges, selections) => {
3090
3808
  return true;
3091
3809
  };
3092
3810
 
3093
- // @ts-ignore
3094
-
3095
- // @ts-ignore
3096
3811
  const deleteLeftWithAutoClose = editor => {
3097
3812
  const {
3098
3813
  selections,
@@ -3105,8 +3820,6 @@ const deleteLeftWithAutoClose = editor => {
3105
3820
  const changes = getChanges$6(lines, selections, twoCharactersLeft);
3106
3821
  return scheduleDocumentAndCursorsSelections(editor, changes);
3107
3822
  };
3108
-
3109
- // @ts-ignore
3110
3823
  const editorDeleteHorizontalLeft = (editor, getDelta) => {
3111
3824
  const {
3112
3825
  autoClosingRanges = [],
@@ -3120,7 +3833,7 @@ const editorDeleteHorizontalLeft = (editor, getDelta) => {
3120
3833
  const changes = getChanges$6(lines, selections, getDelta);
3121
3834
  return scheduleDocumentAndCursorsSelections(editor, changes);
3122
3835
  }
3123
- const changes = editorReplaceSelections(editor, [''], Delete);
3836
+ const changes = editorReplaceSelections(editor, [''], DeleteLeft);
3124
3837
  return scheduleDocumentAndCursorsSelections(editor, changes);
3125
3838
  };
3126
3839
 
@@ -3245,182 +3958,51 @@ const getDocumentEdits = (editor, edits) => {
3245
3958
  documentEdit.inserted = [''];
3246
3959
  }
3247
3960
  documentEdits.push(documentEdit);
3248
- }
3249
- return documentEdits;
3250
- };
3251
-
3252
- // @ts-ignore
3253
- const applyDocumentEdits = (editor, edits) => {
3254
- if (!Array.isArray(edits)) {
3255
- warn('something is wrong with format on save', edits);
3256
- return editor;
3257
- }
3258
- if (edits.length === 0) {
3259
- 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'
3401
- };
3402
- const noDefinitionFound = () => {
3403
- return i18nString(UiStrings.NoDefinitionFound);
3961
+ }
3962
+ return documentEdits;
3404
3963
  };
3405
3964
 
3406
3965
  // @ts-ignore
3407
- const noDefinitionFoundFor = word => {
3408
- return i18nString(UiStrings.NoDefinitionFoundFor, {
3409
- PH1: word
3410
- });
3966
+ const applyDocumentEdits = (editor, edits) => {
3967
+ if (!Array.isArray(edits)) {
3968
+ warn('something is wrong with format on save', edits);
3969
+ return editor;
3970
+ }
3971
+ if (edits.length === 0) {
3972
+ return editor;
3973
+ }
3974
+ const documentEdits = getDocumentEdits(editor, edits);
3975
+ return scheduleDocumentAndCursorsSelections(editor, documentEdits);
3411
3976
  };
3412
3977
 
3413
- // @ts-ignore
3414
- const noTypeDefinitionFoundFor = word => {
3415
- return i18nString(UiStrings.NoTypeDefinitionFoundFor, {
3416
- PH1: word
3417
- });
3978
+ const expectedErrorMessage = 'Failed to execute formatting provider: FormattingError:';
3979
+ const isFormattingError = error => {
3980
+ return error && error instanceof Error && error.message.startsWith(expectedErrorMessage);
3418
3981
  };
3419
- const noTypeDefinitionFound = () => {
3420
- return i18nString(UiStrings.NoTypeDefinitionFound);
3982
+
3983
+ // TODO also format with cursor
3984
+ const format = async editor => {
3985
+ try {
3986
+ const edits = await format$1(editor);
3987
+ return applyDocumentEdits(editor, edits);
3988
+ } catch (error) {
3989
+ if (isFormattingError(error)) {
3990
+ console.error('Formatting Error:',
3991
+ // @ts-ignore
3992
+ error.message.slice(expectedErrorMessage.length));
3993
+ return editor;
3994
+ }
3995
+ console.error(error);
3996
+ const displayErrorMessage = `${error}`;
3997
+ await editorShowMessage(editor, 0, 0, displayErrorMessage, true);
3998
+ return editor;
3999
+ }
3421
4000
  };
3422
- const noResults = () => {
3423
- return i18nString(UiStrings.NoResults);
4001
+
4002
+ // @ts-ignore
4003
+ const getDefinition = async (editor, offset) => {
4004
+ const definition = await invoke$3('ExtensionHostDefinition.executeDefinitionProvider', editor, offset);
4005
+ return definition;
3424
4006
  };
3425
4007
 
3426
4008
  // @ts-ignore
@@ -4642,233 +5224,30 @@ const getCompletions = async editor => {
4642
5224
  };
4643
5225
 
4644
5226
  // TODO don't send unnecessary parts of completion item like matches
4645
- const resolveCompletion = async (editor, name, completionItem) => {
4646
- try {
4647
- object(editor);
4648
- string(name);
4649
- object(completionItem);
4650
- const rowIndex = editor.selections[0];
4651
- 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);
5227
+ const resolveCompletion = async (editor, name, completionItem) => {
5228
+ try {
5229
+ object(editor);
5230
+ string(name);
5231
+ object(completionItem);
5232
+ const rowIndex = editor.selections[0];
5233
+ const columnIndex = editor.selections[1];
5234
+ const offset = await offsetAt(editor, rowIndex, columnIndex);
5235
+ // @ts-ignore
5236
+ const resolvedCompletionItem = await executeResolveCompletionItem(editor, offset, name, completionItem);
5237
+ return resolvedCompletionItem;
5238
+ } catch {
5239
+ return undefined;
4851
5240
  }
4852
- return filteredCompletions;
4853
5241
  };
4854
5242
 
5243
+ const None = 1;
5244
+
4855
5245
  const getFinalDeltaY = (height, itemHeight, itemsLength) => {
4856
5246
  const contentHeight = itemsLength * itemHeight;
4857
5247
  const finalDeltaY = Math.max(contentHeight - height, 0);
4858
5248
  return finalDeltaY;
4859
5249
  };
4860
5250
 
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;
4867
- }
4868
- const totalHeight = itemsLength * itemHeight;
4869
- return Math.min(totalHeight, maxHeight);
4870
- };
4871
-
4872
5251
  const getEditor = editorUid => {
4873
5252
  const instance = get$6(editorUid);
4874
5253
  if (!instance) {
@@ -4940,7 +5319,7 @@ const handleEditorDeleteLeft = (editorUid, state) => {
4940
5319
  const y$1 = y(editor, rowIndex);
4941
5320
  const wordAtOffset = getWordAtOffset(editor);
4942
5321
  if (!wordAtOffset) {
4943
- editor.completionState = None$1;
5322
+ editor.completionState = None;
4944
5323
  return {
4945
5324
  ...state,
4946
5325
  disposed: true
@@ -4966,7 +5345,7 @@ const dispose = state => {
4966
5345
  };
4967
5346
  };
4968
5347
  const disposeWithEditor = (state, editor) => {
4969
- editor.completionState = None$1;
5348
+ editor.completionState = None;
4970
5349
  editor.completionUid = 0;
4971
5350
  // Focus.removeAdditionalFocus(FocusKey.EditorCompletion)
4972
5351
  return dispose(state);
@@ -6866,7 +7245,7 @@ const select = async (editor, completionItem) => {
6866
7245
  ();
6867
7246
  if (index !== -1) {
6868
7247
  editor.widgets.splice(index, 1);
6869
- editor.completionState = None$1;
7248
+ editor.completionState = None;
6870
7249
  editor.completionUid = 0;
6871
7250
  }
6872
7251
  // TODO dispose completion widget
@@ -6929,7 +7308,7 @@ const getHover = async (editor, offset) => {
6929
7308
 
6930
7309
  let _ipc;
6931
7310
  const listen$5 = async () => {
6932
- const ipc = await create$1({
7311
+ const ipc = await create({
6933
7312
  method: RendererProcess
6934
7313
  });
6935
7314
  handleIpc(ipc);
@@ -7158,14 +7537,6 @@ const handleSashPointerUp = (state, eventX, eventY) => {
7158
7537
  return state;
7159
7538
  };
7160
7539
 
7161
- const text = data => {
7162
- return {
7163
- type: Text,
7164
- text: data,
7165
- childCount: 0
7166
- };
7167
- };
7168
-
7169
7540
  const getLineInfoVirtualDom = lineInfo => {
7170
7541
  const dom = [{
7171
7542
  type: Div,
@@ -7253,7 +7624,7 @@ const renderHoverDom = {
7253
7624
  return [/* method */'Viewlet.setDom2', dom];
7254
7625
  }
7255
7626
  };
7256
- const renderBounds$1 = {
7627
+ const renderBounds = {
7257
7628
  isEqual(oldState, newState) {
7258
7629
  return oldState.x === newState.x && oldState.y === newState.y && oldState.resizedWidth === newState.resizedWidth;
7259
7630
  },
@@ -7271,10 +7642,10 @@ const renderBounds$1 = {
7271
7642
  return [SetBounds, x, y, resizedWidth, height];
7272
7643
  }
7273
7644
  };
7274
- const render$2 = [renderHoverDom, renderBounds$1];
7645
+ const render$1 = [renderHoverDom, renderBounds];
7275
7646
  const renderHover = async (oldState, newState) => {
7276
7647
  const commands = [];
7277
- for (const item of render$2) {
7648
+ for (const item of render$1) {
7278
7649
  if (!item.isEqual(oldState, newState)) {
7279
7650
  commands.push(item.apply(oldState, newState));
7280
7651
  }
@@ -7580,7 +7951,7 @@ const moveLineUp = editor => {
7580
7951
  };
7581
7952
 
7582
7953
  const Link$1 = 'Link';
7583
- const Function$1 = 'Function';
7954
+ const Function = 'Function';
7584
7955
  const Parameter = 'Parameter';
7585
7956
  const Type = 'Type';
7586
7957
  const VariableName = 'VariableName';
@@ -7639,7 +8010,7 @@ const getDecorationClassName = type => {
7639
8010
  case Ts3073:
7640
8011
  case Ts3077:
7641
8012
  case Ts3088:
7642
- return Function$1;
8013
+ return Function;
7643
8014
  case Ts1792:
7644
8015
  case Ts1793:
7645
8016
  return Parameter;
@@ -8062,422 +8433,143 @@ const getVisible = async (editor, syncIncremental) => {
8062
8433
  return {
8063
8434
  textInfos: result,
8064
8435
  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)];
8436
+ };
8286
8437
  };
8287
8438
 
8288
- const getCompletionItemsVirtualDom = visibleItems => {
8289
- if (visibleItems.length === 0) {
8290
- return [{
8439
+ const getCursorsVirtualDom = cursors => {
8440
+ const dom = [];
8441
+ for (const translate of cursors) {
8442
+ dom.push({
8291
8443
  type: Div,
8292
- childCount: 1
8293
- }, text(noResults())];
8444
+ className: EditorCursor,
8445
+ translate
8446
+ });
8294
8447
  }
8295
- const root = {
8296
- type: Div,
8297
- childCount: visibleItems.length
8298
- };
8299
- const dom = [root, ...visibleItems.flatMap(getCompletionItemVirtualDom)];
8300
8448
  return dom;
8301
8449
  };
8302
8450
 
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 = '';
8451
+ const Error$1 = 'error';
8452
+ const Warning = 'warning';
8320
8453
 
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;
8454
+ const getDiagnosticClassName = type => {
8455
+ // TODO use classnames enum
8456
+ switch (type) {
8457
+ case Error$1:
8458
+ return 'DiagnosticError';
8459
+ case Warning:
8460
+ return 'DiagnosticWarning';
8337
8461
  default:
8338
- return SymbolDefault;
8462
+ return 'DiagnosticError';
8339
8463
  }
8340
8464
  };
8341
-
8342
- const getHighlights = (item, leadingWord) => {
8465
+ const getDiagnosticVirtualDom = diagnostic => {
8343
8466
  const {
8344
- matches
8345
- } = item;
8346
- return matches.slice(1);
8467
+ x,
8468
+ y,
8469
+ width,
8470
+ height,
8471
+ type
8472
+ } = diagnostic;
8473
+ const extraClassName = getDiagnosticClassName(type);
8474
+ return [{
8475
+ type: Div,
8476
+ className: `${Diagnostic} ${extraClassName}`,
8477
+ width,
8478
+ height,
8479
+ top: y,
8480
+ left: x,
8481
+ childCount: 0
8482
+ }];
8347
8483
  };
8348
8484
 
8349
- // import * as IconTheme from '../IconTheme/IconTheme.ts'
8350
-
8351
- const getLabel = item => {
8352
- return item.label;
8485
+ const getDiagnosticsVirtualDom = diagnostics => {
8486
+ const dom = diagnostics.flatMap(getDiagnosticVirtualDom);
8487
+ return dom;
8353
8488
  };
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
- }
8489
+
8490
+ const getGutterInfoVirtualDom = gutterInfo => {
8491
+ return [{
8492
+ type: Span,
8493
+ className: 'LineNumber',
8494
+ childCount: 1
8495
+ }, text(gutterInfo)];
8365
8496
  };
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
- };
8497
+ const getEditorGutterVirtualDom = gutterInfos => {
8498
+ const dom = gutterInfos.flatMap(getGutterInfoVirtualDom);
8499
+ return dom;
8376
8500
  };
8377
8501
 
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));
8502
+ const getEditorRowsVirtualDom = (textInfos, differences, lineNumbers = true) => {
8503
+ const dom = [];
8504
+ for (let i = 0; i < textInfos.length; i++) {
8505
+ const textInfo = textInfos[i];
8506
+ const difference = differences[i];
8507
+ dom.push({
8508
+ type: Div,
8509
+ className: EditorRow,
8510
+ translate: px(difference),
8511
+ childCount: textInfo.length / 2
8512
+ });
8513
+ for (let j = 0; j < textInfo.length; j += 2) {
8514
+ const tokenText = textInfo[j];
8515
+ const className = textInfo[j + 1];
8516
+ dom.push({
8517
+ type: Span,
8518
+ className,
8519
+ childCount: 1
8520
+ }, text(tokenText));
8521
+ }
8383
8522
  }
8384
- return visibleItems;
8523
+ return dom;
8385
8524
  };
8386
8525
 
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];
8526
+ const getIncrementalEdits = async (oldState, newState) => {
8527
+ if (!newState.undoStack) {
8528
+ return undefined;
8441
8529
  }
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));
8530
+ const lastChanges = newState.undoStack.at(-1);
8531
+ if (lastChanges && lastChanges.length === 1) {
8532
+ const lastChange = lastChanges[0];
8533
+ if (lastChange.origin === EditorType) {
8534
+ const rowIndex = lastChange.start.rowIndex;
8535
+ const lines = newState.lines;
8536
+ const oldLine = oldState.lines[rowIndex];
8537
+ const newLine = lines[rowIndex];
8538
+ const incrementalEdits = await invoke$1('TokenizeIncremental.tokenizeIncremental', newState.uid, newState.languageId, oldLine, newLine, rowIndex, newState.minLineY);
8539
+ if (incrementalEdits && incrementalEdits.length === 1) {
8540
+ return incrementalEdits;
8541
+ }
8449
8542
  }
8450
8543
  }
8451
- return commands;
8544
+ return undefined;
8452
8545
  };
8453
8546
 
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]);
8547
+ const getSelectionsVirtualDom = selections => {
8548
+ const dom = [];
8549
+ for (let i = 0; i < selections.length; i += 4) {
8550
+ const x = selections[i];
8551
+ const y = selections[i + 1];
8552
+ const width = selections[i + 2];
8553
+ const height = selections[i + 3];
8554
+ dom.push({
8555
+ type: Div,
8556
+ className: EditorSelection,
8557
+ left: x,
8558
+ top: y,
8559
+ width,
8560
+ height
8561
+ });
8460
8562
  }
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;
8563
+ return dom;
8473
8564
  };
8565
+
8474
8566
  const addWidget = widget => {
8475
8567
  const {
8476
8568
  id
8477
8569
  } = widget;
8478
8570
  switch (id) {
8479
- case 'completion':
8480
- return addWidgetCompletion(widget);
8571
+ case Completion:
8572
+ return add(widget);
8481
8573
  default:
8482
8574
  throw new Error('unsupported widget');
8483
8575
  }
@@ -8487,22 +8579,19 @@ const renderWidget = widget => {
8487
8579
  id
8488
8580
  } = widget;
8489
8581
  switch (id) {
8490
- case 'completion':
8491
- return renderCompletion(widget.oldState, widget.newState);
8582
+ case Completion:
8583
+ return render$2(widget.oldState, widget.newState);
8492
8584
  default:
8493
8585
  throw new Error(`unsupported widget`);
8494
8586
  }
8495
8587
  };
8496
- const removeCompletion = widget => {
8497
- return [['Viewlet.send', widget.newState.uid, 'dispose']];
8498
- };
8499
8588
  const removeWidget = widget => {
8500
8589
  const {
8501
8590
  id
8502
8591
  } = widget;
8503
8592
  switch (id) {
8504
- case 'completion':
8505
- return removeCompletion(widget);
8593
+ case Completion:
8594
+ return remove$1(widget);
8506
8595
  default:
8507
8596
  throw new Error('unsupported widget');
8508
8597
  }