@lvce-editor/editor-worker 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/editorWorkerMain.js +1465 -1551
- package/package.json +1 -1
package/dist/editorWorkerMain.js
CHANGED
|
@@ -238,1097 +238,131 @@ const IndentMore = 'indentMore';
|
|
|
238
238
|
const InsertLineBreak = 'insertLineBreak';
|
|
239
239
|
const ToggleBlockComment = 'toggleBlockComment';
|
|
240
240
|
|
|
241
|
-
const
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
const T = 't';
|
|
248
|
-
|
|
249
|
-
const getFontString = (fontWeight, fontSize, fontFamily) => {
|
|
250
|
-
return `${fontWeight} ${fontSize}px ${fontFamily}`;
|
|
241
|
+
const modules = Object.create(null);
|
|
242
|
+
const register = (id, value) => {
|
|
243
|
+
modules[id] = value;
|
|
244
|
+
};
|
|
245
|
+
const get$7 = id => {
|
|
246
|
+
return modules[id];
|
|
251
247
|
};
|
|
252
248
|
|
|
253
|
-
const
|
|
254
|
-
return
|
|
249
|
+
const getModule$2 = id => {
|
|
250
|
+
return get$7(id);
|
|
255
251
|
};
|
|
256
252
|
|
|
257
|
-
const
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
253
|
+
const applyWidgetChange = (editor, widget, changes) => {
|
|
254
|
+
const module = getModule$2(widget.id);
|
|
255
|
+
if (changes.length === 1 && changes[0].origin === EditorType && module.handleEditorType) {
|
|
256
|
+
const newState = module.handleEditorType(editor, widget.newState);
|
|
257
|
+
return {
|
|
258
|
+
...widget,
|
|
259
|
+
newState
|
|
260
|
+
};
|
|
262
261
|
}
|
|
263
|
-
|
|
262
|
+
if (changes.length === 1 && changes[0].origin === DeleteLeft && module.handleEditorDeleteLeft) {
|
|
263
|
+
const newState = module.handleEditorDeleteLeft(editor, widget.newState);
|
|
264
|
+
return {
|
|
265
|
+
...widget,
|
|
266
|
+
newState
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
return widget;
|
|
264
270
|
};
|
|
265
271
|
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
if (state$b.ctx) {
|
|
271
|
-
return state$b.ctx;
|
|
272
|
+
const applyWidgetChanges = (editor, changes) => {
|
|
273
|
+
const widgets = editor.widgets || [];
|
|
274
|
+
if (widgets.length === 0) {
|
|
275
|
+
return widgets;
|
|
272
276
|
}
|
|
273
|
-
|
|
274
|
-
|
|
277
|
+
const newWidgets = [];
|
|
278
|
+
for (const widget of widgets) {
|
|
279
|
+
const newWidget = applyWidgetChange(editor, widget, changes);
|
|
280
|
+
if (newWidget.newState) {
|
|
281
|
+
newWidgets.push(newWidget);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return newWidgets;
|
|
275
285
|
};
|
|
276
286
|
|
|
277
|
-
const
|
|
278
|
-
const
|
|
279
|
-
return
|
|
287
|
+
const getScrollBarOffset = (delta, finalDelta, size, scrollBarSize) => {
|
|
288
|
+
const scrollBarOffset = delta / finalDelta * (size - scrollBarSize);
|
|
289
|
+
return scrollBarOffset;
|
|
280
290
|
};
|
|
291
|
+
const getScrollBarY = getScrollBarOffset;
|
|
281
292
|
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
number$1(fontSize);
|
|
286
|
-
string(fontFamily);
|
|
287
|
-
boolean(isMonoSpaceFont);
|
|
288
|
-
number$1(charWidth);
|
|
289
|
-
if (isMonoSpaceFont) {
|
|
290
|
-
return text.length * charWidth;
|
|
291
|
-
}
|
|
292
|
-
if (typeof letterSpacing !== 'number') {
|
|
293
|
-
throw new TypeError('letterSpacing must be of type number');
|
|
293
|
+
const getScrollBarSize = (size, contentSize, minimumSliderSize) => {
|
|
294
|
+
if (size >= contentSize) {
|
|
295
|
+
return 0;
|
|
294
296
|
}
|
|
295
|
-
|
|
296
|
-
const fontString = getFontString(fontWeight, fontSize, fontFamily);
|
|
297
|
-
const ctx = getContext();
|
|
298
|
-
// @ts-ignore
|
|
299
|
-
ctx.letterSpacing = letterSpacingString;
|
|
300
|
-
// @ts-ignore
|
|
301
|
-
ctx.font = fontString;
|
|
302
|
-
// @ts-ignore
|
|
303
|
-
const metrics = ctx.measureText(text);
|
|
304
|
-
const width = metrics.width;
|
|
305
|
-
return width;
|
|
297
|
+
return Math.max(Math.round(size ** 2 / contentSize), minimumSliderSize);
|
|
306
298
|
};
|
|
307
299
|
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
// @ts-ignore
|
|
312
|
-
guess,
|
|
313
|
-
// @ts-ignore
|
|
314
|
-
averageCharWidth,
|
|
315
|
-
// @ts-ignore
|
|
316
|
-
eventX,
|
|
317
|
-
// @ts-ignore
|
|
318
|
-
fontWeight,
|
|
319
|
-
// @ts-ignore
|
|
320
|
-
fontSize,
|
|
321
|
-
// @ts-ignore
|
|
322
|
-
fontFamily,
|
|
323
|
-
// @ts-ignore
|
|
324
|
-
letterSpacing,
|
|
325
|
-
// @ts-ignore
|
|
326
|
-
isMonospaceFont,
|
|
327
|
-
// @ts-ignore
|
|
328
|
-
charWidth) => {
|
|
329
|
-
for (let i = guess; i < line.length; i++) {
|
|
330
|
-
const width = measureTextWidth(line.slice(0, i), fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
|
|
331
|
-
if (eventX - width < averageCharWidth / 2) {
|
|
332
|
-
return i;
|
|
333
|
-
}
|
|
300
|
+
const getScrollBarWidth = (width, longestLineWidth) => {
|
|
301
|
+
if (width > longestLineWidth) {
|
|
302
|
+
return 0;
|
|
334
303
|
}
|
|
335
|
-
return
|
|
304
|
+
return width ** 2 / longestLineWidth;
|
|
336
305
|
};
|
|
337
306
|
|
|
338
|
-
const
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
307
|
+
const getNewDeltaPercent = (height, scrollBarHeight, relativeY) => {
|
|
308
|
+
const halfScrollBarHeight = scrollBarHeight / 2;
|
|
309
|
+
if (relativeY <= halfScrollBarHeight) {
|
|
310
|
+
// clicked at top
|
|
311
|
+
return {
|
|
312
|
+
percent: 0,
|
|
313
|
+
handleOffset: relativeY
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
if (relativeY <= height - halfScrollBarHeight) {
|
|
317
|
+
// clicked in middle
|
|
318
|
+
return {
|
|
319
|
+
percent: (relativeY - halfScrollBarHeight) / (height - scrollBarHeight),
|
|
320
|
+
handleOffset: halfScrollBarHeight
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
// clicked at bottom
|
|
344
324
|
return {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
return segments.containing(index);
|
|
348
|
-
},
|
|
349
|
-
visualIndex(line, index) {
|
|
350
|
-
const segments = segmenter.segment(line);
|
|
351
|
-
let currentVisualIndex = 0;
|
|
352
|
-
for (const segment of segments) {
|
|
353
|
-
if (segment.index >= index) {
|
|
354
|
-
return currentVisualIndex;
|
|
355
|
-
}
|
|
356
|
-
currentVisualIndex++;
|
|
357
|
-
}
|
|
358
|
-
return currentVisualIndex;
|
|
359
|
-
},
|
|
360
|
-
modelIndex(line, visualIndex) {
|
|
361
|
-
const segments = segmenter.segment(line);
|
|
362
|
-
let currentVisualIndex = 0;
|
|
363
|
-
for (const segment of segments) {
|
|
364
|
-
if (currentVisualIndex >= visualIndex) {
|
|
365
|
-
return segment.index;
|
|
366
|
-
}
|
|
367
|
-
currentVisualIndex++;
|
|
368
|
-
}
|
|
369
|
-
return line.length;
|
|
370
|
-
},
|
|
371
|
-
getSegments(line) {
|
|
372
|
-
return segmenter.segment(line);
|
|
373
|
-
}
|
|
325
|
+
percent: 1,
|
|
326
|
+
handleOffset: scrollBarHeight - height + relativeY
|
|
374
327
|
};
|
|
375
328
|
};
|
|
376
329
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
const segments = segmenter.getSegments(line);
|
|
381
|
-
const isMonospaceFont = false;
|
|
382
|
-
const charWidth = 0;
|
|
383
|
-
for (const segment of segments) {
|
|
384
|
-
const width = measureTextWidth(line.slice(0, segment.index), fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
|
|
385
|
-
if (eventX - width < averageCharWidth) {
|
|
386
|
-
return segment.index;
|
|
387
|
-
}
|
|
330
|
+
const splitLines$2 = lines => {
|
|
331
|
+
if (!lines) {
|
|
332
|
+
return [];
|
|
388
333
|
}
|
|
389
|
-
return
|
|
334
|
+
return lines.split('\n');
|
|
390
335
|
};
|
|
391
336
|
|
|
392
|
-
|
|
393
|
-
const isAscii = line => {
|
|
394
|
-
return RE_ASCII.test(line);
|
|
395
|
-
};
|
|
337
|
+
// based on https://github.com/microsoft/vscode/blob/c0769274fa136b45799edeccc0d0a2f645b75caf/src/vs/base/common/arrays.ts#L625 (License MIT)
|
|
396
338
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
339
|
+
// @ts-ignore
|
|
340
|
+
const insertInto = (array, start, newItems) => {
|
|
341
|
+
const originalLength = array.length;
|
|
342
|
+
const newItemsLength = newItems.length;
|
|
343
|
+
array.length = originalLength + newItemsLength;
|
|
344
|
+
// Move the items after the start index, start from the end so that we don't overwrite any value.
|
|
345
|
+
for (let i = originalLength - 1; i >= start; i--) {
|
|
346
|
+
array[i + newItemsLength] = array[i];
|
|
347
|
+
}
|
|
348
|
+
for (let i = 0; i < newItemsLength; i++) {
|
|
349
|
+
array[i + start] = newItems[i];
|
|
400
350
|
}
|
|
401
|
-
return text;
|
|
402
|
-
};
|
|
403
|
-
const shouldNormalizeText = text => {
|
|
404
|
-
return text.includes(Tab);
|
|
405
351
|
};
|
|
406
352
|
|
|
353
|
+
/**
|
|
354
|
+
* Alternative to the native Array.splice method, it
|
|
355
|
+
* can only support limited number of items due to the maximum call stack size limit.
|
|
356
|
+
*/
|
|
407
357
|
// @ts-ignore
|
|
408
|
-
const
|
|
409
|
-
const
|
|
410
|
-
|
|
358
|
+
const spliceLargeArray = (array, start, deleteCount, newItems) => {
|
|
359
|
+
const result = array.splice(start, deleteCount);
|
|
360
|
+
insertInto(array, start, newItems);
|
|
361
|
+
return result;
|
|
411
362
|
};
|
|
412
363
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
let normalizedGuess = guess;
|
|
416
|
-
for (let i = 0; i < guess; i++) {
|
|
417
|
-
if (line[i] === Tab) {
|
|
418
|
-
normalizedGuess -= tabSize - 1;
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
return normalizedGuess;
|
|
422
|
-
};
|
|
423
|
-
|
|
424
|
-
// @ts-ignore
|
|
425
|
-
const getAccurateColumnIndex = (line, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth, tabSize, eventX) => {
|
|
426
|
-
string(line);
|
|
427
|
-
number$1(fontWeight);
|
|
428
|
-
number$1(fontSize);
|
|
429
|
-
string(fontFamily);
|
|
430
|
-
number$1(letterSpacing);
|
|
431
|
-
boolean(isMonospaceFont);
|
|
432
|
-
number$1(charWidth);
|
|
433
|
-
number$1(tabSize);
|
|
434
|
-
number$1(eventX);
|
|
435
|
-
// Assert.greaterZero(charWidth)
|
|
436
|
-
const guess = guessOffset(eventX, charWidth);
|
|
437
|
-
const normalize = shouldNormalizeText(line);
|
|
438
|
-
const normalizedGuess = normalizeGuess(line, guess, tabSize);
|
|
439
|
-
const text = line.slice(0, normalizedGuess);
|
|
440
|
-
const normalizedText = normalizeText(text, normalize, tabSize);
|
|
441
|
-
const actual = measureTextWidth(normalizedText, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
|
|
442
|
-
const isAscii$1 = isAscii(line);
|
|
443
|
-
if (isAscii$1) {
|
|
444
|
-
if (Math.abs(eventX - actual) < charWidth / 2) {
|
|
445
|
-
return normalizedGuess;
|
|
446
|
-
}
|
|
447
|
-
return getAccurateColumnIndexAscii(line, normalizedGuess, charWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
|
|
448
|
-
}
|
|
449
|
-
return getAccurateColumnIndexUnicode(line, normalizedGuess, charWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing);
|
|
450
|
-
};
|
|
451
|
-
|
|
452
|
-
const at = (editor, eventX, eventY) => {
|
|
453
|
-
object(editor);
|
|
454
|
-
number$1(eventX);
|
|
455
|
-
number$1(eventY);
|
|
456
|
-
const {
|
|
457
|
-
y,
|
|
458
|
-
deltaY,
|
|
459
|
-
rowHeight,
|
|
460
|
-
fontSize,
|
|
461
|
-
fontWeight,
|
|
462
|
-
fontFamily,
|
|
463
|
-
letterSpacing,
|
|
464
|
-
lines,
|
|
465
|
-
tabSize,
|
|
466
|
-
differences,
|
|
467
|
-
isMonospaceFont,
|
|
468
|
-
charWidth
|
|
469
|
-
} = editor;
|
|
470
|
-
const rowIndex = Math.floor((eventY - y + deltaY) / rowHeight);
|
|
471
|
-
if (rowIndex < 0) {
|
|
472
|
-
return {
|
|
473
|
-
rowIndex: 0,
|
|
474
|
-
columnIndex: 0
|
|
475
|
-
};
|
|
476
|
-
}
|
|
477
|
-
const clampedRowIndex = clamp(rowIndex, 0, lines.length - 1);
|
|
478
|
-
const line = lines[clampedRowIndex];
|
|
479
|
-
const columnIndex = getAccurateColumnIndex(line, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth, tabSize, eventX);
|
|
480
|
-
return {
|
|
481
|
-
rowIndex: clampedRowIndex,
|
|
482
|
-
columnIndex
|
|
483
|
-
};
|
|
484
|
-
};
|
|
485
|
-
|
|
486
|
-
/**
|
|
487
|
-
* @deprecated this doesn't work for variable width characters (unicode/emoji).
|
|
488
|
-
* Use position computation in renderer process instead
|
|
489
|
-
*
|
|
490
|
-
* @param {object} editor
|
|
491
|
-
* @param {number} rowIndex
|
|
492
|
-
* @param {number} columnIndex
|
|
493
|
-
* @returns
|
|
494
|
-
*/
|
|
495
|
-
const x = (editor, rowIndex, columnIndex) => {
|
|
496
|
-
const {
|
|
497
|
-
columnWidth,
|
|
498
|
-
x
|
|
499
|
-
} = editor;
|
|
500
|
-
const offsetX = columnIndex * columnWidth + x;
|
|
501
|
-
return offsetX;
|
|
502
|
-
};
|
|
503
|
-
const y = (editor, rowIndex) => {
|
|
504
|
-
const {
|
|
505
|
-
rowHeight,
|
|
506
|
-
y
|
|
507
|
-
} = editor;
|
|
508
|
-
const offsetY = (rowIndex + 1) * rowHeight + y;
|
|
509
|
-
return offsetY;
|
|
510
|
-
};
|
|
511
|
-
|
|
512
|
-
const emptyObject = {};
|
|
513
|
-
const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
|
|
514
|
-
const i18nString = (key, placeholders = emptyObject) => {
|
|
515
|
-
if (placeholders === emptyObject) {
|
|
516
|
-
return key;
|
|
517
|
-
}
|
|
518
|
-
const replacer = (match, rest) => {
|
|
519
|
-
return placeholders[rest];
|
|
520
|
-
};
|
|
521
|
-
return key.replaceAll(RE_PLACEHOLDER, replacer);
|
|
522
|
-
};
|
|
523
|
-
|
|
524
|
-
/**
|
|
525
|
-
* @enum {string}
|
|
526
|
-
*/
|
|
527
|
-
const UiStrings = {
|
|
528
|
-
OrganizeImports: 'Organize Imports',
|
|
529
|
-
Copy: 'Copy',
|
|
530
|
-
CopyLineDown: 'Copy Line Down',
|
|
531
|
-
CopyLineUp: 'Copy Line Up',
|
|
532
|
-
Cut: 'Cut',
|
|
533
|
-
DuplicateSelection: 'Duplicate Selection',
|
|
534
|
-
FindAllImplementations: 'Find All Implementations',
|
|
535
|
-
FindAllReferences: 'Find All References',
|
|
536
|
-
GoToDefinition: 'Go to Definition',
|
|
537
|
-
GoToTypeDefinition: 'Go to Type Definition',
|
|
538
|
-
MoveLineDown: 'Move Line Down',
|
|
539
|
-
MoveLineUp: 'Move Line Up',
|
|
540
|
-
NoDefinitionFound: 'No definition found',
|
|
541
|
-
NoDefinitionFoundFor: "No definition found for '{PH1}'",
|
|
542
|
-
NoTypeDefinitionFound: 'No type definition found',
|
|
543
|
-
NoTypeDefinitionFoundFor: "No type definition found for '{PH1}'",
|
|
544
|
-
Paste: 'Paste',
|
|
545
|
-
Redo: 'Redo',
|
|
546
|
-
SelectAll: 'Select All',
|
|
547
|
-
Separator: 'Separator',
|
|
548
|
-
ToggleBlockComment: 'Toggle Block Comment',
|
|
549
|
-
ToggleLineComment: 'Toggle Line Comment',
|
|
550
|
-
Undo: 'Undo',
|
|
551
|
-
FormatDocument: 'Format Document',
|
|
552
|
-
SourceActions: 'Source Actions',
|
|
553
|
-
EditorShowHover: 'Show Hover',
|
|
554
|
-
EditorFormatDocumentForced: 'Editor: Format Document (forced)',
|
|
555
|
-
EditorSelectNextOccurrence: 'Editor: Select Next Occurrence',
|
|
556
|
-
EditorSelectAllOccurrences: 'Editor: Select All Occurrences',
|
|
557
|
-
EditorGoToDefinition: 'Editor: Go To Definition',
|
|
558
|
-
EditorGoToTypeDefinition: 'Editor: Go To Type Definition',
|
|
559
|
-
EditorSelectInsideString: 'Editor: Select Inside String',
|
|
560
|
-
EditorIndent: 'Editor: Indent',
|
|
561
|
-
EditorUnindent: 'Editor: Unindent',
|
|
562
|
-
EditorSortLinesAscending: 'Editor: Sort Lines Ascending',
|
|
563
|
-
EditorToggleComment: 'Editor: Toggle Comment',
|
|
564
|
-
EditorSelectUp: 'Editor: Select Up',
|
|
565
|
-
EditorSelectDown: 'Editor: Select Down',
|
|
566
|
-
EditorToggleBlockComment: 'Editor: Toggle Block Comment',
|
|
567
|
-
EditorOpenColorPicker: 'Editor: Open Color Picker',
|
|
568
|
-
EditorCloseColorPicker: 'Editor: Close Color Picker',
|
|
569
|
-
EditorCopyLineDown: 'Editor: Copy Line Down',
|
|
570
|
-
EditorCopyLineUp: 'Editor: Copy Line Up',
|
|
571
|
-
Replace: 'replace',
|
|
572
|
-
NoResults: 'No Results'
|
|
573
|
-
};
|
|
574
|
-
const noDefinitionFound = () => {
|
|
575
|
-
return i18nString(UiStrings.NoDefinitionFound);
|
|
576
|
-
};
|
|
577
|
-
|
|
578
|
-
// @ts-ignore
|
|
579
|
-
const noDefinitionFoundFor = word => {
|
|
580
|
-
return i18nString(UiStrings.NoDefinitionFoundFor, {
|
|
581
|
-
PH1: word
|
|
582
|
-
});
|
|
583
|
-
};
|
|
584
|
-
|
|
585
|
-
// @ts-ignore
|
|
586
|
-
const noTypeDefinitionFoundFor = word => {
|
|
587
|
-
return i18nString(UiStrings.NoTypeDefinitionFoundFor, {
|
|
588
|
-
PH1: word
|
|
589
|
-
});
|
|
590
|
-
};
|
|
591
|
-
const noTypeDefinitionFound = () => {
|
|
592
|
-
return i18nString(UiStrings.NoTypeDefinitionFound);
|
|
593
|
-
};
|
|
594
|
-
const noResults = () => {
|
|
595
|
-
return i18nString(UiStrings.NoResults);
|
|
596
|
-
};
|
|
597
|
-
|
|
598
|
-
const None$1 = 'none';
|
|
599
|
-
const Option = 'option';
|
|
600
|
-
|
|
601
|
-
const getFileIconVirtualDom = icon => {
|
|
602
|
-
return {
|
|
603
|
-
type: Img,
|
|
604
|
-
className: FileIcon,
|
|
605
|
-
src: icon,
|
|
606
|
-
role: None$1,
|
|
607
|
-
childCount: 0
|
|
608
|
-
};
|
|
609
|
-
};
|
|
610
|
-
|
|
611
|
-
const getIconDom = (fileIcon, symbolName) => {
|
|
612
|
-
if (fileIcon) {
|
|
613
|
-
return getFileIconVirtualDom(fileIcon);
|
|
614
|
-
}
|
|
615
|
-
return {
|
|
616
|
-
type: Div,
|
|
617
|
-
className: `${ColoredMaskIcon} ${symbolName}`,
|
|
618
|
-
childCount: 0
|
|
619
|
-
};
|
|
620
|
-
};
|
|
621
|
-
|
|
622
|
-
const text = data => {
|
|
623
|
-
return {
|
|
624
|
-
type: Text,
|
|
625
|
-
text: data,
|
|
626
|
-
childCount: 0
|
|
627
|
-
};
|
|
628
|
-
};
|
|
629
|
-
|
|
630
|
-
const label1 = {
|
|
631
|
-
type: Div,
|
|
632
|
-
className: Label,
|
|
633
|
-
childCount: 1
|
|
634
|
-
};
|
|
635
|
-
const completionHighlight = {
|
|
636
|
-
type: Span,
|
|
637
|
-
className: EditorCompletionItemHighlight,
|
|
638
|
-
childCount: 1
|
|
639
|
-
};
|
|
640
|
-
const getHighlightedLabelDom = (label, highlights) => {
|
|
641
|
-
if (highlights.length === 0) {
|
|
642
|
-
return [label1, text(label)];
|
|
643
|
-
}
|
|
644
|
-
const dom = [];
|
|
645
|
-
const labelDom = {
|
|
646
|
-
type: Div,
|
|
647
|
-
className: Label,
|
|
648
|
-
childCount: 0
|
|
649
|
-
};
|
|
650
|
-
dom.push(labelDom);
|
|
651
|
-
let position = 0;
|
|
652
|
-
for (let i = 0; i < highlights.length; i += 2) {
|
|
653
|
-
const highlightStart = highlights[i];
|
|
654
|
-
const highlightEnd = highlights[i + 1];
|
|
655
|
-
if (position < highlightStart) {
|
|
656
|
-
const beforeText = label.slice(position, highlightStart);
|
|
657
|
-
labelDom.childCount++;
|
|
658
|
-
dom.push(text(beforeText));
|
|
659
|
-
}
|
|
660
|
-
const highlightText = label.slice(highlightStart, highlightEnd);
|
|
661
|
-
labelDom.childCount++;
|
|
662
|
-
dom.push(completionHighlight, text(highlightText));
|
|
663
|
-
position = highlightEnd;
|
|
664
|
-
}
|
|
665
|
-
if (position < label.length) {
|
|
666
|
-
const afterText = label.slice(position);
|
|
667
|
-
labelDom.childCount++;
|
|
668
|
-
dom.push(text(afterText));
|
|
669
|
-
}
|
|
670
|
-
return dom;
|
|
671
|
-
};
|
|
672
|
-
|
|
673
|
-
const getCompletionItemVirtualDom = visibleItem => {
|
|
674
|
-
const {
|
|
675
|
-
top,
|
|
676
|
-
label,
|
|
677
|
-
symbolName,
|
|
678
|
-
highlights,
|
|
679
|
-
focused,
|
|
680
|
-
deprecated,
|
|
681
|
-
fileIcon
|
|
682
|
-
} = visibleItem;
|
|
683
|
-
let className = EditorCompletionItem;
|
|
684
|
-
if (focused) {
|
|
685
|
-
className += ' ' + EditorCompletionItemFocused;
|
|
686
|
-
}
|
|
687
|
-
if (deprecated) {
|
|
688
|
-
className += ' ' + EditorCompletionItemDeprecated;
|
|
689
|
-
}
|
|
690
|
-
return [{
|
|
691
|
-
type: Div,
|
|
692
|
-
role: Option,
|
|
693
|
-
className,
|
|
694
|
-
top,
|
|
695
|
-
childCount: 2
|
|
696
|
-
}, getIconDom(fileIcon, symbolName), ...getHighlightedLabelDom(label, highlights)];
|
|
697
|
-
};
|
|
698
|
-
|
|
699
|
-
const getCompletionItemsVirtualDom = visibleItems => {
|
|
700
|
-
if (visibleItems.length === 0) {
|
|
701
|
-
return [{
|
|
702
|
-
type: Div,
|
|
703
|
-
childCount: 1
|
|
704
|
-
}, text(noResults())];
|
|
705
|
-
}
|
|
706
|
-
const root = {
|
|
707
|
-
type: Div,
|
|
708
|
-
childCount: visibleItems.length
|
|
709
|
-
};
|
|
710
|
-
const dom = [root, ...visibleItems.flatMap(getCompletionItemVirtualDom)];
|
|
711
|
-
return dom;
|
|
712
|
-
};
|
|
713
|
-
|
|
714
|
-
const Deprecated = 1 << 0;
|
|
715
|
-
|
|
716
|
-
const Property = 1;
|
|
717
|
-
const Value = 2;
|
|
718
|
-
const Function$1 = 3;
|
|
719
|
-
const Variable = 4;
|
|
720
|
-
const Keyword = 5;
|
|
721
|
-
const Folder = 6;
|
|
722
|
-
const File = 7;
|
|
723
|
-
const Field = 8;
|
|
724
|
-
|
|
725
|
-
const SymbolProperty = 'SymbolProperty';
|
|
726
|
-
const SymbolValue = 'SymbolValue';
|
|
727
|
-
const SymbolFunction = 'SymbolFunction';
|
|
728
|
-
const SymbolVariable = 'SymbolVariable';
|
|
729
|
-
const SymbolKeyword = 'SymbolKeyword';
|
|
730
|
-
const SymbolDefault = 'SymbolDefault';
|
|
731
|
-
const SymbolField = 'SymbolField';
|
|
732
|
-
const SymbolNone = '';
|
|
733
|
-
|
|
734
|
-
const getSymbolName = kind => {
|
|
735
|
-
switch (kind) {
|
|
736
|
-
case Property:
|
|
737
|
-
return SymbolProperty;
|
|
738
|
-
case Value:
|
|
739
|
-
return SymbolValue;
|
|
740
|
-
case Function$1:
|
|
741
|
-
return SymbolFunction;
|
|
742
|
-
case Variable:
|
|
743
|
-
return SymbolVariable;
|
|
744
|
-
case Keyword:
|
|
745
|
-
return SymbolKeyword;
|
|
746
|
-
case Field:
|
|
747
|
-
return SymbolField;
|
|
748
|
-
case File:
|
|
749
|
-
return SymbolNone;
|
|
750
|
-
default:
|
|
751
|
-
return SymbolDefault;
|
|
752
|
-
}
|
|
753
|
-
};
|
|
754
|
-
|
|
755
|
-
const getHighlights = item => {
|
|
756
|
-
const {
|
|
757
|
-
matches
|
|
758
|
-
} = item;
|
|
759
|
-
return matches.slice(1);
|
|
760
|
-
};
|
|
761
|
-
|
|
762
|
-
// import * as IconTheme from '../IconTheme/IconTheme.ts'
|
|
763
|
-
|
|
764
|
-
const getLabel = item => {
|
|
765
|
-
return item.label;
|
|
766
|
-
};
|
|
767
|
-
const getFileIcon = item => {
|
|
768
|
-
switch (item.kind) {
|
|
769
|
-
case File:
|
|
770
|
-
// TODO IconTheme.getFileNameIcon(item.label)
|
|
771
|
-
return '';
|
|
772
|
-
case Folder:
|
|
773
|
-
// TODO IconTheme.getFolderNameIcon(item.label)
|
|
774
|
-
return '';
|
|
775
|
-
default:
|
|
776
|
-
return '';
|
|
777
|
-
}
|
|
778
|
-
};
|
|
779
|
-
const getVisibleIem = (item, itemHeight, leadingWord, i, focusedIndex) => {
|
|
780
|
-
return {
|
|
781
|
-
label: getLabel(item),
|
|
782
|
-
symbolName: getSymbolName(item.kind),
|
|
783
|
-
top: i * itemHeight,
|
|
784
|
-
highlights: getHighlights(item),
|
|
785
|
-
focused: i === focusedIndex,
|
|
786
|
-
deprecated: item.flags & Deprecated,
|
|
787
|
-
fileIcon: getFileIcon(item)
|
|
788
|
-
};
|
|
789
|
-
};
|
|
790
|
-
|
|
791
|
-
const getVisibleItems = (filteredItems, itemHeight, leadingWord, minLineY, maxLineY, focusedIndex) => {
|
|
792
|
-
const visibleItems = [];
|
|
793
|
-
for (let i = minLineY; i < maxLineY; i++) {
|
|
794
|
-
const filteredItem = filteredItems[i];
|
|
795
|
-
visibleItems.push(getVisibleIem(filteredItem, itemHeight, leadingWord, i, focusedIndex));
|
|
796
|
-
}
|
|
797
|
-
return visibleItems;
|
|
798
|
-
};
|
|
799
|
-
|
|
800
|
-
/**
|
|
801
|
-
*
|
|
802
|
-
* @param {number} size
|
|
803
|
-
* @param {number} contentSize
|
|
804
|
-
* @param {number} minimumSliderSize
|
|
805
|
-
* @returns
|
|
806
|
-
*/
|
|
807
|
-
const getScrollBarSize = (size, contentSize, minimumSliderSize) => {
|
|
808
|
-
if (size >= contentSize) {
|
|
809
|
-
return 0;
|
|
810
|
-
}
|
|
811
|
-
return Math.max(Math.round(size ** 2 / contentSize), minimumSliderSize);
|
|
812
|
-
};
|
|
813
|
-
const getScrollBarOffset = (delta, finalDelta, size, scrollBarSize) => {
|
|
814
|
-
const scrollBarOffset = delta / finalDelta * (size - scrollBarSize);
|
|
815
|
-
return scrollBarOffset;
|
|
816
|
-
};
|
|
817
|
-
const getScrollBarY = getScrollBarOffset;
|
|
818
|
-
const getScrollBarWidth = (width, longestLineWidth) => {
|
|
819
|
-
if (width > longestLineWidth) {
|
|
820
|
-
return 0;
|
|
821
|
-
}
|
|
822
|
-
return width ** 2 / longestLineWidth;
|
|
823
|
-
};
|
|
824
|
-
const getNewDeltaPercent = (height, scrollBarHeight, relativeY) => {
|
|
825
|
-
const halfScrollBarHeight = scrollBarHeight / 2;
|
|
826
|
-
if (relativeY <= halfScrollBarHeight) {
|
|
827
|
-
// clicked at top
|
|
828
|
-
return {
|
|
829
|
-
percent: 0,
|
|
830
|
-
handleOffset: relativeY
|
|
831
|
-
};
|
|
832
|
-
}
|
|
833
|
-
if (relativeY <= height - halfScrollBarHeight) {
|
|
834
|
-
// clicked in middle
|
|
835
|
-
return {
|
|
836
|
-
percent: (relativeY - halfScrollBarHeight) / (height - scrollBarHeight),
|
|
837
|
-
handleOffset: halfScrollBarHeight
|
|
838
|
-
};
|
|
839
|
-
}
|
|
840
|
-
// clicked at bottom
|
|
841
|
-
return {
|
|
842
|
-
percent: 1,
|
|
843
|
-
handleOffset: scrollBarHeight - height + relativeY
|
|
844
|
-
};
|
|
845
|
-
};
|
|
846
|
-
|
|
847
|
-
const renderItems = {
|
|
848
|
-
isEqual(oldState, newState) {
|
|
849
|
-
return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.focusedIndex === newState.focusedIndex;
|
|
850
|
-
},
|
|
851
|
-
apply(oldState, newState) {
|
|
852
|
-
const visibleItems = getVisibleItems(newState.items, newState.itemHeight, newState.leadingWord, newState.minLineY, newState.maxLineY, newState.focusedIndex);
|
|
853
|
-
const dom = getCompletionItemsVirtualDom(visibleItems);
|
|
854
|
-
return ['setDom', dom];
|
|
855
|
-
}
|
|
856
|
-
};
|
|
857
|
-
const renderBounds$1 = {
|
|
858
|
-
isEqual(oldState, newState) {
|
|
859
|
-
return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.x === newState.x && oldState.y === newState.y;
|
|
860
|
-
},
|
|
861
|
-
apply(oldState, newState) {
|
|
862
|
-
const {
|
|
863
|
-
x,
|
|
864
|
-
y,
|
|
865
|
-
width,
|
|
866
|
-
height
|
|
867
|
-
} = newState;
|
|
868
|
-
return [/* method */SetBounds, /* x */x, /* y */y, /* width */width, /* height */height];
|
|
869
|
-
}
|
|
870
|
-
};
|
|
871
|
-
const renderHeight = {
|
|
872
|
-
isEqual(oldState, newState) {
|
|
873
|
-
return oldState.items.length === newState.items.length;
|
|
874
|
-
},
|
|
875
|
-
apply(oldState, newState) {
|
|
876
|
-
const {
|
|
877
|
-
itemHeight
|
|
878
|
-
} = newState;
|
|
879
|
-
const contentHeight = newState.items.length * itemHeight;
|
|
880
|
-
return [/* method */SetContentHeight, /* contentHeight */contentHeight];
|
|
881
|
-
}
|
|
882
|
-
};
|
|
883
|
-
const renderNegativeMargin = {
|
|
884
|
-
isEqual(oldState, newState) {
|
|
885
|
-
return oldState.deltaY === newState.deltaY;
|
|
886
|
-
},
|
|
887
|
-
apply(oldState, newState) {
|
|
888
|
-
return [/* method */SetNegativeMargin, /* negativeMargin */-newState.deltaY];
|
|
889
|
-
}
|
|
890
|
-
};
|
|
891
|
-
const renderScrollBar = {
|
|
892
|
-
isEqual(oldState, newState) {
|
|
893
|
-
return oldState.negativeMargin === newState.negativeMargin && oldState.deltaY === newState.deltaY && oldState.height === newState.height && oldState.finalDeltaY === newState.finalDeltaY && oldState.items.length === newState.items.length;
|
|
894
|
-
},
|
|
895
|
-
apply(oldState, newState) {
|
|
896
|
-
const total = newState.items.length;
|
|
897
|
-
const contentHeight = total * newState.itemHeight;
|
|
898
|
-
const scrollBarHeight = getScrollBarSize(newState.height, contentHeight, newState.minimumSliderSize);
|
|
899
|
-
const scrollBarY = getScrollBarY(newState.deltaY, newState.finalDeltaY, newState.height - newState.headerHeight, scrollBarHeight);
|
|
900
|
-
return [/* method */SetScrollBar, /* scrollBarY */scrollBarY, /* scrollBarHeight */scrollBarHeight];
|
|
901
|
-
}
|
|
902
|
-
};
|
|
903
|
-
const render$3 = [renderItems, renderBounds$1, renderHeight, renderNegativeMargin, renderScrollBar];
|
|
904
|
-
const renderCompletion = (oldState, newState) => {
|
|
905
|
-
const commands = [];
|
|
906
|
-
for (const item of render$3) {
|
|
907
|
-
if (!item.isEqual(oldState, newState)) {
|
|
908
|
-
commands.push(item.apply(oldState, newState));
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
return commands;
|
|
912
|
-
};
|
|
913
|
-
|
|
914
|
-
const EmptyMatches = [];
|
|
915
|
-
|
|
916
|
-
const Diagonal = 1;
|
|
917
|
-
const Left = 2;
|
|
918
|
-
|
|
919
|
-
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
920
|
-
|
|
921
|
-
const createTable = size => {
|
|
922
|
-
const table = [];
|
|
923
|
-
for (let i = 0; i < size; i++) {
|
|
924
|
-
const row = new Uint8Array(size);
|
|
925
|
-
table.push(row);
|
|
926
|
-
}
|
|
927
|
-
return table;
|
|
928
|
-
};
|
|
929
|
-
|
|
930
|
-
const isLowerCase = char => {
|
|
931
|
-
return char === char.toLowerCase();
|
|
932
|
-
};
|
|
933
|
-
|
|
934
|
-
const isUpperCase = char => {
|
|
935
|
-
return char === char.toUpperCase();
|
|
936
|
-
};
|
|
937
|
-
|
|
938
|
-
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
939
|
-
const isGap = (columnCharBefore, columnChar) => {
|
|
940
|
-
switch (columnCharBefore) {
|
|
941
|
-
case Dash:
|
|
942
|
-
case Underline:
|
|
943
|
-
case EmptyString:
|
|
944
|
-
case T:
|
|
945
|
-
case Space:
|
|
946
|
-
case Dot:
|
|
947
|
-
return true;
|
|
948
|
-
}
|
|
949
|
-
if (isLowerCase(columnCharBefore) && isUpperCase(columnChar)) {
|
|
950
|
-
return true;
|
|
951
|
-
}
|
|
952
|
-
return false;
|
|
953
|
-
};
|
|
954
|
-
|
|
955
|
-
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
956
|
-
const getScore = (rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, column, wordLength, isDiagonalMatch) => {
|
|
957
|
-
if (rowCharLow !== columnCharLow) {
|
|
958
|
-
return -1;
|
|
959
|
-
}
|
|
960
|
-
const isMatch = rowChar === columnChar;
|
|
961
|
-
if (isMatch) {
|
|
962
|
-
if (isDiagonalMatch) {
|
|
963
|
-
return 8;
|
|
964
|
-
}
|
|
965
|
-
if (isGap(columnCharBefore, columnChar)) {
|
|
966
|
-
return 8;
|
|
967
|
-
}
|
|
968
|
-
return 5;
|
|
969
|
-
}
|
|
970
|
-
if (isGap(columnCharBefore, columnChar)) {
|
|
971
|
-
return 8;
|
|
972
|
-
}
|
|
973
|
-
return 5;
|
|
974
|
-
};
|
|
975
|
-
|
|
976
|
-
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
977
|
-
|
|
978
|
-
const isPatternInWord = (patternLow, patternPos, patternLen, wordLow, wordPos, wordLen) => {
|
|
979
|
-
while (patternPos < patternLen && wordPos < wordLen) {
|
|
980
|
-
if (patternLow[patternPos] === wordLow[wordPos]) {
|
|
981
|
-
patternPos += 1;
|
|
982
|
-
}
|
|
983
|
-
wordPos += 1;
|
|
984
|
-
}
|
|
985
|
-
return patternPos === patternLen; // pattern must be exhausted
|
|
986
|
-
};
|
|
987
|
-
|
|
988
|
-
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
989
|
-
const traceHighlights = (table, arrows, patternLength, wordLength) => {
|
|
990
|
-
let row = patternLength;
|
|
991
|
-
let column = wordLength;
|
|
992
|
-
const matches = [];
|
|
993
|
-
while (row >= 1 && column >= 1) {
|
|
994
|
-
const arrow = arrows[row][column];
|
|
995
|
-
if (arrow === Left) {
|
|
996
|
-
column--;
|
|
997
|
-
} else if (arrow === Diagonal) {
|
|
998
|
-
row--;
|
|
999
|
-
column--;
|
|
1000
|
-
const start = column + 1;
|
|
1001
|
-
while (row >= 1 && column >= 1) {
|
|
1002
|
-
const arrow = arrows[row][column];
|
|
1003
|
-
if (arrow === Left) {
|
|
1004
|
-
break;
|
|
1005
|
-
}
|
|
1006
|
-
if (arrow === Diagonal) {
|
|
1007
|
-
row--;
|
|
1008
|
-
column--;
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
const end = column;
|
|
1012
|
-
matches.unshift(end, start);
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
matches.unshift(table[patternLength][wordLength - 1]);
|
|
1016
|
-
return matches;
|
|
1017
|
-
};
|
|
1018
|
-
|
|
1019
|
-
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
1020
|
-
const gridSize = 128;
|
|
1021
|
-
const table = createTable(gridSize);
|
|
1022
|
-
const arrows = createTable(gridSize);
|
|
1023
|
-
const filterCompletionItem = (pattern, word) => {
|
|
1024
|
-
const patternLength = Math.min(pattern.length, gridSize - 1);
|
|
1025
|
-
const wordLength = Math.min(word.length, gridSize - 1);
|
|
1026
|
-
const patternLower = pattern.toLowerCase();
|
|
1027
|
-
const wordLower = word.toLowerCase();
|
|
1028
|
-
if (!isPatternInWord(patternLower, 0, patternLength, wordLower, 0, wordLength)) {
|
|
1029
|
-
return EmptyMatches;
|
|
1030
|
-
}
|
|
1031
|
-
let strongMatch = false;
|
|
1032
|
-
for (let row = 1; row < patternLength + 1; row++) {
|
|
1033
|
-
const rowChar = pattern[row - 1];
|
|
1034
|
-
const rowCharLow = patternLower[row - 1];
|
|
1035
|
-
for (let column = 1; column < wordLength + 1; column++) {
|
|
1036
|
-
const columnChar = word[column - 1];
|
|
1037
|
-
const columnCharLow = wordLower[column - 1];
|
|
1038
|
-
const columnCharBefore = word[column - 2] || '';
|
|
1039
|
-
const isDiagonalMatch = arrows[row - 1][column - 1] === Diagonal;
|
|
1040
|
-
const score = getScore(rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, column, wordLength, isDiagonalMatch);
|
|
1041
|
-
if (row === 1 && score > 5) {
|
|
1042
|
-
strongMatch = true;
|
|
1043
|
-
}
|
|
1044
|
-
let diagonalScore = score + table[row - 1][column - 1];
|
|
1045
|
-
if (isDiagonalMatch && score !== -1) {
|
|
1046
|
-
diagonalScore += 2;
|
|
1047
|
-
}
|
|
1048
|
-
const leftScore = table[row][column - 1];
|
|
1049
|
-
if (leftScore > diagonalScore) {
|
|
1050
|
-
table[row][column] = leftScore;
|
|
1051
|
-
arrows[row][column] = Left;
|
|
1052
|
-
} else {
|
|
1053
|
-
table[row][column] = diagonalScore;
|
|
1054
|
-
arrows[row][column] = Diagonal;
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1057
|
-
}
|
|
1058
|
-
if (!strongMatch) {
|
|
1059
|
-
return EmptyMatches;
|
|
1060
|
-
}
|
|
1061
|
-
const highlights = traceHighlights(table, arrows, patternLength, wordLength);
|
|
1062
|
-
return highlights;
|
|
1063
|
-
};
|
|
1064
|
-
|
|
1065
|
-
const addEmptyMatch = item => {
|
|
1066
|
-
return {
|
|
1067
|
-
...item,
|
|
1068
|
-
matches: EmptyMatches
|
|
1069
|
-
};
|
|
1070
|
-
};
|
|
1071
|
-
const filterCompletionItems = (completionItems, word) => {
|
|
1072
|
-
if (word === EmptyString) {
|
|
1073
|
-
return completionItems.map(addEmptyMatch);
|
|
1074
|
-
}
|
|
1075
|
-
const filteredCompletions = [];
|
|
1076
|
-
const deprecated = [];
|
|
1077
|
-
for (const completionItem of completionItems) {
|
|
1078
|
-
const {
|
|
1079
|
-
label,
|
|
1080
|
-
flags
|
|
1081
|
-
} = completionItem;
|
|
1082
|
-
const result = filterCompletionItem(word, label);
|
|
1083
|
-
if (result !== EmptyMatches) {
|
|
1084
|
-
if (flags & Deprecated) {
|
|
1085
|
-
// TODO avoid mutation
|
|
1086
|
-
completionItem.matches = EmptyMatches;
|
|
1087
|
-
deprecated.push(completionItem);
|
|
1088
|
-
} else {
|
|
1089
|
-
// TODO avoid mutation
|
|
1090
|
-
completionItem.matches = result;
|
|
1091
|
-
filteredCompletions.push(completionItem);
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
if (deprecated.length > 0) {
|
|
1096
|
-
filteredCompletions.push(...deprecated);
|
|
1097
|
-
}
|
|
1098
|
-
return filteredCompletions;
|
|
1099
|
-
};
|
|
1100
|
-
|
|
1101
|
-
const getListHeight = (itemsLength, itemHeight, maxHeight) => {
|
|
1102
|
-
number$1(itemsLength);
|
|
1103
|
-
number$1(itemHeight);
|
|
1104
|
-
number$1(maxHeight);
|
|
1105
|
-
if (itemsLength === 0) {
|
|
1106
|
-
return itemHeight;
|
|
1107
|
-
}
|
|
1108
|
-
const totalHeight = itemsLength * itemHeight;
|
|
1109
|
-
return Math.min(totalHeight, maxHeight);
|
|
1110
|
-
};
|
|
1111
|
-
|
|
1112
|
-
const RE_WORD_START$1 = /^[\w\-]+/;
|
|
1113
|
-
const RE_WORD_END$1 = /[\w\-]+$/;
|
|
1114
|
-
const getWordAt$1 = (line, columnIndex) => {
|
|
1115
|
-
const before = line.slice(0, columnIndex);
|
|
1116
|
-
const matchBefore = before.match(RE_WORD_END$1);
|
|
1117
|
-
const after = line.slice(columnIndex);
|
|
1118
|
-
const matchAfter = after.match(RE_WORD_START$1);
|
|
1119
|
-
let word = EmptyString;
|
|
1120
|
-
if (matchBefore) {
|
|
1121
|
-
word += matchBefore[0];
|
|
1122
|
-
}
|
|
1123
|
-
if (matchAfter) {
|
|
1124
|
-
word += matchAfter[0];
|
|
1125
|
-
}
|
|
1126
|
-
return {
|
|
1127
|
-
word
|
|
1128
|
-
};
|
|
1129
|
-
};
|
|
1130
|
-
const getWordBefore$1 = (line, columnIndex) => {
|
|
1131
|
-
const before = line.slice(0, columnIndex);
|
|
1132
|
-
const matchBefore = before.match(RE_WORD_END$1);
|
|
1133
|
-
if (matchBefore) {
|
|
1134
|
-
return matchBefore[0];
|
|
1135
|
-
}
|
|
1136
|
-
return EmptyString;
|
|
1137
|
-
};
|
|
1138
|
-
|
|
1139
|
-
const getWordAt = (editor, rowIndex, columnIndex) => {
|
|
1140
|
-
const {
|
|
1141
|
-
lines
|
|
1142
|
-
} = editor;
|
|
1143
|
-
const line = lines[rowIndex];
|
|
1144
|
-
return getWordAt$1(line, columnIndex);
|
|
1145
|
-
};
|
|
1146
|
-
const getWordBefore = (editor, rowIndex, columnIndex) => {
|
|
1147
|
-
const {
|
|
1148
|
-
lines
|
|
1149
|
-
} = editor;
|
|
1150
|
-
const line = lines[rowIndex];
|
|
1151
|
-
return getWordBefore$1(line, columnIndex);
|
|
1152
|
-
};
|
|
1153
|
-
|
|
1154
|
-
const render$2 = (oldState, newState) => {
|
|
1155
|
-
const commands = renderCompletion(oldState, newState);
|
|
1156
|
-
const wrappedCommands = [];
|
|
1157
|
-
const uid = newState.uid;
|
|
1158
|
-
for (const command of commands) {
|
|
1159
|
-
wrappedCommands.push(['Viewlet.send', uid, ...command]);
|
|
1160
|
-
}
|
|
1161
|
-
return wrappedCommands;
|
|
1162
|
-
};
|
|
1163
|
-
const add = widget => {
|
|
1164
|
-
const commands = render$2(widget.oldState, widget.newState);
|
|
1165
|
-
const id = 'EditorCompletion';
|
|
1166
|
-
// TODO how to generate a unique integer id
|
|
1167
|
-
// that doesn't collide with ids created in renderer worker?
|
|
1168
|
-
const uid = widget.newState.uid;
|
|
1169
|
-
const allCommands = [];
|
|
1170
|
-
allCommands.push(['Viewlet.create', id, uid]);
|
|
1171
|
-
allCommands.push(...commands);
|
|
1172
|
-
return allCommands;
|
|
1173
|
-
};
|
|
1174
|
-
const remove$1 = widget => {
|
|
1175
|
-
return [['Viewlet.send', widget.newState.uid, 'dispose']];
|
|
1176
|
-
};
|
|
1177
|
-
const handleEditorType$1 = (editor, state) => {
|
|
1178
|
-
const {
|
|
1179
|
-
unfilteredItems,
|
|
1180
|
-
itemHeight,
|
|
1181
|
-
maxHeight
|
|
1182
|
-
} = state;
|
|
1183
|
-
const {
|
|
1184
|
-
selections
|
|
1185
|
-
} = editor;
|
|
1186
|
-
const rowIndex = selections[0];
|
|
1187
|
-
const columnIndex = selections[1];
|
|
1188
|
-
const x$1 = x(editor, rowIndex, columnIndex);
|
|
1189
|
-
const y$1 = y(editor, rowIndex);
|
|
1190
|
-
const wordAtOffset = getWordBefore(editor, rowIndex, columnIndex);
|
|
1191
|
-
const items = filterCompletionItems(unfilteredItems, wordAtOffset);
|
|
1192
|
-
const newMinLineY = 0;
|
|
1193
|
-
const newMaxLineY = Math.min(items.length, 8);
|
|
1194
|
-
const height = getListHeight(items.length, itemHeight, maxHeight);
|
|
1195
|
-
const finalDeltaY = items.length * itemHeight - height;
|
|
1196
|
-
return {
|
|
1197
|
-
...state,
|
|
1198
|
-
items,
|
|
1199
|
-
x: x$1,
|
|
1200
|
-
y: y$1,
|
|
1201
|
-
minLineY: newMinLineY,
|
|
1202
|
-
maxLineY: newMaxLineY,
|
|
1203
|
-
leadingWord: wordAtOffset,
|
|
1204
|
-
height,
|
|
1205
|
-
finalDeltaY
|
|
1206
|
-
};
|
|
1207
|
-
};
|
|
1208
|
-
const handleEditorDeleteLeft$1 = (editor, state) => {
|
|
1209
|
-
const {
|
|
1210
|
-
unfilteredItems,
|
|
1211
|
-
itemHeight,
|
|
1212
|
-
maxHeight
|
|
1213
|
-
} = state;
|
|
1214
|
-
const {
|
|
1215
|
-
selections
|
|
1216
|
-
} = editor;
|
|
1217
|
-
const rowIndex = selections[0];
|
|
1218
|
-
const columnIndex = selections[1];
|
|
1219
|
-
const x$1 = x(editor, rowIndex, columnIndex);
|
|
1220
|
-
const y$1 = y(editor, rowIndex);
|
|
1221
|
-
const wordAtOffset = getWordBefore(editor, rowIndex, columnIndex);
|
|
1222
|
-
if (!wordAtOffset) {
|
|
1223
|
-
return undefined;
|
|
1224
|
-
}
|
|
1225
|
-
const items = filterCompletionItems(unfilteredItems, wordAtOffset);
|
|
1226
|
-
const newMaxLineY = Math.min(items.length, 8);
|
|
1227
|
-
const height = getListHeight(items.length, itemHeight, maxHeight);
|
|
1228
|
-
return {
|
|
1229
|
-
...state,
|
|
1230
|
-
items,
|
|
1231
|
-
x: x$1,
|
|
1232
|
-
y: y$1,
|
|
1233
|
-
maxLineY: newMaxLineY,
|
|
1234
|
-
leadingWord: wordAtOffset,
|
|
1235
|
-
height
|
|
1236
|
-
};
|
|
1237
|
-
};
|
|
1238
|
-
|
|
1239
|
-
const EditorCompletionWidget = {
|
|
1240
|
-
__proto__: null,
|
|
1241
|
-
add,
|
|
1242
|
-
handleEditorDeleteLeft: handleEditorDeleteLeft$1,
|
|
1243
|
-
handleEditorType: handleEditorType$1,
|
|
1244
|
-
remove: remove$1,
|
|
1245
|
-
render: render$2
|
|
1246
|
-
};
|
|
1247
|
-
|
|
1248
|
-
const Completion = 'completion';
|
|
1249
|
-
|
|
1250
|
-
const modules = Object.create(null);
|
|
1251
|
-
const register = (id, value) => {
|
|
1252
|
-
modules[id] = value;
|
|
1253
|
-
};
|
|
1254
|
-
const get$7 = id => {
|
|
1255
|
-
return modules[id];
|
|
1256
|
-
};
|
|
1257
|
-
|
|
1258
|
-
const getModule$2 = id => {
|
|
1259
|
-
return get$7(id);
|
|
1260
|
-
};
|
|
1261
|
-
|
|
1262
|
-
const applyWidgetChange = (editor, widget, changes) => {
|
|
1263
|
-
const module = getModule$2(widget.id);
|
|
1264
|
-
if (changes.length === 1 && changes[0].origin === EditorType && module.handleEditorType) {
|
|
1265
|
-
const newState = module.handleEditorType(editor, widget.newState);
|
|
1266
|
-
return {
|
|
1267
|
-
...widget,
|
|
1268
|
-
newState
|
|
1269
|
-
};
|
|
1270
|
-
}
|
|
1271
|
-
if (changes.length === 1 && changes[0].origin === DeleteLeft && module.handleEditorDeleteLeft) {
|
|
1272
|
-
const newState = module.handleEditorDeleteLeft(editor, widget.newState);
|
|
1273
|
-
return {
|
|
1274
|
-
...widget,
|
|
1275
|
-
newState
|
|
1276
|
-
};
|
|
1277
|
-
}
|
|
1278
|
-
return widget;
|
|
1279
|
-
};
|
|
1280
|
-
|
|
1281
|
-
const applyWidgetChanges = (editor, changes) => {
|
|
1282
|
-
const widgets = editor.widgets || [];
|
|
1283
|
-
if (widgets.length === 0) {
|
|
1284
|
-
return widgets;
|
|
1285
|
-
}
|
|
1286
|
-
const newWidgets = [];
|
|
1287
|
-
for (const widget of widgets) {
|
|
1288
|
-
const newWidget = applyWidgetChange(editor, widget, changes);
|
|
1289
|
-
if (newWidget.newState) {
|
|
1290
|
-
newWidgets.push(newWidget);
|
|
1291
|
-
}
|
|
1292
|
-
}
|
|
1293
|
-
return newWidgets;
|
|
1294
|
-
};
|
|
1295
|
-
|
|
1296
|
-
const splitLines$2 = lines => {
|
|
1297
|
-
if (!lines) {
|
|
1298
|
-
return [];
|
|
1299
|
-
}
|
|
1300
|
-
return lines.split('\n');
|
|
1301
|
-
};
|
|
1302
|
-
|
|
1303
|
-
// based on https://github.com/microsoft/vscode/blob/c0769274fa136b45799edeccc0d0a2f645b75caf/src/vs/base/common/arrays.ts#L625 (License MIT)
|
|
1304
|
-
|
|
1305
|
-
// @ts-ignore
|
|
1306
|
-
const insertInto = (array, start, newItems) => {
|
|
1307
|
-
const originalLength = array.length;
|
|
1308
|
-
const newItemsLength = newItems.length;
|
|
1309
|
-
array.length = originalLength + newItemsLength;
|
|
1310
|
-
// Move the items after the start index, start from the end so that we don't overwrite any value.
|
|
1311
|
-
for (let i = originalLength - 1; i >= start; i--) {
|
|
1312
|
-
array[i + newItemsLength] = array[i];
|
|
1313
|
-
}
|
|
1314
|
-
for (let i = 0; i < newItemsLength; i++) {
|
|
1315
|
-
array[i + start] = newItems[i];
|
|
1316
|
-
}
|
|
1317
|
-
};
|
|
1318
|
-
|
|
1319
|
-
/**
|
|
1320
|
-
* Alternative to the native Array.splice method, it
|
|
1321
|
-
* can only support limited number of items due to the maximum call stack size limit.
|
|
1322
|
-
*/
|
|
1323
|
-
// @ts-ignore
|
|
1324
|
-
const spliceLargeArray = (array, start, deleteCount, newItems) => {
|
|
1325
|
-
const result = array.splice(start, deleteCount);
|
|
1326
|
-
insertInto(array, start, newItems);
|
|
1327
|
-
return result;
|
|
1328
|
-
};
|
|
1329
|
-
|
|
1330
|
-
const joinLines$2 = lines => {
|
|
1331
|
-
return lines.join('\n');
|
|
364
|
+
const joinLines$2 = lines => {
|
|
365
|
+
return lines.join('\n');
|
|
1332
366
|
};
|
|
1333
367
|
|
|
1334
368
|
// TODO have function for single edit (most common, avoid one array)
|
|
@@ -1521,6 +555,14 @@ const getSelectionPairs = (selections, i) => {
|
|
|
1521
555
|
return [first, second, third, fourth, 0];
|
|
1522
556
|
};
|
|
1523
557
|
|
|
558
|
+
const Dash = '-';
|
|
559
|
+
const Dot = '.';
|
|
560
|
+
const EmptyString = '';
|
|
561
|
+
const Space = ' ';
|
|
562
|
+
const Tab = '\t';
|
|
563
|
+
const Underline = '_';
|
|
564
|
+
const T = 't';
|
|
565
|
+
|
|
1524
566
|
const getTabCount = string => {
|
|
1525
567
|
let count = 0;
|
|
1526
568
|
for (const element of string) {
|
|
@@ -1531,6 +573,75 @@ const getTabCount = string => {
|
|
|
1531
573
|
return count;
|
|
1532
574
|
};
|
|
1533
575
|
|
|
576
|
+
const getFontString = (fontWeight, fontSize, fontFamily) => {
|
|
577
|
+
return `${fontWeight} ${fontSize}px ${fontFamily}`;
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
const getLetterSpacingString = letterSpacing => {
|
|
581
|
+
return `${letterSpacing}px`;
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
const createMeasureContext = () => {
|
|
585
|
+
const canvas = new OffscreenCanvas(0, 0);
|
|
586
|
+
const ctx = /** @type {OffscreenCanvasRenderingContext2D} */canvas.getContext('2d');
|
|
587
|
+
if (!ctx) {
|
|
588
|
+
throw new Error('Failed to get canvas context 2d');
|
|
589
|
+
}
|
|
590
|
+
return ctx;
|
|
591
|
+
};
|
|
592
|
+
|
|
593
|
+
const state$b = {
|
|
594
|
+
ctx: undefined
|
|
595
|
+
};
|
|
596
|
+
const getOrCreate = createCtx => {
|
|
597
|
+
if (state$b.ctx) {
|
|
598
|
+
return state$b.ctx;
|
|
599
|
+
}
|
|
600
|
+
state$b.ctx = createCtx();
|
|
601
|
+
return state$b.ctx;
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
const getContext = () => {
|
|
605
|
+
const ctx = getOrCreate(createMeasureContext);
|
|
606
|
+
return ctx;
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
const measureTextWidth = (text, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth) => {
|
|
610
|
+
string(text);
|
|
611
|
+
number$1(fontWeight);
|
|
612
|
+
number$1(fontSize);
|
|
613
|
+
string(fontFamily);
|
|
614
|
+
boolean(isMonoSpaceFont);
|
|
615
|
+
number$1(charWidth);
|
|
616
|
+
if (isMonoSpaceFont) {
|
|
617
|
+
return text.length * charWidth;
|
|
618
|
+
}
|
|
619
|
+
if (typeof letterSpacing !== 'number') {
|
|
620
|
+
throw new TypeError('letterSpacing must be of type number');
|
|
621
|
+
}
|
|
622
|
+
const letterSpacingString = getLetterSpacingString(letterSpacing);
|
|
623
|
+
const fontString = getFontString(fontWeight, fontSize, fontFamily);
|
|
624
|
+
const ctx = getContext();
|
|
625
|
+
// @ts-ignore
|
|
626
|
+
ctx.letterSpacing = letterSpacingString;
|
|
627
|
+
// @ts-ignore
|
|
628
|
+
ctx.font = fontString;
|
|
629
|
+
// @ts-ignore
|
|
630
|
+
const metrics = ctx.measureText(text);
|
|
631
|
+
const width = metrics.width;
|
|
632
|
+
return width;
|
|
633
|
+
};
|
|
634
|
+
|
|
635
|
+
const normalizeText = (text, normalize, tabSize) => {
|
|
636
|
+
if (normalize) {
|
|
637
|
+
return text.replaceAll(Tab, Space.repeat(tabSize));
|
|
638
|
+
}
|
|
639
|
+
return text;
|
|
640
|
+
};
|
|
641
|
+
const shouldNormalizeText = text => {
|
|
642
|
+
return text.includes(Tab);
|
|
643
|
+
};
|
|
644
|
+
|
|
1534
645
|
// TODO visible selections could also be uint16array
|
|
1535
646
|
// [top1, left1, width1, height1, top2, left2, width2, height2...]
|
|
1536
647
|
|
|
@@ -1558,6 +669,7 @@ const getX = (line, column, fontWeight, fontSize, fontFamily, isMonospaceFont, l
|
|
|
1558
669
|
const partialText = normalizedLine.slice(0, column + tabCount);
|
|
1559
670
|
return measureTextWidth(partialText, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, averageCharWidth) - halfCursorWidth + difference;
|
|
1560
671
|
};
|
|
672
|
+
|
|
1561
673
|
const getY = (row, minLineY, rowHeight) => {
|
|
1562
674
|
return (row - minLineY) * rowHeight;
|
|
1563
675
|
};
|
|
@@ -2067,7 +1179,7 @@ const set$5 = (id, fn) => {
|
|
|
2067
1179
|
const get$5 = id => {
|
|
2068
1180
|
return state$1$1.callbacks[id];
|
|
2069
1181
|
};
|
|
2070
|
-
const remove = id => {
|
|
1182
|
+
const remove$1 = id => {
|
|
2071
1183
|
delete state$1$1.callbacks[id];
|
|
2072
1184
|
};
|
|
2073
1185
|
const state$a = {
|
|
@@ -2113,7 +1225,7 @@ const resolve = (id, args) => {
|
|
|
2113
1225
|
return;
|
|
2114
1226
|
}
|
|
2115
1227
|
fn(args);
|
|
2116
|
-
remove(id);
|
|
1228
|
+
remove$1(id);
|
|
2117
1229
|
};
|
|
2118
1230
|
const create$2$1 = (method, params) => {
|
|
2119
1231
|
const {
|
|
@@ -2298,7 +1410,7 @@ const getErrorResponse = (message, error, preparePrettyError, logError) => {
|
|
|
2298
1410
|
const errorProperty = getErrorProperty(error, prettyError);
|
|
2299
1411
|
return create$1$1(message, errorProperty);
|
|
2300
1412
|
};
|
|
2301
|
-
const create$
|
|
1413
|
+
const create$5 = (message, result) => {
|
|
2302
1414
|
return {
|
|
2303
1415
|
jsonrpc: Two,
|
|
2304
1416
|
id: message.id,
|
|
@@ -2307,7 +1419,7 @@ const create$4 = (message, result) => {
|
|
|
2307
1419
|
};
|
|
2308
1420
|
const getSuccessResponse = (message, result) => {
|
|
2309
1421
|
const resultProperty = result ?? null;
|
|
2310
|
-
return create$
|
|
1422
|
+
return create$5(message, resultProperty);
|
|
2311
1423
|
};
|
|
2312
1424
|
const getResponse = async (message, ipc, execute, preparePrettyError, logError, requiresSocket) => {
|
|
2313
1425
|
try {
|
|
@@ -2504,7 +1616,7 @@ const waitForFirstMessage$1 = async port => {
|
|
|
2504
1616
|
return event;
|
|
2505
1617
|
};
|
|
2506
1618
|
|
|
2507
|
-
const create$
|
|
1619
|
+
const create$4 = async () => {
|
|
2508
1620
|
const {
|
|
2509
1621
|
port1,
|
|
2510
1622
|
port2
|
|
@@ -2549,7 +1661,7 @@ const wrap$3 = port => {
|
|
|
2549
1661
|
|
|
2550
1662
|
const IpcParentWithExtensionHostWorker = {
|
|
2551
1663
|
__proto__: null,
|
|
2552
|
-
create: create$
|
|
1664
|
+
create: create$4,
|
|
2553
1665
|
wrap: wrap$3
|
|
2554
1666
|
};
|
|
2555
1667
|
|
|
@@ -2557,7 +1669,7 @@ const sendMessagePortToSyntaxHighlightingWorker = async port => {
|
|
|
2557
1669
|
await invokeAndTransfer([port], 'SendMessagePortToSyntaxHighlightingWorker.sendMessagePortToSyntaxHighlightingWorker', port, 'HandleMessagePort.handleMessagePort');
|
|
2558
1670
|
};
|
|
2559
1671
|
|
|
2560
|
-
const create$
|
|
1672
|
+
const create$3 = async () => {
|
|
2561
1673
|
const {
|
|
2562
1674
|
port1,
|
|
2563
1675
|
port2
|
|
@@ -2602,7 +1714,7 @@ const wrap$1 = port => {
|
|
|
2602
1714
|
|
|
2603
1715
|
const IpcParentWithSyntaxHighlightingWorker = {
|
|
2604
1716
|
__proto__: null,
|
|
2605
|
-
create: create$
|
|
1717
|
+
create: create$3,
|
|
2606
1718
|
wrap: wrap$1
|
|
2607
1719
|
};
|
|
2608
1720
|
|
|
@@ -2610,7 +1722,7 @@ const sendMessagePortToRendererProcess = async port => {
|
|
|
2610
1722
|
await invokeAndTransfer([port], 'SendMessagePortToRendererProcess.sendMessagePortToRendererProcess', port, 'HandleMessagePort.handleMessagePort');
|
|
2611
1723
|
};
|
|
2612
1724
|
|
|
2613
|
-
const create$
|
|
1725
|
+
const create$2 = async () => {
|
|
2614
1726
|
const {
|
|
2615
1727
|
port1,
|
|
2616
1728
|
port2
|
|
@@ -2655,7 +1767,7 @@ const wrap = port => {
|
|
|
2655
1767
|
|
|
2656
1768
|
const IpcParentWithRendererProcess = {
|
|
2657
1769
|
__proto__: null,
|
|
2658
|
-
create: create$
|
|
1770
|
+
create: create$2,
|
|
2659
1771
|
wrap
|
|
2660
1772
|
};
|
|
2661
1773
|
|
|
@@ -2672,7 +1784,7 @@ const getModule$1 = method => {
|
|
|
2672
1784
|
}
|
|
2673
1785
|
};
|
|
2674
1786
|
|
|
2675
|
-
const create = async ({
|
|
1787
|
+
const create$1 = async ({
|
|
2676
1788
|
method,
|
|
2677
1789
|
...options
|
|
2678
1790
|
}) => {
|
|
@@ -2690,7 +1802,7 @@ const create = async ({
|
|
|
2690
1802
|
const createRpc = method => {
|
|
2691
1803
|
let _ipc;
|
|
2692
1804
|
const listen = async () => {
|
|
2693
|
-
const ipc = await create({
|
|
1805
|
+
const ipc = await create$1({
|
|
2694
1806
|
method
|
|
2695
1807
|
});
|
|
2696
1808
|
handleIpc(ipc);
|
|
@@ -2954,6 +2066,180 @@ const editorReplaceSelections = (editor, replacement, origin) => {
|
|
|
2954
2066
|
return replaceRange(editor, selections, replacement, origin);
|
|
2955
2067
|
};
|
|
2956
2068
|
|
|
2069
|
+
const getAccurateColumnIndexAscii = (line, guess, averageCharWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth) => {
|
|
2070
|
+
for (let i = guess; i < line.length; i++) {
|
|
2071
|
+
const width = measureTextWidth(line.slice(0, i), fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
|
|
2072
|
+
if (eventX - width < averageCharWidth / 2) {
|
|
2073
|
+
return i;
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
return line.length;
|
|
2077
|
+
};
|
|
2078
|
+
|
|
2079
|
+
const supported = () => {
|
|
2080
|
+
return 'Segmenter' in Intl;
|
|
2081
|
+
};
|
|
2082
|
+
const create = () => {
|
|
2083
|
+
// @ts-ignore
|
|
2084
|
+
const segmenter = new Intl.Segmenter();
|
|
2085
|
+
return {
|
|
2086
|
+
at(line, index) {
|
|
2087
|
+
const segments = segmenter.segment(line);
|
|
2088
|
+
return segments.containing(index);
|
|
2089
|
+
},
|
|
2090
|
+
visualIndex(line, index) {
|
|
2091
|
+
const segments = segmenter.segment(line);
|
|
2092
|
+
let currentVisualIndex = 0;
|
|
2093
|
+
for (const segment of segments) {
|
|
2094
|
+
if (segment.index >= index) {
|
|
2095
|
+
return currentVisualIndex;
|
|
2096
|
+
}
|
|
2097
|
+
currentVisualIndex++;
|
|
2098
|
+
}
|
|
2099
|
+
return currentVisualIndex;
|
|
2100
|
+
},
|
|
2101
|
+
modelIndex(line, visualIndex) {
|
|
2102
|
+
const segments = segmenter.segment(line);
|
|
2103
|
+
let currentVisualIndex = 0;
|
|
2104
|
+
for (const segment of segments) {
|
|
2105
|
+
if (currentVisualIndex >= visualIndex) {
|
|
2106
|
+
return segment.index;
|
|
2107
|
+
}
|
|
2108
|
+
currentVisualIndex++;
|
|
2109
|
+
}
|
|
2110
|
+
return line.length;
|
|
2111
|
+
},
|
|
2112
|
+
getSegments(line) {
|
|
2113
|
+
return segmenter.segment(line);
|
|
2114
|
+
}
|
|
2115
|
+
};
|
|
2116
|
+
};
|
|
2117
|
+
|
|
2118
|
+
// @ts-ignore
|
|
2119
|
+
const getAccurateColumnIndexUnicode = (line, guess, averageCharWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing) => {
|
|
2120
|
+
const segmenter = create();
|
|
2121
|
+
const segments = segmenter.getSegments(line);
|
|
2122
|
+
const isMonospaceFont = false;
|
|
2123
|
+
const charWidth = 0;
|
|
2124
|
+
for (const segment of segments) {
|
|
2125
|
+
const width = measureTextWidth(line.slice(0, segment.index), fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
|
|
2126
|
+
if (eventX - width < averageCharWidth) {
|
|
2127
|
+
return segment.index;
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
return line.length;
|
|
2131
|
+
};
|
|
2132
|
+
|
|
2133
|
+
const RE_ASCII = /^[\p{ASCII}]*$/u;
|
|
2134
|
+
const isAscii = line => {
|
|
2135
|
+
return RE_ASCII.test(line);
|
|
2136
|
+
};
|
|
2137
|
+
|
|
2138
|
+
// @ts-ignore
|
|
2139
|
+
const guessOffset = (eventX, averageCharWidth) => {
|
|
2140
|
+
const guess = Math.round(eventX / averageCharWidth);
|
|
2141
|
+
return guess;
|
|
2142
|
+
};
|
|
2143
|
+
|
|
2144
|
+
// @ts-ignore
|
|
2145
|
+
const normalizeGuess = (line, guess, tabSize) => {
|
|
2146
|
+
let normalizedGuess = guess;
|
|
2147
|
+
for (let i = 0; i < guess; i++) {
|
|
2148
|
+
if (line[i] === Tab) {
|
|
2149
|
+
normalizedGuess -= tabSize - 1;
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
return normalizedGuess;
|
|
2153
|
+
};
|
|
2154
|
+
|
|
2155
|
+
// @ts-ignore
|
|
2156
|
+
const getAccurateColumnIndex = (line, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth, tabSize, eventX) => {
|
|
2157
|
+
string(line);
|
|
2158
|
+
number$1(fontWeight);
|
|
2159
|
+
number$1(fontSize);
|
|
2160
|
+
string(fontFamily);
|
|
2161
|
+
number$1(letterSpacing);
|
|
2162
|
+
boolean(isMonospaceFont);
|
|
2163
|
+
number$1(charWidth);
|
|
2164
|
+
number$1(tabSize);
|
|
2165
|
+
number$1(eventX);
|
|
2166
|
+
// Assert.greaterZero(charWidth)
|
|
2167
|
+
const guess = guessOffset(eventX, charWidth);
|
|
2168
|
+
const normalize = shouldNormalizeText(line);
|
|
2169
|
+
const normalizedGuess = normalizeGuess(line, guess, tabSize);
|
|
2170
|
+
const text = line.slice(0, normalizedGuess);
|
|
2171
|
+
const normalizedText = normalizeText(text, normalize, tabSize);
|
|
2172
|
+
const actual = measureTextWidth(normalizedText, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
|
|
2173
|
+
const isAscii$1 = isAscii(line);
|
|
2174
|
+
if (isAscii$1) {
|
|
2175
|
+
if (Math.abs(eventX - actual) < charWidth / 2) {
|
|
2176
|
+
return normalizedGuess;
|
|
2177
|
+
}
|
|
2178
|
+
return getAccurateColumnIndexAscii(line, normalizedGuess, charWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
|
|
2179
|
+
}
|
|
2180
|
+
return getAccurateColumnIndexUnicode(line, normalizedGuess, charWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing);
|
|
2181
|
+
};
|
|
2182
|
+
|
|
2183
|
+
const at = (editor, eventX, eventY) => {
|
|
2184
|
+
object(editor);
|
|
2185
|
+
number$1(eventX);
|
|
2186
|
+
number$1(eventY);
|
|
2187
|
+
const {
|
|
2188
|
+
y,
|
|
2189
|
+
deltaY,
|
|
2190
|
+
rowHeight,
|
|
2191
|
+
fontSize,
|
|
2192
|
+
fontWeight,
|
|
2193
|
+
fontFamily,
|
|
2194
|
+
letterSpacing,
|
|
2195
|
+
lines,
|
|
2196
|
+
tabSize,
|
|
2197
|
+
differences,
|
|
2198
|
+
isMonospaceFont,
|
|
2199
|
+
charWidth
|
|
2200
|
+
} = editor;
|
|
2201
|
+
const rowIndex = Math.floor((eventY - y + deltaY) / rowHeight);
|
|
2202
|
+
if (rowIndex < 0) {
|
|
2203
|
+
return {
|
|
2204
|
+
rowIndex: 0,
|
|
2205
|
+
columnIndex: 0
|
|
2206
|
+
};
|
|
2207
|
+
}
|
|
2208
|
+
const clampedRowIndex = clamp(rowIndex, 0, lines.length - 1);
|
|
2209
|
+
const line = lines[clampedRowIndex];
|
|
2210
|
+
const columnIndex = getAccurateColumnIndex(line, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth, tabSize, eventX);
|
|
2211
|
+
return {
|
|
2212
|
+
rowIndex: clampedRowIndex,
|
|
2213
|
+
columnIndex
|
|
2214
|
+
};
|
|
2215
|
+
};
|
|
2216
|
+
|
|
2217
|
+
/**
|
|
2218
|
+
* @deprecated this doesn't work for variable width characters (unicode/emoji).
|
|
2219
|
+
* Use position computation in renderer process instead
|
|
2220
|
+
*
|
|
2221
|
+
* @param {object} editor
|
|
2222
|
+
* @param {number} rowIndex
|
|
2223
|
+
* @param {number} columnIndex
|
|
2224
|
+
* @returns
|
|
2225
|
+
*/
|
|
2226
|
+
const x = (editor, rowIndex, columnIndex) => {
|
|
2227
|
+
const {
|
|
2228
|
+
columnWidth,
|
|
2229
|
+
x
|
|
2230
|
+
} = editor;
|
|
2231
|
+
const offsetX = columnIndex * columnWidth + x;
|
|
2232
|
+
return offsetX;
|
|
2233
|
+
};
|
|
2234
|
+
const y = (editor, rowIndex) => {
|
|
2235
|
+
const {
|
|
2236
|
+
rowHeight,
|
|
2237
|
+
y
|
|
2238
|
+
} = editor;
|
|
2239
|
+
const offsetY = (rowIndex + 1) * rowHeight + y;
|
|
2240
|
+
return offsetY;
|
|
2241
|
+
};
|
|
2242
|
+
|
|
2957
2243
|
const state$7 = {
|
|
2958
2244
|
timeout: -1
|
|
2959
2245
|
};
|
|
@@ -3060,6 +2346,8 @@ const cancelSelection = editor => {
|
|
|
3060
2346
|
return scheduleSelections(editor, newSelections);
|
|
3061
2347
|
};
|
|
3062
2348
|
|
|
2349
|
+
const Completion = 'completion';
|
|
2350
|
+
|
|
3063
2351
|
const isCompletionWidget = widget => {
|
|
3064
2352
|
return widget.id === Completion;
|
|
3065
2353
|
};
|
|
@@ -3388,7 +2676,7 @@ const characterLeft = (line, columnIndex) => {
|
|
|
3388
2676
|
if (!supported()) {
|
|
3389
2677
|
return 1;
|
|
3390
2678
|
}
|
|
3391
|
-
const segmenter = create
|
|
2679
|
+
const segmenter = create();
|
|
3392
2680
|
const last = segmenter.at(line, columnIndex - 1);
|
|
3393
2681
|
return columnIndex - last.index;
|
|
3394
2682
|
};
|
|
@@ -3401,7 +2689,7 @@ const characterRight = (line, columnIndex) => {
|
|
|
3401
2689
|
if (!supported()) {
|
|
3402
2690
|
return 1;
|
|
3403
2691
|
}
|
|
3404
|
-
const segmenter = create
|
|
2692
|
+
const segmenter = create();
|
|
3405
2693
|
const next = segmenter.at(line, columnIndex);
|
|
3406
2694
|
return next.segment.length;
|
|
3407
2695
|
};
|
|
@@ -3946,12 +3234,94 @@ const format = async editor => {
|
|
|
3946
3234
|
}
|
|
3947
3235
|
};
|
|
3948
3236
|
|
|
3237
|
+
const RE_WORD_START$1 = /^[\w\-]+/;
|
|
3238
|
+
const RE_WORD_END$1 = /[\w\-]+$/;
|
|
3239
|
+
const getWordAt$1 = (line, columnIndex) => {
|
|
3240
|
+
const before = line.slice(0, columnIndex);
|
|
3241
|
+
const matchBefore = before.match(RE_WORD_END$1);
|
|
3242
|
+
const after = line.slice(columnIndex);
|
|
3243
|
+
const matchAfter = after.match(RE_WORD_START$1);
|
|
3244
|
+
let word = EmptyString;
|
|
3245
|
+
if (matchBefore) {
|
|
3246
|
+
word += matchBefore[0];
|
|
3247
|
+
}
|
|
3248
|
+
if (matchAfter) {
|
|
3249
|
+
word += matchAfter[0];
|
|
3250
|
+
}
|
|
3251
|
+
return {
|
|
3252
|
+
word
|
|
3253
|
+
};
|
|
3254
|
+
};
|
|
3255
|
+
const getWordBefore$1 = (line, columnIndex) => {
|
|
3256
|
+
const before = line.slice(0, columnIndex);
|
|
3257
|
+
const matchBefore = before.match(RE_WORD_END$1);
|
|
3258
|
+
if (matchBefore) {
|
|
3259
|
+
return matchBefore[0];
|
|
3260
|
+
}
|
|
3261
|
+
return EmptyString;
|
|
3262
|
+
};
|
|
3263
|
+
|
|
3264
|
+
const getWordAt = (editor, rowIndex, columnIndex) => {
|
|
3265
|
+
const {
|
|
3266
|
+
lines
|
|
3267
|
+
} = editor;
|
|
3268
|
+
const line = lines[rowIndex];
|
|
3269
|
+
return getWordAt$1(line, columnIndex);
|
|
3270
|
+
};
|
|
3271
|
+
const getWordBefore = (editor, rowIndex, columnIndex) => {
|
|
3272
|
+
const {
|
|
3273
|
+
lines
|
|
3274
|
+
} = editor;
|
|
3275
|
+
const line = lines[rowIndex];
|
|
3276
|
+
return getWordBefore$1(line, columnIndex);
|
|
3277
|
+
};
|
|
3278
|
+
|
|
3949
3279
|
// @ts-ignore
|
|
3950
3280
|
const getDefinition = async (editor, offset) => {
|
|
3951
3281
|
const definition = await invoke$3('ExtensionHostDefinition.executeDefinitionProvider', editor, offset);
|
|
3952
3282
|
return definition;
|
|
3953
3283
|
};
|
|
3954
3284
|
|
|
3285
|
+
const emptyObject = {};
|
|
3286
|
+
const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
|
|
3287
|
+
const i18nString = (key, placeholders = emptyObject) => {
|
|
3288
|
+
if (placeholders === emptyObject) {
|
|
3289
|
+
return key;
|
|
3290
|
+
}
|
|
3291
|
+
const replacer = (match, rest) => {
|
|
3292
|
+
return placeholders[rest];
|
|
3293
|
+
};
|
|
3294
|
+
return key.replaceAll(RE_PLACEHOLDER, replacer);
|
|
3295
|
+
};
|
|
3296
|
+
|
|
3297
|
+
const UiStrings = {
|
|
3298
|
+
GoToDefinition: 'Go to Definition',
|
|
3299
|
+
NoDefinitionFound: 'No definition found',
|
|
3300
|
+
NoDefinitionFoundFor: "No definition found for '{PH1}'",
|
|
3301
|
+
NoTypeDefinitionFound: 'No type definition found',
|
|
3302
|
+
NoTypeDefinitionFoundFor: "No type definition found for '{PH1}'",
|
|
3303
|
+
NoResults: 'No Results'
|
|
3304
|
+
};
|
|
3305
|
+
const noDefinitionFound = () => {
|
|
3306
|
+
return i18nString(UiStrings.NoDefinitionFound);
|
|
3307
|
+
};
|
|
3308
|
+
const noDefinitionFoundFor = word => {
|
|
3309
|
+
return i18nString(UiStrings.NoDefinitionFoundFor, {
|
|
3310
|
+
PH1: word
|
|
3311
|
+
});
|
|
3312
|
+
};
|
|
3313
|
+
const noTypeDefinitionFoundFor = word => {
|
|
3314
|
+
return i18nString(UiStrings.NoTypeDefinitionFoundFor, {
|
|
3315
|
+
PH1: word
|
|
3316
|
+
});
|
|
3317
|
+
};
|
|
3318
|
+
const noTypeDefinitionFound = () => {
|
|
3319
|
+
return i18nString(UiStrings.NoTypeDefinitionFound);
|
|
3320
|
+
};
|
|
3321
|
+
const noResults = () => {
|
|
3322
|
+
return i18nString(UiStrings.NoResults);
|
|
3323
|
+
};
|
|
3324
|
+
|
|
3955
3325
|
// @ts-ignore
|
|
3956
3326
|
const goTo = async ({
|
|
3957
3327
|
editor,
|
|
@@ -5187,8 +4557,197 @@ const resolveCompletion = async (editor, name, completionItem) => {
|
|
|
5187
4557
|
}
|
|
5188
4558
|
};
|
|
5189
4559
|
|
|
5190
|
-
const None = 1;
|
|
5191
|
-
|
|
4560
|
+
const None$1 = 1;
|
|
4561
|
+
|
|
4562
|
+
const EmptyMatches = [];
|
|
4563
|
+
|
|
4564
|
+
const Diagonal = 1;
|
|
4565
|
+
const Left = 2;
|
|
4566
|
+
|
|
4567
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
4568
|
+
|
|
4569
|
+
const createTable = size => {
|
|
4570
|
+
const table = [];
|
|
4571
|
+
for (let i = 0; i < size; i++) {
|
|
4572
|
+
const row = new Uint8Array(size);
|
|
4573
|
+
table.push(row);
|
|
4574
|
+
}
|
|
4575
|
+
return table;
|
|
4576
|
+
};
|
|
4577
|
+
|
|
4578
|
+
const isLowerCase = char => {
|
|
4579
|
+
return char === char.toLowerCase();
|
|
4580
|
+
};
|
|
4581
|
+
|
|
4582
|
+
const isUpperCase = char => {
|
|
4583
|
+
return char === char.toUpperCase();
|
|
4584
|
+
};
|
|
4585
|
+
|
|
4586
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
4587
|
+
const isGap = (columnCharBefore, columnChar) => {
|
|
4588
|
+
switch (columnCharBefore) {
|
|
4589
|
+
case Dash:
|
|
4590
|
+
case Underline:
|
|
4591
|
+
case EmptyString:
|
|
4592
|
+
case T:
|
|
4593
|
+
case Space:
|
|
4594
|
+
case Dot:
|
|
4595
|
+
return true;
|
|
4596
|
+
}
|
|
4597
|
+
if (isLowerCase(columnCharBefore) && isUpperCase(columnChar)) {
|
|
4598
|
+
return true;
|
|
4599
|
+
}
|
|
4600
|
+
return false;
|
|
4601
|
+
};
|
|
4602
|
+
|
|
4603
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
4604
|
+
const getScore = (rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, column, wordLength, isDiagonalMatch) => {
|
|
4605
|
+
if (rowCharLow !== columnCharLow) {
|
|
4606
|
+
return -1;
|
|
4607
|
+
}
|
|
4608
|
+
const isMatch = rowChar === columnChar;
|
|
4609
|
+
if (isMatch) {
|
|
4610
|
+
if (isDiagonalMatch) {
|
|
4611
|
+
return 8;
|
|
4612
|
+
}
|
|
4613
|
+
if (isGap(columnCharBefore, columnChar)) {
|
|
4614
|
+
return 8;
|
|
4615
|
+
}
|
|
4616
|
+
return 5;
|
|
4617
|
+
}
|
|
4618
|
+
if (isGap(columnCharBefore, columnChar)) {
|
|
4619
|
+
return 8;
|
|
4620
|
+
}
|
|
4621
|
+
return 5;
|
|
4622
|
+
};
|
|
4623
|
+
|
|
4624
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
4625
|
+
|
|
4626
|
+
const isPatternInWord = (patternLow, patternPos, patternLen, wordLow, wordPos, wordLen) => {
|
|
4627
|
+
while (patternPos < patternLen && wordPos < wordLen) {
|
|
4628
|
+
if (patternLow[patternPos] === wordLow[wordPos]) {
|
|
4629
|
+
patternPos += 1;
|
|
4630
|
+
}
|
|
4631
|
+
wordPos += 1;
|
|
4632
|
+
}
|
|
4633
|
+
return patternPos === patternLen; // pattern must be exhausted
|
|
4634
|
+
};
|
|
4635
|
+
|
|
4636
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
4637
|
+
const traceHighlights = (table, arrows, patternLength, wordLength) => {
|
|
4638
|
+
let row = patternLength;
|
|
4639
|
+
let column = wordLength;
|
|
4640
|
+
const matches = [];
|
|
4641
|
+
while (row >= 1 && column >= 1) {
|
|
4642
|
+
const arrow = arrows[row][column];
|
|
4643
|
+
if (arrow === Left) {
|
|
4644
|
+
column--;
|
|
4645
|
+
} else if (arrow === Diagonal) {
|
|
4646
|
+
row--;
|
|
4647
|
+
column--;
|
|
4648
|
+
const start = column + 1;
|
|
4649
|
+
while (row >= 1 && column >= 1) {
|
|
4650
|
+
const arrow = arrows[row][column];
|
|
4651
|
+
if (arrow === Left) {
|
|
4652
|
+
break;
|
|
4653
|
+
}
|
|
4654
|
+
if (arrow === Diagonal) {
|
|
4655
|
+
row--;
|
|
4656
|
+
column--;
|
|
4657
|
+
}
|
|
4658
|
+
}
|
|
4659
|
+
const end = column;
|
|
4660
|
+
matches.unshift(end, start);
|
|
4661
|
+
}
|
|
4662
|
+
}
|
|
4663
|
+
matches.unshift(table[patternLength][wordLength - 1]);
|
|
4664
|
+
return matches;
|
|
4665
|
+
};
|
|
4666
|
+
|
|
4667
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
4668
|
+
const gridSize = 128;
|
|
4669
|
+
const table = createTable(gridSize);
|
|
4670
|
+
const arrows = createTable(gridSize);
|
|
4671
|
+
const filterCompletionItem = (pattern, word) => {
|
|
4672
|
+
const patternLength = Math.min(pattern.length, gridSize - 1);
|
|
4673
|
+
const wordLength = Math.min(word.length, gridSize - 1);
|
|
4674
|
+
const patternLower = pattern.toLowerCase();
|
|
4675
|
+
const wordLower = word.toLowerCase();
|
|
4676
|
+
if (!isPatternInWord(patternLower, 0, patternLength, wordLower, 0, wordLength)) {
|
|
4677
|
+
return EmptyMatches;
|
|
4678
|
+
}
|
|
4679
|
+
let strongMatch = false;
|
|
4680
|
+
for (let row = 1; row < patternLength + 1; row++) {
|
|
4681
|
+
const rowChar = pattern[row - 1];
|
|
4682
|
+
const rowCharLow = patternLower[row - 1];
|
|
4683
|
+
for (let column = 1; column < wordLength + 1; column++) {
|
|
4684
|
+
const columnChar = word[column - 1];
|
|
4685
|
+
const columnCharLow = wordLower[column - 1];
|
|
4686
|
+
const columnCharBefore = word[column - 2] || '';
|
|
4687
|
+
const isDiagonalMatch = arrows[row - 1][column - 1] === Diagonal;
|
|
4688
|
+
const score = getScore(rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, column, wordLength, isDiagonalMatch);
|
|
4689
|
+
if (row === 1 && score > 5) {
|
|
4690
|
+
strongMatch = true;
|
|
4691
|
+
}
|
|
4692
|
+
let diagonalScore = score + table[row - 1][column - 1];
|
|
4693
|
+
if (isDiagonalMatch && score !== -1) {
|
|
4694
|
+
diagonalScore += 2;
|
|
4695
|
+
}
|
|
4696
|
+
const leftScore = table[row][column - 1];
|
|
4697
|
+
if (leftScore > diagonalScore) {
|
|
4698
|
+
table[row][column] = leftScore;
|
|
4699
|
+
arrows[row][column] = Left;
|
|
4700
|
+
} else {
|
|
4701
|
+
table[row][column] = diagonalScore;
|
|
4702
|
+
arrows[row][column] = Diagonal;
|
|
4703
|
+
}
|
|
4704
|
+
}
|
|
4705
|
+
}
|
|
4706
|
+
if (!strongMatch) {
|
|
4707
|
+
return EmptyMatches;
|
|
4708
|
+
}
|
|
4709
|
+
const highlights = traceHighlights(table, arrows, patternLength, wordLength);
|
|
4710
|
+
return highlights;
|
|
4711
|
+
};
|
|
4712
|
+
|
|
4713
|
+
const Deprecated = 1 << 0;
|
|
4714
|
+
|
|
4715
|
+
const addEmptyMatch = item => {
|
|
4716
|
+
return {
|
|
4717
|
+
...item,
|
|
4718
|
+
matches: EmptyMatches
|
|
4719
|
+
};
|
|
4720
|
+
};
|
|
4721
|
+
const filterCompletionItems = (completionItems, word) => {
|
|
4722
|
+
if (word === EmptyString) {
|
|
4723
|
+
return completionItems.map(addEmptyMatch);
|
|
4724
|
+
}
|
|
4725
|
+
const filteredCompletions = [];
|
|
4726
|
+
const deprecated = [];
|
|
4727
|
+
for (const completionItem of completionItems) {
|
|
4728
|
+
const {
|
|
4729
|
+
label,
|
|
4730
|
+
flags
|
|
4731
|
+
} = completionItem;
|
|
4732
|
+
const result = filterCompletionItem(word, label);
|
|
4733
|
+
if (result !== EmptyMatches) {
|
|
4734
|
+
if (flags & Deprecated) {
|
|
4735
|
+
// TODO avoid mutation
|
|
4736
|
+
completionItem.matches = EmptyMatches;
|
|
4737
|
+
deprecated.push(completionItem);
|
|
4738
|
+
} else {
|
|
4739
|
+
// TODO avoid mutation
|
|
4740
|
+
completionItem.matches = result;
|
|
4741
|
+
filteredCompletions.push(completionItem);
|
|
4742
|
+
}
|
|
4743
|
+
}
|
|
4744
|
+
}
|
|
4745
|
+
if (deprecated.length > 0) {
|
|
4746
|
+
filteredCompletions.push(...deprecated);
|
|
4747
|
+
}
|
|
4748
|
+
return filteredCompletions;
|
|
4749
|
+
};
|
|
4750
|
+
|
|
5192
4751
|
const getEditor = editorUid => {
|
|
5193
4752
|
const instance = get$6(editorUid);
|
|
5194
4753
|
if (!instance) {
|
|
@@ -5206,6 +4765,17 @@ const getFinalDeltaY = (height, itemHeight, itemsLength) => {
|
|
|
5206
4765
|
return finalDeltaY;
|
|
5207
4766
|
};
|
|
5208
4767
|
|
|
4768
|
+
const getListHeight = (itemsLength, itemHeight, maxHeight) => {
|
|
4769
|
+
number$1(itemsLength);
|
|
4770
|
+
number$1(itemHeight);
|
|
4771
|
+
number$1(maxHeight);
|
|
4772
|
+
if (itemsLength === 0) {
|
|
4773
|
+
return itemHeight;
|
|
4774
|
+
}
|
|
4775
|
+
const totalHeight = itemsLength * itemHeight;
|
|
4776
|
+
return Math.min(totalHeight, maxHeight);
|
|
4777
|
+
};
|
|
4778
|
+
|
|
5209
4779
|
const RE_WORD = /[\w\-]+$/;
|
|
5210
4780
|
const getWordAtOffset = editor => {
|
|
5211
4781
|
const {
|
|
@@ -5222,7 +4792,7 @@ const getWordAtOffset = editor => {
|
|
|
5222
4792
|
}
|
|
5223
4793
|
return '';
|
|
5224
4794
|
};
|
|
5225
|
-
const handleEditorType = (editorUid, state, text) => {
|
|
4795
|
+
const handleEditorType$1 = (editorUid, state, text) => {
|
|
5226
4796
|
const editor = getEditor(editorUid);
|
|
5227
4797
|
const {
|
|
5228
4798
|
unfilteredItems,
|
|
@@ -5252,7 +4822,7 @@ const handleEditorType = (editorUid, state, text) => {
|
|
|
5252
4822
|
finalDeltaY
|
|
5253
4823
|
};
|
|
5254
4824
|
};
|
|
5255
|
-
const handleEditorDeleteLeft = (editorUid, state) => {
|
|
4825
|
+
const handleEditorDeleteLeft$1 = (editorUid, state) => {
|
|
5256
4826
|
const editor = getEditor(editorUid);
|
|
5257
4827
|
const {
|
|
5258
4828
|
unfilteredItems,
|
|
@@ -5266,7 +4836,7 @@ const handleEditorDeleteLeft = (editorUid, state) => {
|
|
|
5266
4836
|
const y$1 = y(editor, rowIndex);
|
|
5267
4837
|
const wordAtOffset = getWordAtOffset(editor);
|
|
5268
4838
|
if (!wordAtOffset) {
|
|
5269
|
-
editor.completionState = None;
|
|
4839
|
+
editor.completionState = None$1;
|
|
5270
4840
|
return {
|
|
5271
4841
|
...state,
|
|
5272
4842
|
disposed: true
|
|
@@ -5292,7 +4862,7 @@ const dispose = state => {
|
|
|
5292
4862
|
};
|
|
5293
4863
|
};
|
|
5294
4864
|
const disposeWithEditor = (state, editor) => {
|
|
5295
|
-
editor.completionState = None;
|
|
4865
|
+
editor.completionState = None$1;
|
|
5296
4866
|
editor.completionUid = 0;
|
|
5297
4867
|
// Focus.removeAdditionalFocus(FocusKey.EditorCompletion)
|
|
5298
4868
|
return dispose(state);
|
|
@@ -5634,11 +5204,8 @@ const editorSelectAllLeft = editor => {
|
|
|
5634
5204
|
editorSelectHorizontalLeft(editor, lineCharacterStart);
|
|
5635
5205
|
};
|
|
5636
5206
|
|
|
5637
|
-
// @ts-ignore
|
|
5638
|
-
|
|
5639
5207
|
// TODO handle virtual space
|
|
5640
5208
|
|
|
5641
|
-
// @ts-ignore
|
|
5642
5209
|
const getNewSelectionsSingleLineWord = (lines, word) => {
|
|
5643
5210
|
if (word.length === 0) {
|
|
5644
5211
|
throw new Error('word length must be greater than zero');
|
|
@@ -5653,8 +5220,6 @@ const getNewSelectionsSingleLineWord = (lines, word) => {
|
|
|
5653
5220
|
}
|
|
5654
5221
|
return new Uint32Array(newSelections);
|
|
5655
5222
|
};
|
|
5656
|
-
|
|
5657
|
-
// @ts-ignore
|
|
5658
5223
|
const isMultiLineMatch = (lines, rowIndex, wordParts) => {
|
|
5659
5224
|
let j = 0;
|
|
5660
5225
|
if (!lines[rowIndex + j].endsWith(wordParts[j])) {
|
|
@@ -5675,11 +5240,11 @@ const isMultiLineMatch = (lines, rowIndex, wordParts) => {
|
|
|
5675
5240
|
|
|
5676
5241
|
// TODO this is very expensive, there might be a better algorithm for this
|
|
5677
5242
|
// TODO if this matches the given selections, don't schedule selections/rerender
|
|
5678
|
-
// @ts-ignore
|
|
5679
5243
|
const getAllOccurrencesMultiLine = (lines, wordParts) => {
|
|
5680
5244
|
const newSelections = [];
|
|
5681
5245
|
for (let rowIndex = 0; rowIndex < lines.length - wordParts.length + 1; rowIndex) {
|
|
5682
5246
|
if (isMultiLineMatch(lines, rowIndex, wordParts)) {
|
|
5247
|
+
// @ts-ignore
|
|
5683
5248
|
newSelections.push(rowIndex, lines[rowIndex].length - wordParts[0].length, rowIndex + wordParts.length - 1, wordParts.at(-1).length);
|
|
5684
5249
|
rowIndex += wordParts.length - 1;
|
|
5685
5250
|
} else {
|
|
@@ -5691,13 +5256,9 @@ const getAllOccurrencesMultiLine = (lines, wordParts) => {
|
|
|
5691
5256
|
|
|
5692
5257
|
// TODO duplicate code with EditorSelectNextOccurrence
|
|
5693
5258
|
const RE_ALPHA_NUMERIC$1 = /[a-zA-Z\d]/;
|
|
5694
|
-
|
|
5695
|
-
// @ts-ignore
|
|
5696
5259
|
const isAlphaNumeric$1 = char => {
|
|
5697
5260
|
return RE_ALPHA_NUMERIC$1.test(char);
|
|
5698
5261
|
};
|
|
5699
|
-
|
|
5700
|
-
// @ts-ignore
|
|
5701
5262
|
const getWordStartIndex$1 = (line, index) => {
|
|
5702
5263
|
for (let i = index - 1; i >= 0; i--) {
|
|
5703
5264
|
if (!isAlphaNumeric$1(line[i])) {
|
|
@@ -5706,8 +5267,6 @@ const getWordStartIndex$1 = (line, index) => {
|
|
|
5706
5267
|
}
|
|
5707
5268
|
return 0;
|
|
5708
5269
|
};
|
|
5709
|
-
|
|
5710
|
-
// @ts-ignore
|
|
5711
5270
|
const getWordEndIndex$1 = (line, index) => {
|
|
5712
5271
|
for (let i = index; i < line.length; i++) {
|
|
5713
5272
|
if (!isAlphaNumeric$1(line[i])) {
|
|
@@ -5716,8 +5275,6 @@ const getWordEndIndex$1 = (line, index) => {
|
|
|
5716
5275
|
}
|
|
5717
5276
|
return line.length - 1;
|
|
5718
5277
|
};
|
|
5719
|
-
|
|
5720
|
-
// @ts-ignore
|
|
5721
5278
|
const getWordMatchAtPosition$1 = (lines, rowIndex, columnIndex) => {
|
|
5722
5279
|
const line = lines[rowIndex];
|
|
5723
5280
|
const start = getWordStartIndex$1(line, columnIndex);
|
|
@@ -5729,8 +5286,6 @@ const getWordMatchAtPosition$1 = (lines, rowIndex, columnIndex) => {
|
|
|
5729
5286
|
word
|
|
5730
5287
|
};
|
|
5731
5288
|
};
|
|
5732
|
-
|
|
5733
|
-
// @ts-ignore
|
|
5734
5289
|
const getNewSelections$3 = (lines, selections) => {
|
|
5735
5290
|
if (selections.length < 4) {
|
|
5736
5291
|
throw new Error('selections must have at least one entry');
|
|
@@ -5763,12 +5318,12 @@ const getNewSelections$3 = (lines, selections) => {
|
|
|
5763
5318
|
const newSelections = getAllOccurrencesMultiLine(lines, wordParts);
|
|
5764
5319
|
return newSelections;
|
|
5765
5320
|
};
|
|
5766
|
-
|
|
5767
|
-
// @ts-ignore
|
|
5768
5321
|
const selectAllOccurrences = editor => {
|
|
5769
5322
|
// when there are no selections -> first selection is word -> find all selection that include word
|
|
5770
|
-
const
|
|
5771
|
-
|
|
5323
|
+
const {
|
|
5324
|
+
lines,
|
|
5325
|
+
selections
|
|
5326
|
+
} = editor;
|
|
5772
5327
|
const newSelections = getNewSelections$3(lines, selections);
|
|
5773
5328
|
return scheduleSelections(editor, newSelections);
|
|
5774
5329
|
};
|
|
@@ -7203,7 +6758,7 @@ const select = async (editor, completionItem) => {
|
|
|
7203
6758
|
();
|
|
7204
6759
|
if (index !== -1) {
|
|
7205
6760
|
editor.widgets.splice(index, 1);
|
|
7206
|
-
editor.completionState = None;
|
|
6761
|
+
editor.completionState = None$1;
|
|
7207
6762
|
editor.completionUid = 0;
|
|
7208
6763
|
}
|
|
7209
6764
|
// TODO dispose completion widget
|
|
@@ -7266,7 +6821,7 @@ const getHover = async (editor, offset) => {
|
|
|
7266
6821
|
|
|
7267
6822
|
let _ipc;
|
|
7268
6823
|
const listen$5 = async () => {
|
|
7269
|
-
const ipc = await create({
|
|
6824
|
+
const ipc = await create$1({
|
|
7270
6825
|
method: RendererProcess
|
|
7271
6826
|
});
|
|
7272
6827
|
handleIpc(ipc);
|
|
@@ -7495,6 +7050,14 @@ const handleSashPointerUp = (state, eventX, eventY) => {
|
|
|
7495
7050
|
return state;
|
|
7496
7051
|
};
|
|
7497
7052
|
|
|
7053
|
+
const text = data => {
|
|
7054
|
+
return {
|
|
7055
|
+
type: Text,
|
|
7056
|
+
text: data,
|
|
7057
|
+
childCount: 0
|
|
7058
|
+
};
|
|
7059
|
+
};
|
|
7060
|
+
|
|
7498
7061
|
const getLineInfoVirtualDom = lineInfo => {
|
|
7499
7062
|
const dom = [{
|
|
7500
7063
|
type: Div,
|
|
@@ -7582,7 +7145,7 @@ const renderHoverDom = {
|
|
|
7582
7145
|
return [/* method */'Viewlet.setDom2', dom];
|
|
7583
7146
|
}
|
|
7584
7147
|
};
|
|
7585
|
-
const renderBounds = {
|
|
7148
|
+
const renderBounds$1 = {
|
|
7586
7149
|
isEqual(oldState, newState) {
|
|
7587
7150
|
return oldState.x === newState.x && oldState.y === newState.y && oldState.resizedWidth === newState.resizedWidth;
|
|
7588
7151
|
},
|
|
@@ -7600,10 +7163,10 @@ const renderBounds = {
|
|
|
7600
7163
|
return [SetBounds, x, y, resizedWidth, height];
|
|
7601
7164
|
}
|
|
7602
7165
|
};
|
|
7603
|
-
const render$
|
|
7166
|
+
const render$3 = [renderHoverDom, renderBounds$1];
|
|
7604
7167
|
const renderHover = async (oldState, newState) => {
|
|
7605
7168
|
const commands = [];
|
|
7606
|
-
for (const item of render$
|
|
7169
|
+
for (const item of render$3) {
|
|
7607
7170
|
if (!item.isEqual(oldState, newState)) {
|
|
7608
7171
|
commands.push(item.apply(oldState, newState));
|
|
7609
7172
|
}
|
|
@@ -7909,7 +7472,7 @@ const moveLineUp = editor => {
|
|
|
7909
7472
|
};
|
|
7910
7473
|
|
|
7911
7474
|
const Link$1 = 'Link';
|
|
7912
|
-
const Function = 'Function';
|
|
7475
|
+
const Function$1 = 'Function';
|
|
7913
7476
|
const Parameter = 'Parameter';
|
|
7914
7477
|
const Type = 'Type';
|
|
7915
7478
|
const VariableName = 'VariableName';
|
|
@@ -7968,7 +7531,7 @@ const getDecorationClassName = type => {
|
|
|
7968
7531
|
case Ts3073:
|
|
7969
7532
|
case Ts3077:
|
|
7970
7533
|
case Ts3088:
|
|
7971
|
-
return Function;
|
|
7534
|
+
return Function$1;
|
|
7972
7535
|
case Ts1792:
|
|
7973
7536
|
case Ts1793:
|
|
7974
7537
|
return Parameter;
|
|
@@ -8004,521 +7567,872 @@ const getDecorationClassName = type => {
|
|
|
8004
7567
|
return `Unknown-${type}`;
|
|
8005
7568
|
}
|
|
8006
7569
|
};
|
|
8007
|
-
|
|
8008
|
-
const getTokensViewportEmbedded = (langageId, lines, lineCache, linesWithEmbed) => {
|
|
8009
|
-
const tokenizersToLoad = [];
|
|
8010
|
-
const embeddedResults = [];
|
|
8011
|
-
let topContext;
|
|
8012
|
-
for (const index of linesWithEmbed) {
|
|
8013
|
-
const result = lineCache[index + 1];
|
|
8014
|
-
const line = lines[index];
|
|
8015
|
-
if (result.embeddedLanguage) {
|
|
8016
|
-
const {
|
|
8017
|
-
embeddedLanguage,
|
|
8018
|
-
embeddedLanguageStart,
|
|
8019
|
-
embeddedLanguageEnd
|
|
8020
|
-
} = result;
|
|
8021
|
-
const embeddedTokenizer = getTokenizer(embeddedLanguage);
|
|
8022
|
-
if (embeddedLanguageStart !== line.length && embeddedTokenizer && embeddedTokenizer !== TokenizePlainText) {
|
|
8023
|
-
const isFull = embeddedLanguageStart === 0 && embeddedLanguageEnd === line.length;
|
|
8024
|
-
const partialLine = line.slice(embeddedLanguageStart, embeddedLanguageEnd);
|
|
8025
|
-
const embedResult = safeTokenizeLine(langageId, embeddedTokenizer.tokenizeLine, partialLine, topContext || getInitialLineState(embeddedTokenizer.initialLineState), embeddedTokenizer.hasArrayReturn);
|
|
8026
|
-
topContext = embedResult;
|
|
8027
|
-
result.embeddedResultIndex = embeddedResults.length;
|
|
8028
|
-
embeddedResults.push({
|
|
8029
|
-
result: embedResult,
|
|
8030
|
-
TokenMap: embeddedTokenizer.TokenMap,
|
|
8031
|
-
isFull
|
|
8032
|
-
});
|
|
8033
|
-
} else if (line.length === 0) {
|
|
8034
|
-
const embedResult = {
|
|
8035
|
-
tokens: []
|
|
8036
|
-
};
|
|
8037
|
-
result.embeddedResultIndex = embeddedResults.length;
|
|
8038
|
-
embeddedResults.push({
|
|
8039
|
-
result: embedResult,
|
|
8040
|
-
isFull: true,
|
|
8041
|
-
TokenMap: []
|
|
8042
|
-
});
|
|
8043
|
-
} else {
|
|
8044
|
-
tokenizersToLoad.push(embeddedLanguage);
|
|
8045
|
-
embeddedResults.push({
|
|
8046
|
-
result: {},
|
|
8047
|
-
isFull: false,
|
|
8048
|
-
TokenMap: []
|
|
8049
|
-
});
|
|
8050
|
-
topContext = undefined;
|
|
8051
|
-
}
|
|
8052
|
-
} else {
|
|
8053
|
-
topContext = undefined;
|
|
7570
|
+
|
|
7571
|
+
const getTokensViewportEmbedded = (langageId, lines, lineCache, linesWithEmbed) => {
|
|
7572
|
+
const tokenizersToLoad = [];
|
|
7573
|
+
const embeddedResults = [];
|
|
7574
|
+
let topContext;
|
|
7575
|
+
for (const index of linesWithEmbed) {
|
|
7576
|
+
const result = lineCache[index + 1];
|
|
7577
|
+
const line = lines[index];
|
|
7578
|
+
if (result.embeddedLanguage) {
|
|
7579
|
+
const {
|
|
7580
|
+
embeddedLanguage,
|
|
7581
|
+
embeddedLanguageStart,
|
|
7582
|
+
embeddedLanguageEnd
|
|
7583
|
+
} = result;
|
|
7584
|
+
const embeddedTokenizer = getTokenizer(embeddedLanguage);
|
|
7585
|
+
if (embeddedLanguageStart !== line.length && embeddedTokenizer && embeddedTokenizer !== TokenizePlainText) {
|
|
7586
|
+
const isFull = embeddedLanguageStart === 0 && embeddedLanguageEnd === line.length;
|
|
7587
|
+
const partialLine = line.slice(embeddedLanguageStart, embeddedLanguageEnd);
|
|
7588
|
+
const embedResult = safeTokenizeLine(langageId, embeddedTokenizer.tokenizeLine, partialLine, topContext || getInitialLineState(embeddedTokenizer.initialLineState), embeddedTokenizer.hasArrayReturn);
|
|
7589
|
+
topContext = embedResult;
|
|
7590
|
+
result.embeddedResultIndex = embeddedResults.length;
|
|
7591
|
+
embeddedResults.push({
|
|
7592
|
+
result: embedResult,
|
|
7593
|
+
TokenMap: embeddedTokenizer.TokenMap,
|
|
7594
|
+
isFull
|
|
7595
|
+
});
|
|
7596
|
+
} else if (line.length === 0) {
|
|
7597
|
+
const embedResult = {
|
|
7598
|
+
tokens: []
|
|
7599
|
+
};
|
|
7600
|
+
result.embeddedResultIndex = embeddedResults.length;
|
|
7601
|
+
embeddedResults.push({
|
|
7602
|
+
result: embedResult,
|
|
7603
|
+
isFull: true,
|
|
7604
|
+
TokenMap: []
|
|
7605
|
+
});
|
|
7606
|
+
} else {
|
|
7607
|
+
tokenizersToLoad.push(embeddedLanguage);
|
|
7608
|
+
embeddedResults.push({
|
|
7609
|
+
result: {},
|
|
7610
|
+
isFull: false,
|
|
7611
|
+
TokenMap: []
|
|
7612
|
+
});
|
|
7613
|
+
topContext = undefined;
|
|
7614
|
+
}
|
|
7615
|
+
} else {
|
|
7616
|
+
topContext = undefined;
|
|
7617
|
+
}
|
|
7618
|
+
}
|
|
7619
|
+
return {
|
|
7620
|
+
tokenizersToLoad,
|
|
7621
|
+
embeddedResults
|
|
7622
|
+
};
|
|
7623
|
+
};
|
|
7624
|
+
const getTokenizeEndIndex = (invalidStartIndex, endLineIndex, tokenizeStartIndex) => {
|
|
7625
|
+
return invalidStartIndex < endLineIndex ? endLineIndex : tokenizeStartIndex;
|
|
7626
|
+
};
|
|
7627
|
+
|
|
7628
|
+
// TODO only send changed lines to renderer process instead of all lines in viewport
|
|
7629
|
+
const getTokensViewport = (editor, startLineIndex, endLineIndex) => {
|
|
7630
|
+
const {
|
|
7631
|
+
invalidStartIndex,
|
|
7632
|
+
lineCache,
|
|
7633
|
+
tokenizerId,
|
|
7634
|
+
lines,
|
|
7635
|
+
languageId
|
|
7636
|
+
} = editor;
|
|
7637
|
+
const tokenizer = get(tokenizerId);
|
|
7638
|
+
const {
|
|
7639
|
+
hasArrayReturn,
|
|
7640
|
+
tokenizeLine,
|
|
7641
|
+
initialLineState
|
|
7642
|
+
} = tokenizer;
|
|
7643
|
+
const tokenizeStartIndex = invalidStartIndex;
|
|
7644
|
+
const tokenizeEndIndex = getTokenizeEndIndex(invalidStartIndex, endLineIndex, tokenizeStartIndex);
|
|
7645
|
+
const tokenizersToLoad = [];
|
|
7646
|
+
const embeddedResults = [];
|
|
7647
|
+
const linesWithEmbed = [];
|
|
7648
|
+
for (let i = tokenizeStartIndex; i < tokenizeEndIndex; i++) {
|
|
7649
|
+
const lineState = i === 0 ? getInitialLineState(initialLineState) : lineCache[i];
|
|
7650
|
+
const line = lines[i];
|
|
7651
|
+
const result = safeTokenizeLine(languageId, tokenizeLine, line, lineState, hasArrayReturn);
|
|
7652
|
+
// TODO if lineCacheEnd matches the one before, skip tokenizing lines after
|
|
7653
|
+
lineCache[i + 1] = result;
|
|
7654
|
+
if (result.embeddedLanguage) {
|
|
7655
|
+
result.embeddedResultIndex = linesWithEmbed.length;
|
|
7656
|
+
linesWithEmbed.push(i);
|
|
7657
|
+
}
|
|
7658
|
+
}
|
|
7659
|
+
const visibleLines = lineCache.slice(startLineIndex + 1, endLineIndex + 1);
|
|
7660
|
+
if (linesWithEmbed.length > 0) {
|
|
7661
|
+
const {
|
|
7662
|
+
tokenizersToLoad,
|
|
7663
|
+
embeddedResults
|
|
7664
|
+
} = getTokensViewportEmbedded(languageId, lines, lineCache, linesWithEmbed);
|
|
7665
|
+
// TODO support lineCache with embedded content
|
|
7666
|
+
editor.invalidStartIndex = 0;
|
|
7667
|
+
return {
|
|
7668
|
+
tokens: visibleLines,
|
|
7669
|
+
tokenizersToLoad,
|
|
7670
|
+
embeddedResults
|
|
7671
|
+
};
|
|
7672
|
+
}
|
|
7673
|
+
editor.invalidStartIndex = Math.max(invalidStartIndex, tokenizeEndIndex);
|
|
7674
|
+
return {
|
|
7675
|
+
tokens: visibleLines,
|
|
7676
|
+
tokenizersToLoad,
|
|
7677
|
+
embeddedResults
|
|
7678
|
+
};
|
|
7679
|
+
};
|
|
7680
|
+
|
|
7681
|
+
const sentLines = Object.create(null);
|
|
7682
|
+
|
|
7683
|
+
// TODO only send changed lines to renderer process instead of all lines in viewport
|
|
7684
|
+
const getTokensViewport2 = (editor, startLineIndex, endLineIndex, syncIncremental) => {
|
|
7685
|
+
if (getEnabled$1()) {
|
|
7686
|
+
if (syncIncremental) {
|
|
7687
|
+
const {
|
|
7688
|
+
invalidStartIndex,
|
|
7689
|
+
lines,
|
|
7690
|
+
languageId,
|
|
7691
|
+
id
|
|
7692
|
+
} = editor;
|
|
7693
|
+
let hasLinesToSend = true;
|
|
7694
|
+
let linesToSend = lines;
|
|
7695
|
+
if (sentLines[id] === lines) {
|
|
7696
|
+
hasLinesToSend = false;
|
|
7697
|
+
linesToSend = [];
|
|
7698
|
+
} else {
|
|
7699
|
+
sentLines[id] = lines;
|
|
7700
|
+
}
|
|
7701
|
+
const slimEditor = {
|
|
7702
|
+
languageId,
|
|
7703
|
+
invalidStartIndex
|
|
7704
|
+
};
|
|
7705
|
+
return invoke$1('GetTokensViewport.getTokensViewport', slimEditor, startLineIndex, endLineIndex, hasLinesToSend, id, linesToSend);
|
|
7706
|
+
}
|
|
7707
|
+
// TODO only send needed lines of text
|
|
7708
|
+
return invoke$1('GetTokensViewport.getTokensViewport', editor, startLineIndex, endLineIndex, true, editor.id, editor.lines);
|
|
7709
|
+
}
|
|
7710
|
+
return getTokensViewport(editor, startLineIndex, endLineIndex);
|
|
7711
|
+
};
|
|
7712
|
+
|
|
7713
|
+
const loadTokenizers = async languageIds => {
|
|
7714
|
+
for (const languageId of languageIds) {
|
|
7715
|
+
// @ts-ignore
|
|
7716
|
+
await loadTokenizer(languageId);
|
|
7717
|
+
}
|
|
7718
|
+
};
|
|
7719
|
+
|
|
7720
|
+
// const getTokensIncremental = (editor, min, max) => {
|
|
7721
|
+
// const currentLength = editor.lineStateCache.length
|
|
7722
|
+
// const tokens = []
|
|
7723
|
+
// const lines = editor.lines
|
|
7724
|
+
// let lineState = editor.tokenizer.initialLineState
|
|
7725
|
+
// for (let i = currentLength; i < max; i++) {
|
|
7726
|
+
// const line = lines[i]
|
|
7727
|
+
// try {
|
|
7728
|
+
// lineState = editor.tokenizer.tokenizeLine(line, lineState)
|
|
7729
|
+
// if (!lineState || !lineState.tokens || !lineState.state) {
|
|
7730
|
+
// throw new Error('invalid tokenization result')
|
|
7731
|
+
// }
|
|
7732
|
+
// } catch (error) {
|
|
7733
|
+
// tokens.push([{ length: line.length, type: 0 }])
|
|
7734
|
+
// console.error(error)
|
|
7735
|
+
// // renderWithoutSyntaxHighlighting(state, firstRow, lastRow)
|
|
7736
|
+
// continue
|
|
7737
|
+
// }
|
|
7738
|
+
// const newTokens = lineState.tokens
|
|
7739
|
+
// tokens.push(newTokens)
|
|
7740
|
+
// }
|
|
7741
|
+
// return tokens
|
|
7742
|
+
// }
|
|
7743
|
+
|
|
7744
|
+
// const getLineInfosIncremental = (editor, tokens, minLineY, maxLineY) => {
|
|
7745
|
+
// const result = []
|
|
7746
|
+
// const lines = editor.lines
|
|
7747
|
+
// const TokenMap = editor.tokenizer.TokenMap
|
|
7748
|
+
// for (let i = minLineY; i < maxLineY; i++) {
|
|
7749
|
+
// result.push(getLineInfo(lines[i], tokens[i], TokenMap))
|
|
7750
|
+
// }
|
|
7751
|
+
// return result
|
|
7752
|
+
// }
|
|
7753
|
+
|
|
7754
|
+
const getStartDefaults = (tokens, minOffset) => {
|
|
7755
|
+
let start = 0;
|
|
7756
|
+
let end = 0;
|
|
7757
|
+
let startIndex = 0;
|
|
7758
|
+
const tokensLength = tokens.length;
|
|
7759
|
+
for (let i = 0; i < tokensLength; i += 2) {
|
|
7760
|
+
const tokenLength = tokens[i + 1];
|
|
7761
|
+
end += tokenLength;
|
|
7762
|
+
start = end;
|
|
7763
|
+
if (start >= minOffset) {
|
|
7764
|
+
start -= tokenLength;
|
|
7765
|
+
end -= tokenLength;
|
|
7766
|
+
startIndex = i;
|
|
7767
|
+
break;
|
|
7768
|
+
}
|
|
7769
|
+
}
|
|
7770
|
+
return {
|
|
7771
|
+
start,
|
|
7772
|
+
end,
|
|
7773
|
+
startIndex
|
|
7774
|
+
};
|
|
7775
|
+
};
|
|
7776
|
+
const getLineInfoEmbeddedFull = (embeddedResults, tokenResults, line, normalize, tabSize, width, deltaX, averageCharWidth, minOffset, maxOffset) => {
|
|
7777
|
+
const lineInfo = [];
|
|
7778
|
+
const embeddedResult = embeddedResults[tokenResults.embeddedResultIndex];
|
|
7779
|
+
const embeddedTokens = embeddedResult.result.tokens;
|
|
7780
|
+
const embeddedTokenMap = embeddedResult.TokenMap;
|
|
7781
|
+
const tokensLength = embeddedTokens.length;
|
|
7782
|
+
let {
|
|
7783
|
+
startIndex,
|
|
7784
|
+
start,
|
|
7785
|
+
end
|
|
7786
|
+
} = getStartDefaults(embeddedTokens, minOffset);
|
|
7787
|
+
const difference = getDifference(start, averageCharWidth, deltaX);
|
|
7788
|
+
for (let i = startIndex; i < tokensLength; i += 2) {
|
|
7789
|
+
const tokenType = embeddedTokens[i];
|
|
7790
|
+
const tokenLength = embeddedTokens[i + 1];
|
|
7791
|
+
end += tokenLength;
|
|
7792
|
+
const className = `Token ${embeddedTokenMap[tokenType] || 'Unknown'}`;
|
|
7793
|
+
const text = line.slice(start, end);
|
|
7794
|
+
const normalizedText = normalizeText(text, normalize, tabSize);
|
|
7795
|
+
lineInfo.push(normalizedText, className);
|
|
7796
|
+
start = end;
|
|
7797
|
+
if (end >= maxOffset) {
|
|
7798
|
+
break;
|
|
8054
7799
|
}
|
|
8055
7800
|
}
|
|
8056
7801
|
return {
|
|
8057
|
-
|
|
8058
|
-
|
|
7802
|
+
lineInfo,
|
|
7803
|
+
difference
|
|
8059
7804
|
};
|
|
8060
7805
|
};
|
|
8061
|
-
const
|
|
8062
|
-
|
|
7806
|
+
const getOffsets = (deltaX, width, averageCharWidth) => {
|
|
7807
|
+
// TODO accurately measure char widths using offscreen canvas
|
|
7808
|
+
// and use fast measurements for monospace ascii text
|
|
7809
|
+
if (deltaX === 0) {
|
|
7810
|
+
return {
|
|
7811
|
+
minOffset: 0,
|
|
7812
|
+
maxOffset: Math.ceil(width / averageCharWidth)
|
|
7813
|
+
};
|
|
7814
|
+
}
|
|
7815
|
+
const minOffset = Math.ceil(deltaX / averageCharWidth);
|
|
7816
|
+
const maxOffset = minOffset + Math.ceil(width / averageCharWidth);
|
|
7817
|
+
return {
|
|
7818
|
+
minOffset,
|
|
7819
|
+
maxOffset
|
|
7820
|
+
};
|
|
7821
|
+
};
|
|
7822
|
+
const getDifference = (start, averageCharWidth, deltaX) => {
|
|
7823
|
+
const beforeWidth = start * averageCharWidth;
|
|
7824
|
+
const difference = beforeWidth - deltaX;
|
|
7825
|
+
return difference;
|
|
7826
|
+
};
|
|
7827
|
+
const getLineInfoDefault = (line, tokenResults, embeddedResults, decorations, TokenMap, lineOffset, normalize, tabSize, width, deltaX, averageCharWidth, minOffset, maxOffset) => {
|
|
7828
|
+
const lineInfo = [];
|
|
7829
|
+
let decorationIndex = 0;
|
|
7830
|
+
for (; decorationIndex < decorations.length; decorationIndex += 3) {
|
|
7831
|
+
const decorationOffset = decorations[decorationIndex];
|
|
7832
|
+
if (decorationOffset >= lineOffset) {
|
|
7833
|
+
break;
|
|
7834
|
+
}
|
|
7835
|
+
}
|
|
7836
|
+
const tokens = tokenResults.tokens;
|
|
7837
|
+
let {
|
|
7838
|
+
startIndex,
|
|
7839
|
+
start,
|
|
7840
|
+
end
|
|
7841
|
+
} = getStartDefaults(tokens, minOffset);
|
|
7842
|
+
const difference = getDifference(start, averageCharWidth, deltaX);
|
|
7843
|
+
const tokensLength = tokens.length;
|
|
7844
|
+
for (let i = startIndex; i < tokensLength; i += 2) {
|
|
7845
|
+
const tokenType = tokens[i];
|
|
7846
|
+
const tokenLength = tokens[i + 1];
|
|
7847
|
+
const decorationOffset = decorations[decorationIndex];
|
|
7848
|
+
let extraClassName = '';
|
|
7849
|
+
if (decorationOffset !== undefined && decorationOffset - lineOffset === start) {
|
|
7850
|
+
// @ts-ignore
|
|
7851
|
+
decorations[++decorationIndex];
|
|
7852
|
+
const decorationType = decorations[++decorationIndex];
|
|
7853
|
+
// @ts-ignore
|
|
7854
|
+
decorations[++decorationIndex];
|
|
7855
|
+
// console.log('MATCHING DECORATION', {
|
|
7856
|
+
// decorationIndex,
|
|
7857
|
+
// decorationLength,
|
|
7858
|
+
// decorationType,
|
|
7859
|
+
// decorationModifiers,
|
|
7860
|
+
// })
|
|
7861
|
+
extraClassName = getDecorationClassName(decorationType);
|
|
7862
|
+
}
|
|
7863
|
+
end += tokenLength;
|
|
7864
|
+
const text = line.slice(start, end);
|
|
7865
|
+
const className = `Token ${extraClassName || TokenMap[tokenType] || 'Unknown'}`;
|
|
7866
|
+
const normalizedText = normalizeText(text, normalize, tabSize);
|
|
7867
|
+
lineInfo.push(normalizedText, className);
|
|
7868
|
+
start = end;
|
|
7869
|
+
if (end >= maxOffset) {
|
|
7870
|
+
break;
|
|
7871
|
+
}
|
|
7872
|
+
}
|
|
7873
|
+
return {
|
|
7874
|
+
lineInfo,
|
|
7875
|
+
difference
|
|
7876
|
+
};
|
|
7877
|
+
};
|
|
7878
|
+
const getLineInfo = (line, tokenResults, embeddedResults, decorations, TokenMap, lineOffset, normalize, tabSize, width, deltaX, averageCharWidth) => {
|
|
7879
|
+
const {
|
|
7880
|
+
minOffset,
|
|
7881
|
+
maxOffset
|
|
7882
|
+
} = getOffsets(deltaX, width, averageCharWidth);
|
|
7883
|
+
if (embeddedResults.length > 0 && tokenResults.embeddedResultIndex !== undefined) {
|
|
7884
|
+
const embeddedResult = embeddedResults[tokenResults.embeddedResultIndex];
|
|
7885
|
+
if (embeddedResult && embeddedResult.isFull) {
|
|
7886
|
+
return getLineInfoEmbeddedFull(embeddedResults, tokenResults, line, normalize, tabSize, width, deltaX, averageCharWidth, minOffset, maxOffset);
|
|
7887
|
+
}
|
|
7888
|
+
}
|
|
7889
|
+
return getLineInfoDefault(line, tokenResults, embeddedResults, decorations, TokenMap, lineOffset, normalize, tabSize, width, deltaX, averageCharWidth, minOffset, maxOffset);
|
|
8063
7890
|
};
|
|
8064
7891
|
|
|
8065
|
-
// TODO
|
|
8066
|
-
const
|
|
7892
|
+
// TODO need lots of tests for this
|
|
7893
|
+
const getLineInfosViewport = (editor, tokens, embeddedResults, minLineY, maxLineY, minLineOffset, width, deltaX, averageCharWidth) => {
|
|
7894
|
+
const result = [];
|
|
7895
|
+
const differences = [];
|
|
8067
7896
|
const {
|
|
8068
|
-
invalidStartIndex,
|
|
8069
|
-
lineCache,
|
|
8070
|
-
tokenizerId,
|
|
8071
7897
|
lines,
|
|
7898
|
+
decorations,
|
|
8072
7899
|
languageId
|
|
8073
7900
|
} = editor;
|
|
8074
|
-
const
|
|
8075
|
-
|
|
8076
|
-
|
|
8077
|
-
|
|
8078
|
-
initialLineState
|
|
8079
|
-
} = tokenizer;
|
|
8080
|
-
const tokenizeStartIndex = invalidStartIndex;
|
|
8081
|
-
const tokenizeEndIndex = getTokenizeEndIndex(invalidStartIndex, endLineIndex, tokenizeStartIndex);
|
|
8082
|
-
const tokenizersToLoad = [];
|
|
8083
|
-
const embeddedResults = [];
|
|
8084
|
-
const linesWithEmbed = [];
|
|
8085
|
-
for (let i = tokenizeStartIndex; i < tokenizeEndIndex; i++) {
|
|
8086
|
-
const lineState = i === 0 ? getInitialLineState(initialLineState) : lineCache[i];
|
|
7901
|
+
const tokenMap = get$1(languageId);
|
|
7902
|
+
let offset = minLineOffset;
|
|
7903
|
+
const tabSize = 2;
|
|
7904
|
+
for (let i = minLineY; i < maxLineY; i++) {
|
|
8087
7905
|
const line = lines[i];
|
|
8088
|
-
const
|
|
8089
|
-
// TODO if lineCacheEnd matches the one before, skip tokenizing lines after
|
|
8090
|
-
lineCache[i + 1] = result;
|
|
8091
|
-
if (result.embeddedLanguage) {
|
|
8092
|
-
result.embeddedResultIndex = linesWithEmbed.length;
|
|
8093
|
-
linesWithEmbed.push(i);
|
|
8094
|
-
}
|
|
8095
|
-
}
|
|
8096
|
-
const visibleLines = lineCache.slice(startLineIndex + 1, endLineIndex + 1);
|
|
8097
|
-
if (linesWithEmbed.length > 0) {
|
|
7906
|
+
const normalize = shouldNormalizeText(line);
|
|
8098
7907
|
const {
|
|
8099
|
-
|
|
8100
|
-
|
|
8101
|
-
} =
|
|
8102
|
-
|
|
8103
|
-
|
|
8104
|
-
|
|
8105
|
-
tokens: visibleLines,
|
|
8106
|
-
tokenizersToLoad,
|
|
8107
|
-
embeddedResults
|
|
8108
|
-
};
|
|
7908
|
+
lineInfo,
|
|
7909
|
+
difference
|
|
7910
|
+
} = getLineInfo(line, tokens[i - minLineY], embeddedResults, decorations, tokenMap, offset, normalize, tabSize, width, deltaX, averageCharWidth);
|
|
7911
|
+
result.push(lineInfo);
|
|
7912
|
+
differences.push(difference);
|
|
7913
|
+
offset += line.length + 1;
|
|
8109
7914
|
}
|
|
8110
|
-
editor.invalidStartIndex = Math.max(invalidStartIndex, tokenizeEndIndex);
|
|
8111
7915
|
return {
|
|
8112
|
-
|
|
7916
|
+
result,
|
|
7917
|
+
differences
|
|
7918
|
+
};
|
|
7919
|
+
};
|
|
7920
|
+
const getVisible = async (editor, syncIncremental) => {
|
|
7921
|
+
// console.log({ editor })
|
|
7922
|
+
// TODO should separate rendering from business logic somehow
|
|
7923
|
+
// currently hard to test because need to mock editor height, top, left,
|
|
7924
|
+
// invalidStartIndex, lineCache, etc. just for testing editorType
|
|
7925
|
+
// editor.invalidStartIndex = changes[0].start.rowIndex
|
|
7926
|
+
// @ts-ignore
|
|
7927
|
+
const {
|
|
7928
|
+
minLineY,
|
|
7929
|
+
numberOfVisibleLines,
|
|
7930
|
+
lines,
|
|
7931
|
+
width,
|
|
7932
|
+
deltaX,
|
|
7933
|
+
fontWeight,
|
|
7934
|
+
fontSize,
|
|
7935
|
+
fontFamily,
|
|
7936
|
+
letterSpacing,
|
|
7937
|
+
charWidth
|
|
7938
|
+
} = editor;
|
|
7939
|
+
const maxLineY = Math.min(minLineY + numberOfVisibleLines, lines.length);
|
|
7940
|
+
const {
|
|
7941
|
+
tokens,
|
|
8113
7942
|
tokenizersToLoad,
|
|
8114
7943
|
embeddedResults
|
|
7944
|
+
} = await getTokensViewport2(editor, minLineY, maxLineY, syncIncremental);
|
|
7945
|
+
const minLineOffset = offsetAtSync(editor, minLineY, 0);
|
|
7946
|
+
const averageCharWidth = charWidth;
|
|
7947
|
+
const {
|
|
7948
|
+
result,
|
|
7949
|
+
differences
|
|
7950
|
+
} = getLineInfosViewport(editor, tokens, embeddedResults, minLineY, maxLineY, minLineOffset, width, deltaX, averageCharWidth);
|
|
7951
|
+
if (tokenizersToLoad.length > 0) {
|
|
7952
|
+
loadTokenizers(tokenizersToLoad);
|
|
7953
|
+
}
|
|
7954
|
+
return {
|
|
7955
|
+
textInfos: result,
|
|
7956
|
+
differences
|
|
8115
7957
|
};
|
|
8116
7958
|
};
|
|
8117
7959
|
|
|
8118
|
-
const
|
|
8119
|
-
|
|
8120
|
-
|
|
8121
|
-
|
|
8122
|
-
|
|
8123
|
-
|
|
8124
|
-
|
|
8125
|
-
|
|
8126
|
-
lines,
|
|
8127
|
-
languageId,
|
|
8128
|
-
id
|
|
8129
|
-
} = editor;
|
|
8130
|
-
let hasLinesToSend = true;
|
|
8131
|
-
let linesToSend = lines;
|
|
8132
|
-
if (sentLines[id] === lines) {
|
|
8133
|
-
hasLinesToSend = false;
|
|
8134
|
-
linesToSend = [];
|
|
8135
|
-
} else {
|
|
8136
|
-
sentLines[id] = lines;
|
|
8137
|
-
}
|
|
8138
|
-
const slimEditor = {
|
|
8139
|
-
languageId,
|
|
8140
|
-
invalidStartIndex
|
|
8141
|
-
};
|
|
8142
|
-
return invoke$1('GetTokensViewport.getTokensViewport', slimEditor, startLineIndex, endLineIndex, hasLinesToSend, id, linesToSend);
|
|
8143
|
-
}
|
|
8144
|
-
// TODO only send needed lines of text
|
|
8145
|
-
return invoke$1('GetTokensViewport.getTokensViewport', editor, startLineIndex, endLineIndex, true, editor.id, editor.lines);
|
|
7960
|
+
const getCursorsVirtualDom = cursors => {
|
|
7961
|
+
const dom = [];
|
|
7962
|
+
for (const translate of cursors) {
|
|
7963
|
+
dom.push({
|
|
7964
|
+
type: Div,
|
|
7965
|
+
className: EditorCursor,
|
|
7966
|
+
translate
|
|
7967
|
+
});
|
|
8146
7968
|
}
|
|
8147
|
-
return
|
|
7969
|
+
return dom;
|
|
8148
7970
|
};
|
|
8149
7971
|
|
|
8150
|
-
const
|
|
8151
|
-
|
|
8152
|
-
|
|
8153
|
-
|
|
7972
|
+
const Error$1 = 'error';
|
|
7973
|
+
const Warning = 'warning';
|
|
7974
|
+
|
|
7975
|
+
const getDiagnosticClassName = type => {
|
|
7976
|
+
// TODO use classnames enum
|
|
7977
|
+
switch (type) {
|
|
7978
|
+
case Error$1:
|
|
7979
|
+
return 'DiagnosticError';
|
|
7980
|
+
case Warning:
|
|
7981
|
+
return 'DiagnosticWarning';
|
|
7982
|
+
default:
|
|
7983
|
+
return 'DiagnosticError';
|
|
8154
7984
|
}
|
|
8155
7985
|
};
|
|
7986
|
+
const getDiagnosticVirtualDom = diagnostic => {
|
|
7987
|
+
const {
|
|
7988
|
+
x,
|
|
7989
|
+
y,
|
|
7990
|
+
width,
|
|
7991
|
+
height,
|
|
7992
|
+
type
|
|
7993
|
+
} = diagnostic;
|
|
7994
|
+
const extraClassName = getDiagnosticClassName(type);
|
|
7995
|
+
return [{
|
|
7996
|
+
type: Div,
|
|
7997
|
+
className: `${Diagnostic} ${extraClassName}`,
|
|
7998
|
+
width,
|
|
7999
|
+
height,
|
|
8000
|
+
top: y,
|
|
8001
|
+
left: x,
|
|
8002
|
+
childCount: 0
|
|
8003
|
+
}];
|
|
8004
|
+
};
|
|
8156
8005
|
|
|
8157
|
-
|
|
8158
|
-
|
|
8159
|
-
|
|
8160
|
-
|
|
8161
|
-
// let lineState = editor.tokenizer.initialLineState
|
|
8162
|
-
// for (let i = currentLength; i < max; i++) {
|
|
8163
|
-
// const line = lines[i]
|
|
8164
|
-
// try {
|
|
8165
|
-
// lineState = editor.tokenizer.tokenizeLine(line, lineState)
|
|
8166
|
-
// if (!lineState || !lineState.tokens || !lineState.state) {
|
|
8167
|
-
// throw new Error('invalid tokenization result')
|
|
8168
|
-
// }
|
|
8169
|
-
// } catch (error) {
|
|
8170
|
-
// tokens.push([{ length: line.length, type: 0 }])
|
|
8171
|
-
// console.error(error)
|
|
8172
|
-
// // renderWithoutSyntaxHighlighting(state, firstRow, lastRow)
|
|
8173
|
-
// continue
|
|
8174
|
-
// }
|
|
8175
|
-
// const newTokens = lineState.tokens
|
|
8176
|
-
// tokens.push(newTokens)
|
|
8177
|
-
// }
|
|
8178
|
-
// return tokens
|
|
8179
|
-
// }
|
|
8006
|
+
const getDiagnosticsVirtualDom = diagnostics => {
|
|
8007
|
+
const dom = diagnostics.flatMap(getDiagnosticVirtualDom);
|
|
8008
|
+
return dom;
|
|
8009
|
+
};
|
|
8180
8010
|
|
|
8181
|
-
|
|
8182
|
-
|
|
8183
|
-
|
|
8184
|
-
|
|
8185
|
-
|
|
8186
|
-
|
|
8187
|
-
|
|
8188
|
-
|
|
8189
|
-
|
|
8011
|
+
const getGutterInfoVirtualDom = gutterInfo => {
|
|
8012
|
+
return [{
|
|
8013
|
+
type: Span,
|
|
8014
|
+
className: 'LineNumber',
|
|
8015
|
+
childCount: 1
|
|
8016
|
+
}, text(gutterInfo)];
|
|
8017
|
+
};
|
|
8018
|
+
const getEditorGutterVirtualDom = gutterInfos => {
|
|
8019
|
+
const dom = gutterInfos.flatMap(getGutterInfoVirtualDom);
|
|
8020
|
+
return dom;
|
|
8021
|
+
};
|
|
8190
8022
|
|
|
8191
|
-
const
|
|
8192
|
-
|
|
8193
|
-
let
|
|
8194
|
-
|
|
8195
|
-
|
|
8196
|
-
|
|
8197
|
-
|
|
8198
|
-
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
|
|
8202
|
-
|
|
8203
|
-
|
|
8204
|
-
|
|
8023
|
+
const getEditorRowsVirtualDom = (textInfos, differences, lineNumbers = true) => {
|
|
8024
|
+
const dom = [];
|
|
8025
|
+
for (let i = 0; i < textInfos.length; i++) {
|
|
8026
|
+
const textInfo = textInfos[i];
|
|
8027
|
+
const difference = differences[i];
|
|
8028
|
+
dom.push({
|
|
8029
|
+
type: Div,
|
|
8030
|
+
className: EditorRow,
|
|
8031
|
+
translate: px(difference),
|
|
8032
|
+
childCount: textInfo.length / 2
|
|
8033
|
+
});
|
|
8034
|
+
for (let j = 0; j < textInfo.length; j += 2) {
|
|
8035
|
+
const tokenText = textInfo[j];
|
|
8036
|
+
const className = textInfo[j + 1];
|
|
8037
|
+
dom.push({
|
|
8038
|
+
type: Span,
|
|
8039
|
+
className,
|
|
8040
|
+
childCount: 1
|
|
8041
|
+
}, text(tokenText));
|
|
8205
8042
|
}
|
|
8206
8043
|
}
|
|
8207
|
-
return
|
|
8208
|
-
start,
|
|
8209
|
-
end,
|
|
8210
|
-
startIndex
|
|
8211
|
-
};
|
|
8044
|
+
return dom;
|
|
8212
8045
|
};
|
|
8213
|
-
|
|
8214
|
-
|
|
8215
|
-
|
|
8216
|
-
|
|
8217
|
-
|
|
8218
|
-
const
|
|
8219
|
-
|
|
8220
|
-
|
|
8221
|
-
|
|
8222
|
-
|
|
8223
|
-
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
|
|
8229
|
-
|
|
8230
|
-
const text = line.slice(start, end);
|
|
8231
|
-
const normalizedText = normalizeText(text, normalize, tabSize);
|
|
8232
|
-
lineInfo.push(normalizedText, className);
|
|
8233
|
-
start = end;
|
|
8234
|
-
if (end >= maxOffset) {
|
|
8235
|
-
break;
|
|
8046
|
+
|
|
8047
|
+
const getIncrementalEdits = async (oldState, newState) => {
|
|
8048
|
+
if (!newState.undoStack) {
|
|
8049
|
+
return undefined;
|
|
8050
|
+
}
|
|
8051
|
+
const lastChanges = newState.undoStack.at(-1);
|
|
8052
|
+
if (lastChanges && lastChanges.length === 1) {
|
|
8053
|
+
const lastChange = lastChanges[0];
|
|
8054
|
+
if (lastChange.origin === EditorType) {
|
|
8055
|
+
const rowIndex = lastChange.start.rowIndex;
|
|
8056
|
+
const lines = newState.lines;
|
|
8057
|
+
const oldLine = oldState.lines[rowIndex];
|
|
8058
|
+
const newLine = lines[rowIndex];
|
|
8059
|
+
const incrementalEdits = await invoke$1('TokenizeIncremental.tokenizeIncremental', newState.uid, newState.languageId, oldLine, newLine, rowIndex, newState.minLineY);
|
|
8060
|
+
if (incrementalEdits && incrementalEdits.length === 1) {
|
|
8061
|
+
return incrementalEdits;
|
|
8062
|
+
}
|
|
8236
8063
|
}
|
|
8237
8064
|
}
|
|
8065
|
+
return undefined;
|
|
8066
|
+
};
|
|
8067
|
+
|
|
8068
|
+
const getSelectionsVirtualDom = selections => {
|
|
8069
|
+
const dom = [];
|
|
8070
|
+
for (let i = 0; i < selections.length; i += 4) {
|
|
8071
|
+
const x = selections[i];
|
|
8072
|
+
const y = selections[i + 1];
|
|
8073
|
+
const width = selections[i + 2];
|
|
8074
|
+
const height = selections[i + 3];
|
|
8075
|
+
dom.push({
|
|
8076
|
+
type: Div,
|
|
8077
|
+
className: EditorSelection,
|
|
8078
|
+
left: x,
|
|
8079
|
+
top: y,
|
|
8080
|
+
width,
|
|
8081
|
+
height
|
|
8082
|
+
});
|
|
8083
|
+
}
|
|
8084
|
+
return dom;
|
|
8085
|
+
};
|
|
8086
|
+
|
|
8087
|
+
const None = 'none';
|
|
8088
|
+
const Option = 'option';
|
|
8089
|
+
|
|
8090
|
+
const getFileIconVirtualDom = icon => {
|
|
8238
8091
|
return {
|
|
8239
|
-
|
|
8240
|
-
|
|
8092
|
+
type: Img,
|
|
8093
|
+
className: FileIcon,
|
|
8094
|
+
src: icon,
|
|
8095
|
+
role: None,
|
|
8096
|
+
childCount: 0
|
|
8241
8097
|
};
|
|
8242
8098
|
};
|
|
8243
|
-
|
|
8244
|
-
|
|
8245
|
-
|
|
8246
|
-
|
|
8247
|
-
return {
|
|
8248
|
-
minOffset: 0,
|
|
8249
|
-
maxOffset: Math.ceil(width / averageCharWidth)
|
|
8250
|
-
};
|
|
8099
|
+
|
|
8100
|
+
const getIconDom = (fileIcon, symbolName) => {
|
|
8101
|
+
if (fileIcon) {
|
|
8102
|
+
return getFileIconVirtualDom(fileIcon);
|
|
8251
8103
|
}
|
|
8252
|
-
const minOffset = Math.ceil(deltaX / averageCharWidth);
|
|
8253
|
-
const maxOffset = minOffset + Math.ceil(width / averageCharWidth);
|
|
8254
8104
|
return {
|
|
8255
|
-
|
|
8256
|
-
|
|
8105
|
+
type: Div,
|
|
8106
|
+
className: `${ColoredMaskIcon} ${symbolName}`,
|
|
8107
|
+
childCount: 0
|
|
8257
8108
|
};
|
|
8258
8109
|
};
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8110
|
+
|
|
8111
|
+
const label1 = {
|
|
8112
|
+
type: Div,
|
|
8113
|
+
className: Label,
|
|
8114
|
+
childCount: 1
|
|
8263
8115
|
};
|
|
8264
|
-
const
|
|
8265
|
-
|
|
8266
|
-
|
|
8267
|
-
|
|
8268
|
-
|
|
8269
|
-
|
|
8270
|
-
|
|
8271
|
-
|
|
8116
|
+
const completionHighlight = {
|
|
8117
|
+
type: Span,
|
|
8118
|
+
className: EditorCompletionItemHighlight,
|
|
8119
|
+
childCount: 1
|
|
8120
|
+
};
|
|
8121
|
+
const getHighlightedLabelDom = (label, highlights) => {
|
|
8122
|
+
if (highlights.length === 0) {
|
|
8123
|
+
return [label1, text(label)];
|
|
8272
8124
|
}
|
|
8273
|
-
const
|
|
8274
|
-
|
|
8275
|
-
|
|
8276
|
-
|
|
8277
|
-
|
|
8278
|
-
}
|
|
8279
|
-
|
|
8280
|
-
|
|
8281
|
-
for (let i =
|
|
8282
|
-
const
|
|
8283
|
-
const
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
decorations[++decorationIndex];
|
|
8289
|
-
const decorationType = decorations[++decorationIndex];
|
|
8290
|
-
// @ts-ignore
|
|
8291
|
-
decorations[++decorationIndex];
|
|
8292
|
-
// console.log('MATCHING DECORATION', {
|
|
8293
|
-
// decorationIndex,
|
|
8294
|
-
// decorationLength,
|
|
8295
|
-
// decorationType,
|
|
8296
|
-
// decorationModifiers,
|
|
8297
|
-
// })
|
|
8298
|
-
extraClassName = getDecorationClassName(decorationType);
|
|
8299
|
-
}
|
|
8300
|
-
end += tokenLength;
|
|
8301
|
-
const text = line.slice(start, end);
|
|
8302
|
-
const className = `Token ${extraClassName || TokenMap[tokenType] || 'Unknown'}`;
|
|
8303
|
-
const normalizedText = normalizeText(text, normalize, tabSize);
|
|
8304
|
-
lineInfo.push(normalizedText, className);
|
|
8305
|
-
start = end;
|
|
8306
|
-
if (end >= maxOffset) {
|
|
8307
|
-
break;
|
|
8125
|
+
const dom = [];
|
|
8126
|
+
const labelDom = {
|
|
8127
|
+
type: Div,
|
|
8128
|
+
className: Label,
|
|
8129
|
+
childCount: 0
|
|
8130
|
+
};
|
|
8131
|
+
dom.push(labelDom);
|
|
8132
|
+
let position = 0;
|
|
8133
|
+
for (let i = 0; i < highlights.length; i += 2) {
|
|
8134
|
+
const highlightStart = highlights[i];
|
|
8135
|
+
const highlightEnd = highlights[i + 1];
|
|
8136
|
+
if (position < highlightStart) {
|
|
8137
|
+
const beforeText = label.slice(position, highlightStart);
|
|
8138
|
+
labelDom.childCount++;
|
|
8139
|
+
dom.push(text(beforeText));
|
|
8308
8140
|
}
|
|
8141
|
+
const highlightText = label.slice(highlightStart, highlightEnd);
|
|
8142
|
+
labelDom.childCount++;
|
|
8143
|
+
dom.push(completionHighlight, text(highlightText));
|
|
8144
|
+
position = highlightEnd;
|
|
8309
8145
|
}
|
|
8310
|
-
|
|
8311
|
-
|
|
8312
|
-
|
|
8313
|
-
|
|
8146
|
+
if (position < label.length) {
|
|
8147
|
+
const afterText = label.slice(position);
|
|
8148
|
+
labelDom.childCount++;
|
|
8149
|
+
dom.push(text(afterText));
|
|
8150
|
+
}
|
|
8151
|
+
return dom;
|
|
8314
8152
|
};
|
|
8315
|
-
|
|
8153
|
+
|
|
8154
|
+
const getCompletionItemVirtualDom = visibleItem => {
|
|
8316
8155
|
const {
|
|
8317
|
-
|
|
8318
|
-
|
|
8319
|
-
|
|
8320
|
-
|
|
8321
|
-
|
|
8322
|
-
|
|
8323
|
-
|
|
8324
|
-
|
|
8156
|
+
top,
|
|
8157
|
+
label,
|
|
8158
|
+
symbolName,
|
|
8159
|
+
highlights,
|
|
8160
|
+
focused,
|
|
8161
|
+
deprecated,
|
|
8162
|
+
fileIcon
|
|
8163
|
+
} = visibleItem;
|
|
8164
|
+
let className = EditorCompletionItem;
|
|
8165
|
+
if (focused) {
|
|
8166
|
+
className += ' ' + EditorCompletionItemFocused;
|
|
8325
8167
|
}
|
|
8326
|
-
|
|
8168
|
+
if (deprecated) {
|
|
8169
|
+
className += ' ' + EditorCompletionItemDeprecated;
|
|
8170
|
+
}
|
|
8171
|
+
return [{
|
|
8172
|
+
type: Div,
|
|
8173
|
+
role: Option,
|
|
8174
|
+
className,
|
|
8175
|
+
top,
|
|
8176
|
+
childCount: 2
|
|
8177
|
+
}, getIconDom(fileIcon, symbolName), ...getHighlightedLabelDom(label, highlights)];
|
|
8327
8178
|
};
|
|
8328
8179
|
|
|
8329
|
-
|
|
8330
|
-
|
|
8331
|
-
|
|
8332
|
-
|
|
8333
|
-
|
|
8334
|
-
|
|
8335
|
-
decorations,
|
|
8336
|
-
languageId
|
|
8337
|
-
} = editor;
|
|
8338
|
-
const tokenMap = get$1(languageId);
|
|
8339
|
-
let offset = minLineOffset;
|
|
8340
|
-
const tabSize = 2;
|
|
8341
|
-
for (let i = minLineY; i < maxLineY; i++) {
|
|
8342
|
-
const line = lines[i];
|
|
8343
|
-
const normalize = shouldNormalizeText(line);
|
|
8344
|
-
const {
|
|
8345
|
-
lineInfo,
|
|
8346
|
-
difference
|
|
8347
|
-
} = getLineInfo(line, tokens[i - minLineY], embeddedResults, decorations, tokenMap, offset, normalize, tabSize, width, deltaX, averageCharWidth);
|
|
8348
|
-
result.push(lineInfo);
|
|
8349
|
-
differences.push(difference);
|
|
8350
|
-
offset += line.length + 1;
|
|
8180
|
+
const getCompletionItemsVirtualDom = visibleItems => {
|
|
8181
|
+
if (visibleItems.length === 0) {
|
|
8182
|
+
return [{
|
|
8183
|
+
type: Div,
|
|
8184
|
+
childCount: 1
|
|
8185
|
+
}, text(noResults())];
|
|
8351
8186
|
}
|
|
8352
|
-
|
|
8353
|
-
|
|
8354
|
-
|
|
8187
|
+
const root = {
|
|
8188
|
+
type: Div,
|
|
8189
|
+
childCount: visibleItems.length
|
|
8355
8190
|
};
|
|
8191
|
+
const dom = [root, ...visibleItems.flatMap(getCompletionItemVirtualDom)];
|
|
8192
|
+
return dom;
|
|
8356
8193
|
};
|
|
8357
|
-
|
|
8358
|
-
|
|
8359
|
-
|
|
8360
|
-
|
|
8361
|
-
|
|
8362
|
-
|
|
8363
|
-
|
|
8364
|
-
|
|
8365
|
-
|
|
8366
|
-
|
|
8367
|
-
|
|
8368
|
-
|
|
8369
|
-
|
|
8370
|
-
|
|
8371
|
-
|
|
8372
|
-
|
|
8373
|
-
|
|
8374
|
-
|
|
8375
|
-
|
|
8376
|
-
|
|
8377
|
-
|
|
8378
|
-
|
|
8379
|
-
|
|
8380
|
-
|
|
8381
|
-
|
|
8382
|
-
|
|
8383
|
-
|
|
8384
|
-
|
|
8385
|
-
|
|
8386
|
-
|
|
8387
|
-
|
|
8388
|
-
|
|
8389
|
-
|
|
8194
|
+
|
|
8195
|
+
const Property = 1;
|
|
8196
|
+
const Value = 2;
|
|
8197
|
+
const Function = 3;
|
|
8198
|
+
const Variable = 4;
|
|
8199
|
+
const Keyword = 5;
|
|
8200
|
+
const Folder = 6;
|
|
8201
|
+
const File = 7;
|
|
8202
|
+
const Field = 8;
|
|
8203
|
+
|
|
8204
|
+
const SymbolProperty = 'SymbolProperty';
|
|
8205
|
+
const SymbolValue = 'SymbolValue';
|
|
8206
|
+
const SymbolFunction = 'SymbolFunction';
|
|
8207
|
+
const SymbolVariable = 'SymbolVariable';
|
|
8208
|
+
const SymbolKeyword = 'SymbolKeyword';
|
|
8209
|
+
const SymbolDefault = 'SymbolDefault';
|
|
8210
|
+
const SymbolField = 'SymbolField';
|
|
8211
|
+
const SymbolNone = '';
|
|
8212
|
+
|
|
8213
|
+
const getSymbolName = kind => {
|
|
8214
|
+
switch (kind) {
|
|
8215
|
+
case Property:
|
|
8216
|
+
return SymbolProperty;
|
|
8217
|
+
case Value:
|
|
8218
|
+
return SymbolValue;
|
|
8219
|
+
case Function:
|
|
8220
|
+
return SymbolFunction;
|
|
8221
|
+
case Variable:
|
|
8222
|
+
return SymbolVariable;
|
|
8223
|
+
case Keyword:
|
|
8224
|
+
return SymbolKeyword;
|
|
8225
|
+
case Field:
|
|
8226
|
+
return SymbolField;
|
|
8227
|
+
case File:
|
|
8228
|
+
return SymbolNone;
|
|
8229
|
+
default:
|
|
8230
|
+
return SymbolDefault;
|
|
8231
|
+
}
|
|
8232
|
+
};
|
|
8233
|
+
|
|
8234
|
+
// TODO
|
|
8235
|
+
const getCompletionFileIcon = kind => {
|
|
8236
|
+
switch (kind) {
|
|
8237
|
+
case File:
|
|
8238
|
+
return EmptyString;
|
|
8239
|
+
case Folder:
|
|
8240
|
+
return EmptyString;
|
|
8241
|
+
default:
|
|
8242
|
+
return EmptyString;
|
|
8390
8243
|
}
|
|
8244
|
+
};
|
|
8245
|
+
|
|
8246
|
+
const getHighlights = item => {
|
|
8247
|
+
const {
|
|
8248
|
+
matches
|
|
8249
|
+
} = item;
|
|
8250
|
+
return matches.slice(1);
|
|
8251
|
+
};
|
|
8252
|
+
|
|
8253
|
+
const getLabel = item => {
|
|
8254
|
+
return item.label;
|
|
8255
|
+
};
|
|
8256
|
+
const getVisibleIem = (item, itemHeight, leadingWord, i, focusedIndex) => {
|
|
8391
8257
|
return {
|
|
8392
|
-
|
|
8393
|
-
|
|
8258
|
+
label: getLabel(item),
|
|
8259
|
+
symbolName: getSymbolName(item.kind),
|
|
8260
|
+
top: i * itemHeight,
|
|
8261
|
+
highlights: getHighlights(item),
|
|
8262
|
+
focused: i === focusedIndex,
|
|
8263
|
+
deprecated: item.flags & Deprecated,
|
|
8264
|
+
fileIcon: getCompletionFileIcon(item.kind)
|
|
8394
8265
|
};
|
|
8395
8266
|
};
|
|
8396
8267
|
|
|
8397
|
-
const
|
|
8398
|
-
const
|
|
8399
|
-
for (
|
|
8400
|
-
|
|
8401
|
-
|
|
8402
|
-
className: EditorCursor,
|
|
8403
|
-
translate
|
|
8404
|
-
});
|
|
8268
|
+
const getVisibleItems = (filteredItems, itemHeight, leadingWord, minLineY, maxLineY, focusedIndex) => {
|
|
8269
|
+
const visibleItems = [];
|
|
8270
|
+
for (let i = minLineY; i < maxLineY; i++) {
|
|
8271
|
+
const filteredItem = filteredItems[i];
|
|
8272
|
+
visibleItems.push(getVisibleIem(filteredItem, itemHeight, leadingWord, i, focusedIndex));
|
|
8405
8273
|
}
|
|
8406
|
-
return
|
|
8274
|
+
return visibleItems;
|
|
8407
8275
|
};
|
|
8408
8276
|
|
|
8409
|
-
const
|
|
8410
|
-
|
|
8411
|
-
|
|
8412
|
-
|
|
8413
|
-
|
|
8414
|
-
|
|
8415
|
-
|
|
8416
|
-
|
|
8417
|
-
case Warning:
|
|
8418
|
-
return 'DiagnosticWarning';
|
|
8419
|
-
default:
|
|
8420
|
-
return 'DiagnosticError';
|
|
8277
|
+
const renderItems = {
|
|
8278
|
+
isEqual(oldState, newState) {
|
|
8279
|
+
return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.focusedIndex === newState.focusedIndex;
|
|
8280
|
+
},
|
|
8281
|
+
apply(oldState, newState) {
|
|
8282
|
+
const visibleItems = getVisibleItems(newState.items, newState.itemHeight, newState.leadingWord, newState.minLineY, newState.maxLineY, newState.focusedIndex);
|
|
8283
|
+
const dom = getCompletionItemsVirtualDom(visibleItems);
|
|
8284
|
+
return ['setDom', dom];
|
|
8421
8285
|
}
|
|
8422
8286
|
};
|
|
8423
|
-
const
|
|
8424
|
-
|
|
8425
|
-
x
|
|
8426
|
-
|
|
8427
|
-
|
|
8428
|
-
|
|
8429
|
-
|
|
8430
|
-
|
|
8431
|
-
|
|
8432
|
-
|
|
8433
|
-
|
|
8434
|
-
|
|
8435
|
-
|
|
8436
|
-
height,
|
|
8437
|
-
top: y,
|
|
8438
|
-
left: x,
|
|
8439
|
-
childCount: 0
|
|
8440
|
-
}];
|
|
8287
|
+
const renderBounds = {
|
|
8288
|
+
isEqual(oldState, newState) {
|
|
8289
|
+
return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.x === newState.x && oldState.y === newState.y;
|
|
8290
|
+
},
|
|
8291
|
+
apply(oldState, newState) {
|
|
8292
|
+
const {
|
|
8293
|
+
x,
|
|
8294
|
+
y,
|
|
8295
|
+
width,
|
|
8296
|
+
height
|
|
8297
|
+
} = newState;
|
|
8298
|
+
return [/* method */SetBounds, /* x */x, /* y */y, /* width */width, /* height */height];
|
|
8299
|
+
}
|
|
8441
8300
|
};
|
|
8442
|
-
|
|
8443
|
-
|
|
8444
|
-
|
|
8445
|
-
|
|
8301
|
+
const renderHeight = {
|
|
8302
|
+
isEqual(oldState, newState) {
|
|
8303
|
+
return oldState.items.length === newState.items.length;
|
|
8304
|
+
},
|
|
8305
|
+
apply(oldState, newState) {
|
|
8306
|
+
const {
|
|
8307
|
+
itemHeight
|
|
8308
|
+
} = newState;
|
|
8309
|
+
const contentHeight = newState.items.length * itemHeight;
|
|
8310
|
+
return [/* method */SetContentHeight, /* contentHeight */contentHeight];
|
|
8311
|
+
}
|
|
8446
8312
|
};
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
|
|
8453
|
-
}
|
|
8313
|
+
const renderNegativeMargin = {
|
|
8314
|
+
isEqual(oldState, newState) {
|
|
8315
|
+
return oldState.deltaY === newState.deltaY;
|
|
8316
|
+
},
|
|
8317
|
+
apply(oldState, newState) {
|
|
8318
|
+
return [/* method */SetNegativeMargin, /* negativeMargin */-newState.deltaY];
|
|
8319
|
+
}
|
|
8454
8320
|
};
|
|
8455
|
-
const
|
|
8456
|
-
|
|
8457
|
-
|
|
8321
|
+
const renderScrollBar = {
|
|
8322
|
+
isEqual(oldState, newState) {
|
|
8323
|
+
return oldState.negativeMargin === newState.negativeMargin && oldState.deltaY === newState.deltaY && oldState.height === newState.height && oldState.finalDeltaY === newState.finalDeltaY && oldState.items.length === newState.items.length;
|
|
8324
|
+
},
|
|
8325
|
+
apply(oldState, newState) {
|
|
8326
|
+
const total = newState.items.length;
|
|
8327
|
+
const contentHeight = total * newState.itemHeight;
|
|
8328
|
+
const scrollBarHeight = getScrollBarSize(newState.height, contentHeight, newState.minimumSliderSize);
|
|
8329
|
+
const scrollBarY = getScrollBarY(newState.deltaY, newState.finalDeltaY, newState.height - newState.headerHeight, scrollBarHeight);
|
|
8330
|
+
return [/* method */SetScrollBar, /* scrollBarY */scrollBarY, /* scrollBarHeight */scrollBarHeight];
|
|
8331
|
+
}
|
|
8458
8332
|
};
|
|
8459
|
-
|
|
8460
|
-
const
|
|
8461
|
-
const
|
|
8462
|
-
for (
|
|
8463
|
-
|
|
8464
|
-
|
|
8465
|
-
dom.push({
|
|
8466
|
-
type: Div,
|
|
8467
|
-
className: EditorRow,
|
|
8468
|
-
translate: px(difference),
|
|
8469
|
-
childCount: textInfo.length / 2
|
|
8470
|
-
});
|
|
8471
|
-
for (let j = 0; j < textInfo.length; j += 2) {
|
|
8472
|
-
const tokenText = textInfo[j];
|
|
8473
|
-
const className = textInfo[j + 1];
|
|
8474
|
-
dom.push({
|
|
8475
|
-
type: Span,
|
|
8476
|
-
className,
|
|
8477
|
-
childCount: 1
|
|
8478
|
-
}, text(tokenText));
|
|
8333
|
+
const render$2 = [renderItems, renderBounds, renderHeight, renderNegativeMargin, renderScrollBar];
|
|
8334
|
+
const renderCompletion = (oldState, newState) => {
|
|
8335
|
+
const commands = [];
|
|
8336
|
+
for (const item of render$2) {
|
|
8337
|
+
if (!item.isEqual(oldState, newState)) {
|
|
8338
|
+
commands.push(item.apply(oldState, newState));
|
|
8479
8339
|
}
|
|
8480
8340
|
}
|
|
8481
|
-
return
|
|
8341
|
+
return commands;
|
|
8482
8342
|
};
|
|
8483
8343
|
|
|
8484
|
-
const
|
|
8485
|
-
|
|
8486
|
-
|
|
8344
|
+
const render$1 = (oldState, newState) => {
|
|
8345
|
+
const commands = renderCompletion(oldState, newState);
|
|
8346
|
+
const wrappedCommands = [];
|
|
8347
|
+
const uid = newState.uid;
|
|
8348
|
+
for (const command of commands) {
|
|
8349
|
+
wrappedCommands.push(['Viewlet.send', uid, ...command]);
|
|
8487
8350
|
}
|
|
8488
|
-
|
|
8489
|
-
|
|
8490
|
-
|
|
8491
|
-
|
|
8492
|
-
|
|
8493
|
-
|
|
8494
|
-
|
|
8495
|
-
|
|
8496
|
-
|
|
8497
|
-
|
|
8498
|
-
|
|
8499
|
-
|
|
8500
|
-
|
|
8351
|
+
return wrappedCommands;
|
|
8352
|
+
};
|
|
8353
|
+
const add = widget => {
|
|
8354
|
+
const commands = render$1(widget.oldState, widget.newState);
|
|
8355
|
+
const id = 'EditorCompletion';
|
|
8356
|
+
// TODO how to generate a unique integer id
|
|
8357
|
+
// that doesn't collide with ids created in renderer worker?
|
|
8358
|
+
const uid = widget.newState.uid;
|
|
8359
|
+
const allCommands = [];
|
|
8360
|
+
allCommands.push(['Viewlet.create', id, uid]);
|
|
8361
|
+
allCommands.push(...commands);
|
|
8362
|
+
return allCommands;
|
|
8363
|
+
};
|
|
8364
|
+
const remove = widget => {
|
|
8365
|
+
return [['Viewlet.send', widget.newState.uid, 'dispose']];
|
|
8366
|
+
};
|
|
8367
|
+
const handleEditorType = (editor, state) => {
|
|
8368
|
+
const {
|
|
8369
|
+
unfilteredItems,
|
|
8370
|
+
itemHeight,
|
|
8371
|
+
maxHeight
|
|
8372
|
+
} = state;
|
|
8373
|
+
const {
|
|
8374
|
+
selections
|
|
8375
|
+
} = editor;
|
|
8376
|
+
const rowIndex = selections[0];
|
|
8377
|
+
const columnIndex = selections[1];
|
|
8378
|
+
const x$1 = x(editor, rowIndex, columnIndex);
|
|
8379
|
+
const y$1 = y(editor, rowIndex);
|
|
8380
|
+
const wordAtOffset = getWordBefore(editor, rowIndex, columnIndex);
|
|
8381
|
+
const items = filterCompletionItems(unfilteredItems, wordAtOffset);
|
|
8382
|
+
const newMinLineY = 0;
|
|
8383
|
+
const newMaxLineY = Math.min(items.length, 8);
|
|
8384
|
+
const height = getListHeight(items.length, itemHeight, maxHeight);
|
|
8385
|
+
const finalDeltaY = items.length * itemHeight - height;
|
|
8386
|
+
return {
|
|
8387
|
+
...state,
|
|
8388
|
+
items,
|
|
8389
|
+
x: x$1,
|
|
8390
|
+
y: y$1,
|
|
8391
|
+
minLineY: newMinLineY,
|
|
8392
|
+
maxLineY: newMaxLineY,
|
|
8393
|
+
leadingWord: wordAtOffset,
|
|
8394
|
+
height,
|
|
8395
|
+
finalDeltaY
|
|
8396
|
+
};
|
|
8397
|
+
};
|
|
8398
|
+
const handleEditorDeleteLeft = (editor, state) => {
|
|
8399
|
+
const {
|
|
8400
|
+
unfilteredItems,
|
|
8401
|
+
itemHeight,
|
|
8402
|
+
maxHeight
|
|
8403
|
+
} = state;
|
|
8404
|
+
const {
|
|
8405
|
+
selections
|
|
8406
|
+
} = editor;
|
|
8407
|
+
const rowIndex = selections[0];
|
|
8408
|
+
const columnIndex = selections[1];
|
|
8409
|
+
const x$1 = x(editor, rowIndex, columnIndex);
|
|
8410
|
+
const y$1 = y(editor, rowIndex);
|
|
8411
|
+
const wordAtOffset = getWordBefore(editor, rowIndex, columnIndex);
|
|
8412
|
+
if (!wordAtOffset) {
|
|
8413
|
+
return undefined;
|
|
8501
8414
|
}
|
|
8502
|
-
|
|
8415
|
+
const items = filterCompletionItems(unfilteredItems, wordAtOffset);
|
|
8416
|
+
const newMaxLineY = Math.min(items.length, 8);
|
|
8417
|
+
const height = getListHeight(items.length, itemHeight, maxHeight);
|
|
8418
|
+
return {
|
|
8419
|
+
...state,
|
|
8420
|
+
items,
|
|
8421
|
+
x: x$1,
|
|
8422
|
+
y: y$1,
|
|
8423
|
+
maxLineY: newMaxLineY,
|
|
8424
|
+
leadingWord: wordAtOffset,
|
|
8425
|
+
height
|
|
8426
|
+
};
|
|
8503
8427
|
};
|
|
8504
8428
|
|
|
8505
|
-
const
|
|
8506
|
-
|
|
8507
|
-
|
|
8508
|
-
|
|
8509
|
-
|
|
8510
|
-
|
|
8511
|
-
|
|
8512
|
-
dom.push({
|
|
8513
|
-
type: Div,
|
|
8514
|
-
className: EditorSelection,
|
|
8515
|
-
left: x,
|
|
8516
|
-
top: y,
|
|
8517
|
-
width,
|
|
8518
|
-
height
|
|
8519
|
-
});
|
|
8520
|
-
}
|
|
8521
|
-
return dom;
|
|
8429
|
+
const EditorCompletionWidget = {
|
|
8430
|
+
__proto__: null,
|
|
8431
|
+
add,
|
|
8432
|
+
handleEditorDeleteLeft,
|
|
8433
|
+
handleEditorType,
|
|
8434
|
+
remove,
|
|
8435
|
+
render: render$1
|
|
8522
8436
|
};
|
|
8523
8437
|
|
|
8524
8438
|
const addWidget = widget => {
|
|
@@ -8538,7 +8452,7 @@ const renderWidget = widget => {
|
|
|
8538
8452
|
} = widget;
|
|
8539
8453
|
switch (id) {
|
|
8540
8454
|
case Completion:
|
|
8541
|
-
return render$
|
|
8455
|
+
return render$1(widget.oldState, widget.newState);
|
|
8542
8456
|
default:
|
|
8543
8457
|
throw new Error(`unsupported widget`);
|
|
8544
8458
|
}
|
|
@@ -8549,7 +8463,7 @@ const removeWidget = widget => {
|
|
|
8549
8463
|
} = widget;
|
|
8550
8464
|
switch (id) {
|
|
8551
8465
|
case Completion:
|
|
8552
|
-
return remove
|
|
8466
|
+
return remove(widget);
|
|
8553
8467
|
default:
|
|
8554
8468
|
throw new Error('unsupported widget');
|
|
8555
8469
|
}
|
|
@@ -8897,8 +8811,8 @@ const commandMap = {
|
|
|
8897
8811
|
'EditorCompletion.focusPrevious': focusPrevious$1,
|
|
8898
8812
|
'EditorCompletion.handleEditorBlur': handleEditorBlur,
|
|
8899
8813
|
'EditorCompletion.handleEditorClick': handleEditorClick,
|
|
8900
|
-
'EditorCompletion.handleEditorDeleteLeft': handleEditorDeleteLeft,
|
|
8901
|
-
'EditorCompletion.handleEditorType': handleEditorType,
|
|
8814
|
+
'EditorCompletion.handleEditorDeleteLeft': handleEditorDeleteLeft$1,
|
|
8815
|
+
'EditorCompletion.handleEditorType': handleEditorType$1,
|
|
8902
8816
|
'EditorCompletion.loadContent': loadContent$2,
|
|
8903
8817
|
'EditorCompletion.selectCurrent': selectCurrent,
|
|
8904
8818
|
'EditorCompletion.selectIndex': selectIndex,
|