@lvce-editor/editor-worker 2.3.0 → 2.5.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 +7 -1
- package/dist/editorWorkerMain.js +1726 -1864
- 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,15 @@ 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 DoubleQuote$1 = '"';
|
|
565
|
+
const T = 't';
|
|
566
|
+
|
|
1524
567
|
const getTabCount = string => {
|
|
1525
568
|
let count = 0;
|
|
1526
569
|
for (const element of string) {
|
|
@@ -1531,8 +574,74 @@ const getTabCount = string => {
|
|
|
1531
574
|
return count;
|
|
1532
575
|
};
|
|
1533
576
|
|
|
1534
|
-
|
|
1535
|
-
|
|
577
|
+
const getFontString = (fontWeight, fontSize, fontFamily) => {
|
|
578
|
+
return `${fontWeight} ${fontSize}px ${fontFamily}`;
|
|
579
|
+
};
|
|
580
|
+
|
|
581
|
+
const getLetterSpacingString = letterSpacing => {
|
|
582
|
+
return `${letterSpacing}px`;
|
|
583
|
+
};
|
|
584
|
+
|
|
585
|
+
const createMeasureContext = () => {
|
|
586
|
+
const canvas = new OffscreenCanvas(0, 0);
|
|
587
|
+
const ctx = /** @type {OffscreenCanvasRenderingContext2D} */canvas.getContext('2d');
|
|
588
|
+
if (!ctx) {
|
|
589
|
+
throw new Error('Failed to get canvas context 2d');
|
|
590
|
+
}
|
|
591
|
+
return ctx;
|
|
592
|
+
};
|
|
593
|
+
|
|
594
|
+
const state$b = {
|
|
595
|
+
ctx: undefined
|
|
596
|
+
};
|
|
597
|
+
const getOrCreate = createCtx => {
|
|
598
|
+
if (state$b.ctx) {
|
|
599
|
+
return state$b.ctx;
|
|
600
|
+
}
|
|
601
|
+
state$b.ctx = createCtx();
|
|
602
|
+
return state$b.ctx;
|
|
603
|
+
};
|
|
604
|
+
|
|
605
|
+
const getContext = () => {
|
|
606
|
+
const ctx = getOrCreate(createMeasureContext);
|
|
607
|
+
return ctx;
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
const measureTextWidth = (text, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth) => {
|
|
611
|
+
string(text);
|
|
612
|
+
number$1(fontWeight);
|
|
613
|
+
number$1(fontSize);
|
|
614
|
+
string(fontFamily);
|
|
615
|
+
boolean(isMonoSpaceFont);
|
|
616
|
+
number$1(charWidth);
|
|
617
|
+
if (isMonoSpaceFont) {
|
|
618
|
+
return text.length * charWidth;
|
|
619
|
+
}
|
|
620
|
+
if (typeof letterSpacing !== 'number') {
|
|
621
|
+
throw new TypeError('letterSpacing must be of type number');
|
|
622
|
+
}
|
|
623
|
+
const letterSpacingString = getLetterSpacingString(letterSpacing);
|
|
624
|
+
const fontString = getFontString(fontWeight, fontSize, fontFamily);
|
|
625
|
+
const ctx = getContext();
|
|
626
|
+
// @ts-ignore
|
|
627
|
+
ctx.letterSpacing = letterSpacingString;
|
|
628
|
+
// @ts-ignore
|
|
629
|
+
ctx.font = fontString;
|
|
630
|
+
// @ts-ignore
|
|
631
|
+
const metrics = ctx.measureText(text);
|
|
632
|
+
const width = metrics.width;
|
|
633
|
+
return width;
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
const normalizeText = (text, normalize, tabSize) => {
|
|
637
|
+
if (normalize) {
|
|
638
|
+
return text.replaceAll(Tab, Space.repeat(tabSize));
|
|
639
|
+
}
|
|
640
|
+
return text;
|
|
641
|
+
};
|
|
642
|
+
const shouldNormalizeText = text => {
|
|
643
|
+
return text.includes(Tab);
|
|
644
|
+
};
|
|
1536
645
|
|
|
1537
646
|
const getX = (line, column, fontWeight, fontSize, fontFamily, isMonospaceFont, letterSpacing, tabSize, halfCursorWidth, width, averageCharWidth, difference = 0) => {
|
|
1538
647
|
if (!line) {
|
|
@@ -1558,6 +667,7 @@ const getX = (line, column, fontWeight, fontSize, fontFamily, isMonospaceFont, l
|
|
|
1558
667
|
const partialText = normalizedLine.slice(0, column + tabCount);
|
|
1559
668
|
return measureTextWidth(partialText, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, averageCharWidth) - halfCursorWidth + difference;
|
|
1560
669
|
};
|
|
670
|
+
|
|
1561
671
|
const getY = (row, minLineY, rowHeight) => {
|
|
1562
672
|
return (row - minLineY) * rowHeight;
|
|
1563
673
|
};
|
|
@@ -2067,7 +1177,7 @@ const set$5 = (id, fn) => {
|
|
|
2067
1177
|
const get$5 = id => {
|
|
2068
1178
|
return state$1$1.callbacks[id];
|
|
2069
1179
|
};
|
|
2070
|
-
const remove = id => {
|
|
1180
|
+
const remove$1 = id => {
|
|
2071
1181
|
delete state$1$1.callbacks[id];
|
|
2072
1182
|
};
|
|
2073
1183
|
const state$a = {
|
|
@@ -2113,7 +1223,7 @@ const resolve = (id, args) => {
|
|
|
2113
1223
|
return;
|
|
2114
1224
|
}
|
|
2115
1225
|
fn(args);
|
|
2116
|
-
remove(id);
|
|
1226
|
+
remove$1(id);
|
|
2117
1227
|
};
|
|
2118
1228
|
const create$2$1 = (method, params) => {
|
|
2119
1229
|
const {
|
|
@@ -2298,7 +1408,7 @@ const getErrorResponse = (message, error, preparePrettyError, logError) => {
|
|
|
2298
1408
|
const errorProperty = getErrorProperty(error, prettyError);
|
|
2299
1409
|
return create$1$1(message, errorProperty);
|
|
2300
1410
|
};
|
|
2301
|
-
const create$
|
|
1411
|
+
const create$5 = (message, result) => {
|
|
2302
1412
|
return {
|
|
2303
1413
|
jsonrpc: Two,
|
|
2304
1414
|
id: message.id,
|
|
@@ -2307,7 +1417,7 @@ const create$4 = (message, result) => {
|
|
|
2307
1417
|
};
|
|
2308
1418
|
const getSuccessResponse = (message, result) => {
|
|
2309
1419
|
const resultProperty = result ?? null;
|
|
2310
|
-
return create$
|
|
1420
|
+
return create$5(message, resultProperty);
|
|
2311
1421
|
};
|
|
2312
1422
|
const getResponse = async (message, ipc, execute, preparePrettyError, logError, requiresSocket) => {
|
|
2313
1423
|
try {
|
|
@@ -2504,7 +1614,7 @@ const waitForFirstMessage$1 = async port => {
|
|
|
2504
1614
|
return event;
|
|
2505
1615
|
};
|
|
2506
1616
|
|
|
2507
|
-
const create$
|
|
1617
|
+
const create$4 = async () => {
|
|
2508
1618
|
const {
|
|
2509
1619
|
port1,
|
|
2510
1620
|
port2
|
|
@@ -2549,7 +1659,7 @@ const wrap$3 = port => {
|
|
|
2549
1659
|
|
|
2550
1660
|
const IpcParentWithExtensionHostWorker = {
|
|
2551
1661
|
__proto__: null,
|
|
2552
|
-
create: create$
|
|
1662
|
+
create: create$4,
|
|
2553
1663
|
wrap: wrap$3
|
|
2554
1664
|
};
|
|
2555
1665
|
|
|
@@ -2557,7 +1667,7 @@ const sendMessagePortToSyntaxHighlightingWorker = async port => {
|
|
|
2557
1667
|
await invokeAndTransfer([port], 'SendMessagePortToSyntaxHighlightingWorker.sendMessagePortToSyntaxHighlightingWorker', port, 'HandleMessagePort.handleMessagePort');
|
|
2558
1668
|
};
|
|
2559
1669
|
|
|
2560
|
-
const create$
|
|
1670
|
+
const create$3 = async () => {
|
|
2561
1671
|
const {
|
|
2562
1672
|
port1,
|
|
2563
1673
|
port2
|
|
@@ -2602,7 +1712,7 @@ const wrap$1 = port => {
|
|
|
2602
1712
|
|
|
2603
1713
|
const IpcParentWithSyntaxHighlightingWorker = {
|
|
2604
1714
|
__proto__: null,
|
|
2605
|
-
create: create$
|
|
1715
|
+
create: create$3,
|
|
2606
1716
|
wrap: wrap$1
|
|
2607
1717
|
};
|
|
2608
1718
|
|
|
@@ -2610,7 +1720,7 @@ const sendMessagePortToRendererProcess = async port => {
|
|
|
2610
1720
|
await invokeAndTransfer([port], 'SendMessagePortToRendererProcess.sendMessagePortToRendererProcess', port, 'HandleMessagePort.handleMessagePort');
|
|
2611
1721
|
};
|
|
2612
1722
|
|
|
2613
|
-
const create$
|
|
1723
|
+
const create$2 = async () => {
|
|
2614
1724
|
const {
|
|
2615
1725
|
port1,
|
|
2616
1726
|
port2
|
|
@@ -2655,7 +1765,7 @@ const wrap = port => {
|
|
|
2655
1765
|
|
|
2656
1766
|
const IpcParentWithRendererProcess = {
|
|
2657
1767
|
__proto__: null,
|
|
2658
|
-
create: create$
|
|
1768
|
+
create: create$2,
|
|
2659
1769
|
wrap
|
|
2660
1770
|
};
|
|
2661
1771
|
|
|
@@ -2672,7 +1782,7 @@ const getModule$1 = method => {
|
|
|
2672
1782
|
}
|
|
2673
1783
|
};
|
|
2674
1784
|
|
|
2675
|
-
const create = async ({
|
|
1785
|
+
const create$1 = async ({
|
|
2676
1786
|
method,
|
|
2677
1787
|
...options
|
|
2678
1788
|
}) => {
|
|
@@ -2690,7 +1800,7 @@ const create = async ({
|
|
|
2690
1800
|
const createRpc = method => {
|
|
2691
1801
|
let _ipc;
|
|
2692
1802
|
const listen = async () => {
|
|
2693
|
-
const ipc = await create({
|
|
1803
|
+
const ipc = await create$1({
|
|
2694
1804
|
method
|
|
2695
1805
|
});
|
|
2696
1806
|
handleIpc(ipc);
|
|
@@ -2860,98 +1970,272 @@ const getNewSelections$d = selections => {
|
|
|
2860
1970
|
};
|
|
2861
1971
|
|
|
2862
1972
|
// @ts-ignore
|
|
2863
|
-
const addCursorAbove = editor => {
|
|
2864
|
-
const {
|
|
2865
|
-
selections
|
|
2866
|
-
} = editor;
|
|
2867
|
-
const newSelections = getNewSelections$d(selections);
|
|
2868
|
-
return {
|
|
2869
|
-
...editor,
|
|
2870
|
-
selections: newSelections
|
|
2871
|
-
};
|
|
1973
|
+
const addCursorAbove = editor => {
|
|
1974
|
+
const {
|
|
1975
|
+
selections
|
|
1976
|
+
} = editor;
|
|
1977
|
+
const newSelections = getNewSelections$d(selections);
|
|
1978
|
+
return {
|
|
1979
|
+
...editor,
|
|
1980
|
+
selections: newSelections
|
|
1981
|
+
};
|
|
1982
|
+
};
|
|
1983
|
+
|
|
1984
|
+
// @ts-ignore
|
|
1985
|
+
const getNewSelections$c = (selections, linesLength) => {
|
|
1986
|
+
const newSelections = [];
|
|
1987
|
+
for (let i = 0; i < selections.length; i += 4) {
|
|
1988
|
+
const startRowIndex = selections[i];
|
|
1989
|
+
const startColumnIndex = selections[i + 1];
|
|
1990
|
+
const endRowIndex = selections[i + 2];
|
|
1991
|
+
const endColumnIndex = selections[i + 3];
|
|
1992
|
+
newSelections.push(startRowIndex, startColumnIndex, endRowIndex, endColumnIndex);
|
|
1993
|
+
if (i === selections.length - 4 && endRowIndex < linesLength) {
|
|
1994
|
+
newSelections.push(endRowIndex + 1, endColumnIndex, endRowIndex + 1, endColumnIndex);
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
return new Uint32Array(newSelections);
|
|
1998
|
+
};
|
|
1999
|
+
|
|
2000
|
+
// @ts-ignore
|
|
2001
|
+
const addCursorBelow = editor => {
|
|
2002
|
+
const {
|
|
2003
|
+
selections,
|
|
2004
|
+
lines
|
|
2005
|
+
} = editor;
|
|
2006
|
+
const newSelections = getNewSelections$c(selections, lines.length);
|
|
2007
|
+
return {
|
|
2008
|
+
...editor,
|
|
2009
|
+
selections: newSelections
|
|
2010
|
+
};
|
|
2011
|
+
};
|
|
2012
|
+
|
|
2013
|
+
const applyEdit = async (editor, changes) => {
|
|
2014
|
+
object(editor);
|
|
2015
|
+
array(changes);
|
|
2016
|
+
return scheduleDocumentAndCursorsSelections(editor, changes);
|
|
2017
|
+
};
|
|
2018
|
+
|
|
2019
|
+
const handleBlur = editor => {
|
|
2020
|
+
// for (const listener of state.blurListeners) {
|
|
2021
|
+
// listener(editor)
|
|
2022
|
+
// }
|
|
2023
|
+
// TODO save on blur
|
|
2024
|
+
// Command.execute(/* Main.save */ 89)
|
|
2025
|
+
const newEditor = {
|
|
2026
|
+
...editor,
|
|
2027
|
+
focused: false
|
|
2028
|
+
};
|
|
2029
|
+
return newEditor;
|
|
2030
|
+
};
|
|
2031
|
+
|
|
2032
|
+
const replaceRange = (editor, ranges, replacement, origin) => {
|
|
2033
|
+
const changes = [];
|
|
2034
|
+
const rangesLength = ranges.length;
|
|
2035
|
+
for (let i = 0; i < rangesLength; i += 4) {
|
|
2036
|
+
const [selectionStartRow, selectionStartColumn, selectionEndRow, selectionEndColumn] = getSelectionPairs(ranges, i);
|
|
2037
|
+
const start = {
|
|
2038
|
+
rowIndex: selectionStartRow,
|
|
2039
|
+
columnIndex: selectionStartColumn
|
|
2040
|
+
};
|
|
2041
|
+
const end = {
|
|
2042
|
+
rowIndex: selectionEndRow,
|
|
2043
|
+
columnIndex: selectionEndColumn
|
|
2044
|
+
};
|
|
2045
|
+
const selection = {
|
|
2046
|
+
start,
|
|
2047
|
+
end
|
|
2048
|
+
};
|
|
2049
|
+
changes.push({
|
|
2050
|
+
start: start,
|
|
2051
|
+
end: end,
|
|
2052
|
+
inserted: replacement,
|
|
2053
|
+
deleted: getSelectionText(editor, selection),
|
|
2054
|
+
origin
|
|
2055
|
+
});
|
|
2056
|
+
}
|
|
2057
|
+
return changes;
|
|
2058
|
+
};
|
|
2059
|
+
|
|
2060
|
+
const editorReplaceSelections = (editor, replacement, origin) => {
|
|
2061
|
+
const {
|
|
2062
|
+
selections
|
|
2063
|
+
} = editor;
|
|
2064
|
+
return replaceRange(editor, selections, replacement, origin);
|
|
2065
|
+
};
|
|
2066
|
+
|
|
2067
|
+
const getAccurateColumnIndexAscii = (line, guess, averageCharWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth) => {
|
|
2068
|
+
for (let i = guess; i < line.length; i++) {
|
|
2069
|
+
const width = measureTextWidth(line.slice(0, i), fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
|
|
2070
|
+
if (eventX - width < averageCharWidth / 2) {
|
|
2071
|
+
return i;
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
return line.length;
|
|
2075
|
+
};
|
|
2076
|
+
|
|
2077
|
+
const supported = () => {
|
|
2078
|
+
return 'Segmenter' in Intl;
|
|
2079
|
+
};
|
|
2080
|
+
const create = () => {
|
|
2081
|
+
// @ts-ignore
|
|
2082
|
+
const segmenter = new Intl.Segmenter();
|
|
2083
|
+
return {
|
|
2084
|
+
at(line, index) {
|
|
2085
|
+
const segments = segmenter.segment(line);
|
|
2086
|
+
return segments.containing(index);
|
|
2087
|
+
},
|
|
2088
|
+
visualIndex(line, index) {
|
|
2089
|
+
const segments = segmenter.segment(line);
|
|
2090
|
+
let currentVisualIndex = 0;
|
|
2091
|
+
for (const segment of segments) {
|
|
2092
|
+
if (segment.index >= index) {
|
|
2093
|
+
return currentVisualIndex;
|
|
2094
|
+
}
|
|
2095
|
+
currentVisualIndex++;
|
|
2096
|
+
}
|
|
2097
|
+
return currentVisualIndex;
|
|
2098
|
+
},
|
|
2099
|
+
modelIndex(line, visualIndex) {
|
|
2100
|
+
const segments = segmenter.segment(line);
|
|
2101
|
+
let currentVisualIndex = 0;
|
|
2102
|
+
for (const segment of segments) {
|
|
2103
|
+
if (currentVisualIndex >= visualIndex) {
|
|
2104
|
+
return segment.index;
|
|
2105
|
+
}
|
|
2106
|
+
currentVisualIndex++;
|
|
2107
|
+
}
|
|
2108
|
+
return line.length;
|
|
2109
|
+
},
|
|
2110
|
+
getSegments(line) {
|
|
2111
|
+
return segmenter.segment(line);
|
|
2112
|
+
}
|
|
2113
|
+
};
|
|
2114
|
+
};
|
|
2115
|
+
|
|
2116
|
+
// @ts-ignore
|
|
2117
|
+
const getAccurateColumnIndexUnicode = (line, guess, averageCharWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing) => {
|
|
2118
|
+
const segmenter = create();
|
|
2119
|
+
const segments = segmenter.getSegments(line);
|
|
2120
|
+
const isMonospaceFont = false;
|
|
2121
|
+
const charWidth = 0;
|
|
2122
|
+
for (const segment of segments) {
|
|
2123
|
+
const width = measureTextWidth(line.slice(0, segment.index), fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
|
|
2124
|
+
if (eventX - width < averageCharWidth) {
|
|
2125
|
+
return segment.index;
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
return line.length;
|
|
2129
|
+
};
|
|
2130
|
+
|
|
2131
|
+
const RE_ASCII = /^[\p{ASCII}]*$/u;
|
|
2132
|
+
const isAscii = line => {
|
|
2133
|
+
return RE_ASCII.test(line);
|
|
2134
|
+
};
|
|
2135
|
+
|
|
2136
|
+
// @ts-ignore
|
|
2137
|
+
const guessOffset = (eventX, averageCharWidth) => {
|
|
2138
|
+
const guess = Math.round(eventX / averageCharWidth);
|
|
2139
|
+
return guess;
|
|
2140
|
+
};
|
|
2141
|
+
|
|
2142
|
+
// @ts-ignore
|
|
2143
|
+
const normalizeGuess = (line, guess, tabSize) => {
|
|
2144
|
+
let normalizedGuess = guess;
|
|
2145
|
+
for (let i = 0; i < guess; i++) {
|
|
2146
|
+
if (line[i] === Tab) {
|
|
2147
|
+
normalizedGuess -= tabSize - 1;
|
|
2148
|
+
}
|
|
2149
|
+
}
|
|
2150
|
+
return normalizedGuess;
|
|
2872
2151
|
};
|
|
2873
2152
|
|
|
2874
2153
|
// @ts-ignore
|
|
2875
|
-
const
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2154
|
+
const getAccurateColumnIndex = (line, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth, tabSize, eventX) => {
|
|
2155
|
+
string(line);
|
|
2156
|
+
number$1(fontWeight);
|
|
2157
|
+
number$1(fontSize);
|
|
2158
|
+
string(fontFamily);
|
|
2159
|
+
number$1(letterSpacing);
|
|
2160
|
+
boolean(isMonospaceFont);
|
|
2161
|
+
number$1(charWidth);
|
|
2162
|
+
number$1(tabSize);
|
|
2163
|
+
number$1(eventX);
|
|
2164
|
+
// Assert.greaterZero(charWidth)
|
|
2165
|
+
const guess = guessOffset(eventX, charWidth);
|
|
2166
|
+
const normalize = shouldNormalizeText(line);
|
|
2167
|
+
const normalizedGuess = normalizeGuess(line, guess, tabSize);
|
|
2168
|
+
const text = line.slice(0, normalizedGuess);
|
|
2169
|
+
const normalizedText = normalizeText(text, normalize, tabSize);
|
|
2170
|
+
const actual = measureTextWidth(normalizedText, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
|
|
2171
|
+
const isAscii$1 = isAscii(line);
|
|
2172
|
+
if (isAscii$1) {
|
|
2173
|
+
if (Math.abs(eventX - actual) < charWidth / 2) {
|
|
2174
|
+
return normalizedGuess;
|
|
2885
2175
|
}
|
|
2176
|
+
return getAccurateColumnIndexAscii(line, normalizedGuess, charWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
|
|
2886
2177
|
}
|
|
2887
|
-
return
|
|
2178
|
+
return getAccurateColumnIndexUnicode(line, normalizedGuess, charWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing);
|
|
2888
2179
|
};
|
|
2889
2180
|
|
|
2890
|
-
|
|
2891
|
-
|
|
2181
|
+
const at = (editor, eventX, eventY) => {
|
|
2182
|
+
object(editor);
|
|
2183
|
+
number$1(eventX);
|
|
2184
|
+
number$1(eventY);
|
|
2892
2185
|
const {
|
|
2893
|
-
|
|
2894
|
-
|
|
2186
|
+
y,
|
|
2187
|
+
deltaY,
|
|
2188
|
+
rowHeight,
|
|
2189
|
+
fontSize,
|
|
2190
|
+
fontWeight,
|
|
2191
|
+
fontFamily,
|
|
2192
|
+
letterSpacing,
|
|
2193
|
+
lines,
|
|
2194
|
+
tabSize,
|
|
2195
|
+
differences,
|
|
2196
|
+
isMonospaceFont,
|
|
2197
|
+
charWidth
|
|
2895
2198
|
} = editor;
|
|
2896
|
-
const
|
|
2199
|
+
const rowIndex = Math.floor((eventY - y + deltaY) / rowHeight);
|
|
2200
|
+
if (rowIndex < 0) {
|
|
2201
|
+
return {
|
|
2202
|
+
rowIndex: 0,
|
|
2203
|
+
columnIndex: 0
|
|
2204
|
+
};
|
|
2205
|
+
}
|
|
2206
|
+
const clampedRowIndex = clamp(rowIndex, 0, lines.length - 1);
|
|
2207
|
+
const line = lines[clampedRowIndex];
|
|
2208
|
+
const columnIndex = getAccurateColumnIndex(line, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth, tabSize, eventX);
|
|
2897
2209
|
return {
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
};
|
|
2901
|
-
};
|
|
2902
|
-
|
|
2903
|
-
const applyEdit = async (editor, changes) => {
|
|
2904
|
-
object(editor);
|
|
2905
|
-
array(changes);
|
|
2906
|
-
return scheduleDocumentAndCursorsSelections(editor, changes);
|
|
2907
|
-
};
|
|
2908
|
-
|
|
2909
|
-
const handleBlur = editor => {
|
|
2910
|
-
// for (const listener of state.blurListeners) {
|
|
2911
|
-
// listener(editor)
|
|
2912
|
-
// }
|
|
2913
|
-
// TODO save on blur
|
|
2914
|
-
// Command.execute(/* Main.save */ 89)
|
|
2915
|
-
const newEditor = {
|
|
2916
|
-
...editor,
|
|
2917
|
-
focused: false
|
|
2210
|
+
rowIndex: clampedRowIndex,
|
|
2211
|
+
columnIndex
|
|
2918
2212
|
};
|
|
2919
|
-
return newEditor;
|
|
2920
2213
|
};
|
|
2921
2214
|
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
};
|
|
2939
|
-
changes.push({
|
|
2940
|
-
start: start,
|
|
2941
|
-
end: end,
|
|
2942
|
-
inserted: replacement,
|
|
2943
|
-
deleted: getSelectionText(editor, selection),
|
|
2944
|
-
origin
|
|
2945
|
-
});
|
|
2946
|
-
}
|
|
2947
|
-
return changes;
|
|
2215
|
+
/**
|
|
2216
|
+
* @deprecated this doesn't work for variable width characters (unicode/emoji).
|
|
2217
|
+
* Use position computation in renderer process instead
|
|
2218
|
+
*
|
|
2219
|
+
* @param {object} editor
|
|
2220
|
+
* @param {number} rowIndex
|
|
2221
|
+
* @param {number} columnIndex
|
|
2222
|
+
* @returns
|
|
2223
|
+
*/
|
|
2224
|
+
const x = (editor, rowIndex, columnIndex) => {
|
|
2225
|
+
const {
|
|
2226
|
+
columnWidth,
|
|
2227
|
+
x
|
|
2228
|
+
} = editor;
|
|
2229
|
+
const offsetX = columnIndex * columnWidth + x;
|
|
2230
|
+
return offsetX;
|
|
2948
2231
|
};
|
|
2949
|
-
|
|
2950
|
-
const editorReplaceSelections = (editor, replacement, origin) => {
|
|
2232
|
+
const y = (editor, rowIndex) => {
|
|
2951
2233
|
const {
|
|
2952
|
-
|
|
2234
|
+
rowHeight,
|
|
2235
|
+
y
|
|
2953
2236
|
} = editor;
|
|
2954
|
-
|
|
2237
|
+
const offsetY = (rowIndex + 1) * rowHeight + y;
|
|
2238
|
+
return offsetY;
|
|
2955
2239
|
};
|
|
2956
2240
|
|
|
2957
2241
|
const state$7 = {
|
|
@@ -3060,6 +2344,8 @@ const cancelSelection = editor => {
|
|
|
3060
2344
|
return scheduleSelections(editor, newSelections);
|
|
3061
2345
|
};
|
|
3062
2346
|
|
|
2347
|
+
const Completion = 'completion';
|
|
2348
|
+
|
|
3063
2349
|
const isCompletionWidget = widget => {
|
|
3064
2350
|
return widget.id === Completion;
|
|
3065
2351
|
};
|
|
@@ -3256,36 +2542,30 @@ const copy = async editor => {
|
|
|
3256
2542
|
// TODO handle multiline selection
|
|
3257
2543
|
// TODO handle multiple cursors
|
|
3258
2544
|
|
|
3259
|
-
// @ts-ignore
|
|
3260
2545
|
const copyLineDown = editor => {
|
|
3261
2546
|
const {
|
|
3262
|
-
selections
|
|
3263
|
-
primarySelectionIndex
|
|
2547
|
+
selections
|
|
3264
2548
|
} = editor;
|
|
3265
|
-
const rowIndex = selections[
|
|
2549
|
+
const rowIndex = selections[0];
|
|
3266
2550
|
number$1(rowIndex);
|
|
3267
2551
|
const position = {
|
|
3268
2552
|
rowIndex,
|
|
3269
2553
|
columnIndex: 0
|
|
3270
2554
|
};
|
|
3271
2555
|
const changes = [{
|
|
3272
|
-
inserted: [getLine(editor, rowIndex), ''],
|
|
3273
|
-
deleted: [''],
|
|
3274
2556
|
start: position,
|
|
3275
|
-
end: position
|
|
2557
|
+
end: position,
|
|
2558
|
+
inserted: [getLine(editor, rowIndex), ''],
|
|
2559
|
+
deleted: ['']
|
|
3276
2560
|
}];
|
|
3277
2561
|
return scheduleDocumentAndCursorsSelections(editor, changes);
|
|
3278
2562
|
};
|
|
3279
2563
|
|
|
3280
|
-
// @ts-ignore
|
|
3281
|
-
|
|
3282
|
-
// @ts-ignore
|
|
3283
2564
|
const copyLineUp = editor => {
|
|
3284
2565
|
const {
|
|
3285
|
-
selections
|
|
3286
|
-
primarySelectionIndex
|
|
2566
|
+
selections
|
|
3287
2567
|
} = editor;
|
|
3288
|
-
const rowIndex = selections[
|
|
2568
|
+
const rowIndex = selections[0];
|
|
3289
2569
|
const position = {
|
|
3290
2570
|
rowIndex: rowIndex,
|
|
3291
2571
|
columnIndex: 0
|
|
@@ -3383,35 +2663,28 @@ const editorCursorHorizontalLeft = (editor, getDelta) => {
|
|
|
3383
2663
|
return scheduleSelections(editor, newSelections);
|
|
3384
2664
|
};
|
|
3385
2665
|
|
|
3386
|
-
// @ts-ignore
|
|
3387
2666
|
const characterLeft = (line, columnIndex) => {
|
|
3388
2667
|
if (!supported()) {
|
|
3389
2668
|
return 1;
|
|
3390
2669
|
}
|
|
3391
|
-
const segmenter = create
|
|
2670
|
+
const segmenter = create();
|
|
3392
2671
|
const last = segmenter.at(line, columnIndex - 1);
|
|
3393
2672
|
return columnIndex - last.index;
|
|
3394
2673
|
};
|
|
3395
2674
|
const twoCharactersLeft = () => {
|
|
3396
2675
|
return 2;
|
|
3397
2676
|
};
|
|
3398
|
-
|
|
3399
|
-
// @ts-ignore
|
|
3400
2677
|
const characterRight = (line, columnIndex) => {
|
|
3401
2678
|
if (!supported()) {
|
|
3402
2679
|
return 1;
|
|
3403
2680
|
}
|
|
3404
|
-
const segmenter = create
|
|
2681
|
+
const segmenter = create();
|
|
3405
2682
|
const next = segmenter.at(line, columnIndex);
|
|
3406
2683
|
return next.segment.length;
|
|
3407
2684
|
};
|
|
3408
|
-
|
|
3409
|
-
// @ts-ignore
|
|
3410
2685
|
const isWhitespace = char => {
|
|
3411
2686
|
return char === Space || char === Tab;
|
|
3412
2687
|
};
|
|
3413
|
-
|
|
3414
|
-
// @ts-ignore
|
|
3415
2688
|
const lineCharacterStart = (line, columnIndex) => {
|
|
3416
2689
|
if (line.length === 0) {
|
|
3417
2690
|
return 0;
|
|
@@ -3423,13 +2696,9 @@ const lineCharacterStart = (line, columnIndex) => {
|
|
|
3423
2696
|
}
|
|
3424
2697
|
return columnIndex;
|
|
3425
2698
|
};
|
|
3426
|
-
|
|
3427
|
-
// @ts-ignore
|
|
3428
2699
|
const lineEnd = (line, columnIndex) => {
|
|
3429
2700
|
return line.length - columnIndex;
|
|
3430
2701
|
};
|
|
3431
|
-
|
|
3432
|
-
// @ts-ignore
|
|
3433
2702
|
const tryRegexArray = (partialLine, regexArray) => {
|
|
3434
2703
|
for (const regex of regexArray) {
|
|
3435
2704
|
const match = partialLine.match(regex);
|
|
@@ -3454,8 +2723,6 @@ const wordLeft = (line, columnIndex) => {
|
|
|
3454
2723
|
const RE_WORD_RIGHT_1 = /^\s*[\u00C0-\u017F\w]+/i;
|
|
3455
2724
|
const RE_WORD_RIGHT_2 = /^[^a-zA-Z\d]+\w*/;
|
|
3456
2725
|
const RE_WORD_RIGHT = [RE_WORD_RIGHT_1, RE_WORD_RIGHT_2];
|
|
3457
|
-
|
|
3458
|
-
// @ts-ignore
|
|
3459
2726
|
const wordRight = (line, columnIndex) => {
|
|
3460
2727
|
const partialLine = line.slice(columnIndex);
|
|
3461
2728
|
return tryRegexArray(partialLine, RE_WORD_RIGHT);
|
|
@@ -3470,8 +2737,6 @@ const RE_PARTIAL_WORD_LEFT_7 = /(?<![A-Z])[A-Z]_+\s*$/;
|
|
|
3470
2737
|
const RE_PARTIAL_WORD_LEFT_8 = /[a-z]+\s*$/;
|
|
3471
2738
|
const RE_PARTIAL_WORD_LEFT_9 = /[^a-zA-Z\d\s]+\s*$/;
|
|
3472
2739
|
const RE_PARTIAL_WORD_LEFT = [RE_PARTIAL_WORD_LEFT_1, RE_PARTIAL_WORD_LEFT_2, RE_PARTIAL_WORD_LEFT_3, RE_PARTIAL_WORD_LEFT_4, RE_PARTIAL_WORD_LEFT_5, RE_PARTIAL_WORD_LEFT_6, RE_PARTIAL_WORD_LEFT_7, RE_PARTIAL_WORD_LEFT_8, RE_PARTIAL_WORD_LEFT_9];
|
|
3473
|
-
|
|
3474
|
-
// @ts-ignore
|
|
3475
2740
|
const wordPartLeft = (line, columnIndex) => {
|
|
3476
2741
|
const partialLine = line.slice(0, columnIndex);
|
|
3477
2742
|
return tryRegexArray(partialLine, RE_PARTIAL_WORD_LEFT);
|
|
@@ -3490,8 +2755,6 @@ const ARRAY_PARTIAL_WORD_RIGHT_1 = [RE_PARTIAL_WORD_RIGHT_1,
|
|
|
3490
2755
|
RE_PARTIAL_WORD_RIGHT_3, RE_PARTIAL_WORD_RIGHT_4, RE_PARTIAL_WORD_RIGHT_5, RE_PARTIAL_WORD_RIGHT_6];
|
|
3491
2756
|
const ARRAY_PARTIAL_WORD_RIGHT_2 = [RE_PARTIAL_WORD_RIGHT_1, RE_PARTIAL_WORD_RIGHT_2, RE_PARTIAL_WORD_RIGHT_3, RE_PARTIAL_WORD_RIGHT_4, RE_PARTIAL_WORD_RIGHT_5, RE_PARTIAL_WORD_RIGHT_6];
|
|
3492
2757
|
const RE_UPPERCASE = /[A-Z]/;
|
|
3493
|
-
|
|
3494
|
-
// @ts-ignore
|
|
3495
2758
|
const wordPartRight = (line, columnIndex) => {
|
|
3496
2759
|
const partialLine = line.slice(columnIndex);
|
|
3497
2760
|
// line[columnIndex]//?
|
|
@@ -3506,7 +2769,6 @@ const cursorCharacterLeft = editor => {
|
|
|
3506
2769
|
return editorCursorHorizontalLeft(editor, characterLeft);
|
|
3507
2770
|
};
|
|
3508
2771
|
|
|
3509
|
-
// @ts-ignore
|
|
3510
2772
|
const editorGetPositionRight = (position, lines, getDelta) => {
|
|
3511
2773
|
const rowIndex = position.rowIndex;
|
|
3512
2774
|
const columnIndex = position.columnIndex;
|
|
@@ -3525,8 +2787,6 @@ const editorGetPositionRight = (position, lines, getDelta) => {
|
|
|
3525
2787
|
columnIndex: columnIndex + delta
|
|
3526
2788
|
};
|
|
3527
2789
|
};
|
|
3528
|
-
|
|
3529
|
-
// @ts-ignore
|
|
3530
2790
|
const moveToPositionRight = (selections, i, rowIndex, columnIndex, lines, getDelta) => {
|
|
3531
2791
|
if (rowIndex >= lines.length) {
|
|
3532
2792
|
return;
|
|
@@ -3542,9 +2802,6 @@ const moveToPositionRight = (selections, i, rowIndex, columnIndex, lines, getDel
|
|
|
3542
2802
|
}
|
|
3543
2803
|
};
|
|
3544
2804
|
|
|
3545
|
-
// @ts-ignore
|
|
3546
|
-
|
|
3547
|
-
// @ts-ignore
|
|
3548
2805
|
const getNewSelections$a = (selections, lines, getDelta) => {
|
|
3549
2806
|
const newSelections = new Uint32Array(selections.length);
|
|
3550
2807
|
for (let i = 0; i < selections.length; i += 4) {
|
|
@@ -3558,8 +2815,6 @@ const getNewSelections$a = (selections, lines, getDelta) => {
|
|
|
3558
2815
|
}
|
|
3559
2816
|
return newSelections;
|
|
3560
2817
|
};
|
|
3561
|
-
|
|
3562
|
-
// @ts-ignore
|
|
3563
2818
|
const editorCursorHorizontalRight = (editor, getDelta) => {
|
|
3564
2819
|
const {
|
|
3565
2820
|
lines,
|
|
@@ -3616,16 +2871,9 @@ const getNewSelections$8 = selections => {
|
|
|
3616
2871
|
return map(selections, moveSelectionWithoutIntlSegmenter);
|
|
3617
2872
|
};
|
|
3618
2873
|
const cursorVertical = (editor, getPosition, getEdgePosition, delta) => {
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
// getPosition,
|
|
3623
|
-
// getEdgePosition,
|
|
3624
|
-
// delta
|
|
3625
|
-
// )
|
|
3626
|
-
// }
|
|
3627
|
-
const selections = editor.selections;
|
|
3628
|
-
// @ts-ignore
|
|
2874
|
+
const {
|
|
2875
|
+
selections
|
|
2876
|
+
} = editor;
|
|
3629
2877
|
const newSelections = getNewSelections$8(selections);
|
|
3630
2878
|
return scheduleSelections(editor, newSelections);
|
|
3631
2879
|
};
|
|
@@ -3652,7 +2900,6 @@ const cursorWordPartRight = editor => {
|
|
|
3652
2900
|
return editorCursorHorizontalRight(editor, wordPartRight);
|
|
3653
2901
|
};
|
|
3654
2902
|
|
|
3655
|
-
// @ts-ignore
|
|
3656
2903
|
const cursorWordRight = editor => {
|
|
3657
2904
|
return editorCursorHorizontalRight(editor, wordRight);
|
|
3658
2905
|
};
|
|
@@ -3918,32 +3165,74 @@ const applyDocumentEdits = (editor, edits) => {
|
|
|
3918
3165
|
if (edits.length === 0) {
|
|
3919
3166
|
return editor;
|
|
3920
3167
|
}
|
|
3921
|
-
const documentEdits = getDocumentEdits(editor, edits);
|
|
3922
|
-
return scheduleDocumentAndCursorsSelections(editor, documentEdits);
|
|
3168
|
+
const documentEdits = getDocumentEdits(editor, edits);
|
|
3169
|
+
return scheduleDocumentAndCursorsSelections(editor, documentEdits);
|
|
3170
|
+
};
|
|
3171
|
+
|
|
3172
|
+
const expectedErrorMessage = 'Failed to execute formatting provider: FormattingError:';
|
|
3173
|
+
const isFormattingError = error => {
|
|
3174
|
+
return error && error instanceof Error && error.message.startsWith(expectedErrorMessage);
|
|
3175
|
+
};
|
|
3176
|
+
|
|
3177
|
+
// TODO also format with cursor
|
|
3178
|
+
const format = async editor => {
|
|
3179
|
+
try {
|
|
3180
|
+
const edits = await format$1(editor);
|
|
3181
|
+
return applyDocumentEdits(editor, edits);
|
|
3182
|
+
} catch (error) {
|
|
3183
|
+
if (isFormattingError(error)) {
|
|
3184
|
+
console.error('Formatting Error:',
|
|
3185
|
+
// @ts-ignore
|
|
3186
|
+
error.message.slice(expectedErrorMessage.length));
|
|
3187
|
+
return editor;
|
|
3188
|
+
}
|
|
3189
|
+
console.error(error);
|
|
3190
|
+
const displayErrorMessage = `${error}`;
|
|
3191
|
+
await editorShowMessage(editor, 0, 0, displayErrorMessage, true);
|
|
3192
|
+
return editor;
|
|
3193
|
+
}
|
|
3194
|
+
};
|
|
3195
|
+
|
|
3196
|
+
const RE_WORD_START$1 = /^[\w\-]+/;
|
|
3197
|
+
const RE_WORD_END$1 = /[\w\-]+$/;
|
|
3198
|
+
const getWordAt$1 = (line, columnIndex) => {
|
|
3199
|
+
const before = line.slice(0, columnIndex);
|
|
3200
|
+
const matchBefore = before.match(RE_WORD_END$1);
|
|
3201
|
+
const after = line.slice(columnIndex);
|
|
3202
|
+
const matchAfter = after.match(RE_WORD_START$1);
|
|
3203
|
+
let word = EmptyString;
|
|
3204
|
+
if (matchBefore) {
|
|
3205
|
+
word += matchBefore[0];
|
|
3206
|
+
}
|
|
3207
|
+
if (matchAfter) {
|
|
3208
|
+
word += matchAfter[0];
|
|
3209
|
+
}
|
|
3210
|
+
return {
|
|
3211
|
+
word
|
|
3212
|
+
};
|
|
3213
|
+
};
|
|
3214
|
+
const getWordBefore$1 = (line, columnIndex) => {
|
|
3215
|
+
const before = line.slice(0, columnIndex);
|
|
3216
|
+
const matchBefore = before.match(RE_WORD_END$1);
|
|
3217
|
+
if (matchBefore) {
|
|
3218
|
+
return matchBefore[0];
|
|
3219
|
+
}
|
|
3220
|
+
return EmptyString;
|
|
3923
3221
|
};
|
|
3924
3222
|
|
|
3925
|
-
const
|
|
3926
|
-
const
|
|
3927
|
-
|
|
3223
|
+
const getWordAt = (editor, rowIndex, columnIndex) => {
|
|
3224
|
+
const {
|
|
3225
|
+
lines
|
|
3226
|
+
} = editor;
|
|
3227
|
+
const line = lines[rowIndex];
|
|
3228
|
+
return getWordAt$1(line, columnIndex);
|
|
3928
3229
|
};
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
} catch (error) {
|
|
3936
|
-
if (isFormattingError(error)) {
|
|
3937
|
-
console.error('Formatting Error:',
|
|
3938
|
-
// @ts-ignore
|
|
3939
|
-
error.message.slice(expectedErrorMessage.length));
|
|
3940
|
-
return editor;
|
|
3941
|
-
}
|
|
3942
|
-
console.error(error);
|
|
3943
|
-
const displayErrorMessage = `${error}`;
|
|
3944
|
-
await editorShowMessage(editor, 0, 0, displayErrorMessage, true);
|
|
3945
|
-
return editor;
|
|
3946
|
-
}
|
|
3230
|
+
const getWordBefore = (editor, rowIndex, columnIndex) => {
|
|
3231
|
+
const {
|
|
3232
|
+
lines
|
|
3233
|
+
} = editor;
|
|
3234
|
+
const line = lines[rowIndex];
|
|
3235
|
+
return getWordBefore$1(line, columnIndex);
|
|
3947
3236
|
};
|
|
3948
3237
|
|
|
3949
3238
|
// @ts-ignore
|
|
@@ -3952,6 +3241,46 @@ const getDefinition = async (editor, offset) => {
|
|
|
3952
3241
|
return definition;
|
|
3953
3242
|
};
|
|
3954
3243
|
|
|
3244
|
+
const emptyObject = {};
|
|
3245
|
+
const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
|
|
3246
|
+
const i18nString = (key, placeholders = emptyObject) => {
|
|
3247
|
+
if (placeholders === emptyObject) {
|
|
3248
|
+
return key;
|
|
3249
|
+
}
|
|
3250
|
+
const replacer = (match, rest) => {
|
|
3251
|
+
return placeholders[rest];
|
|
3252
|
+
};
|
|
3253
|
+
return key.replaceAll(RE_PLACEHOLDER, replacer);
|
|
3254
|
+
};
|
|
3255
|
+
|
|
3256
|
+
const UiStrings = {
|
|
3257
|
+
GoToDefinition: 'Go to Definition',
|
|
3258
|
+
NoDefinitionFound: 'No definition found',
|
|
3259
|
+
NoDefinitionFoundFor: "No definition found for '{PH1}'",
|
|
3260
|
+
NoTypeDefinitionFound: 'No type definition found',
|
|
3261
|
+
NoTypeDefinitionFoundFor: "No type definition found for '{PH1}'",
|
|
3262
|
+
NoResults: 'No Results'
|
|
3263
|
+
};
|
|
3264
|
+
const noDefinitionFound = () => {
|
|
3265
|
+
return i18nString(UiStrings.NoDefinitionFound);
|
|
3266
|
+
};
|
|
3267
|
+
const noDefinitionFoundFor = word => {
|
|
3268
|
+
return i18nString(UiStrings.NoDefinitionFoundFor, {
|
|
3269
|
+
PH1: word
|
|
3270
|
+
});
|
|
3271
|
+
};
|
|
3272
|
+
const noTypeDefinitionFoundFor = word => {
|
|
3273
|
+
return i18nString(UiStrings.NoTypeDefinitionFoundFor, {
|
|
3274
|
+
PH1: word
|
|
3275
|
+
});
|
|
3276
|
+
};
|
|
3277
|
+
const noTypeDefinitionFound = () => {
|
|
3278
|
+
return i18nString(UiStrings.NoTypeDefinitionFound);
|
|
3279
|
+
};
|
|
3280
|
+
const noResults = () => {
|
|
3281
|
+
return i18nString(UiStrings.NoResults);
|
|
3282
|
+
};
|
|
3283
|
+
|
|
3955
3284
|
// @ts-ignore
|
|
3956
3285
|
const goTo = async ({
|
|
3957
3286
|
editor,
|
|
@@ -5114,81 +4443,270 @@ const activateByEvent = async event => {
|
|
|
5114
4443
|
await invoke$3('ExtensionHostManagement.activateByEvent', event);
|
|
5115
4444
|
};
|
|
5116
4445
|
|
|
5117
|
-
const execute = async ({
|
|
5118
|
-
editor,
|
|
5119
|
-
args,
|
|
5120
|
-
event,
|
|
5121
|
-
method,
|
|
5122
|
-
noProviderFoundMessage,
|
|
5123
|
-
noProviderFoundResult = undefined
|
|
5124
|
-
}) => {
|
|
5125
|
-
const fullEvent = `${event}:${editor.languageId}`;
|
|
5126
|
-
await activateByEvent(fullEvent);
|
|
5127
|
-
const result = await invoke$2(method, editor.uid, ...args);
|
|
5128
|
-
return result;
|
|
4446
|
+
const execute = async ({
|
|
4447
|
+
editor,
|
|
4448
|
+
args,
|
|
4449
|
+
event,
|
|
4450
|
+
method,
|
|
4451
|
+
noProviderFoundMessage,
|
|
4452
|
+
noProviderFoundResult = undefined
|
|
4453
|
+
}) => {
|
|
4454
|
+
const fullEvent = `${event}:${editor.languageId}`;
|
|
4455
|
+
await activateByEvent(fullEvent);
|
|
4456
|
+
const result = await invoke$2(method, editor.uid, ...args);
|
|
4457
|
+
return result;
|
|
4458
|
+
};
|
|
4459
|
+
|
|
4460
|
+
const combineResults = results => {
|
|
4461
|
+
return results[0] ?? [];
|
|
4462
|
+
};
|
|
4463
|
+
const executeCompletionProvider = (editor, offset) => {
|
|
4464
|
+
return execute({
|
|
4465
|
+
editor,
|
|
4466
|
+
event: OnCompletion,
|
|
4467
|
+
method: CompletionExecute,
|
|
4468
|
+
args: [offset],
|
|
4469
|
+
noProviderFoundMessage: 'no completion provider found',
|
|
4470
|
+
noProviderFoundResult: [],
|
|
4471
|
+
combineResults
|
|
4472
|
+
});
|
|
4473
|
+
};
|
|
4474
|
+
const combineResultsResolve = items => {
|
|
4475
|
+
return items[0] ?? undefined;
|
|
4476
|
+
};
|
|
4477
|
+
const executeResolveCompletionItem = (editor, offset, name, completionItem) => {
|
|
4478
|
+
return execute({
|
|
4479
|
+
editor,
|
|
4480
|
+
event: OnCompletion,
|
|
4481
|
+
method: CompletionResolveExecute,
|
|
4482
|
+
args: [offset, name, completionItem],
|
|
4483
|
+
noProviderFoundMessage: 'no completion provider found',
|
|
4484
|
+
noProviderFoundResult: [],
|
|
4485
|
+
combineResults: combineResultsResolve
|
|
4486
|
+
});
|
|
4487
|
+
};
|
|
4488
|
+
|
|
4489
|
+
// TODO possible to do this with events/state machine instead of promises -> enables canceling operations / concurrent calls
|
|
4490
|
+
const getCompletions = async editor => {
|
|
4491
|
+
const {
|
|
4492
|
+
selections
|
|
4493
|
+
} = editor;
|
|
4494
|
+
const rowIndex = selections[0];
|
|
4495
|
+
const columnIndex = selections[1];
|
|
4496
|
+
// Editor.sync(editor)
|
|
4497
|
+
const offset = await offsetAt(editor, rowIndex, columnIndex);
|
|
4498
|
+
const completions = await executeCompletionProvider(editor, offset);
|
|
4499
|
+
return completions;
|
|
4500
|
+
};
|
|
4501
|
+
|
|
4502
|
+
// TODO don't send unnecessary parts of completion item like matches
|
|
4503
|
+
const resolveCompletion = async (editor, name, completionItem) => {
|
|
4504
|
+
try {
|
|
4505
|
+
object(editor);
|
|
4506
|
+
string(name);
|
|
4507
|
+
object(completionItem);
|
|
4508
|
+
const rowIndex = editor.selections[0];
|
|
4509
|
+
const columnIndex = editor.selections[1];
|
|
4510
|
+
const offset = await offsetAt(editor, rowIndex, columnIndex);
|
|
4511
|
+
// @ts-ignore
|
|
4512
|
+
const resolvedCompletionItem = await executeResolveCompletionItem(editor, offset, name, completionItem);
|
|
4513
|
+
return resolvedCompletionItem;
|
|
4514
|
+
} catch {
|
|
4515
|
+
return undefined;
|
|
4516
|
+
}
|
|
4517
|
+
};
|
|
4518
|
+
|
|
4519
|
+
const None$1 = 1;
|
|
4520
|
+
|
|
4521
|
+
const EmptyMatches = [];
|
|
4522
|
+
|
|
4523
|
+
const Diagonal = 1;
|
|
4524
|
+
const Left = 2;
|
|
4525
|
+
|
|
4526
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
4527
|
+
|
|
4528
|
+
const createTable = size => {
|
|
4529
|
+
const table = [];
|
|
4530
|
+
for (let i = 0; i < size; i++) {
|
|
4531
|
+
const row = new Uint8Array(size);
|
|
4532
|
+
table.push(row);
|
|
4533
|
+
}
|
|
4534
|
+
return table;
|
|
4535
|
+
};
|
|
4536
|
+
|
|
4537
|
+
const isLowerCase = char => {
|
|
4538
|
+
return char === char.toLowerCase();
|
|
4539
|
+
};
|
|
4540
|
+
|
|
4541
|
+
const isUpperCase = char => {
|
|
4542
|
+
return char === char.toUpperCase();
|
|
4543
|
+
};
|
|
4544
|
+
|
|
4545
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
4546
|
+
const isGap = (columnCharBefore, columnChar) => {
|
|
4547
|
+
switch (columnCharBefore) {
|
|
4548
|
+
case Dash:
|
|
4549
|
+
case Underline:
|
|
4550
|
+
case EmptyString:
|
|
4551
|
+
case T:
|
|
4552
|
+
case Space:
|
|
4553
|
+
case Dot:
|
|
4554
|
+
return true;
|
|
4555
|
+
}
|
|
4556
|
+
if (isLowerCase(columnCharBefore) && isUpperCase(columnChar)) {
|
|
4557
|
+
return true;
|
|
4558
|
+
}
|
|
4559
|
+
return false;
|
|
4560
|
+
};
|
|
4561
|
+
|
|
4562
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
4563
|
+
const getScore = (rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, column, wordLength, isDiagonalMatch) => {
|
|
4564
|
+
if (rowCharLow !== columnCharLow) {
|
|
4565
|
+
return -1;
|
|
4566
|
+
}
|
|
4567
|
+
const isMatch = rowChar === columnChar;
|
|
4568
|
+
if (isMatch) {
|
|
4569
|
+
if (isDiagonalMatch) {
|
|
4570
|
+
return 8;
|
|
4571
|
+
}
|
|
4572
|
+
if (isGap(columnCharBefore, columnChar)) {
|
|
4573
|
+
return 8;
|
|
4574
|
+
}
|
|
4575
|
+
return 5;
|
|
4576
|
+
}
|
|
4577
|
+
if (isGap(columnCharBefore, columnChar)) {
|
|
4578
|
+
return 8;
|
|
4579
|
+
}
|
|
4580
|
+
return 5;
|
|
4581
|
+
};
|
|
4582
|
+
|
|
4583
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
4584
|
+
|
|
4585
|
+
const isPatternInWord = (patternLow, patternPos, patternLen, wordLow, wordPos, wordLen) => {
|
|
4586
|
+
while (patternPos < patternLen && wordPos < wordLen) {
|
|
4587
|
+
if (patternLow[patternPos] === wordLow[wordPos]) {
|
|
4588
|
+
patternPos += 1;
|
|
4589
|
+
}
|
|
4590
|
+
wordPos += 1;
|
|
4591
|
+
}
|
|
4592
|
+
return patternPos === patternLen; // pattern must be exhausted
|
|
4593
|
+
};
|
|
4594
|
+
|
|
4595
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
4596
|
+
const traceHighlights = (table, arrows, patternLength, wordLength) => {
|
|
4597
|
+
let row = patternLength;
|
|
4598
|
+
let column = wordLength;
|
|
4599
|
+
const matches = [];
|
|
4600
|
+
while (row >= 1 && column >= 1) {
|
|
4601
|
+
const arrow = arrows[row][column];
|
|
4602
|
+
if (arrow === Left) {
|
|
4603
|
+
column--;
|
|
4604
|
+
} else if (arrow === Diagonal) {
|
|
4605
|
+
row--;
|
|
4606
|
+
column--;
|
|
4607
|
+
const start = column + 1;
|
|
4608
|
+
while (row >= 1 && column >= 1) {
|
|
4609
|
+
const arrow = arrows[row][column];
|
|
4610
|
+
if (arrow === Left) {
|
|
4611
|
+
break;
|
|
4612
|
+
}
|
|
4613
|
+
if (arrow === Diagonal) {
|
|
4614
|
+
row--;
|
|
4615
|
+
column--;
|
|
4616
|
+
}
|
|
4617
|
+
}
|
|
4618
|
+
const end = column;
|
|
4619
|
+
matches.unshift(end, start);
|
|
4620
|
+
}
|
|
4621
|
+
}
|
|
4622
|
+
matches.unshift(table[patternLength][wordLength - 1]);
|
|
4623
|
+
return matches;
|
|
4624
|
+
};
|
|
4625
|
+
|
|
4626
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
4627
|
+
const gridSize = 128;
|
|
4628
|
+
const table = createTable(gridSize);
|
|
4629
|
+
const arrows = createTable(gridSize);
|
|
4630
|
+
const filterCompletionItem = (pattern, word) => {
|
|
4631
|
+
const patternLength = Math.min(pattern.length, gridSize - 1);
|
|
4632
|
+
const wordLength = Math.min(word.length, gridSize - 1);
|
|
4633
|
+
const patternLower = pattern.toLowerCase();
|
|
4634
|
+
const wordLower = word.toLowerCase();
|
|
4635
|
+
if (!isPatternInWord(patternLower, 0, patternLength, wordLower, 0, wordLength)) {
|
|
4636
|
+
return EmptyMatches;
|
|
4637
|
+
}
|
|
4638
|
+
let strongMatch = false;
|
|
4639
|
+
for (let row = 1; row < patternLength + 1; row++) {
|
|
4640
|
+
const rowChar = pattern[row - 1];
|
|
4641
|
+
const rowCharLow = patternLower[row - 1];
|
|
4642
|
+
for (let column = 1; column < wordLength + 1; column++) {
|
|
4643
|
+
const columnChar = word[column - 1];
|
|
4644
|
+
const columnCharLow = wordLower[column - 1];
|
|
4645
|
+
const columnCharBefore = word[column - 2] || '';
|
|
4646
|
+
const isDiagonalMatch = arrows[row - 1][column - 1] === Diagonal;
|
|
4647
|
+
const score = getScore(rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, column, wordLength, isDiagonalMatch);
|
|
4648
|
+
if (row === 1 && score > 5) {
|
|
4649
|
+
strongMatch = true;
|
|
4650
|
+
}
|
|
4651
|
+
let diagonalScore = score + table[row - 1][column - 1];
|
|
4652
|
+
if (isDiagonalMatch && score !== -1) {
|
|
4653
|
+
diagonalScore += 2;
|
|
4654
|
+
}
|
|
4655
|
+
const leftScore = table[row][column - 1];
|
|
4656
|
+
if (leftScore > diagonalScore) {
|
|
4657
|
+
table[row][column] = leftScore;
|
|
4658
|
+
arrows[row][column] = Left;
|
|
4659
|
+
} else {
|
|
4660
|
+
table[row][column] = diagonalScore;
|
|
4661
|
+
arrows[row][column] = Diagonal;
|
|
4662
|
+
}
|
|
4663
|
+
}
|
|
4664
|
+
}
|
|
4665
|
+
if (!strongMatch) {
|
|
4666
|
+
return EmptyMatches;
|
|
4667
|
+
}
|
|
4668
|
+
const highlights = traceHighlights(table, arrows, patternLength, wordLength);
|
|
4669
|
+
return highlights;
|
|
5129
4670
|
};
|
|
5130
4671
|
|
|
5131
|
-
const
|
|
5132
|
-
return results[0] ?? [];
|
|
5133
|
-
};
|
|
5134
|
-
const executeCompletionProvider = (editor, offset) => {
|
|
5135
|
-
return execute({
|
|
5136
|
-
editor,
|
|
5137
|
-
event: OnCompletion,
|
|
5138
|
-
method: CompletionExecute,
|
|
5139
|
-
args: [offset],
|
|
5140
|
-
noProviderFoundMessage: 'no completion provider found',
|
|
5141
|
-
noProviderFoundResult: [],
|
|
5142
|
-
combineResults
|
|
5143
|
-
});
|
|
5144
|
-
};
|
|
5145
|
-
const combineResultsResolve = items => {
|
|
5146
|
-
return items[0] ?? undefined;
|
|
5147
|
-
};
|
|
5148
|
-
const executeResolveCompletionItem = (editor, offset, name, completionItem) => {
|
|
5149
|
-
return execute({
|
|
5150
|
-
editor,
|
|
5151
|
-
event: OnCompletion,
|
|
5152
|
-
method: CompletionResolveExecute,
|
|
5153
|
-
args: [offset, name, completionItem],
|
|
5154
|
-
noProviderFoundMessage: 'no completion provider found',
|
|
5155
|
-
noProviderFoundResult: [],
|
|
5156
|
-
combineResults: combineResultsResolve
|
|
5157
|
-
});
|
|
5158
|
-
};
|
|
4672
|
+
const Deprecated = 1 << 0;
|
|
5159
4673
|
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
}
|
|
5165
|
-
const rowIndex = selections[0];
|
|
5166
|
-
const columnIndex = selections[1];
|
|
5167
|
-
// Editor.sync(editor)
|
|
5168
|
-
const offset = await offsetAt(editor, rowIndex, columnIndex);
|
|
5169
|
-
const completions = await executeCompletionProvider(editor, offset);
|
|
5170
|
-
return completions;
|
|
4674
|
+
const addEmptyMatch = item => {
|
|
4675
|
+
return {
|
|
4676
|
+
...item,
|
|
4677
|
+
matches: EmptyMatches
|
|
4678
|
+
};
|
|
5171
4679
|
};
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
const
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
const
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
4680
|
+
const filterCompletionItems = (completionItems, word) => {
|
|
4681
|
+
if (word === EmptyString) {
|
|
4682
|
+
return completionItems.map(addEmptyMatch);
|
|
4683
|
+
}
|
|
4684
|
+
const filteredCompletions = [];
|
|
4685
|
+
const deprecated = [];
|
|
4686
|
+
for (const completionItem of completionItems) {
|
|
4687
|
+
const {
|
|
4688
|
+
label,
|
|
4689
|
+
flags
|
|
4690
|
+
} = completionItem;
|
|
4691
|
+
const result = filterCompletionItem(word, label);
|
|
4692
|
+
if (result !== EmptyMatches) {
|
|
4693
|
+
if (flags & Deprecated) {
|
|
4694
|
+
// TODO avoid mutation
|
|
4695
|
+
completionItem.matches = EmptyMatches;
|
|
4696
|
+
deprecated.push(completionItem);
|
|
4697
|
+
} else {
|
|
4698
|
+
// TODO avoid mutation
|
|
4699
|
+
completionItem.matches = result;
|
|
4700
|
+
filteredCompletions.push(completionItem);
|
|
4701
|
+
}
|
|
4702
|
+
}
|
|
4703
|
+
}
|
|
4704
|
+
if (deprecated.length > 0) {
|
|
4705
|
+
filteredCompletions.push(...deprecated);
|
|
5187
4706
|
}
|
|
4707
|
+
return filteredCompletions;
|
|
5188
4708
|
};
|
|
5189
4709
|
|
|
5190
|
-
const None = 1;
|
|
5191
|
-
|
|
5192
4710
|
const getEditor = editorUid => {
|
|
5193
4711
|
const instance = get$6(editorUid);
|
|
5194
4712
|
if (!instance) {
|
|
@@ -5206,6 +4724,17 @@ const getFinalDeltaY = (height, itemHeight, itemsLength) => {
|
|
|
5206
4724
|
return finalDeltaY;
|
|
5207
4725
|
};
|
|
5208
4726
|
|
|
4727
|
+
const getListHeight = (itemsLength, itemHeight, maxHeight) => {
|
|
4728
|
+
number$1(itemsLength);
|
|
4729
|
+
number$1(itemHeight);
|
|
4730
|
+
number$1(maxHeight);
|
|
4731
|
+
if (itemsLength === 0) {
|
|
4732
|
+
return itemHeight;
|
|
4733
|
+
}
|
|
4734
|
+
const totalHeight = itemsLength * itemHeight;
|
|
4735
|
+
return Math.min(totalHeight, maxHeight);
|
|
4736
|
+
};
|
|
4737
|
+
|
|
5209
4738
|
const RE_WORD = /[\w\-]+$/;
|
|
5210
4739
|
const getWordAtOffset = editor => {
|
|
5211
4740
|
const {
|
|
@@ -5222,7 +4751,7 @@ const getWordAtOffset = editor => {
|
|
|
5222
4751
|
}
|
|
5223
4752
|
return '';
|
|
5224
4753
|
};
|
|
5225
|
-
const handleEditorType = (editorUid, state, text) => {
|
|
4754
|
+
const handleEditorType$1 = (editorUid, state, text) => {
|
|
5226
4755
|
const editor = getEditor(editorUid);
|
|
5227
4756
|
const {
|
|
5228
4757
|
unfilteredItems,
|
|
@@ -5252,7 +4781,7 @@ const handleEditorType = (editorUid, state, text) => {
|
|
|
5252
4781
|
finalDeltaY
|
|
5253
4782
|
};
|
|
5254
4783
|
};
|
|
5255
|
-
const handleEditorDeleteLeft = (editorUid, state) => {
|
|
4784
|
+
const handleEditorDeleteLeft$1 = (editorUid, state) => {
|
|
5256
4785
|
const editor = getEditor(editorUid);
|
|
5257
4786
|
const {
|
|
5258
4787
|
unfilteredItems,
|
|
@@ -5266,7 +4795,7 @@ const handleEditorDeleteLeft = (editorUid, state) => {
|
|
|
5266
4795
|
const y$1 = y(editor, rowIndex);
|
|
5267
4796
|
const wordAtOffset = getWordAtOffset(editor);
|
|
5268
4797
|
if (!wordAtOffset) {
|
|
5269
|
-
editor.completionState = None;
|
|
4798
|
+
editor.completionState = None$1;
|
|
5270
4799
|
return {
|
|
5271
4800
|
...state,
|
|
5272
4801
|
disposed: true
|
|
@@ -5292,7 +4821,7 @@ const dispose = state => {
|
|
|
5292
4821
|
};
|
|
5293
4822
|
};
|
|
5294
4823
|
const disposeWithEditor = (state, editor) => {
|
|
5295
|
-
editor.completionState = None;
|
|
4824
|
+
editor.completionState = None$1;
|
|
5296
4825
|
editor.completionUid = 0;
|
|
5297
4826
|
// Focus.removeAdditionalFocus(FocusKey.EditorCompletion)
|
|
5298
4827
|
return dispose(state);
|
|
@@ -5634,27 +5163,39 @@ const editorSelectAllLeft = editor => {
|
|
|
5634
5163
|
editorSelectHorizontalLeft(editor, lineCharacterStart);
|
|
5635
5164
|
};
|
|
5636
5165
|
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5166
|
+
const RE_ALPHA_NUMERIC = /[a-zA-Z\d]/;
|
|
5167
|
+
const isAlphaNumeric = char => {
|
|
5168
|
+
return RE_ALPHA_NUMERIC.test(char);
|
|
5169
|
+
};
|
|
5640
5170
|
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5171
|
+
const getWordStartIndex = (line, index) => {
|
|
5172
|
+
for (let i = index - 1; i >= 0; i--) {
|
|
5173
|
+
if (!isAlphaNumeric(line[i])) {
|
|
5174
|
+
return i + 1;
|
|
5175
|
+
}
|
|
5645
5176
|
}
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5177
|
+
return 0;
|
|
5178
|
+
};
|
|
5179
|
+
const getWordEndIndex = (line, index) => {
|
|
5180
|
+
for (let i = index; i < line.length; i++) {
|
|
5181
|
+
if (!isAlphaNumeric(line[i])) {
|
|
5182
|
+
return i;
|
|
5652
5183
|
}
|
|
5653
5184
|
}
|
|
5654
|
-
return
|
|
5185
|
+
return line.length - 1;
|
|
5186
|
+
};
|
|
5187
|
+
const getWordMatchAtPosition = (lines, rowIndex, columnIndex) => {
|
|
5188
|
+
const line = lines[rowIndex];
|
|
5189
|
+
const start = getWordStartIndex(line, columnIndex);
|
|
5190
|
+
const end = getWordEndIndex(line, columnIndex);
|
|
5191
|
+
const word = line.slice(start, end);
|
|
5192
|
+
return {
|
|
5193
|
+
start,
|
|
5194
|
+
end,
|
|
5195
|
+
word
|
|
5196
|
+
};
|
|
5655
5197
|
};
|
|
5656
5198
|
|
|
5657
|
-
// @ts-ignore
|
|
5658
5199
|
const isMultiLineMatch = (lines, rowIndex, wordParts) => {
|
|
5659
5200
|
let j = 0;
|
|
5660
5201
|
if (!lines[rowIndex + j].endsWith(wordParts[j])) {
|
|
@@ -5665,21 +5206,36 @@ const isMultiLineMatch = (lines, rowIndex, wordParts) => {
|
|
|
5665
5206
|
return false;
|
|
5666
5207
|
}
|
|
5667
5208
|
}
|
|
5668
|
-
// j--
|
|
5669
5209
|
if (!lines[rowIndex + j].startsWith(wordParts[j])) {
|
|
5670
|
-
|
|
5671
5210
|
return false;
|
|
5672
5211
|
}
|
|
5673
5212
|
return true;
|
|
5674
5213
|
};
|
|
5675
5214
|
|
|
5215
|
+
// TODO handle virtual space
|
|
5216
|
+
|
|
5217
|
+
const getNewSelectionsSingleLineWord = (lines, word) => {
|
|
5218
|
+
if (word.length === 0) {
|
|
5219
|
+
throw new Error('word length must be greater than zero');
|
|
5220
|
+
}
|
|
5221
|
+
const newSelections = [];
|
|
5222
|
+
for (let i = 0; i < lines.length; i++) {
|
|
5223
|
+
const line = lines[i];
|
|
5224
|
+
let columnIndex = -word.length;
|
|
5225
|
+
while ((columnIndex = line.indexOf(word, columnIndex + word.length)) !== -1) {
|
|
5226
|
+
newSelections.push(i, columnIndex, i, columnIndex + word.length);
|
|
5227
|
+
}
|
|
5228
|
+
}
|
|
5229
|
+
return new Uint32Array(newSelections);
|
|
5230
|
+
};
|
|
5231
|
+
|
|
5676
5232
|
// TODO this is very expensive, there might be a better algorithm for this
|
|
5677
5233
|
// TODO if this matches the given selections, don't schedule selections/rerender
|
|
5678
|
-
// @ts-ignore
|
|
5679
5234
|
const getAllOccurrencesMultiLine = (lines, wordParts) => {
|
|
5680
5235
|
const newSelections = [];
|
|
5681
5236
|
for (let rowIndex = 0; rowIndex < lines.length - wordParts.length + 1; rowIndex) {
|
|
5682
5237
|
if (isMultiLineMatch(lines, rowIndex, wordParts)) {
|
|
5238
|
+
// @ts-ignore
|
|
5683
5239
|
newSelections.push(rowIndex, lines[rowIndex].length - wordParts[0].length, rowIndex + wordParts.length - 1, wordParts.at(-1).length);
|
|
5684
5240
|
rowIndex += wordParts.length - 1;
|
|
5685
5241
|
} else {
|
|
@@ -5688,49 +5244,6 @@ const getAllOccurrencesMultiLine = (lines, wordParts) => {
|
|
|
5688
5244
|
}
|
|
5689
5245
|
return new Uint32Array(newSelections);
|
|
5690
5246
|
};
|
|
5691
|
-
|
|
5692
|
-
// TODO duplicate code with EditorSelectNextOccurrence
|
|
5693
|
-
const RE_ALPHA_NUMERIC$1 = /[a-zA-Z\d]/;
|
|
5694
|
-
|
|
5695
|
-
// @ts-ignore
|
|
5696
|
-
const isAlphaNumeric$1 = char => {
|
|
5697
|
-
return RE_ALPHA_NUMERIC$1.test(char);
|
|
5698
|
-
};
|
|
5699
|
-
|
|
5700
|
-
// @ts-ignore
|
|
5701
|
-
const getWordStartIndex$1 = (line, index) => {
|
|
5702
|
-
for (let i = index - 1; i >= 0; i--) {
|
|
5703
|
-
if (!isAlphaNumeric$1(line[i])) {
|
|
5704
|
-
return i + 1;
|
|
5705
|
-
}
|
|
5706
|
-
}
|
|
5707
|
-
return 0;
|
|
5708
|
-
};
|
|
5709
|
-
|
|
5710
|
-
// @ts-ignore
|
|
5711
|
-
const getWordEndIndex$1 = (line, index) => {
|
|
5712
|
-
for (let i = index; i < line.length; i++) {
|
|
5713
|
-
if (!isAlphaNumeric$1(line[i])) {
|
|
5714
|
-
return i;
|
|
5715
|
-
}
|
|
5716
|
-
}
|
|
5717
|
-
return line.length - 1;
|
|
5718
|
-
};
|
|
5719
|
-
|
|
5720
|
-
// @ts-ignore
|
|
5721
|
-
const getWordMatchAtPosition$1 = (lines, rowIndex, columnIndex) => {
|
|
5722
|
-
const line = lines[rowIndex];
|
|
5723
|
-
const start = getWordStartIndex$1(line, columnIndex);
|
|
5724
|
-
const end = getWordEndIndex$1(line, columnIndex);
|
|
5725
|
-
const word = line.slice(start, end);
|
|
5726
|
-
return {
|
|
5727
|
-
start,
|
|
5728
|
-
end,
|
|
5729
|
-
word
|
|
5730
|
-
};
|
|
5731
|
-
};
|
|
5732
|
-
|
|
5733
|
-
// @ts-ignore
|
|
5734
5247
|
const getNewSelections$3 = (lines, selections) => {
|
|
5735
5248
|
if (selections.length < 4) {
|
|
5736
5249
|
throw new Error('selections must have at least one entry');
|
|
@@ -5742,7 +5255,7 @@ const getNewSelections$3 = (lines, selections) => {
|
|
|
5742
5255
|
const endColumnIndex = selections[firstSelectionIndex + 3];
|
|
5743
5256
|
if (startRowIndex === endRowIndex) {
|
|
5744
5257
|
if (startColumnIndex === endColumnIndex) {
|
|
5745
|
-
const wordMatch = getWordMatchAtPosition
|
|
5258
|
+
const wordMatch = getWordMatchAtPosition(lines, endRowIndex, endColumnIndex);
|
|
5746
5259
|
if (wordMatch.start === wordMatch.end) {
|
|
5747
5260
|
return selections;
|
|
5748
5261
|
}
|
|
@@ -5763,12 +5276,12 @@ const getNewSelections$3 = (lines, selections) => {
|
|
|
5763
5276
|
const newSelections = getAllOccurrencesMultiLine(lines, wordParts);
|
|
5764
5277
|
return newSelections;
|
|
5765
5278
|
};
|
|
5766
|
-
|
|
5767
|
-
// @ts-ignore
|
|
5768
5279
|
const selectAllOccurrences = editor => {
|
|
5769
5280
|
// when there are no selections -> first selection is word -> find all selection that include word
|
|
5770
|
-
const
|
|
5771
|
-
|
|
5281
|
+
const {
|
|
5282
|
+
lines,
|
|
5283
|
+
selections
|
|
5284
|
+
} = editor;
|
|
5772
5285
|
const newSelections = getNewSelections$3(lines, selections);
|
|
5773
5286
|
return scheduleSelections(editor, newSelections);
|
|
5774
5287
|
};
|
|
@@ -5852,11 +5365,11 @@ const getNewSelections$1 = (lines, selections) => {
|
|
|
5852
5365
|
let startColumnIndex = selectionStartColumn;
|
|
5853
5366
|
let endColumnIndex = selectionEndColumn;
|
|
5854
5367
|
const line = lines[rowIndex];
|
|
5855
|
-
while (startColumnIndex > 0 && line[startColumnIndex] !==
|
|
5368
|
+
while (startColumnIndex > 0 && line[startColumnIndex] !== DoubleQuote$1) {
|
|
5856
5369
|
startColumnIndex--;
|
|
5857
5370
|
}
|
|
5858
5371
|
startColumnIndex++;
|
|
5859
|
-
while (endColumnIndex < line.length && line[endColumnIndex] !==
|
|
5372
|
+
while (endColumnIndex < line.length && line[endColumnIndex] !== DoubleQuote$1) {
|
|
5860
5373
|
endColumnIndex++;
|
|
5861
5374
|
}
|
|
5862
5375
|
newSelections[i] = rowIndex;
|
|
@@ -5879,9 +5392,26 @@ const selectInsideString = editor => {
|
|
|
5879
5392
|
return scheduleSelections(editor, newSelections);
|
|
5880
5393
|
};
|
|
5881
5394
|
|
|
5882
|
-
//
|
|
5395
|
+
// TODO handle virtual space
|
|
5396
|
+
|
|
5397
|
+
// TODO editors behave differently when selecting next occurrence, for example:
|
|
5398
|
+
|
|
5399
|
+
// aaa
|
|
5400
|
+
// bbb 1
|
|
5401
|
+
// ccc
|
|
5402
|
+
// bbb 2
|
|
5403
|
+
// bbb 3
|
|
5404
|
+
// aaa
|
|
5405
|
+
// bbb 4
|
|
5406
|
+
// ccc
|
|
5407
|
+
|
|
5408
|
+
// when clicking first at position 4 and then position 2,
|
|
5409
|
+
// - vscode selects next position 3 and refuses to select position 1
|
|
5410
|
+
// - atom also selects next position 3 and refuses to select position 1
|
|
5411
|
+
// - WebStorm also selects next position 3 and refuses to select position 1
|
|
5412
|
+
// - brackets (codemirror) selects position 3 and then selects position 1
|
|
5413
|
+
// - sublime selects next position 1, then next position 3
|
|
5883
5414
|
|
|
5884
|
-
// @ts-ignore
|
|
5885
5415
|
const getSelectionEditsSingleLineWord = (lines, selections) => {
|
|
5886
5416
|
const lastSelectionIndex = selections.length - 4;
|
|
5887
5417
|
const rowIndex = selections[lastSelectionIndex];
|
|
@@ -5960,48 +5490,6 @@ const getSelectionEditsSingleLineWord = (lines, selections) => {
|
|
|
5960
5490
|
}
|
|
5961
5491
|
return undefined;
|
|
5962
5492
|
};
|
|
5963
|
-
const RE_ALPHA_NUMERIC = /[a-zA-Z\d]/;
|
|
5964
|
-
|
|
5965
|
-
// @ts-ignore
|
|
5966
|
-
const isAlphaNumeric = char => {
|
|
5967
|
-
return RE_ALPHA_NUMERIC.test(char);
|
|
5968
|
-
};
|
|
5969
|
-
|
|
5970
|
-
// @ts-ignore
|
|
5971
|
-
const getWordStartIndex = (line, index) => {
|
|
5972
|
-
for (let i = index - 1; i >= 0; i--) {
|
|
5973
|
-
if (!isAlphaNumeric(line[i])) {
|
|
5974
|
-
return i + 1;
|
|
5975
|
-
}
|
|
5976
|
-
}
|
|
5977
|
-
return 0;
|
|
5978
|
-
};
|
|
5979
|
-
|
|
5980
|
-
// @ts-ignore
|
|
5981
|
-
const getWordEndIndex = (line, index) => {
|
|
5982
|
-
for (let i = index; i < line.length; i++) {
|
|
5983
|
-
if (!isAlphaNumeric(line[i])) {
|
|
5984
|
-
return i;
|
|
5985
|
-
}
|
|
5986
|
-
}
|
|
5987
|
-
return line.length - 1;
|
|
5988
|
-
};
|
|
5989
|
-
|
|
5990
|
-
// @ts-ignore
|
|
5991
|
-
const getWordMatchAtPosition = (lines, rowIndex, columnIndex) => {
|
|
5992
|
-
const line = lines[rowIndex];
|
|
5993
|
-
const index = columnIndex;
|
|
5994
|
-
const start = getWordStartIndex(line, index);
|
|
5995
|
-
const end = getWordEndIndex(line, index);
|
|
5996
|
-
const word = line.slice(start, end);
|
|
5997
|
-
return {
|
|
5998
|
-
start,
|
|
5999
|
-
end,
|
|
6000
|
-
word
|
|
6001
|
-
};
|
|
6002
|
-
};
|
|
6003
|
-
|
|
6004
|
-
// @ts-ignore
|
|
6005
5493
|
const getSelectNextOccurrenceResult = editor => {
|
|
6006
5494
|
const lines = editor.lines;
|
|
6007
5495
|
const selections = editor.selections;
|
|
@@ -6033,13 +5521,31 @@ const getSelectNextOccurrenceResult = editor => {
|
|
|
6033
5521
|
return undefined;
|
|
6034
5522
|
};
|
|
6035
5523
|
|
|
6036
|
-
//
|
|
5524
|
+
// TODO handle virtual space
|
|
5525
|
+
|
|
5526
|
+
// TODO editors behave differently when selecting next occurrence, for example:
|
|
5527
|
+
|
|
5528
|
+
// aaa
|
|
5529
|
+
// bbb 1
|
|
5530
|
+
// ccc
|
|
5531
|
+
// bbb 2
|
|
5532
|
+
// bbb 3
|
|
5533
|
+
// aaa
|
|
5534
|
+
// bbb 4
|
|
5535
|
+
// ccc
|
|
5536
|
+
|
|
5537
|
+
// when clicking first at position 4 and then position 2,
|
|
5538
|
+
// - vscode selects next position 3 and refuses to select position 1
|
|
5539
|
+
// - atom also selects next position 3 and refuses to select position 1
|
|
5540
|
+
// - WebStorm also selects next position 3 and refuses to select position 1
|
|
5541
|
+
// - brackets (codemirror) selects position 3 and then selects position 1
|
|
5542
|
+
// - sublime selects next position 1, then next position 3
|
|
5543
|
+
|
|
6037
5544
|
const isRangeInViewPort = (minLineY, maxLineY, startRowIndex, endRowIndex) => {
|
|
6038
5545
|
return startRowIndex >= minLineY && endRowIndex <= maxLineY;
|
|
6039
5546
|
};
|
|
6040
5547
|
|
|
6041
5548
|
// TODO handle virtual space
|
|
6042
|
-
// @ts-ignore
|
|
6043
5549
|
const selectNextOccurrence = editor => {
|
|
6044
5550
|
const result = getSelectNextOccurrenceResult(editor);
|
|
6045
5551
|
if (!result) {
|
|
@@ -6054,7 +5560,6 @@ const selectNextOccurrence = editor => {
|
|
|
6054
5560
|
}
|
|
6055
5561
|
// TODO what is this magic number 5?
|
|
6056
5562
|
// const deltaY = (revealRangeStartRowIndex - 5) * editor.rowHeight
|
|
6057
|
-
// @ts-ignore
|
|
6058
5563
|
return scheduleDocumentAndCursorsSelections(editor, [], selectionEdits);
|
|
6059
5564
|
};
|
|
6060
5565
|
|
|
@@ -6973,7 +6478,6 @@ const typeWithAutoClosing = async (editor, text) => {
|
|
|
6973
6478
|
// EditorCommandCompletion.openFromType(editor, text)
|
|
6974
6479
|
};
|
|
6975
6480
|
|
|
6976
|
-
// @ts-ignore
|
|
6977
6481
|
const inverseChange = edit => {
|
|
6978
6482
|
const endColumnIndex = edit.end.columnIndex - edit.deleted[0].length + edit.inserted[0].length;
|
|
6979
6483
|
return {
|
|
@@ -6987,7 +6491,6 @@ const inverseChange = edit => {
|
|
|
6987
6491
|
};
|
|
6988
6492
|
};
|
|
6989
6493
|
|
|
6990
|
-
// @ts-ignore
|
|
6991
6494
|
const undo = state => {
|
|
6992
6495
|
const {
|
|
6993
6496
|
undoStack
|
|
@@ -7203,7 +6706,7 @@ const select = async (editor, completionItem) => {
|
|
|
7203
6706
|
();
|
|
7204
6707
|
if (index !== -1) {
|
|
7205
6708
|
editor.widgets.splice(index, 1);
|
|
7206
|
-
editor.completionState = None;
|
|
6709
|
+
editor.completionState = None$1;
|
|
7207
6710
|
editor.completionUid = 0;
|
|
7208
6711
|
}
|
|
7209
6712
|
// TODO dispose completion widget
|
|
@@ -7266,7 +6769,7 @@ const getHover = async (editor, offset) => {
|
|
|
7266
6769
|
|
|
7267
6770
|
let _ipc;
|
|
7268
6771
|
const listen$5 = async () => {
|
|
7269
|
-
const ipc = await create({
|
|
6772
|
+
const ipc = await create$1({
|
|
7270
6773
|
method: RendererProcess
|
|
7271
6774
|
});
|
|
7272
6775
|
handleIpc(ipc);
|
|
@@ -7495,6 +6998,14 @@ const handleSashPointerUp = (state, eventX, eventY) => {
|
|
|
7495
6998
|
return state;
|
|
7496
6999
|
};
|
|
7497
7000
|
|
|
7001
|
+
const text = data => {
|
|
7002
|
+
return {
|
|
7003
|
+
type: Text,
|
|
7004
|
+
text: data,
|
|
7005
|
+
childCount: 0
|
|
7006
|
+
};
|
|
7007
|
+
};
|
|
7008
|
+
|
|
7498
7009
|
const getLineInfoVirtualDom = lineInfo => {
|
|
7499
7010
|
const dom = [{
|
|
7500
7011
|
type: Div,
|
|
@@ -7582,7 +7093,7 @@ const renderHoverDom = {
|
|
|
7582
7093
|
return [/* method */'Viewlet.setDom2', dom];
|
|
7583
7094
|
}
|
|
7584
7095
|
};
|
|
7585
|
-
const renderBounds = {
|
|
7096
|
+
const renderBounds$1 = {
|
|
7586
7097
|
isEqual(oldState, newState) {
|
|
7587
7098
|
return oldState.x === newState.x && oldState.y === newState.y && oldState.resizedWidth === newState.resizedWidth;
|
|
7588
7099
|
},
|
|
@@ -7600,10 +7111,10 @@ const renderBounds = {
|
|
|
7600
7111
|
return [SetBounds, x, y, resizedWidth, height];
|
|
7601
7112
|
}
|
|
7602
7113
|
};
|
|
7603
|
-
const render$
|
|
7114
|
+
const render$3 = [renderHoverDom, renderBounds$1];
|
|
7604
7115
|
const renderHover = async (oldState, newState) => {
|
|
7605
7116
|
const commands = [];
|
|
7606
|
-
for (const item of render$
|
|
7117
|
+
for (const item of render$3) {
|
|
7607
7118
|
if (!item.isEqual(oldState, newState)) {
|
|
7608
7119
|
commands.push(item.apply(oldState, newState));
|
|
7609
7120
|
}
|
|
@@ -7909,7 +7420,7 @@ const moveLineUp = editor => {
|
|
|
7909
7420
|
};
|
|
7910
7421
|
|
|
7911
7422
|
const Link$1 = 'Link';
|
|
7912
|
-
const Function = 'Function';
|
|
7423
|
+
const Function$1 = 'Function';
|
|
7913
7424
|
const Parameter = 'Parameter';
|
|
7914
7425
|
const Type = 'Type';
|
|
7915
7426
|
const VariableName = 'VariableName';
|
|
@@ -7968,7 +7479,7 @@ const getDecorationClassName = type => {
|
|
|
7968
7479
|
case Ts3073:
|
|
7969
7480
|
case Ts3077:
|
|
7970
7481
|
case Ts3088:
|
|
7971
|
-
return Function;
|
|
7482
|
+
return Function$1;
|
|
7972
7483
|
case Ts1792:
|
|
7973
7484
|
case Ts1793:
|
|
7974
7485
|
return Parameter;
|
|
@@ -8004,521 +7515,872 @@ const getDecorationClassName = type => {
|
|
|
8004
7515
|
return `Unknown-${type}`;
|
|
8005
7516
|
}
|
|
8006
7517
|
};
|
|
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;
|
|
7518
|
+
|
|
7519
|
+
const getTokensViewportEmbedded = (langageId, lines, lineCache, linesWithEmbed) => {
|
|
7520
|
+
const tokenizersToLoad = [];
|
|
7521
|
+
const embeddedResults = [];
|
|
7522
|
+
let topContext;
|
|
7523
|
+
for (const index of linesWithEmbed) {
|
|
7524
|
+
const result = lineCache[index + 1];
|
|
7525
|
+
const line = lines[index];
|
|
7526
|
+
if (result.embeddedLanguage) {
|
|
7527
|
+
const {
|
|
7528
|
+
embeddedLanguage,
|
|
7529
|
+
embeddedLanguageStart,
|
|
7530
|
+
embeddedLanguageEnd
|
|
7531
|
+
} = result;
|
|
7532
|
+
const embeddedTokenizer = getTokenizer(embeddedLanguage);
|
|
7533
|
+
if (embeddedLanguageStart !== line.length && embeddedTokenizer && embeddedTokenizer !== TokenizePlainText) {
|
|
7534
|
+
const isFull = embeddedLanguageStart === 0 && embeddedLanguageEnd === line.length;
|
|
7535
|
+
const partialLine = line.slice(embeddedLanguageStart, embeddedLanguageEnd);
|
|
7536
|
+
const embedResult = safeTokenizeLine(langageId, embeddedTokenizer.tokenizeLine, partialLine, topContext || getInitialLineState(embeddedTokenizer.initialLineState), embeddedTokenizer.hasArrayReturn);
|
|
7537
|
+
topContext = embedResult;
|
|
7538
|
+
result.embeddedResultIndex = embeddedResults.length;
|
|
7539
|
+
embeddedResults.push({
|
|
7540
|
+
result: embedResult,
|
|
7541
|
+
TokenMap: embeddedTokenizer.TokenMap,
|
|
7542
|
+
isFull
|
|
7543
|
+
});
|
|
7544
|
+
} else if (line.length === 0) {
|
|
7545
|
+
const embedResult = {
|
|
7546
|
+
tokens: []
|
|
7547
|
+
};
|
|
7548
|
+
result.embeddedResultIndex = embeddedResults.length;
|
|
7549
|
+
embeddedResults.push({
|
|
7550
|
+
result: embedResult,
|
|
7551
|
+
isFull: true,
|
|
7552
|
+
TokenMap: []
|
|
7553
|
+
});
|
|
7554
|
+
} else {
|
|
7555
|
+
tokenizersToLoad.push(embeddedLanguage);
|
|
7556
|
+
embeddedResults.push({
|
|
7557
|
+
result: {},
|
|
7558
|
+
isFull: false,
|
|
7559
|
+
TokenMap: []
|
|
7560
|
+
});
|
|
7561
|
+
topContext = undefined;
|
|
7562
|
+
}
|
|
7563
|
+
} else {
|
|
7564
|
+
topContext = undefined;
|
|
7565
|
+
}
|
|
7566
|
+
}
|
|
7567
|
+
return {
|
|
7568
|
+
tokenizersToLoad,
|
|
7569
|
+
embeddedResults
|
|
7570
|
+
};
|
|
7571
|
+
};
|
|
7572
|
+
const getTokenizeEndIndex = (invalidStartIndex, endLineIndex, tokenizeStartIndex) => {
|
|
7573
|
+
return invalidStartIndex < endLineIndex ? endLineIndex : tokenizeStartIndex;
|
|
7574
|
+
};
|
|
7575
|
+
|
|
7576
|
+
// TODO only send changed lines to renderer process instead of all lines in viewport
|
|
7577
|
+
const getTokensViewport = (editor, startLineIndex, endLineIndex) => {
|
|
7578
|
+
const {
|
|
7579
|
+
invalidStartIndex,
|
|
7580
|
+
lineCache,
|
|
7581
|
+
tokenizerId,
|
|
7582
|
+
lines,
|
|
7583
|
+
languageId
|
|
7584
|
+
} = editor;
|
|
7585
|
+
const tokenizer = get(tokenizerId);
|
|
7586
|
+
const {
|
|
7587
|
+
hasArrayReturn,
|
|
7588
|
+
tokenizeLine,
|
|
7589
|
+
initialLineState
|
|
7590
|
+
} = tokenizer;
|
|
7591
|
+
const tokenizeStartIndex = invalidStartIndex;
|
|
7592
|
+
const tokenizeEndIndex = getTokenizeEndIndex(invalidStartIndex, endLineIndex, tokenizeStartIndex);
|
|
7593
|
+
const tokenizersToLoad = [];
|
|
7594
|
+
const embeddedResults = [];
|
|
7595
|
+
const linesWithEmbed = [];
|
|
7596
|
+
for (let i = tokenizeStartIndex; i < tokenizeEndIndex; i++) {
|
|
7597
|
+
const lineState = i === 0 ? getInitialLineState(initialLineState) : lineCache[i];
|
|
7598
|
+
const line = lines[i];
|
|
7599
|
+
const result = safeTokenizeLine(languageId, tokenizeLine, line, lineState, hasArrayReturn);
|
|
7600
|
+
// TODO if lineCacheEnd matches the one before, skip tokenizing lines after
|
|
7601
|
+
lineCache[i + 1] = result;
|
|
7602
|
+
if (result.embeddedLanguage) {
|
|
7603
|
+
result.embeddedResultIndex = linesWithEmbed.length;
|
|
7604
|
+
linesWithEmbed.push(i);
|
|
7605
|
+
}
|
|
7606
|
+
}
|
|
7607
|
+
const visibleLines = lineCache.slice(startLineIndex + 1, endLineIndex + 1);
|
|
7608
|
+
if (linesWithEmbed.length > 0) {
|
|
7609
|
+
const {
|
|
7610
|
+
tokenizersToLoad,
|
|
7611
|
+
embeddedResults
|
|
7612
|
+
} = getTokensViewportEmbedded(languageId, lines, lineCache, linesWithEmbed);
|
|
7613
|
+
// TODO support lineCache with embedded content
|
|
7614
|
+
editor.invalidStartIndex = 0;
|
|
7615
|
+
return {
|
|
7616
|
+
tokens: visibleLines,
|
|
7617
|
+
tokenizersToLoad,
|
|
7618
|
+
embeddedResults
|
|
7619
|
+
};
|
|
7620
|
+
}
|
|
7621
|
+
editor.invalidStartIndex = Math.max(invalidStartIndex, tokenizeEndIndex);
|
|
7622
|
+
return {
|
|
7623
|
+
tokens: visibleLines,
|
|
7624
|
+
tokenizersToLoad,
|
|
7625
|
+
embeddedResults
|
|
7626
|
+
};
|
|
7627
|
+
};
|
|
7628
|
+
|
|
7629
|
+
const sentLines = Object.create(null);
|
|
7630
|
+
|
|
7631
|
+
// TODO only send changed lines to renderer process instead of all lines in viewport
|
|
7632
|
+
const getTokensViewport2 = (editor, startLineIndex, endLineIndex, syncIncremental) => {
|
|
7633
|
+
if (getEnabled$1()) {
|
|
7634
|
+
if (syncIncremental) {
|
|
7635
|
+
const {
|
|
7636
|
+
invalidStartIndex,
|
|
7637
|
+
lines,
|
|
7638
|
+
languageId,
|
|
7639
|
+
id
|
|
7640
|
+
} = editor;
|
|
7641
|
+
let hasLinesToSend = true;
|
|
7642
|
+
let linesToSend = lines;
|
|
7643
|
+
if (sentLines[id] === lines) {
|
|
7644
|
+
hasLinesToSend = false;
|
|
7645
|
+
linesToSend = [];
|
|
7646
|
+
} else {
|
|
7647
|
+
sentLines[id] = lines;
|
|
7648
|
+
}
|
|
7649
|
+
const slimEditor = {
|
|
7650
|
+
languageId,
|
|
7651
|
+
invalidStartIndex
|
|
7652
|
+
};
|
|
7653
|
+
return invoke$1('GetTokensViewport.getTokensViewport', slimEditor, startLineIndex, endLineIndex, hasLinesToSend, id, linesToSend);
|
|
7654
|
+
}
|
|
7655
|
+
// TODO only send needed lines of text
|
|
7656
|
+
return invoke$1('GetTokensViewport.getTokensViewport', editor, startLineIndex, endLineIndex, true, editor.id, editor.lines);
|
|
7657
|
+
}
|
|
7658
|
+
return getTokensViewport(editor, startLineIndex, endLineIndex);
|
|
7659
|
+
};
|
|
7660
|
+
|
|
7661
|
+
const loadTokenizers = async languageIds => {
|
|
7662
|
+
for (const languageId of languageIds) {
|
|
7663
|
+
// @ts-ignore
|
|
7664
|
+
await loadTokenizer(languageId);
|
|
7665
|
+
}
|
|
7666
|
+
};
|
|
7667
|
+
|
|
7668
|
+
// const getTokensIncremental = (editor, min, max) => {
|
|
7669
|
+
// const currentLength = editor.lineStateCache.length
|
|
7670
|
+
// const tokens = []
|
|
7671
|
+
// const lines = editor.lines
|
|
7672
|
+
// let lineState = editor.tokenizer.initialLineState
|
|
7673
|
+
// for (let i = currentLength; i < max; i++) {
|
|
7674
|
+
// const line = lines[i]
|
|
7675
|
+
// try {
|
|
7676
|
+
// lineState = editor.tokenizer.tokenizeLine(line, lineState)
|
|
7677
|
+
// if (!lineState || !lineState.tokens || !lineState.state) {
|
|
7678
|
+
// throw new Error('invalid tokenization result')
|
|
7679
|
+
// }
|
|
7680
|
+
// } catch (error) {
|
|
7681
|
+
// tokens.push([{ length: line.length, type: 0 }])
|
|
7682
|
+
// console.error(error)
|
|
7683
|
+
// // renderWithoutSyntaxHighlighting(state, firstRow, lastRow)
|
|
7684
|
+
// continue
|
|
7685
|
+
// }
|
|
7686
|
+
// const newTokens = lineState.tokens
|
|
7687
|
+
// tokens.push(newTokens)
|
|
7688
|
+
// }
|
|
7689
|
+
// return tokens
|
|
7690
|
+
// }
|
|
7691
|
+
|
|
7692
|
+
// const getLineInfosIncremental = (editor, tokens, minLineY, maxLineY) => {
|
|
7693
|
+
// const result = []
|
|
7694
|
+
// const lines = editor.lines
|
|
7695
|
+
// const TokenMap = editor.tokenizer.TokenMap
|
|
7696
|
+
// for (let i = minLineY; i < maxLineY; i++) {
|
|
7697
|
+
// result.push(getLineInfo(lines[i], tokens[i], TokenMap))
|
|
7698
|
+
// }
|
|
7699
|
+
// return result
|
|
7700
|
+
// }
|
|
7701
|
+
|
|
7702
|
+
const getStartDefaults = (tokens, minOffset) => {
|
|
7703
|
+
let start = 0;
|
|
7704
|
+
let end = 0;
|
|
7705
|
+
let startIndex = 0;
|
|
7706
|
+
const tokensLength = tokens.length;
|
|
7707
|
+
for (let i = 0; i < tokensLength; i += 2) {
|
|
7708
|
+
const tokenLength = tokens[i + 1];
|
|
7709
|
+
end += tokenLength;
|
|
7710
|
+
start = end;
|
|
7711
|
+
if (start >= minOffset) {
|
|
7712
|
+
start -= tokenLength;
|
|
7713
|
+
end -= tokenLength;
|
|
7714
|
+
startIndex = i;
|
|
7715
|
+
break;
|
|
7716
|
+
}
|
|
7717
|
+
}
|
|
7718
|
+
return {
|
|
7719
|
+
start,
|
|
7720
|
+
end,
|
|
7721
|
+
startIndex
|
|
7722
|
+
};
|
|
7723
|
+
};
|
|
7724
|
+
const getLineInfoEmbeddedFull = (embeddedResults, tokenResults, line, normalize, tabSize, width, deltaX, averageCharWidth, minOffset, maxOffset) => {
|
|
7725
|
+
const lineInfo = [];
|
|
7726
|
+
const embeddedResult = embeddedResults[tokenResults.embeddedResultIndex];
|
|
7727
|
+
const embeddedTokens = embeddedResult.result.tokens;
|
|
7728
|
+
const embeddedTokenMap = embeddedResult.TokenMap;
|
|
7729
|
+
const tokensLength = embeddedTokens.length;
|
|
7730
|
+
let {
|
|
7731
|
+
startIndex,
|
|
7732
|
+
start,
|
|
7733
|
+
end
|
|
7734
|
+
} = getStartDefaults(embeddedTokens, minOffset);
|
|
7735
|
+
const difference = getDifference(start, averageCharWidth, deltaX);
|
|
7736
|
+
for (let i = startIndex; i < tokensLength; i += 2) {
|
|
7737
|
+
const tokenType = embeddedTokens[i];
|
|
7738
|
+
const tokenLength = embeddedTokens[i + 1];
|
|
7739
|
+
end += tokenLength;
|
|
7740
|
+
const className = `Token ${embeddedTokenMap[tokenType] || 'Unknown'}`;
|
|
7741
|
+
const text = line.slice(start, end);
|
|
7742
|
+
const normalizedText = normalizeText(text, normalize, tabSize);
|
|
7743
|
+
lineInfo.push(normalizedText, className);
|
|
7744
|
+
start = end;
|
|
7745
|
+
if (end >= maxOffset) {
|
|
7746
|
+
break;
|
|
8054
7747
|
}
|
|
8055
7748
|
}
|
|
8056
7749
|
return {
|
|
8057
|
-
|
|
8058
|
-
|
|
7750
|
+
lineInfo,
|
|
7751
|
+
difference
|
|
8059
7752
|
};
|
|
8060
7753
|
};
|
|
8061
|
-
const
|
|
8062
|
-
|
|
7754
|
+
const getOffsets = (deltaX, width, averageCharWidth) => {
|
|
7755
|
+
// TODO accurately measure char widths using offscreen canvas
|
|
7756
|
+
// and use fast measurements for monospace ascii text
|
|
7757
|
+
if (deltaX === 0) {
|
|
7758
|
+
return {
|
|
7759
|
+
minOffset: 0,
|
|
7760
|
+
maxOffset: Math.ceil(width / averageCharWidth)
|
|
7761
|
+
};
|
|
7762
|
+
}
|
|
7763
|
+
const minOffset = Math.ceil(deltaX / averageCharWidth);
|
|
7764
|
+
const maxOffset = minOffset + Math.ceil(width / averageCharWidth);
|
|
7765
|
+
return {
|
|
7766
|
+
minOffset,
|
|
7767
|
+
maxOffset
|
|
7768
|
+
};
|
|
7769
|
+
};
|
|
7770
|
+
const getDifference = (start, averageCharWidth, deltaX) => {
|
|
7771
|
+
const beforeWidth = start * averageCharWidth;
|
|
7772
|
+
const difference = beforeWidth - deltaX;
|
|
7773
|
+
return difference;
|
|
7774
|
+
};
|
|
7775
|
+
const getLineInfoDefault = (line, tokenResults, embeddedResults, decorations, TokenMap, lineOffset, normalize, tabSize, width, deltaX, averageCharWidth, minOffset, maxOffset) => {
|
|
7776
|
+
const lineInfo = [];
|
|
7777
|
+
let decorationIndex = 0;
|
|
7778
|
+
for (; decorationIndex < decorations.length; decorationIndex += 3) {
|
|
7779
|
+
const decorationOffset = decorations[decorationIndex];
|
|
7780
|
+
if (decorationOffset >= lineOffset) {
|
|
7781
|
+
break;
|
|
7782
|
+
}
|
|
7783
|
+
}
|
|
7784
|
+
const tokens = tokenResults.tokens;
|
|
7785
|
+
let {
|
|
7786
|
+
startIndex,
|
|
7787
|
+
start,
|
|
7788
|
+
end
|
|
7789
|
+
} = getStartDefaults(tokens, minOffset);
|
|
7790
|
+
const difference = getDifference(start, averageCharWidth, deltaX);
|
|
7791
|
+
const tokensLength = tokens.length;
|
|
7792
|
+
for (let i = startIndex; i < tokensLength; i += 2) {
|
|
7793
|
+
const tokenType = tokens[i];
|
|
7794
|
+
const tokenLength = tokens[i + 1];
|
|
7795
|
+
const decorationOffset = decorations[decorationIndex];
|
|
7796
|
+
let extraClassName = '';
|
|
7797
|
+
if (decorationOffset !== undefined && decorationOffset - lineOffset === start) {
|
|
7798
|
+
// @ts-ignore
|
|
7799
|
+
decorations[++decorationIndex];
|
|
7800
|
+
const decorationType = decorations[++decorationIndex];
|
|
7801
|
+
// @ts-ignore
|
|
7802
|
+
decorations[++decorationIndex];
|
|
7803
|
+
// console.log('MATCHING DECORATION', {
|
|
7804
|
+
// decorationIndex,
|
|
7805
|
+
// decorationLength,
|
|
7806
|
+
// decorationType,
|
|
7807
|
+
// decorationModifiers,
|
|
7808
|
+
// })
|
|
7809
|
+
extraClassName = getDecorationClassName(decorationType);
|
|
7810
|
+
}
|
|
7811
|
+
end += tokenLength;
|
|
7812
|
+
const text = line.slice(start, end);
|
|
7813
|
+
const className = `Token ${extraClassName || TokenMap[tokenType] || 'Unknown'}`;
|
|
7814
|
+
const normalizedText = normalizeText(text, normalize, tabSize);
|
|
7815
|
+
lineInfo.push(normalizedText, className);
|
|
7816
|
+
start = end;
|
|
7817
|
+
if (end >= maxOffset) {
|
|
7818
|
+
break;
|
|
7819
|
+
}
|
|
7820
|
+
}
|
|
7821
|
+
return {
|
|
7822
|
+
lineInfo,
|
|
7823
|
+
difference
|
|
7824
|
+
};
|
|
7825
|
+
};
|
|
7826
|
+
const getLineInfo = (line, tokenResults, embeddedResults, decorations, TokenMap, lineOffset, normalize, tabSize, width, deltaX, averageCharWidth) => {
|
|
7827
|
+
const {
|
|
7828
|
+
minOffset,
|
|
7829
|
+
maxOffset
|
|
7830
|
+
} = getOffsets(deltaX, width, averageCharWidth);
|
|
7831
|
+
if (embeddedResults.length > 0 && tokenResults.embeddedResultIndex !== undefined) {
|
|
7832
|
+
const embeddedResult = embeddedResults[tokenResults.embeddedResultIndex];
|
|
7833
|
+
if (embeddedResult && embeddedResult.isFull) {
|
|
7834
|
+
return getLineInfoEmbeddedFull(embeddedResults, tokenResults, line, normalize, tabSize, width, deltaX, averageCharWidth, minOffset, maxOffset);
|
|
7835
|
+
}
|
|
7836
|
+
}
|
|
7837
|
+
return getLineInfoDefault(line, tokenResults, embeddedResults, decorations, TokenMap, lineOffset, normalize, tabSize, width, deltaX, averageCharWidth, minOffset, maxOffset);
|
|
8063
7838
|
};
|
|
8064
7839
|
|
|
8065
|
-
// TODO
|
|
8066
|
-
const
|
|
7840
|
+
// TODO need lots of tests for this
|
|
7841
|
+
const getLineInfosViewport = (editor, tokens, embeddedResults, minLineY, maxLineY, minLineOffset, width, deltaX, averageCharWidth) => {
|
|
7842
|
+
const result = [];
|
|
7843
|
+
const differences = [];
|
|
8067
7844
|
const {
|
|
8068
|
-
invalidStartIndex,
|
|
8069
|
-
lineCache,
|
|
8070
|
-
tokenizerId,
|
|
8071
7845
|
lines,
|
|
7846
|
+
decorations,
|
|
8072
7847
|
languageId
|
|
8073
7848
|
} = 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];
|
|
7849
|
+
const tokenMap = get$1(languageId);
|
|
7850
|
+
let offset = minLineOffset;
|
|
7851
|
+
const tabSize = 2;
|
|
7852
|
+
for (let i = minLineY; i < maxLineY; i++) {
|
|
8087
7853
|
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) {
|
|
7854
|
+
const normalize = shouldNormalizeText(line);
|
|
8098
7855
|
const {
|
|
8099
|
-
|
|
8100
|
-
|
|
8101
|
-
} =
|
|
8102
|
-
|
|
8103
|
-
|
|
8104
|
-
|
|
8105
|
-
tokens: visibleLines,
|
|
8106
|
-
tokenizersToLoad,
|
|
8107
|
-
embeddedResults
|
|
8108
|
-
};
|
|
7856
|
+
lineInfo,
|
|
7857
|
+
difference
|
|
7858
|
+
} = getLineInfo(line, tokens[i - minLineY], embeddedResults, decorations, tokenMap, offset, normalize, tabSize, width, deltaX, averageCharWidth);
|
|
7859
|
+
result.push(lineInfo);
|
|
7860
|
+
differences.push(difference);
|
|
7861
|
+
offset += line.length + 1;
|
|
8109
7862
|
}
|
|
8110
|
-
editor.invalidStartIndex = Math.max(invalidStartIndex, tokenizeEndIndex);
|
|
8111
7863
|
return {
|
|
8112
|
-
|
|
7864
|
+
result,
|
|
7865
|
+
differences
|
|
7866
|
+
};
|
|
7867
|
+
};
|
|
7868
|
+
const getVisible = async (editor, syncIncremental) => {
|
|
7869
|
+
// console.log({ editor })
|
|
7870
|
+
// TODO should separate rendering from business logic somehow
|
|
7871
|
+
// currently hard to test because need to mock editor height, top, left,
|
|
7872
|
+
// invalidStartIndex, lineCache, etc. just for testing editorType
|
|
7873
|
+
// editor.invalidStartIndex = changes[0].start.rowIndex
|
|
7874
|
+
// @ts-ignore
|
|
7875
|
+
const {
|
|
7876
|
+
minLineY,
|
|
7877
|
+
numberOfVisibleLines,
|
|
7878
|
+
lines,
|
|
7879
|
+
width,
|
|
7880
|
+
deltaX,
|
|
7881
|
+
fontWeight,
|
|
7882
|
+
fontSize,
|
|
7883
|
+
fontFamily,
|
|
7884
|
+
letterSpacing,
|
|
7885
|
+
charWidth
|
|
7886
|
+
} = editor;
|
|
7887
|
+
const maxLineY = Math.min(minLineY + numberOfVisibleLines, lines.length);
|
|
7888
|
+
const {
|
|
7889
|
+
tokens,
|
|
8113
7890
|
tokenizersToLoad,
|
|
8114
7891
|
embeddedResults
|
|
7892
|
+
} = await getTokensViewport2(editor, minLineY, maxLineY, syncIncremental);
|
|
7893
|
+
const minLineOffset = offsetAtSync(editor, minLineY, 0);
|
|
7894
|
+
const averageCharWidth = charWidth;
|
|
7895
|
+
const {
|
|
7896
|
+
result,
|
|
7897
|
+
differences
|
|
7898
|
+
} = getLineInfosViewport(editor, tokens, embeddedResults, minLineY, maxLineY, minLineOffset, width, deltaX, averageCharWidth);
|
|
7899
|
+
if (tokenizersToLoad.length > 0) {
|
|
7900
|
+
loadTokenizers(tokenizersToLoad);
|
|
7901
|
+
}
|
|
7902
|
+
return {
|
|
7903
|
+
textInfos: result,
|
|
7904
|
+
differences
|
|
8115
7905
|
};
|
|
8116
7906
|
};
|
|
8117
7907
|
|
|
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);
|
|
7908
|
+
const getCursorsVirtualDom = cursors => {
|
|
7909
|
+
const dom = [];
|
|
7910
|
+
for (const translate of cursors) {
|
|
7911
|
+
dom.push({
|
|
7912
|
+
type: Div,
|
|
7913
|
+
className: EditorCursor,
|
|
7914
|
+
translate
|
|
7915
|
+
});
|
|
8146
7916
|
}
|
|
8147
|
-
return
|
|
7917
|
+
return dom;
|
|
8148
7918
|
};
|
|
8149
7919
|
|
|
8150
|
-
const
|
|
8151
|
-
|
|
8152
|
-
|
|
8153
|
-
|
|
7920
|
+
const Error$1 = 'error';
|
|
7921
|
+
const Warning = 'warning';
|
|
7922
|
+
|
|
7923
|
+
const getDiagnosticClassName = type => {
|
|
7924
|
+
// TODO use classnames enum
|
|
7925
|
+
switch (type) {
|
|
7926
|
+
case Error$1:
|
|
7927
|
+
return 'DiagnosticError';
|
|
7928
|
+
case Warning:
|
|
7929
|
+
return 'DiagnosticWarning';
|
|
7930
|
+
default:
|
|
7931
|
+
return 'DiagnosticError';
|
|
8154
7932
|
}
|
|
8155
7933
|
};
|
|
7934
|
+
const getDiagnosticVirtualDom = diagnostic => {
|
|
7935
|
+
const {
|
|
7936
|
+
x,
|
|
7937
|
+
y,
|
|
7938
|
+
width,
|
|
7939
|
+
height,
|
|
7940
|
+
type
|
|
7941
|
+
} = diagnostic;
|
|
7942
|
+
const extraClassName = getDiagnosticClassName(type);
|
|
7943
|
+
return [{
|
|
7944
|
+
type: Div,
|
|
7945
|
+
className: `${Diagnostic} ${extraClassName}`,
|
|
7946
|
+
width,
|
|
7947
|
+
height,
|
|
7948
|
+
top: y,
|
|
7949
|
+
left: x,
|
|
7950
|
+
childCount: 0
|
|
7951
|
+
}];
|
|
7952
|
+
};
|
|
8156
7953
|
|
|
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
|
-
// }
|
|
7954
|
+
const getDiagnosticsVirtualDom = diagnostics => {
|
|
7955
|
+
const dom = diagnostics.flatMap(getDiagnosticVirtualDom);
|
|
7956
|
+
return dom;
|
|
7957
|
+
};
|
|
8180
7958
|
|
|
8181
|
-
|
|
8182
|
-
|
|
8183
|
-
|
|
8184
|
-
|
|
8185
|
-
|
|
8186
|
-
|
|
8187
|
-
|
|
8188
|
-
|
|
8189
|
-
|
|
7959
|
+
const getGutterInfoVirtualDom = gutterInfo => {
|
|
7960
|
+
return [{
|
|
7961
|
+
type: Span,
|
|
7962
|
+
className: 'LineNumber',
|
|
7963
|
+
childCount: 1
|
|
7964
|
+
}, text(gutterInfo)];
|
|
7965
|
+
};
|
|
7966
|
+
const getEditorGutterVirtualDom = gutterInfos => {
|
|
7967
|
+
const dom = gutterInfos.flatMap(getGutterInfoVirtualDom);
|
|
7968
|
+
return dom;
|
|
7969
|
+
};
|
|
8190
7970
|
|
|
8191
|
-
const
|
|
8192
|
-
|
|
8193
|
-
let
|
|
8194
|
-
|
|
8195
|
-
|
|
8196
|
-
|
|
8197
|
-
|
|
8198
|
-
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
|
|
8202
|
-
|
|
8203
|
-
|
|
8204
|
-
|
|
7971
|
+
const getEditorRowsVirtualDom = (textInfos, differences, lineNumbers = true) => {
|
|
7972
|
+
const dom = [];
|
|
7973
|
+
for (let i = 0; i < textInfos.length; i++) {
|
|
7974
|
+
const textInfo = textInfos[i];
|
|
7975
|
+
const difference = differences[i];
|
|
7976
|
+
dom.push({
|
|
7977
|
+
type: Div,
|
|
7978
|
+
className: EditorRow,
|
|
7979
|
+
translate: px(difference),
|
|
7980
|
+
childCount: textInfo.length / 2
|
|
7981
|
+
});
|
|
7982
|
+
for (let j = 0; j < textInfo.length; j += 2) {
|
|
7983
|
+
const tokenText = textInfo[j];
|
|
7984
|
+
const className = textInfo[j + 1];
|
|
7985
|
+
dom.push({
|
|
7986
|
+
type: Span,
|
|
7987
|
+
className,
|
|
7988
|
+
childCount: 1
|
|
7989
|
+
}, text(tokenText));
|
|
8205
7990
|
}
|
|
8206
7991
|
}
|
|
8207
|
-
return
|
|
8208
|
-
start,
|
|
8209
|
-
end,
|
|
8210
|
-
startIndex
|
|
8211
|
-
};
|
|
7992
|
+
return dom;
|
|
8212
7993
|
};
|
|
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;
|
|
7994
|
+
|
|
7995
|
+
const getIncrementalEdits = async (oldState, newState) => {
|
|
7996
|
+
if (!newState.undoStack) {
|
|
7997
|
+
return undefined;
|
|
7998
|
+
}
|
|
7999
|
+
const lastChanges = newState.undoStack.at(-1);
|
|
8000
|
+
if (lastChanges && lastChanges.length === 1) {
|
|
8001
|
+
const lastChange = lastChanges[0];
|
|
8002
|
+
if (lastChange.origin === EditorType) {
|
|
8003
|
+
const rowIndex = lastChange.start.rowIndex;
|
|
8004
|
+
const lines = newState.lines;
|
|
8005
|
+
const oldLine = oldState.lines[rowIndex];
|
|
8006
|
+
const newLine = lines[rowIndex];
|
|
8007
|
+
const incrementalEdits = await invoke$1('TokenizeIncremental.tokenizeIncremental', newState.uid, newState.languageId, oldLine, newLine, rowIndex, newState.minLineY);
|
|
8008
|
+
if (incrementalEdits && incrementalEdits.length === 1) {
|
|
8009
|
+
return incrementalEdits;
|
|
8010
|
+
}
|
|
8236
8011
|
}
|
|
8237
8012
|
}
|
|
8013
|
+
return undefined;
|
|
8014
|
+
};
|
|
8015
|
+
|
|
8016
|
+
const getSelectionsVirtualDom = selections => {
|
|
8017
|
+
const dom = [];
|
|
8018
|
+
for (let i = 0; i < selections.length; i += 4) {
|
|
8019
|
+
const x = selections[i];
|
|
8020
|
+
const y = selections[i + 1];
|
|
8021
|
+
const width = selections[i + 2];
|
|
8022
|
+
const height = selections[i + 3];
|
|
8023
|
+
dom.push({
|
|
8024
|
+
type: Div,
|
|
8025
|
+
className: EditorSelection,
|
|
8026
|
+
left: x,
|
|
8027
|
+
top: y,
|
|
8028
|
+
width,
|
|
8029
|
+
height
|
|
8030
|
+
});
|
|
8031
|
+
}
|
|
8032
|
+
return dom;
|
|
8033
|
+
};
|
|
8034
|
+
|
|
8035
|
+
const None = 'none';
|
|
8036
|
+
const Option = 'option';
|
|
8037
|
+
|
|
8038
|
+
const getFileIconVirtualDom = icon => {
|
|
8238
8039
|
return {
|
|
8239
|
-
|
|
8240
|
-
|
|
8040
|
+
type: Img,
|
|
8041
|
+
className: FileIcon,
|
|
8042
|
+
src: icon,
|
|
8043
|
+
role: None,
|
|
8044
|
+
childCount: 0
|
|
8241
8045
|
};
|
|
8242
8046
|
};
|
|
8243
|
-
|
|
8244
|
-
|
|
8245
|
-
|
|
8246
|
-
|
|
8247
|
-
return {
|
|
8248
|
-
minOffset: 0,
|
|
8249
|
-
maxOffset: Math.ceil(width / averageCharWidth)
|
|
8250
|
-
};
|
|
8047
|
+
|
|
8048
|
+
const getIconDom = (fileIcon, symbolName) => {
|
|
8049
|
+
if (fileIcon) {
|
|
8050
|
+
return getFileIconVirtualDom(fileIcon);
|
|
8251
8051
|
}
|
|
8252
|
-
const minOffset = Math.ceil(deltaX / averageCharWidth);
|
|
8253
|
-
const maxOffset = minOffset + Math.ceil(width / averageCharWidth);
|
|
8254
8052
|
return {
|
|
8255
|
-
|
|
8256
|
-
|
|
8053
|
+
type: Div,
|
|
8054
|
+
className: `${ColoredMaskIcon} ${symbolName}`,
|
|
8055
|
+
childCount: 0
|
|
8257
8056
|
};
|
|
8258
8057
|
};
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8058
|
+
|
|
8059
|
+
const label1 = {
|
|
8060
|
+
type: Div,
|
|
8061
|
+
className: Label,
|
|
8062
|
+
childCount: 1
|
|
8263
8063
|
};
|
|
8264
|
-
const
|
|
8265
|
-
|
|
8266
|
-
|
|
8267
|
-
|
|
8268
|
-
|
|
8269
|
-
|
|
8270
|
-
|
|
8271
|
-
|
|
8064
|
+
const completionHighlight = {
|
|
8065
|
+
type: Span,
|
|
8066
|
+
className: EditorCompletionItemHighlight,
|
|
8067
|
+
childCount: 1
|
|
8068
|
+
};
|
|
8069
|
+
const getHighlightedLabelDom = (label, highlights) => {
|
|
8070
|
+
if (highlights.length === 0) {
|
|
8071
|
+
return [label1, text(label)];
|
|
8272
8072
|
}
|
|
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;
|
|
8073
|
+
const dom = [];
|
|
8074
|
+
const labelDom = {
|
|
8075
|
+
type: Div,
|
|
8076
|
+
className: Label,
|
|
8077
|
+
childCount: 0
|
|
8078
|
+
};
|
|
8079
|
+
dom.push(labelDom);
|
|
8080
|
+
let position = 0;
|
|
8081
|
+
for (let i = 0; i < highlights.length; i += 2) {
|
|
8082
|
+
const highlightStart = highlights[i];
|
|
8083
|
+
const highlightEnd = highlights[i + 1];
|
|
8084
|
+
if (position < highlightStart) {
|
|
8085
|
+
const beforeText = label.slice(position, highlightStart);
|
|
8086
|
+
labelDom.childCount++;
|
|
8087
|
+
dom.push(text(beforeText));
|
|
8308
8088
|
}
|
|
8089
|
+
const highlightText = label.slice(highlightStart, highlightEnd);
|
|
8090
|
+
labelDom.childCount++;
|
|
8091
|
+
dom.push(completionHighlight, text(highlightText));
|
|
8092
|
+
position = highlightEnd;
|
|
8309
8093
|
}
|
|
8310
|
-
|
|
8311
|
-
|
|
8312
|
-
|
|
8313
|
-
|
|
8094
|
+
if (position < label.length) {
|
|
8095
|
+
const afterText = label.slice(position);
|
|
8096
|
+
labelDom.childCount++;
|
|
8097
|
+
dom.push(text(afterText));
|
|
8098
|
+
}
|
|
8099
|
+
return dom;
|
|
8314
8100
|
};
|
|
8315
|
-
|
|
8101
|
+
|
|
8102
|
+
const getCompletionItemVirtualDom = visibleItem => {
|
|
8316
8103
|
const {
|
|
8317
|
-
|
|
8318
|
-
|
|
8319
|
-
|
|
8320
|
-
|
|
8321
|
-
|
|
8322
|
-
|
|
8323
|
-
|
|
8324
|
-
|
|
8104
|
+
top,
|
|
8105
|
+
label,
|
|
8106
|
+
symbolName,
|
|
8107
|
+
highlights,
|
|
8108
|
+
focused,
|
|
8109
|
+
deprecated,
|
|
8110
|
+
fileIcon
|
|
8111
|
+
} = visibleItem;
|
|
8112
|
+
let className = EditorCompletionItem;
|
|
8113
|
+
if (focused) {
|
|
8114
|
+
className += ' ' + EditorCompletionItemFocused;
|
|
8325
8115
|
}
|
|
8326
|
-
|
|
8116
|
+
if (deprecated) {
|
|
8117
|
+
className += ' ' + EditorCompletionItemDeprecated;
|
|
8118
|
+
}
|
|
8119
|
+
return [{
|
|
8120
|
+
type: Div,
|
|
8121
|
+
role: Option,
|
|
8122
|
+
className,
|
|
8123
|
+
top,
|
|
8124
|
+
childCount: 2
|
|
8125
|
+
}, getIconDom(fileIcon, symbolName), ...getHighlightedLabelDom(label, highlights)];
|
|
8327
8126
|
};
|
|
8328
8127
|
|
|
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;
|
|
8128
|
+
const getCompletionItemsVirtualDom = visibleItems => {
|
|
8129
|
+
if (visibleItems.length === 0) {
|
|
8130
|
+
return [{
|
|
8131
|
+
type: Div,
|
|
8132
|
+
childCount: 1
|
|
8133
|
+
}, text(noResults())];
|
|
8351
8134
|
}
|
|
8352
|
-
|
|
8353
|
-
|
|
8354
|
-
|
|
8135
|
+
const root = {
|
|
8136
|
+
type: Div,
|
|
8137
|
+
childCount: visibleItems.length
|
|
8355
8138
|
};
|
|
8139
|
+
const dom = [root, ...visibleItems.flatMap(getCompletionItemVirtualDom)];
|
|
8140
|
+
return dom;
|
|
8356
8141
|
};
|
|
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
|
-
|
|
8142
|
+
|
|
8143
|
+
const Property = 1;
|
|
8144
|
+
const Value = 2;
|
|
8145
|
+
const Function = 3;
|
|
8146
|
+
const Variable = 4;
|
|
8147
|
+
const Keyword = 5;
|
|
8148
|
+
const Folder = 6;
|
|
8149
|
+
const File = 7;
|
|
8150
|
+
const Field = 8;
|
|
8151
|
+
|
|
8152
|
+
const SymbolProperty = 'SymbolProperty';
|
|
8153
|
+
const SymbolValue = 'SymbolValue';
|
|
8154
|
+
const SymbolFunction = 'SymbolFunction';
|
|
8155
|
+
const SymbolVariable = 'SymbolVariable';
|
|
8156
|
+
const SymbolKeyword = 'SymbolKeyword';
|
|
8157
|
+
const SymbolDefault = 'SymbolDefault';
|
|
8158
|
+
const SymbolField = 'SymbolField';
|
|
8159
|
+
const SymbolNone = '';
|
|
8160
|
+
|
|
8161
|
+
const getSymbolName = kind => {
|
|
8162
|
+
switch (kind) {
|
|
8163
|
+
case Property:
|
|
8164
|
+
return SymbolProperty;
|
|
8165
|
+
case Value:
|
|
8166
|
+
return SymbolValue;
|
|
8167
|
+
case Function:
|
|
8168
|
+
return SymbolFunction;
|
|
8169
|
+
case Variable:
|
|
8170
|
+
return SymbolVariable;
|
|
8171
|
+
case Keyword:
|
|
8172
|
+
return SymbolKeyword;
|
|
8173
|
+
case Field:
|
|
8174
|
+
return SymbolField;
|
|
8175
|
+
case File:
|
|
8176
|
+
return SymbolNone;
|
|
8177
|
+
default:
|
|
8178
|
+
return SymbolDefault;
|
|
8179
|
+
}
|
|
8180
|
+
};
|
|
8181
|
+
|
|
8182
|
+
// TODO
|
|
8183
|
+
const getCompletionFileIcon = kind => {
|
|
8184
|
+
switch (kind) {
|
|
8185
|
+
case File:
|
|
8186
|
+
return EmptyString;
|
|
8187
|
+
case Folder:
|
|
8188
|
+
return EmptyString;
|
|
8189
|
+
default:
|
|
8190
|
+
return EmptyString;
|
|
8390
8191
|
}
|
|
8192
|
+
};
|
|
8193
|
+
|
|
8194
|
+
const getHighlights = item => {
|
|
8195
|
+
const {
|
|
8196
|
+
matches
|
|
8197
|
+
} = item;
|
|
8198
|
+
return matches.slice(1);
|
|
8199
|
+
};
|
|
8200
|
+
|
|
8201
|
+
const getLabel = item => {
|
|
8202
|
+
return item.label;
|
|
8203
|
+
};
|
|
8204
|
+
const getVisibleIem = (item, itemHeight, leadingWord, i, focusedIndex) => {
|
|
8391
8205
|
return {
|
|
8392
|
-
|
|
8393
|
-
|
|
8206
|
+
label: getLabel(item),
|
|
8207
|
+
symbolName: getSymbolName(item.kind),
|
|
8208
|
+
top: i * itemHeight,
|
|
8209
|
+
highlights: getHighlights(item),
|
|
8210
|
+
focused: i === focusedIndex,
|
|
8211
|
+
deprecated: item.flags & Deprecated,
|
|
8212
|
+
fileIcon: getCompletionFileIcon(item.kind)
|
|
8394
8213
|
};
|
|
8395
8214
|
};
|
|
8396
8215
|
|
|
8397
|
-
const
|
|
8398
|
-
const
|
|
8399
|
-
for (
|
|
8400
|
-
|
|
8401
|
-
|
|
8402
|
-
className: EditorCursor,
|
|
8403
|
-
translate
|
|
8404
|
-
});
|
|
8216
|
+
const getVisibleItems = (filteredItems, itemHeight, leadingWord, minLineY, maxLineY, focusedIndex) => {
|
|
8217
|
+
const visibleItems = [];
|
|
8218
|
+
for (let i = minLineY; i < maxLineY; i++) {
|
|
8219
|
+
const filteredItem = filteredItems[i];
|
|
8220
|
+
visibleItems.push(getVisibleIem(filteredItem, itemHeight, leadingWord, i, focusedIndex));
|
|
8405
8221
|
}
|
|
8406
|
-
return
|
|
8222
|
+
return visibleItems;
|
|
8407
8223
|
};
|
|
8408
8224
|
|
|
8409
|
-
const
|
|
8410
|
-
|
|
8411
|
-
|
|
8412
|
-
|
|
8413
|
-
|
|
8414
|
-
|
|
8415
|
-
|
|
8416
|
-
|
|
8417
|
-
case Warning:
|
|
8418
|
-
return 'DiagnosticWarning';
|
|
8419
|
-
default:
|
|
8420
|
-
return 'DiagnosticError';
|
|
8225
|
+
const renderItems = {
|
|
8226
|
+
isEqual(oldState, newState) {
|
|
8227
|
+
return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.focusedIndex === newState.focusedIndex;
|
|
8228
|
+
},
|
|
8229
|
+
apply(oldState, newState) {
|
|
8230
|
+
const visibleItems = getVisibleItems(newState.items, newState.itemHeight, newState.leadingWord, newState.minLineY, newState.maxLineY, newState.focusedIndex);
|
|
8231
|
+
const dom = getCompletionItemsVirtualDom(visibleItems);
|
|
8232
|
+
return ['setDom', dom];
|
|
8421
8233
|
}
|
|
8422
8234
|
};
|
|
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
|
-
}];
|
|
8235
|
+
const renderBounds = {
|
|
8236
|
+
isEqual(oldState, newState) {
|
|
8237
|
+
return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.x === newState.x && oldState.y === newState.y;
|
|
8238
|
+
},
|
|
8239
|
+
apply(oldState, newState) {
|
|
8240
|
+
const {
|
|
8241
|
+
x,
|
|
8242
|
+
y,
|
|
8243
|
+
width,
|
|
8244
|
+
height
|
|
8245
|
+
} = newState;
|
|
8246
|
+
return [/* method */SetBounds, /* x */x, /* y */y, /* width */width, /* height */height];
|
|
8247
|
+
}
|
|
8441
8248
|
};
|
|
8442
|
-
|
|
8443
|
-
|
|
8444
|
-
|
|
8445
|
-
|
|
8249
|
+
const renderHeight = {
|
|
8250
|
+
isEqual(oldState, newState) {
|
|
8251
|
+
return oldState.items.length === newState.items.length;
|
|
8252
|
+
},
|
|
8253
|
+
apply(oldState, newState) {
|
|
8254
|
+
const {
|
|
8255
|
+
itemHeight
|
|
8256
|
+
} = newState;
|
|
8257
|
+
const contentHeight = newState.items.length * itemHeight;
|
|
8258
|
+
return [/* method */SetContentHeight, /* contentHeight */contentHeight];
|
|
8259
|
+
}
|
|
8446
8260
|
};
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
|
|
8453
|
-
}
|
|
8261
|
+
const renderNegativeMargin = {
|
|
8262
|
+
isEqual(oldState, newState) {
|
|
8263
|
+
return oldState.deltaY === newState.deltaY;
|
|
8264
|
+
},
|
|
8265
|
+
apply(oldState, newState) {
|
|
8266
|
+
return [/* method */SetNegativeMargin, /* negativeMargin */-newState.deltaY];
|
|
8267
|
+
}
|
|
8454
8268
|
};
|
|
8455
|
-
const
|
|
8456
|
-
|
|
8457
|
-
|
|
8269
|
+
const renderScrollBar = {
|
|
8270
|
+
isEqual(oldState, newState) {
|
|
8271
|
+
return oldState.negativeMargin === newState.negativeMargin && oldState.deltaY === newState.deltaY && oldState.height === newState.height && oldState.finalDeltaY === newState.finalDeltaY && oldState.items.length === newState.items.length;
|
|
8272
|
+
},
|
|
8273
|
+
apply(oldState, newState) {
|
|
8274
|
+
const total = newState.items.length;
|
|
8275
|
+
const contentHeight = total * newState.itemHeight;
|
|
8276
|
+
const scrollBarHeight = getScrollBarSize(newState.height, contentHeight, newState.minimumSliderSize);
|
|
8277
|
+
const scrollBarY = getScrollBarY(newState.deltaY, newState.finalDeltaY, newState.height - newState.headerHeight, scrollBarHeight);
|
|
8278
|
+
return [/* method */SetScrollBar, /* scrollBarY */scrollBarY, /* scrollBarHeight */scrollBarHeight];
|
|
8279
|
+
}
|
|
8458
8280
|
};
|
|
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));
|
|
8281
|
+
const render$2 = [renderItems, renderBounds, renderHeight, renderNegativeMargin, renderScrollBar];
|
|
8282
|
+
const renderCompletion = (oldState, newState) => {
|
|
8283
|
+
const commands = [];
|
|
8284
|
+
for (const item of render$2) {
|
|
8285
|
+
if (!item.isEqual(oldState, newState)) {
|
|
8286
|
+
commands.push(item.apply(oldState, newState));
|
|
8479
8287
|
}
|
|
8480
8288
|
}
|
|
8481
|
-
return
|
|
8289
|
+
return commands;
|
|
8482
8290
|
};
|
|
8483
8291
|
|
|
8484
|
-
const
|
|
8485
|
-
|
|
8486
|
-
|
|
8292
|
+
const render$1 = (oldState, newState) => {
|
|
8293
|
+
const commands = renderCompletion(oldState, newState);
|
|
8294
|
+
const wrappedCommands = [];
|
|
8295
|
+
const uid = newState.uid;
|
|
8296
|
+
for (const command of commands) {
|
|
8297
|
+
wrappedCommands.push(['Viewlet.send', uid, ...command]);
|
|
8487
8298
|
}
|
|
8488
|
-
|
|
8489
|
-
|
|
8490
|
-
|
|
8491
|
-
|
|
8492
|
-
|
|
8493
|
-
|
|
8494
|
-
|
|
8495
|
-
|
|
8496
|
-
|
|
8497
|
-
|
|
8498
|
-
|
|
8499
|
-
|
|
8500
|
-
|
|
8299
|
+
return wrappedCommands;
|
|
8300
|
+
};
|
|
8301
|
+
const add = widget => {
|
|
8302
|
+
const commands = render$1(widget.oldState, widget.newState);
|
|
8303
|
+
const id = 'EditorCompletion';
|
|
8304
|
+
// TODO how to generate a unique integer id
|
|
8305
|
+
// that doesn't collide with ids created in renderer worker?
|
|
8306
|
+
const uid = widget.newState.uid;
|
|
8307
|
+
const allCommands = [];
|
|
8308
|
+
allCommands.push(['Viewlet.create', id, uid]);
|
|
8309
|
+
allCommands.push(...commands);
|
|
8310
|
+
return allCommands;
|
|
8311
|
+
};
|
|
8312
|
+
const remove = widget => {
|
|
8313
|
+
return [['Viewlet.send', widget.newState.uid, 'dispose']];
|
|
8314
|
+
};
|
|
8315
|
+
const handleEditorType = (editor, state) => {
|
|
8316
|
+
const {
|
|
8317
|
+
unfilteredItems,
|
|
8318
|
+
itemHeight,
|
|
8319
|
+
maxHeight
|
|
8320
|
+
} = state;
|
|
8321
|
+
const {
|
|
8322
|
+
selections
|
|
8323
|
+
} = editor;
|
|
8324
|
+
const rowIndex = selections[0];
|
|
8325
|
+
const columnIndex = selections[1];
|
|
8326
|
+
const x$1 = x(editor, rowIndex, columnIndex);
|
|
8327
|
+
const y$1 = y(editor, rowIndex);
|
|
8328
|
+
const wordAtOffset = getWordBefore(editor, rowIndex, columnIndex);
|
|
8329
|
+
const items = filterCompletionItems(unfilteredItems, wordAtOffset);
|
|
8330
|
+
const newMinLineY = 0;
|
|
8331
|
+
const newMaxLineY = Math.min(items.length, 8);
|
|
8332
|
+
const height = getListHeight(items.length, itemHeight, maxHeight);
|
|
8333
|
+
const finalDeltaY = items.length * itemHeight - height;
|
|
8334
|
+
return {
|
|
8335
|
+
...state,
|
|
8336
|
+
items,
|
|
8337
|
+
x: x$1,
|
|
8338
|
+
y: y$1,
|
|
8339
|
+
minLineY: newMinLineY,
|
|
8340
|
+
maxLineY: newMaxLineY,
|
|
8341
|
+
leadingWord: wordAtOffset,
|
|
8342
|
+
height,
|
|
8343
|
+
finalDeltaY
|
|
8344
|
+
};
|
|
8345
|
+
};
|
|
8346
|
+
const handleEditorDeleteLeft = (editor, state) => {
|
|
8347
|
+
const {
|
|
8348
|
+
unfilteredItems,
|
|
8349
|
+
itemHeight,
|
|
8350
|
+
maxHeight
|
|
8351
|
+
} = state;
|
|
8352
|
+
const {
|
|
8353
|
+
selections
|
|
8354
|
+
} = editor;
|
|
8355
|
+
const rowIndex = selections[0];
|
|
8356
|
+
const columnIndex = selections[1];
|
|
8357
|
+
const x$1 = x(editor, rowIndex, columnIndex);
|
|
8358
|
+
const y$1 = y(editor, rowIndex);
|
|
8359
|
+
const wordAtOffset = getWordBefore(editor, rowIndex, columnIndex);
|
|
8360
|
+
if (!wordAtOffset) {
|
|
8361
|
+
return undefined;
|
|
8501
8362
|
}
|
|
8502
|
-
|
|
8363
|
+
const items = filterCompletionItems(unfilteredItems, wordAtOffset);
|
|
8364
|
+
const newMaxLineY = Math.min(items.length, 8);
|
|
8365
|
+
const height = getListHeight(items.length, itemHeight, maxHeight);
|
|
8366
|
+
return {
|
|
8367
|
+
...state,
|
|
8368
|
+
items,
|
|
8369
|
+
x: x$1,
|
|
8370
|
+
y: y$1,
|
|
8371
|
+
maxLineY: newMaxLineY,
|
|
8372
|
+
leadingWord: wordAtOffset,
|
|
8373
|
+
height
|
|
8374
|
+
};
|
|
8503
8375
|
};
|
|
8504
8376
|
|
|
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;
|
|
8377
|
+
const EditorCompletionWidget = {
|
|
8378
|
+
__proto__: null,
|
|
8379
|
+
add,
|
|
8380
|
+
handleEditorDeleteLeft,
|
|
8381
|
+
handleEditorType,
|
|
8382
|
+
remove,
|
|
8383
|
+
render: render$1
|
|
8522
8384
|
};
|
|
8523
8385
|
|
|
8524
8386
|
const addWidget = widget => {
|
|
@@ -8538,7 +8400,7 @@ const renderWidget = widget => {
|
|
|
8538
8400
|
} = widget;
|
|
8539
8401
|
switch (id) {
|
|
8540
8402
|
case Completion:
|
|
8541
|
-
return render$
|
|
8403
|
+
return render$1(widget.oldState, widget.newState);
|
|
8542
8404
|
default:
|
|
8543
8405
|
throw new Error(`unsupported widget`);
|
|
8544
8406
|
}
|
|
@@ -8549,7 +8411,7 @@ const removeWidget = widget => {
|
|
|
8549
8411
|
} = widget;
|
|
8550
8412
|
switch (id) {
|
|
8551
8413
|
case Completion:
|
|
8552
|
-
return remove
|
|
8414
|
+
return remove(widget);
|
|
8553
8415
|
default:
|
|
8554
8416
|
throw new Error('unsupported widget');
|
|
8555
8417
|
}
|
|
@@ -8897,8 +8759,8 @@ const commandMap = {
|
|
|
8897
8759
|
'EditorCompletion.focusPrevious': focusPrevious$1,
|
|
8898
8760
|
'EditorCompletion.handleEditorBlur': handleEditorBlur,
|
|
8899
8761
|
'EditorCompletion.handleEditorClick': handleEditorClick,
|
|
8900
|
-
'EditorCompletion.handleEditorDeleteLeft': handleEditorDeleteLeft,
|
|
8901
|
-
'EditorCompletion.handleEditorType': handleEditorType,
|
|
8762
|
+
'EditorCompletion.handleEditorDeleteLeft': handleEditorDeleteLeft$1,
|
|
8763
|
+
'EditorCompletion.handleEditorType': handleEditorType$1,
|
|
8902
8764
|
'EditorCompletion.loadContent': loadContent$2,
|
|
8903
8765
|
'EditorCompletion.selectCurrent': selectCurrent,
|
|
8904
8766
|
'EditorCompletion.selectIndex': selectIndex,
|