@lvce-editor/editor-worker 3.18.0 → 3.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/editorWorkerMain.js +1613 -1521
  2. package/package.json +1 -1
@@ -258,9 +258,9 @@ const renderColorPickerDom = {
258
258
  return ['Viewlet.setDom2', dom];
259
259
  }
260
260
  };
261
- const render$a = [renderColorPickerDom, renderColor$1, renderOffsetX$1];
261
+ const render$b = [renderColorPickerDom, renderColor$1, renderOffsetX$1];
262
262
  const renderColorPicker = async (oldState, newState) => {
263
- return renderParts(render$a, oldState, newState);
263
+ return renderParts(render$b, oldState, newState);
264
264
  };
265
265
 
266
266
  // TODO use numeric enum
@@ -1213,7 +1213,7 @@ const set$6 = (id, fn) => {
1213
1213
  const get$6 = id => {
1214
1214
  return state$1$1.callbacks[id];
1215
1215
  };
1216
- const remove$4 = id => {
1216
+ const remove$5 = id => {
1217
1217
  delete state$1$1.callbacks[id];
1218
1218
  };
1219
1219
  const state$9 = {
@@ -1259,7 +1259,7 @@ const resolve = (id, args) => {
1259
1259
  return;
1260
1260
  }
1261
1261
  fn(args);
1262
- remove$4(id);
1262
+ remove$5(id);
1263
1263
  };
1264
1264
  const create$2$1 = (method, params) => {
1265
1265
  const {
@@ -1451,7 +1451,7 @@ const getErrorResponse = (message, error, preparePrettyError, logError) => {
1451
1451
  const errorProperty = getErrorProperty(error, prettyError);
1452
1452
  return create$1$1(message, errorProperty);
1453
1453
  };
1454
- const create$a = (message, result) => {
1454
+ const create$b = (message, result) => {
1455
1455
  return {
1456
1456
  jsonrpc: Two,
1457
1457
  id: message.id,
@@ -1460,7 +1460,7 @@ const create$a = (message, result) => {
1460
1460
  };
1461
1461
  const getSuccessResponse = (message, result) => {
1462
1462
  const resultProperty = result ?? null;
1463
- return create$a(message, resultProperty);
1463
+ return create$b(message, resultProperty);
1464
1464
  };
1465
1465
  const getResponse = async (message, ipc, execute, preparePrettyError, logError, requiresSocket) => {
1466
1466
  try {
@@ -1660,7 +1660,7 @@ const waitForFirstMessage$1 = async port => {
1660
1660
  return event;
1661
1661
  };
1662
1662
 
1663
- const create$9 = async () => {
1663
+ const create$a = async () => {
1664
1664
  const {
1665
1665
  port1,
1666
1666
  port2
@@ -1705,7 +1705,7 @@ const wrap$3 = port => {
1705
1705
 
1706
1706
  const IpcParentWithExtensionHostWorker = {
1707
1707
  __proto__: null,
1708
- create: create$9,
1708
+ create: create$a,
1709
1709
  wrap: wrap$3
1710
1710
  };
1711
1711
 
@@ -1713,7 +1713,7 @@ const sendMessagePortToSyntaxHighlightingWorker = async port => {
1713
1713
  await invokeAndTransfer('SendMessagePortToSyntaxHighlightingWorker.sendMessagePortToSyntaxHighlightingWorker', port, 'HandleMessagePort.handleMessagePort');
1714
1714
  };
1715
1715
 
1716
- const create$8 = async () => {
1716
+ const create$9 = async () => {
1717
1717
  const {
1718
1718
  port1,
1719
1719
  port2
@@ -1758,7 +1758,7 @@ const wrap$1 = port => {
1758
1758
 
1759
1759
  const IpcParentWithSyntaxHighlightingWorker = {
1760
1760
  __proto__: null,
1761
- create: create$8,
1761
+ create: create$9,
1762
1762
  wrap: wrap$1
1763
1763
  };
1764
1764
 
@@ -1766,7 +1766,7 @@ const sendMessagePortToRendererProcess = async port => {
1766
1766
  await invokeAndTransfer('SendMessagePortToRendererProcess.sendMessagePortToRendererProcess', port, 'HandleMessagePort.handleMessagePort');
1767
1767
  };
1768
1768
 
1769
- const create$7 = async () => {
1769
+ const create$8 = async () => {
1770
1770
  const {
1771
1771
  port1,
1772
1772
  port2
@@ -1811,7 +1811,7 @@ const wrap = port => {
1811
1811
 
1812
1812
  const IpcParentWithRendererProcess = {
1813
1813
  __proto__: null,
1814
- create: create$7,
1814
+ create: create$8,
1815
1815
  wrap
1816
1816
  };
1817
1817
 
@@ -1828,7 +1828,7 @@ const getModule$1 = method => {
1828
1828
  }
1829
1829
  };
1830
1830
 
1831
- const create$6 = async ({
1831
+ const create$7 = async ({
1832
1832
  method,
1833
1833
  ...options
1834
1834
  }) => {
@@ -1846,7 +1846,7 @@ const create$6 = async ({
1846
1846
  const createRpc = method => {
1847
1847
  let _ipc;
1848
1848
  const listen = async () => {
1849
- const ipc = await create$6({
1849
+ const ipc = await create$7({
1850
1850
  method
1851
1851
  });
1852
1852
  handleIpc(ipc);
@@ -2122,7 +2122,7 @@ const getAccurateColumnIndexAscii = (line, guess, averageCharWidth, eventX, font
2122
2122
  const supported = () => {
2123
2123
  return 'Segmenter' in Intl;
2124
2124
  };
2125
- const create$5 = () => {
2125
+ const create$6 = () => {
2126
2126
  // @ts-ignore
2127
2127
  const segmenter = new Intl.Segmenter();
2128
2128
  return {
@@ -2160,7 +2160,7 @@ const create$5 = () => {
2160
2160
 
2161
2161
  // @ts-ignore
2162
2162
  const getAccurateColumnIndexUnicode = (line, guess, averageCharWidth, eventX, fontWeight, fontSize, fontFamily, letterSpacing) => {
2163
- const segmenter = create$5();
2163
+ const segmenter = create$6();
2164
2164
  const segments = segmenter.getSegments(line);
2165
2165
  const isMonospaceFont = false;
2166
2166
  const charWidth = 0;
@@ -2394,6 +2394,7 @@ const Completion = 'completion';
2394
2394
  const CompletionDetail$1 = 'completionDetail';
2395
2395
  const ColorPicker$1 = 'colorPicker';
2396
2396
  const Find = 'find';
2397
+ const Hover = 'hover';
2397
2398
 
2398
2399
  const isCompletionWidget = widget => {
2399
2400
  return widget.id === Completion;
@@ -2441,7 +2442,11 @@ const addWidgetToEditor = async (widgetId, focusKey, editor, factory, newStateGe
2441
2442
  return editor;
2442
2443
  }
2443
2444
  const widget = factory();
2445
+ // @ts-ignore
2446
+ widget.newState.editorUid = editor.uid;
2444
2447
  const newState = await newStateGenerator(widget.newState);
2448
+ // @ts-ignore
2449
+ newState.editorUid = editor.uid;
2445
2450
  const latestWidget = {
2446
2451
  ...widget,
2447
2452
  newState
@@ -2460,12 +2465,12 @@ const addWidgetToEditor = async (widgetId, focusKey, editor, factory, newStateGe
2460
2465
  return newEditor;
2461
2466
  };
2462
2467
 
2463
- const create$4 = () => {
2468
+ const create$5 = () => {
2464
2469
  return Math.random();
2465
2470
  };
2466
2471
 
2467
- const create$3 = () => {
2468
- const completionUid = create$4();
2472
+ const create$4 = () => {
2473
+ const completionUid = create$5();
2469
2474
  const widget = {
2470
2475
  id: ColorPicker$1,
2471
2476
  oldState: {
@@ -2506,12 +2511,13 @@ const FocusFindWidgetReplaceAllButton = 47;
2506
2511
  const FocusFindWidgetCloseButton = 48;
2507
2512
  const FocusFindWidgetNextMatchButton = 49;
2508
2513
  const FocusFindWidgetPreviousMatchButton = 50;
2514
+ const FocusEditorHover = 51;
2509
2515
 
2510
- const newStateGenerator = state => {
2516
+ const newStateGenerator$1 = state => {
2511
2517
  return loadContent$3(state);
2512
2518
  };
2513
2519
  const openColorPicker = async editor => {
2514
- return addWidgetToEditor(ColorPicker$1, ColorPicker, editor, create$3, newStateGenerator);
2520
+ return addWidgetToEditor(ColorPicker$1, ColorPicker, editor, create$4, newStateGenerator$1);
2515
2521
  };
2516
2522
 
2517
2523
  const state$6 = {
@@ -2808,7 +2814,7 @@ const characterLeft = (line, columnIndex) => {
2808
2814
  if (!supported()) {
2809
2815
  return 1;
2810
2816
  }
2811
- const segmenter = create$5();
2817
+ const segmenter = create$6();
2812
2818
  const last = segmenter.at(line, columnIndex - 1);
2813
2819
  return columnIndex - last.index;
2814
2820
  };
@@ -2819,7 +2825,7 @@ const characterRight = (line, columnIndex) => {
2819
2825
  if (!supported()) {
2820
2826
  return 1;
2821
2827
  }
2822
- const segmenter = create$5();
2828
+ const segmenter = create$6();
2823
2829
  const next = segmenter.at(line, columnIndex);
2824
2830
  return next.segment.length;
2825
2831
  };
@@ -3233,105 +3239,36 @@ const deleteWordLeft = editor => {
3233
3239
  return newEditor;
3234
3240
  };
3235
3241
 
3236
- const deleteWordPartLeft = editor => {
3237
- const newEditor = editorDeleteHorizontalLeft(editor, wordPartLeft);
3238
- return newEditor;
3239
- };
3240
-
3241
- const deleteWordPartRight = editor => {
3242
- return editorDeleteHorizontalRight(editor, wordPartRight);
3243
- };
3244
-
3245
- const deleteWordRight = editor => {
3246
- return editorDeleteHorizontalRight(editor, wordRight);
3247
- };
3248
-
3249
- const findAllReferences = async editor => {
3250
- await invoke$3('SideBar.show', 'References', /* focus */true);
3251
- return editor;
3252
- };
3253
-
3254
- // TODO format should be executed in parallel with saving
3255
- // -> fast save, no need to wait for formatting
3256
- // -> fast formatting, no need to wait for save
3257
-
3258
- // TODO should format on save when closing/switching editor?
3259
-
3260
- // TODO format with cursor
3261
- // TODO should be in editor folder
3262
-
3263
- const format$1 = async editor => {
3264
- const edits = await invoke$3('Format.format', editor);
3265
- return edits;
3266
- };
3267
-
3268
- const warn = (...args) => {
3269
- console.warn(...args);
3270
- };
3271
- const error = (...args) => {
3272
- console.error(...args);
3273
- };
3274
-
3275
- // @ts-ignore
3276
- const getDocumentEdits = (editor, edits) => {
3277
- const documentEdits = [];
3278
- for (const edit of edits) {
3279
- const start = positionAt(editor, edit.startOffset);
3280
- const end = positionAt(editor, edit.endOffset);
3281
- const deleted = getSelectionText(editor, {
3282
- start,
3283
- end
3284
- });
3285
- const documentEdit = {
3286
- start,
3287
- end,
3288
- inserted: splitLines$2(edit.inserted),
3289
- deleted,
3290
- origin: Format
3291
- };
3292
- if (documentEdit.inserted.length === 0) {
3293
- documentEdit.inserted = [''];
3294
- }
3295
- documentEdits.push(documentEdit);
3296
- }
3297
- return documentEdits;
3298
- };
3299
-
3300
- // @ts-ignore
3301
- const applyDocumentEdits = (editor, edits) => {
3302
- if (!Array.isArray(edits)) {
3303
- warn('something is wrong with format on save', edits);
3304
- return editor;
3305
- }
3306
- if (edits.length === 0) {
3307
- return editor;
3308
- }
3309
- const documentEdits = getDocumentEdits(editor, edits);
3310
- return scheduleDocumentAndCursorsSelections(editor, documentEdits);
3311
- };
3312
-
3313
- const expectedErrorMessage = 'Failed to execute formatting provider: FormattingError:';
3314
- const isFormattingError = error => {
3315
- return error && error instanceof Error && error.message.startsWith(expectedErrorMessage);
3316
- };
3317
-
3318
- // TODO also format with cursor
3319
- const format = async editor => {
3320
- try {
3321
- const edits = await format$1(editor);
3322
- return applyDocumentEdits(editor, edits);
3323
- } catch (error) {
3324
- if (isFormattingError(error)) {
3325
- console.error('Formatting Error:',
3326
- // @ts-ignore
3327
- error.message.slice(expectedErrorMessage.length));
3328
- return editor;
3242
+ const create$3 = () => {
3243
+ const uid = create$5();
3244
+ const widget = {
3245
+ id: Hover,
3246
+ oldState: {
3247
+ uid: uid,
3248
+ x: 0,
3249
+ y: 0,
3250
+ width: 0,
3251
+ height: 0,
3252
+ content: '',
3253
+ diagnostics: [],
3254
+ documentation: '',
3255
+ editorUid: 0,
3256
+ lineInfos: []
3257
+ },
3258
+ newState: {
3259
+ uid: uid,
3260
+ x: 0,
3261
+ y: 0,
3262
+ width: 0,
3263
+ height: 0,
3264
+ content: '',
3265
+ diagnostics: [],
3266
+ documentation: '',
3267
+ editorUid: 0,
3268
+ lineInfos: []
3329
3269
  }
3330
- console.error(error);
3331
- const displayErrorMessage = `${error}`;
3332
- await editorShowMessage(editor, 0, 0, displayErrorMessage, true);
3333
- return editor;
3334
- }
3270
+ };
3271
+ return widget;
3335
3272
  };
3336
3273
 
3337
3274
  const RE_WORD_START$1 = /^[\w\-]+/;
@@ -3376,905 +3313,1391 @@ const getWordBefore = (editor, rowIndex, columnIndex) => {
3376
3313
  return getWordBefore$1(line, columnIndex);
3377
3314
  };
3378
3315
 
3379
- // @ts-ignore
3380
- const getDefinition = async (editor, offset) => {
3381
- const definition = await invoke$3('ExtensionHostDefinition.executeDefinitionProvider', editor, offset);
3382
- return definition;
3316
+ const OnCompletion = 'onCompletion';
3317
+ const OnHover = 'onHover';
3318
+
3319
+ // TODO add tests for this
3320
+ const activateByEvent = async event => {
3321
+ await invoke$3('ExtensionHostManagement.activateByEvent', event);
3383
3322
  };
3384
3323
 
3385
- const emptyObject = {};
3386
- const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
3387
- const i18nString = (key, placeholders = emptyObject) => {
3388
- if (placeholders === emptyObject) {
3389
- return key;
3390
- }
3391
- const replacer = (match, rest) => {
3392
- return placeholders[rest];
3393
- };
3394
- return key.replaceAll(RE_PLACEHOLDER, replacer);
3324
+ const execute = async ({
3325
+ editor,
3326
+ args,
3327
+ event,
3328
+ method,
3329
+ noProviderFoundMessage,
3330
+ noProviderFoundResult = undefined
3331
+ }) => {
3332
+ const fullEvent = `${event}:${editor.languageId}`;
3333
+ await activateByEvent(fullEvent);
3334
+ const result = await invoke$2(method, editor.uid, ...args);
3335
+ return result;
3395
3336
  };
3396
3337
 
3397
- const UiStrings$1 = {
3398
- GoToDefinition: 'Go to Definition',
3399
- NoDefinitionFound: 'No definition found',
3400
- NoDefinitionFoundFor: "No definition found for '{PH1}'",
3401
- NoTypeDefinitionFound: 'No type definition found',
3402
- NoTypeDefinitionFoundFor: "No type definition found for '{PH1}'",
3403
- NoResults: 'No Results',
3404
- Replace: 'Replace'
3338
+ const executeHoverProvider = (editor, offset) => {
3339
+ object(editor);
3340
+ number$1(offset);
3341
+ return execute({
3342
+ event: OnHover,
3343
+ editor,
3344
+ method: HoverExecute,
3345
+ args: [offset],
3346
+ noProviderFoundMessage: 'No hover provider found'
3347
+ });
3405
3348
  };
3406
- const noDefinitionFound = () => {
3407
- return i18nString(UiStrings$1.NoDefinitionFound);
3349
+
3350
+ const getHover = async (editor, offset) => {
3351
+ object(editor);
3352
+ number$1(offset);
3353
+ // TODO invoke extension host worker directly
3354
+ const hover = await executeHoverProvider(editor, offset);
3355
+ return hover;
3408
3356
  };
3409
- const noDefinitionFoundFor = word => {
3410
- return i18nString(UiStrings$1.NoDefinitionFoundFor, {
3411
- PH1: word
3357
+
3358
+ let _ipc;
3359
+ const listen$6 = async () => {
3360
+ const ipc = await create$7({
3361
+ method: RendererProcess
3412
3362
  });
3363
+ handleIpc(ipc);
3364
+ _ipc = ipc;
3413
3365
  };
3414
- const noTypeDefinitionFoundFor = word => {
3415
- return i18nString(UiStrings$1.NoTypeDefinitionFoundFor, {
3416
- PH1: word
3417
- });
3366
+ const invoke$1 = async (method, ...args) => {
3367
+ return invoke$5(_ipc, method, ...args);
3418
3368
  };
3419
- const noTypeDefinitionFound = () => {
3420
- return i18nString(UiStrings$1.NoTypeDefinitionFound);
3369
+
3370
+ const measureTextBlockHeight = (text, fontFamily, fontSize, lineHeight, width) => {
3371
+ return invoke$1('MeasureTextBlockHeight.measureTextBlockHeight', text, fontSize, fontFamily, lineHeight, width);
3421
3372
  };
3422
- const noResults$1 = () => {
3423
- return i18nString(UiStrings$1.NoResults);
3373
+
3374
+ const deepCopy = value => {
3375
+ return structuredClone(value);
3424
3376
  };
3425
3377
 
3426
- // @ts-ignore
3427
- const goTo = async ({
3428
- editor,
3429
- getLocation,
3430
- getNoLocationFoundMessage,
3431
- getErrorMessage,
3432
- isNoProviderFoundError
3433
- }) => {
3434
- const {
3435
- selections
3436
- } = editor;
3437
- const rowIndex = selections[0];
3438
- const columnIndex = selections[1];
3439
- try {
3440
- const definition = await getLocation(editor, rowIndex, columnIndex);
3441
- // TODO if editor is already disposed at this point, do nothing
3442
- if (!definition) {
3443
- // TODO show popup that no definition was found
3444
- // TODO if there was an error, show popup that go to definition resulted in an error
3445
- const info = getWordAt(editor, rowIndex, columnIndex);
3446
- const message = getNoLocationFoundMessage(info);
3447
- return editorShowMessage(editor, rowIndex, columnIndex, message, false);
3448
- }
3449
- if (typeof definition.uri !== 'string' || typeof definition.startOffset !== 'number' || typeof definition.endOffset !== 'number') {
3450
- // Logger.warn('invalid definition result', definition)
3451
- return editor;
3452
- }
3453
- const uri = definition.uri;
3454
- if (uri === editor.uri) {
3455
- // TODO set cursor to the definition position
3456
- const position = positionAt(editor, definition.startOffset);
3457
- const selectionEdits = new Uint32Array([position.rowIndex, position.columnIndex, position.rowIndex, position.columnIndex]);
3458
- return scheduleSelections(editor, selectionEdits);
3459
- }
3460
- // TODO if definition.file is not of type string, show a popup that definition.file must be of type string
3461
- // TODO open file and scroll to that position and set cursor to that position
3378
+ const getInitialLineState = initialLineState => {
3379
+ return deepCopy(initialLineState);
3380
+ };
3462
3381
 
3463
- const context = {
3464
- startRowIndex: definition.startRowIndex,
3465
- startColumnIndex: definition.startColumnIndex,
3466
- endRowIndex: definition.endRowIndex,
3467
- endColumnIndex: definition.endColumnIndex
3468
- };
3469
- await invoke$3(/* Main.openUri */'Main.openUri', /* uri */uri, /* focus */true, context);
3470
- return editor;
3471
- } catch (error) {
3472
- // TODO if editor is already disposed at this point, do nothing
3473
- if (isNoProviderFoundError(error)) {
3474
- const displayErrorMessage = getErrorMessage(error);
3475
- await editorShowMessage(editor, rowIndex, columnIndex, displayErrorMessage, false);
3476
- return editor;
3477
- }
3478
- // @ts-ignore
3479
- // ErrorHandling.handleError(error, false)
3480
- const displayErrorMessage = getErrorMessage(error);
3481
- await editorShowMessage(editor, rowIndex, columnIndex, displayErrorMessage, true);
3482
- return editor;
3382
+ const getLineInfo$1 = (line, tokens, TokenMap) => {
3383
+ const tokensLength = tokens.length;
3384
+ let end = 0;
3385
+ let start = 0;
3386
+ const lineInfo = [];
3387
+ for (let i = 0; i < tokensLength; i += 2) {
3388
+ const tokenType = tokens[i];
3389
+ const tokenLength = tokens[i + 1];
3390
+ end += tokenLength;
3391
+ const text = line.slice(start, end);
3392
+ const className = `Token ${TokenMap[tokenType] || 'Unknown'}`;
3393
+ const normalizedText = text;
3394
+ lineInfo.push(normalizedText, className);
3395
+ start = end;
3483
3396
  }
3397
+ return lineInfo;
3484
3398
  };
3485
3399
 
3486
- // TODO race condition, check that editor hasn't been closed in the meantime
3487
-
3488
- // TODO in case of error should show message "Definition Error: Cannot ready Property x of undefined"
3489
-
3490
- // TODO show some kind of message maybe ("No Definition found")
3491
-
3492
- // TODO possible to do this with events/state machine instead of promises -> enables canceling operations / concurrent calls
3493
-
3494
- // TODO there are still race conditions in this function:
3495
- // - when open is called twice, previous dom nodes can either be reused or the previous dom nodes must be disposed
3496
-
3497
- // @ts-ignore
3498
- const getLocation$1 = async (editor, rowIndex, columnIndex) => {
3499
- const offset = offsetAt(editor, rowIndex, columnIndex);
3500
- const definition = await getDefinition(editor, offset);
3501
- return definition;
3400
+ const state$5 = {
3401
+ warned: []
3502
3402
  };
3503
-
3504
- // @ts-ignore
3505
- const getNoLocationFoundMessage$1 = info => {
3506
- if (info.word) {
3507
- return noDefinitionFoundFor(info.word);
3403
+ const flattenTokensArray = tokens => {
3404
+ const flattened = [];
3405
+ for (const token of tokens) {
3406
+ object(token);
3407
+ flattened.push(token.type, token.length);
3508
3408
  }
3509
- return noDefinitionFound();
3510
- };
3511
-
3512
- // @ts-ignore
3513
- const getErrorMessage$3 = error => {
3514
- // if (
3515
- // error &&
3516
- // error.message &&
3517
- // error.message.startsWith('Failed to execute definition provider: ')
3518
- // ) {
3519
- // return error.message.replace('Failed to execute definition provider: ', '')
3520
- // }
3521
- return `${error}`;
3409
+ return flattened;
3522
3410
  };
3523
-
3524
- // @ts-ignore
3525
- const isNoProviderFoundError$1 = error => {
3526
- return error &&
3527
- // @ts-ignore
3528
- error.message &&
3529
- // @ts-ignore
3530
- error.message.startsWith('Failed to execute definition provider: No definition provider found');
3411
+ const warnDeprecatedArrayReturn = (languageId, fn) => {
3412
+ if (state$5.warned.includes(fn)) {
3413
+ return;
3414
+ }
3415
+ state$5.warned.push(fn);
3416
+ console.warn(`tokenizers without hasArrayReturn=false are deprecated (language ${languageId})`);
3531
3417
  };
3532
- const goToDefinition = editor => {
3533
- return goTo({
3534
- editor,
3535
- getLocation: getLocation$1,
3536
- getNoLocationFoundMessage: getNoLocationFoundMessage$1,
3537
- getErrorMessage: getErrorMessage$3,
3538
- isNoProviderFoundError: isNoProviderFoundError$1
3539
- });
3418
+ const safeTokenizeLine = (languageId, tokenizeLine, line, lineStateAtStart, hasArrayReturn) => {
3419
+ try {
3420
+ const lineState = tokenizeLine(line, lineStateAtStart);
3421
+ if (!lineState || !lineState.tokens || !lineState.state) {
3422
+ throw new Error('invalid tokenization result');
3423
+ }
3424
+ if (!hasArrayReturn) {
3425
+ warnDeprecatedArrayReturn(languageId, tokenizeLine);
3426
+ // workaround for old tokenizers
3427
+ lineState.tokens = flattenTokensArray(lineState.tokens);
3428
+ }
3429
+ return lineState;
3430
+ } catch (error) {
3431
+ console.error(error);
3432
+ return {
3433
+ tokens: [/* type */0, /* length */line.length],
3434
+ lineState: lineStateAtStart
3435
+ };
3436
+ }
3540
3437
  };
3541
3438
 
3542
- const getNoLocationFoundMessage = info => {
3543
- if (info.word) {
3544
- return noTypeDefinitionFoundFor(info.word);
3439
+ const getLineInfos = (lines, tokenizer, languageId) => {
3440
+ const lineInfos = [];
3441
+ const {
3442
+ tokenizeLine,
3443
+ initialLineState,
3444
+ hasArrayReturn,
3445
+ TokenMap
3446
+ } = tokenizer;
3447
+ let currentLineState = getInitialLineState(initialLineState);
3448
+ for (const line of lines) {
3449
+ const result = safeTokenizeLine(languageId, tokenizeLine, line, currentLineState, hasArrayReturn);
3450
+ const {
3451
+ tokens
3452
+ } = result;
3453
+ const lineInfo = getLineInfo$1(line, tokens, TokenMap);
3454
+ lineInfos.push(lineInfo);
3455
+ currentLineState = result;
3545
3456
  }
3546
- return noTypeDefinitionFound();
3457
+ return lineInfos;
3547
3458
  };
3548
3459
 
3549
- const getTypeDefinition = async (editor, offset) => {
3550
- const definition = await invoke$3('ExtensionHostTypeDefinition.executeTypeDefinitionProvider', editor, offset);
3551
- return definition;
3460
+ /**
3461
+ * @enum number
3462
+ */
3463
+ const State = {
3464
+ TopLevelContent: 1
3552
3465
  };
3553
3466
 
3554
- const getLocation = async (editor, rowIndex, columnIndex) => {
3555
- const offset = offsetAt(editor, rowIndex, columnIndex);
3556
- const definition = await getTypeDefinition(editor, offset);
3557
- return definition;
3467
+ /**
3468
+ * @enum number
3469
+ */
3470
+ const TokenType = {
3471
+ Text: 1
3558
3472
  };
3559
-
3560
- // @ts-ignore
3561
- const getErrorMessage$2 = error => {
3562
- // if (
3563
- // error &&
3564
- // error.message &&
3565
- // error.message.startsWith('Failed to execute type definition provider: ')
3566
- // ) {
3567
- // return error.message.replace(
3568
- // 'Failed to execute type definition provider: ',
3569
- // ''
3570
- // )
3571
- // }
3572
- return `${error}`;
3473
+ const TokenMap = {
3474
+ [TokenType.Text]: 'Text'
3573
3475
  };
3574
- const isNoProviderFoundError = error => {
3575
- return error &&
3576
- // @ts-ignore
3577
- error.message &&
3578
- // @ts-ignore
3579
- error.message.startsWith('Failed to execute type definition provider: No type definition provider found');
3476
+ const initialLineState = {
3477
+ state: State.TopLevelContent
3580
3478
  };
3581
- const goToTypeDefinition = (editor, explicit = true) => {
3582
- return goTo({
3583
- editor,
3584
- getLocation,
3585
- getNoLocationFoundMessage: getNoLocationFoundMessage,
3586
- isNoProviderFoundError,
3587
- getErrorMessage: getErrorMessage$2
3588
- });
3479
+ const hasArrayReturn = true;
3480
+ const tokenizeLine = (line, lineState) => {
3481
+ return {
3482
+ tokens: [TokenType.Text, line.length],
3483
+ state: lineState.state
3484
+ };
3589
3485
  };
3590
3486
 
3591
- const Editor = 3;
3592
-
3593
- const handleContextMenu = async (editor, button, x, y) => {
3594
- await invoke$3(/* ContextMenu.show */'ContextMenu.show', /* x */x, /* y */y, /* id */Editor);
3595
- return editor;
3487
+ const TokenizePlainText = {
3488
+ __proto__: null,
3489
+ State,
3490
+ TokenMap,
3491
+ TokenType,
3492
+ hasArrayReturn,
3493
+ initialLineState,
3494
+ tokenizeLine
3596
3495
  };
3597
3496
 
3598
- // @ts-ignore
3599
-
3600
- // match all words, including umlauts, see https://stackoverflow.com/questions/5436824/matching-accented-characters-with-javascript-regexes/#answer-11550799
3601
- const RE_WORD_START = /^[a-z\u00C0-\u017F\d]+/i;
3602
- const RE_WORD_END = /[a-z\u00C0-\u017F\d]+$/i;
3603
-
3604
- // @ts-ignore
3605
- const getNewSelections$7 = (line, rowIndex, columnIndex) => {
3606
- const before = line.slice(0, columnIndex);
3607
- const after = line.slice(columnIndex);
3608
- const beforeMatch = before.match(RE_WORD_END);
3609
- const afterMatch = after.match(RE_WORD_START);
3610
- const columnStart = columnIndex - (beforeMatch ? beforeMatch[0].length : 0);
3611
- const columnEnd = columnIndex + (afterMatch ? afterMatch[0].length : 0);
3612
- const newSelections = new Uint32Array([rowIndex, columnStart, rowIndex, columnEnd]);
3613
- return newSelections;
3497
+ const state$4 = {
3498
+ tokenizers: Object.create(null),
3499
+ tokenizePaths: Object.create(null),
3500
+ listeners: [],
3501
+ pending: Object.create(null),
3502
+ /**
3503
+ * @type {number[]}
3504
+ */
3505
+ connectedEditors: []
3614
3506
  };
3615
-
3616
- // @ts-ignore
3617
- const selectWord = (editor, rowIndex, columnIndex) => {
3618
- const line = getLine(editor, rowIndex);
3619
- const newSelections = getNewSelections$7(line, rowIndex, columnIndex);
3620
- return scheduleSelections(editor, newSelections);
3507
+ const has = languageId => {
3508
+ return languageId in state$4.tokenizers;
3621
3509
  };
3622
-
3623
- const handleDoubleClick = (editor, modifier, x, y) => {
3624
- const position = at(editor, x, y);
3625
- return selectWord(editor, position.rowIndex, position.columnIndex);
3510
+ const set$4 = (languageId, tokenizer) => {
3511
+ state$4.tokenizers[languageId] = tokenizer;
3512
+ };
3513
+ const get$4 = languageId => {
3514
+ return state$4.tokenizers[languageId];
3515
+ };
3516
+ const isPending = languageId => {
3517
+ return languageId in state$4.pending;
3626
3518
  };
3627
3519
 
3628
- const WhenExpressionEditorText = 12;
3629
- const handleFocus = editor => {
3630
- // TODO make change events functional,
3631
- // when rendering, send focus changes to renderer worker
3632
- invoke$3('Focus.setFocus', WhenExpressionEditorText);
3633
- return editor;
3520
+ let enabled$1 = false;
3521
+ const setEnabled$1 = value => {
3522
+ enabled$1 = value;
3523
+ };
3524
+ const getEnabled$1 = () => {
3525
+ return enabled$1;
3634
3526
  };
3635
3527
 
3636
- const Single = 1;
3637
- const Double = 2;
3638
- const Triple = 3;
3528
+ const {
3529
+ listen: listen$5,
3530
+ invoke
3531
+ } = createRpc(SyntaxHighlightingWorker);
3639
3532
 
3640
- const state$5 = {
3641
- position: {
3642
- rowIndex: 0,
3643
- columnIndex: 0
3644
- }
3533
+ const tokenMaps = Object.create(null);
3534
+ const set$3 = (languageId, tokenMap) => {
3535
+ tokenMaps[languageId] = tokenMap;
3645
3536
  };
3646
- const getPosition$1 = () => {
3647
- return state$5.position;
3537
+ const get$3 = languageId => {
3538
+ return tokenMaps[languageId] || {};
3648
3539
  };
3649
3540
 
3650
- // @ts-ignore
3651
- const setPosition$1 = position => {
3652
- state$5.position = position;
3541
+ // TODO loadTokenizer should be invoked from renderer worker
3542
+ const loadTokenizer = async (languageId, tokenizePath) => {
3543
+ if (!tokenizePath) {
3544
+ return;
3545
+ }
3546
+ if (getEnabled$1()) {
3547
+ const tokenMap = await invoke('Tokenizer.load', languageId, tokenizePath);
3548
+ set$3(languageId, tokenMap);
3549
+ return;
3550
+ }
3551
+ try {
3552
+ // TODO check that tokenizer is valid
3553
+ // 1. tokenizeLine should be of type function
3554
+ // 2. getTokenClass should be of type function
3555
+ const tokenizer = await import(tokenizePath);
3556
+ if (typeof tokenizer.tokenizeLine !== 'function') {
3557
+ console.warn(`tokenizer.tokenizeLine should be a function in "${tokenizePath}"`);
3558
+ return;
3559
+ }
3560
+ if (!tokenizer.TokenMap || typeof tokenizer.TokenMap !== 'object' || Array.isArray(tokenizer.TokenMap)) {
3561
+ console.warn(`tokenizer.TokenMap should be an object in "${tokenizePath}"`);
3562
+ return;
3563
+ }
3564
+ set$3(languageId, tokenizer.TokenMap);
3565
+ set$4(languageId, tokenizer);
3566
+ } catch (error) {
3567
+ // TODO better error handling
3568
+ console.error(error);
3569
+ return;
3570
+ }
3571
+ };
3572
+ const getTokenizer = languageId => {
3573
+ if (has(languageId)) {
3574
+ return get$4(languageId);
3575
+ }
3576
+ if (isPending(languageId)) {
3577
+ return TokenizePlainText;
3578
+ }
3579
+ return TokenizePlainText;
3653
3580
  };
3654
3581
 
3655
- const Ctrl = 1;
3656
- const Alt = 2;
3582
+ const tokenizeCodeBlock = async (codeBlock, languageId, tokenizerPath) => {
3583
+ await loadTokenizer(languageId, tokenizerPath);
3584
+ const tokenizer = getTokenizer(languageId);
3585
+ const lines = splitLines$2(codeBlock);
3586
+ const lineInfos = getLineInfos(lines, tokenizer, languageId);
3587
+ return lineInfos;
3588
+ };
3657
3589
 
3658
- // TODO first change cursor position, then run go to definition
3659
- // cursor should appear at mousedown position immediately
3660
- const handleSingleClickWithAlt = async (editor, position) => {
3661
- const {
3590
+ const getHoverPosition = (position, selections) => {
3591
+ if (position) {
3592
+ return position;
3593
+ }
3594
+ const rowIndex = selections[0];
3595
+ const columnIndex = selections[1];
3596
+ return {
3662
3597
  rowIndex,
3663
3598
  columnIndex
3664
- } = position;
3665
- const newEditor = {
3666
- ...editor,
3667
- selections: new Uint32Array([rowIndex, columnIndex, rowIndex, columnIndex])
3668
3599
  };
3669
- // TODO rectangular selection with alt click,
3670
- // but also go to definition with alt click
3671
- const newEditor2 = await goToDefinition(newEditor);
3672
- return newEditor2;
3673
3600
  };
3674
- const handleSingleClickWithCtrl = async (editor, position) => {
3675
- const selections = editor.selections;
3676
- for (let i = 0; i < selections.length; i += 4) {
3677
- const [selectionStartRow, selectionStartColumn, selectionEndRow, selectionEndColumn] = getSelectionPairs(selections, i);
3678
- if (selectionStartRow === position.rowIndex && selectionStartColumn === position.columnIndex && selectionEndRow === position.rowIndex && selectionEndColumn === position.columnIndex) {
3679
- // selection exists -> remove
3680
- const newSelections = new Uint32Array(selections.length - 4);
3681
- newSelections.set(selections.subarray(0, i), 0);
3682
- newSelections.set(selections.subarray(i + 4), i);
3683
- return scheduleSelections(editor, newSelections);
3601
+ const getMatchingDiagnostics = (diagnostics, rowIndex, columnIndex) => {
3602
+ const matching = [];
3603
+ for (const diagnostic of diagnostics) {
3604
+ if (diagnostic.rowIndex === rowIndex) {
3605
+ matching.push(diagnostic);
3684
3606
  }
3685
3607
  }
3686
- // TODO selection does not exist -> add
3687
- // TODO insert in order
3688
- const newSelections = new Uint32Array(selections.length + 4);
3689
- newSelections.set(selections, 0);
3690
- const insertIndex = selections.length;
3691
- newSelections[insertIndex] = position.rowIndex;
3692
- newSelections[insertIndex + 1] = position.columnIndex;
3693
- newSelections[insertIndex + 2] = position.rowIndex;
3694
- newSelections[insertIndex + 3] = position.columnIndex;
3695
- return scheduleSelections(editor, newSelections);
3608
+ return matching;
3696
3609
  };
3697
- const handleSingleClickDefault = (editor, position) => {
3698
- setPosition$1(position);
3610
+ const fallbackDisplayStringLanguageId = 'typescript'; // TODO remove this
3611
+
3612
+ const hoverDocumentationFontSize = 15;
3613
+ const hoverDocumentationFontFamily = 'Fira Code';
3614
+ const hoverDocumentationLineHeight = '1.33333';
3615
+ const hoverBorderLeft = 1;
3616
+ const hoverBorderRight = 1;
3617
+ const hoverPaddingLeft = 8;
3618
+ const hoverPaddingRight = 8;
3619
+ const hovverFullWidth = 400;
3620
+ const hoverDocumentationWidth = hovverFullWidth - hoverPaddingLeft - hoverPaddingRight - hoverBorderLeft - hoverBorderRight;
3621
+ const getHoverPositionXy = (editor, rowIndex, wordStart, documentationHeight) => {
3622
+ const x$1 = x(editor, rowIndex, wordStart);
3623
+ const y$1 = editor.height - y(editor, rowIndex) + editor.y + 40;
3699
3624
  return {
3700
- ...editor,
3701
- selections: new Uint32Array([position.rowIndex, position.columnIndex, position.rowIndex, position.columnIndex]),
3702
- focused: true
3625
+ x: x$1,
3626
+ y: y$1
3703
3627
  };
3704
3628
  };
3705
- const getFn = modifier => {
3706
- switch (modifier) {
3707
- case Alt:
3708
- return handleSingleClickWithAlt;
3709
- case Ctrl:
3710
- return handleSingleClickWithCtrl;
3711
- default:
3712
- return handleSingleClickDefault;
3629
+ const getEditorHoverInfo = async (editorUid, position) => {
3630
+ number$1(editorUid);
3631
+ const instance = get$7(editorUid);
3632
+ const editor = instance.newState;
3633
+ const {
3634
+ selections
3635
+ } = editor;
3636
+ const {
3637
+ rowIndex,
3638
+ columnIndex
3639
+ } = getHoverPosition(position, selections);
3640
+ const offset = offsetAt(editor, rowIndex, columnIndex);
3641
+ const hover = await getHover(editor, offset);
3642
+ if (!hover) {
3643
+ return undefined;
3713
3644
  }
3645
+ const {
3646
+ displayString,
3647
+ documentation,
3648
+ displayStringLanguageId
3649
+ } = hover;
3650
+ const tokenizerPath = '';
3651
+ const lineInfos = await tokenizeCodeBlock(displayString, displayStringLanguageId || fallbackDisplayStringLanguageId, tokenizerPath);
3652
+ const wordPart = await getWordBefore(editor, rowIndex, columnIndex);
3653
+ const wordStart = columnIndex - wordPart.length;
3654
+ await measureTextBlockHeight(documentation, hoverDocumentationFontFamily, hoverDocumentationFontSize, hoverDocumentationLineHeight, hoverDocumentationWidth);
3655
+ const {
3656
+ x,
3657
+ y
3658
+ } = getHoverPositionXy(editor, rowIndex, wordStart);
3659
+ const diagnostics = editor.diagnostics || [];
3660
+ const matchingDiagnostics = getMatchingDiagnostics(diagnostics, rowIndex);
3661
+ return {
3662
+ lineInfos,
3663
+ documentation,
3664
+ x,
3665
+ y,
3666
+ matchingDiagnostics
3667
+ };
3714
3668
  };
3715
- const handleSingleClick = async (editor, modifier, x, y) => {
3716
- object(editor);
3717
- number$1(modifier);
3718
- number$1(x);
3719
- number$1(y);
3720
- const position = at(editor, x, y);
3721
- const fn = getFn(modifier);
3722
- const newEditor = await fn(editor, position);
3723
- // switch (newEditor.completionState) {
3724
- // case EditorCompletionState.None:
3725
- // case EditorCompletionState.Visible:
3726
- // case EditorCompletionState.Loading:
3727
- // return {
3728
- // newState: newEditor,
3729
- // commands: [],
3730
- // }
3731
- // default:
3732
- // break
3733
- // }
3734
- return newEditor;
3669
+
3670
+ const loadHoverContent = async state => {
3671
+ // TODO
3672
+ const position = undefined;
3673
+ const hoverInfo = await getEditorHoverInfo(state.editorUid, position);
3674
+ if (!hoverInfo) {
3675
+ return state;
3676
+ }
3677
+ const {
3678
+ lineInfos,
3679
+ documentation,
3680
+ x,
3681
+ y,
3682
+ matchingDiagnostics
3683
+ } = hoverInfo;
3684
+ return {
3685
+ ...state,
3686
+ lineInfos,
3687
+ documentation,
3688
+ x,
3689
+ y,
3690
+ diagnostics: matchingDiagnostics
3691
+ };
3735
3692
  };
3736
3693
 
3737
- // @ts-ignore
3694
+ const newStateGenerator = state => {
3695
+ return loadHoverContent(state);
3696
+ };
3697
+ const showHover2 = async editor => {
3698
+ return addWidgetToEditor(Hover, FocusEditorHover, editor, create$3, newStateGenerator);
3699
+ };
3738
3700
 
3739
- // @ts-ignore
3740
- const getNewSelections$6 = (line, rowIndex) => {
3741
- // TODO handle virtual space when columnIndex is greater than line length
3742
- return new Uint32Array([rowIndex, 0, rowIndex, line.length]);
3701
+ const deleteWordPartLeft = editor => {
3702
+ const newEditor = editorDeleteHorizontalLeft(editor, wordPartLeft);
3703
+ return newEditor;
3743
3704
  };
3744
3705
 
3745
- // @ts-ignore
3746
- const selectLine = editor => {
3747
- const selections = editor.selections;
3748
- const rowIndex = selections[editor.primarySelectionIndex];
3749
- const line = getLine(editor, rowIndex);
3750
- const newSelections = getNewSelections$6(line, rowIndex);
3751
- return scheduleSelections(editor, newSelections);
3706
+ const deleteWordPartRight = editor => {
3707
+ return editorDeleteHorizontalRight(editor, wordPartRight);
3752
3708
  };
3753
3709
 
3754
- // TODO rowIndex and columnIndex should already be set because of singleClick which occurred before triple click
3755
- // @ts-ignore
3756
- const handleTripleClick = (editor, modifier, x, y) => {
3757
- object(editor);
3758
- number$1(x);
3759
- number$1(y);
3760
- return {
3761
- newState: selectLine(editor),
3762
- commands: []
3763
- };
3710
+ const deleteWordRight = editor => {
3711
+ return editorDeleteHorizontalRight(editor, wordRight);
3764
3712
  };
3765
3713
 
3766
- const handleMouseDown = (state, modifier, x, y, detail) => {
3767
- switch (detail) {
3768
- case Single:
3769
- return handleSingleClick(state, modifier, x, y);
3770
- case Double:
3771
- return handleDoubleClick(state, modifier, x, y);
3772
- case Triple:
3773
- return handleTripleClick(state, modifier, x, y);
3774
- default:
3775
- return state;
3776
- }
3714
+ const findAllReferences = async editor => {
3715
+ await invoke$3('SideBar.show', 'References', /* focus */true);
3716
+ return editor;
3777
3717
  };
3778
3718
 
3779
- const state$4 = {
3780
- timeout: -1,
3781
- x: 0,
3782
- y: 0,
3783
- editor: undefined
3784
- };
3785
- const get$4 = () => {
3786
- return state$4;
3787
- };
3788
- const set$4 = (editor, timeout, x, y) => {
3789
- state$4.editor = editor;
3790
- state$4.timeout = timeout;
3791
- state$4.x = x;
3792
- state$4.y = y;
3793
- };
3719
+ // TODO format should be executed in parallel with saving
3720
+ // -> fast save, no need to wait for formatting
3721
+ // -> fast formatting, no need to wait for save
3794
3722
 
3795
- const showHover$1 = async (editor, position) => {
3796
- // TODO race condition
3797
- // await Viewlet.closeWidget(ViewletModuleId.EditorHover)
3798
- // await Viewlet.openWidget(ViewletModuleId.EditorHover, position)
3799
- };
3723
+ // TODO should format on save when closing/switching editor?
3800
3724
 
3801
- // TODO several things can happen:
3802
- // 1. highlight link when alt key is pressed
3803
- // 2. show hover info
3804
- // 3. selection moves
3805
- // 4. highlight go to definition
3806
- // 5. show color picker
3807
- // 6. show error info
3725
+ // TODO format with cursor
3726
+ // TODO should be in editor folder
3808
3727
 
3809
- const onHoverIdle = async () => {
3810
- const {
3811
- x,
3812
- y,
3813
- editor
3814
- } = get$4();
3815
- at(editor, x, y);
3816
- await showHover$1();
3728
+ const format$1 = async editor => {
3729
+ const edits = await invoke$3('Format.format', editor);
3730
+ return edits;
3817
3731
  };
3818
- const hoverDelay = 300;
3819
3732
 
3820
- // @ts-ignore
3821
- const handleMouseMove = (editor, x, y) => {
3822
- if (!editor.hoverEnabled) {
3823
- return editor;
3824
- }
3825
- const oldState = get$4();
3826
- if (oldState.timeout !== -1) {
3827
- clearTimeout(oldState.timeout);
3828
- }
3829
- const timeout = setTimeout(onHoverIdle, hoverDelay);
3830
- set$4(editor, timeout, x, y);
3831
- return editor;
3733
+ const warn = (...args) => {
3734
+ console.warn(...args);
3735
+ };
3736
+ const error = (...args) => {
3737
+ console.error(...args);
3832
3738
  };
3833
3739
 
3834
3740
  // @ts-ignore
3835
- const getTokenIndex = (tokens, offset) => {
3836
- let currentOffset = 0;
3837
- for (let i = 0; i < tokens.length; i++) {
3838
- const token = tokens[i];
3839
- currentOffset += token.length;
3840
- if (currentOffset >= offset) {
3841
- return i;
3741
+ const getDocumentEdits = (editor, edits) => {
3742
+ const documentEdits = [];
3743
+ for (const edit of edits) {
3744
+ const start = positionAt(editor, edit.startOffset);
3745
+ const end = positionAt(editor, edit.endOffset);
3746
+ const deleted = getSelectionText(editor, {
3747
+ start,
3748
+ end
3749
+ });
3750
+ const documentEdit = {
3751
+ start,
3752
+ end,
3753
+ inserted: splitLines$2(edit.inserted),
3754
+ deleted,
3755
+ origin: Format
3756
+ };
3757
+ if (documentEdit.inserted.length === 0) {
3758
+ documentEdit.inserted = [''];
3842
3759
  }
3760
+ documentEdits.push(documentEdit);
3843
3761
  }
3844
- return -1;
3762
+ return documentEdits;
3845
3763
  };
3846
3764
 
3847
3765
  // @ts-ignore
3848
- const handleMouseMoveWithAltKey = async (editor, x, y) => {
3849
- object(editor);
3850
- number$1(x);
3851
- number$1(y);
3852
- const position = at(editor, x, y);
3853
- const documentOffset = offsetAt(editor, position.rowIndex, position.columnIndex);
3854
- try {
3855
- const definition = await getDefinition(editor, documentOffset);
3856
- if (!definition) {
3857
- return editor;
3858
- }
3859
-
3860
- // TODO make sure that editor is not disposed
3861
-
3862
- const definitionStartPosition = positionAt(editor, definition.startOffset);
3863
- const definitionEndPosition = positionAt(editor, definition.endOffset);
3864
- // @ts-ignore
3865
- const definitionRelativeStartX = definitionStartPosition.columnIndex;
3866
- // @ts-ignore
3867
- const definitionRelativeEndX = definitionEndPosition.columnIndex;
3868
- // const definitionRelativeY = definitionStartPosition.rowIndex - editor.minLineY
3869
-
3870
- const lineTokenMap = editor.lineCache[definitionStartPosition.rowIndex + 1];
3871
- if (!lineTokenMap) {
3872
- return editor;
3873
- }
3874
- const tokenIndex = getTokenIndex(lineTokenMap.tokens, definitionStartPosition.columnIndex);
3875
- if (tokenIndex === -1) {
3876
- return editor;
3877
- }
3878
- // .tokens
3879
- // await RendererProcess.invoke(
3880
- // /* Viewlet.invoke */ 'Viewlet.send',
3881
- // /* id */ ViewletModuleId.EditorText,
3882
- // /* method */ 'highlightAsLink',
3883
- // /* relativeY */ definitionRelativeY,
3884
- // /* tokenIndex */ tokenIndex,
3885
- // )
3766
+ const applyDocumentEdits = (editor, edits) => {
3767
+ if (!Array.isArray(edits)) {
3768
+ warn('something is wrong with format on save', edits);
3769
+ return editor;
3770
+ }
3771
+ if (edits.length === 0) {
3886
3772
  return editor;
3887
- } catch (error) {
3888
- // @ts-ignore
3889
- if (error && error.message.startsWith('Failed to execute definition provider: No definition provider found')) {
3890
- return editor;
3891
- }
3892
- throw error;
3893
3773
  }
3774
+ const documentEdits = getDocumentEdits(editor, edits);
3775
+ return scheduleDocumentAndCursorsSelections(editor, documentEdits);
3894
3776
  };
3895
3777
 
3896
- // TODO adjust relative position
3897
- // @ts-ignore
3898
- const getSelectionFromNativeRange = (editor, range) => {
3899
- return new Uint32Array([range.startRowIndex, range.startColumnIndex, range.endRowIndex, range.endColumnIndex]);
3778
+ const expectedErrorMessage = 'Failed to execute formatting provider: FormattingError:';
3779
+ const isFormattingError = error => {
3780
+ return error && error instanceof Error && error.message.startsWith(expectedErrorMessage);
3900
3781
  };
3901
3782
 
3902
- // @ts-ignore
3903
- const getChanges$4 = (editor, data, range) => {
3904
- const selection = getSelectionFromNativeRange(editor, range);
3905
- const selectionRange = {
3906
- start: {
3907
- rowIndex: selection[0],
3908
- columnIndex: selection[1]
3909
- },
3910
- end: {
3911
- rowIndex: selection[2],
3912
- columnIndex: selection[3]
3783
+ // TODO also format with cursor
3784
+ const format = async editor => {
3785
+ try {
3786
+ const edits = await format$1(editor);
3787
+ return applyDocumentEdits(editor, edits);
3788
+ } catch (error) {
3789
+ if (isFormattingError(error)) {
3790
+ console.error('Formatting Error:',
3791
+ // @ts-ignore
3792
+ error.message.slice(expectedErrorMessage.length));
3793
+ return editor;
3913
3794
  }
3914
- };
3915
- const changes = [{
3916
- start: selectionRange.start,
3917
- end: selectionRange.end,
3918
- inserted: [data],
3919
- deleted: getSelectionText(editor, selectionRange),
3920
- origin: ContentEditableInput
3921
- }];
3922
- return changes;
3923
- };
3924
- const handleBeforeInputFromContentEditable = (editor, data, range) => {
3925
- const changes = getChanges$4(editor, data, range);
3926
- return scheduleDocumentAndCursorsSelections(editor, changes);
3795
+ console.error(error);
3796
+ const displayErrorMessage = `${error}`;
3797
+ await editorShowMessage(editor, 0, 0, displayErrorMessage, true);
3798
+ return editor;
3799
+ }
3927
3800
  };
3928
3801
 
3929
3802
  // @ts-ignore
3930
-
3931
- // @ts-ignore
3932
- const editorHandleNativeSelectionChange = (editor, range) => {
3933
- const selections = getSelectionFromNativeRange(editor, range);
3934
- return scheduleSelections(editor, selections);
3803
+ const getDefinition = async (editor, offset) => {
3804
+ const definition = await invoke$3('ExtensionHostDefinition.executeDefinitionProvider', editor, offset);
3805
+ return definition;
3935
3806
  };
3936
3807
 
3937
- const state$3 = {
3938
- /**
3939
- * @type {any}
3940
- */
3941
- currentEditor: undefined,
3942
- hasListener: false,
3943
- position: {
3944
- rowIndex: 0,
3945
- columnIndex: 0
3808
+ const emptyObject = {};
3809
+ const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
3810
+ const i18nString = (key, placeholders = emptyObject) => {
3811
+ if (placeholders === emptyObject) {
3812
+ return key;
3946
3813
  }
3814
+ const replacer = (match, rest) => {
3815
+ return placeholders[rest];
3816
+ };
3817
+ return key.replaceAll(RE_PLACEHOLDER, replacer);
3947
3818
  };
3948
3819
 
3949
- // @ts-ignore
3950
- const setEditor = editor => {
3951
- state$3.currentEditor = editor;
3952
- state$3.hasListener = true;
3953
- };
3954
- const clearEditor = () => {
3955
- state$3.currentEditor = undefined;
3956
- state$3.hasListener = false;
3820
+ const UiStrings$1 = {
3821
+ GoToDefinition: 'Go to Definition',
3822
+ NoDefinitionFound: 'No definition found',
3823
+ NoDefinitionFoundFor: "No definition found for '{PH1}'",
3824
+ NoTypeDefinitionFound: 'No type definition found',
3825
+ NoTypeDefinitionFoundFor: "No type definition found for '{PH1}'",
3826
+ NoResults: 'No Results',
3827
+ Replace: 'Replace'
3957
3828
  };
3958
-
3959
- // @ts-ignore
3960
- const setPosition = position => {
3961
- state$3.position = position;
3829
+ const noDefinitionFound = () => {
3830
+ return i18nString(UiStrings$1.NoDefinitionFound);
3962
3831
  };
3963
- const getEditor$1 = () => {
3964
- return state$3.currentEditor;
3832
+ const noDefinitionFoundFor = word => {
3833
+ return i18nString(UiStrings$1.NoDefinitionFoundFor, {
3834
+ PH1: word
3835
+ });
3965
3836
  };
3966
- const getPosition = () => {
3967
- return state$3.position;
3837
+ const noTypeDefinitionFoundFor = word => {
3838
+ return i18nString(UiStrings$1.NoTypeDefinitionFoundFor, {
3839
+ PH1: word
3840
+ });
3968
3841
  };
3969
- const hasListener = () => {
3970
- return state$3.hasListener;
3842
+ const noTypeDefinitionFound = () => {
3843
+ return i18nString(UiStrings$1.NoTypeDefinitionFound);
3971
3844
  };
3972
-
3973
- // @ts-ignore
3974
- const handlePointerCaptureLost = editor => {
3975
- clearEditor();
3976
- return editor;
3845
+ const noResults$1 = () => {
3846
+ return i18nString(UiStrings$1.NoResults);
3977
3847
  };
3978
3848
 
3979
3849
  // @ts-ignore
3980
-
3981
- // @ts-ignore
3982
- const getNewPercent$1 = (size, scrollBarSize, relativeX) => {
3983
- if (relativeX <= 0) {
3984
- return 0;
3985
- }
3986
- // if (relativeY <= editor.scrollBarHeight / 2) {
3987
- // console.log('clicked at top')
3988
- // // clicked at top
3989
- // return 0
3990
- // }
3991
- if (relativeX <= size - scrollBarSize / 2) {
3992
- // clicked in middle
3993
- return relativeX / (size - scrollBarSize);
3994
- }
3995
- // clicked at bottom
3996
- return 1;
3997
- };
3998
-
3999
- // @ts-ignore
4000
- const handleScrollBarHorizontalMove = (state, eventX) => {
3850
+ const goTo = async ({
3851
+ editor,
3852
+ getLocation,
3853
+ getNoLocationFoundMessage,
3854
+ getErrorMessage,
3855
+ isNoProviderFoundError
3856
+ }) => {
4001
3857
  const {
4002
- x,
4003
- width,
4004
- longestLineWidth,
4005
- handleOffsetX
4006
- } = state;
4007
- const spaceRight = 20; // TODO make this configurable
4008
- const normalizedEventX = clamp(eventX, x, x + width);
4009
- if (width > longestLineWidth) {
4010
- return {
4011
- ...state,
4012
- deltaX: 0,
4013
- scrollBarWidth: 0
3858
+ selections
3859
+ } = editor;
3860
+ const rowIndex = selections[0];
3861
+ const columnIndex = selections[1];
3862
+ try {
3863
+ const definition = await getLocation(editor, rowIndex, columnIndex);
3864
+ // TODO if editor is already disposed at this point, do nothing
3865
+ if (!definition) {
3866
+ // TODO show popup that no definition was found
3867
+ // TODO if there was an error, show popup that go to definition resulted in an error
3868
+ const info = getWordAt(editor, rowIndex, columnIndex);
3869
+ const message = getNoLocationFoundMessage(info);
3870
+ return editorShowMessage(editor, rowIndex, columnIndex, message, false);
3871
+ }
3872
+ if (typeof definition.uri !== 'string' || typeof definition.startOffset !== 'number' || typeof definition.endOffset !== 'number') {
3873
+ // Logger.warn('invalid definition result', definition)
3874
+ return editor;
3875
+ }
3876
+ const uri = definition.uri;
3877
+ if (uri === editor.uri) {
3878
+ // TODO set cursor to the definition position
3879
+ const position = positionAt(editor, definition.startOffset);
3880
+ const selectionEdits = new Uint32Array([position.rowIndex, position.columnIndex, position.rowIndex, position.columnIndex]);
3881
+ return scheduleSelections(editor, selectionEdits);
3882
+ }
3883
+ // TODO if definition.file is not of type string, show a popup that definition.file must be of type string
3884
+ // TODO open file and scroll to that position and set cursor to that position
3885
+
3886
+ const context = {
3887
+ startRowIndex: definition.startRowIndex,
3888
+ startColumnIndex: definition.startColumnIndex,
3889
+ endRowIndex: definition.endRowIndex,
3890
+ endColumnIndex: definition.endColumnIndex
4014
3891
  };
3892
+ await invoke$3(/* Main.openUri */'Main.openUri', /* uri */uri, /* focus */true, context);
3893
+ return editor;
3894
+ } catch (error) {
3895
+ // TODO if editor is already disposed at this point, do nothing
3896
+ if (isNoProviderFoundError(error)) {
3897
+ const displayErrorMessage = getErrorMessage(error);
3898
+ await editorShowMessage(editor, rowIndex, columnIndex, displayErrorMessage, false);
3899
+ return editor;
3900
+ }
3901
+ // @ts-ignore
3902
+ // ErrorHandling.handleError(error, false)
3903
+ const displayErrorMessage = getErrorMessage(error);
3904
+ await editorShowMessage(editor, rowIndex, columnIndex, displayErrorMessage, true);
3905
+ return editor;
4015
3906
  }
4016
- const relativeX = normalizedEventX - x - handleOffsetX;
4017
- const scrollBarWidth = getScrollBarWidth(width, longestLineWidth);
4018
- const finalDeltaX = longestLineWidth - width + spaceRight;
4019
- const newPercent = getNewPercent$1(width, scrollBarWidth, relativeX);
4020
- const clampedPercent = clamp(newPercent, 0, 1);
4021
- const newDeltaX = clampedPercent * finalDeltaX;
4022
- return {
4023
- ...state,
4024
- deltaX: newDeltaX
4025
- };
4026
3907
  };
4027
3908
 
4028
- // @ts-ignore
3909
+ // TODO race condition, check that editor hasn't been closed in the meantime
4029
3910
 
4030
- // TODO duplicate code with vertical pointer down event listener
3911
+ // TODO in case of error should show message "Definition Error: Cannot ready Property x of undefined"
4031
3912
 
4032
- // @ts-ignore
4033
- const handleScrollBarHorizontalPointerDown = (state, eventX) => {
4034
- // @ts-ignore
4035
- const {
4036
- x,
4037
- deltaX,
4038
- width,
4039
- finalDeltaY,
4040
- height,
4041
- scrollBarHeight,
4042
- longestLineWidth
4043
- } = state;
4044
- const relativeX = eventX - x;
4045
- const scrollBarWidth = getScrollBarWidth(width, longestLineWidth);
4046
- const finalDeltaX = width - scrollBarWidth;
4047
- const currentScrollBarX = getScrollBarOffset(deltaX, finalDeltaX, width, scrollBarWidth);
4048
- const diff = relativeX - currentScrollBarX;
4049
- if (diff >= 0 && diff < scrollBarWidth) {
4050
- return {
4051
- ...state,
4052
- handleOffsetX: diff
4053
- };
4054
- }
4055
- const {
4056
- percent,
4057
- handleOffset
4058
- } = getNewDeltaPercent(width, scrollBarWidth, relativeX);
4059
- const newDeltaX = percent * finalDeltaX;
4060
- return {
4061
- ...state,
4062
- handleOffsetX: handleOffset,
4063
- deltaX: newDeltaX
4064
- };
4065
- };
3913
+ // TODO show some kind of message maybe ("No Definition found")
4066
3914
 
4067
- // @ts-ignore
3915
+ // TODO possible to do this with events/state machine instead of promises -> enables canceling operations / concurrent calls
3916
+
3917
+ // TODO there are still race conditions in this function:
3918
+ // - when open is called twice, previous dom nodes can either be reused or the previous dom nodes must be disposed
4068
3919
 
4069
3920
  // @ts-ignore
4070
- const getNewPercent = (state, relativeY) => {
4071
- const {
4072
- height,
4073
- scrollBarHeight
4074
- } = state;
4075
- // if (relativeY <= editor.scrollBarHeight / 2) {
4076
- // console.log('clicked at top')
4077
- // // clicked at top
4078
- // return 0
4079
- // }
4080
- if (relativeY <= height - scrollBarHeight / 2) {
4081
- // clicked in middle
4082
- return relativeY / (height - scrollBarHeight);
4083
- }
4084
- // clicked at bottom
4085
- return 1;
3921
+ const getLocation$1 = async (editor, rowIndex, columnIndex) => {
3922
+ const offset = offsetAt(editor, rowIndex, columnIndex);
3923
+ const definition = await getDefinition(editor, offset);
3924
+ return definition;
4086
3925
  };
4087
3926
 
4088
3927
  // @ts-ignore
4089
- const handleScrollBarMove = (state, eventY) => {
4090
- const {
4091
- y,
4092
- finalDeltaY,
4093
- handleOffset
4094
- } = state;
4095
- const relativeY = eventY - y - handleOffset;
4096
- const newPercent = getNewPercent(state, relativeY);
4097
- const newDeltaY = newPercent * finalDeltaY;
4098
- return setDeltaYFixedValue$1(state, newDeltaY);
3928
+ const getNoLocationFoundMessage$1 = info => {
3929
+ if (info.word) {
3930
+ return noDefinitionFoundFor(info.word);
3931
+ }
3932
+ return noDefinitionFound();
4099
3933
  };
4100
- const handleScrollBarVerticalPointerMove = handleScrollBarMove;
4101
3934
 
4102
3935
  // @ts-ignore
4103
-
4104
- // TODO scrollbar position can be in interval [0, editor.height - editor.scrollBarHeight]
4105
- // when clicked at y <= editor.scrollbarHeight/2, position is set to zero
4106
- // when clicked at y >= editor.height - editor.scrollBarHeight/2, position is set to (editor.height - scrollBarHeight/2)
4107
- // when clicked at y > editor.height - editor.scrollBarHeight/2, position scrollbar at (y - scrollbarHeight/2)
4108
- // additionally, when clicked on scrollbar, scrollbar position shouldn't move
3936
+ const getErrorMessage$3 = error => {
3937
+ // if (
3938
+ // error &&
3939
+ // error.message &&
3940
+ // error.message.startsWith('Failed to execute definition provider: ')
3941
+ // ) {
3942
+ // return error.message.replace('Failed to execute definition provider: ', '')
3943
+ // }
3944
+ return `${error}`;
3945
+ };
4109
3946
 
4110
3947
  // @ts-ignore
4111
- const handleScrollBarPointerDown = (state, eventY) => {
4112
- const {
4113
- y,
4114
- deltaY,
4115
- finalDeltaY,
4116
- height,
4117
- scrollBarHeight
4118
- } = state;
4119
- const relativeY = eventY - y;
4120
- const currentScrollBarY = getScrollBarY(deltaY, finalDeltaY, height, scrollBarHeight);
4121
- const diff = relativeY - currentScrollBarY;
4122
- if (diff >= 0 && diff < scrollBarHeight) {
4123
- return {
4124
- ...state,
4125
- handleOffset: diff
4126
- };
4127
- }
4128
- const {
4129
- percent,
4130
- handleOffset
4131
- } = getNewDeltaPercent(height, scrollBarHeight, relativeY);
4132
- const newDeltaY = percent * finalDeltaY;
4133
- return {
4134
- ...setDeltaYFixedValue$1(state, newDeltaY),
4135
- handleOffset
4136
- };
3948
+ const isNoProviderFoundError$1 = error => {
3949
+ return error &&
3950
+ // @ts-ignore
3951
+ error.message &&
3952
+ // @ts-ignore
3953
+ error.message.startsWith('Failed to execute definition provider: No definition provider found');
4137
3954
  };
4138
-
4139
- const state$2 = {
4140
- touchOffsetY: 0,
4141
- deltaY: 0
3955
+ const goToDefinition = editor => {
3956
+ return goTo({
3957
+ editor,
3958
+ getLocation: getLocation$1,
3959
+ getNoLocationFoundMessage: getNoLocationFoundMessage$1,
3960
+ getErrorMessage: getErrorMessage$3,
3961
+ isNoProviderFoundError: isNoProviderFoundError$1
3962
+ });
4142
3963
  };
4143
3964
 
4144
- // @ts-ignore
4145
- const handleTouchStart = (editor, touchEvent) => {
4146
- if (touchEvent.touches.length === 0) {
4147
- return;
3965
+ const getNoLocationFoundMessage = info => {
3966
+ if (info.word) {
3967
+ return noTypeDefinitionFoundFor(info.word);
4148
3968
  }
4149
- const firstTouch = touchEvent.touches[0];
4150
- state$2.touchOffsetY = firstTouch.y;
4151
- state$2.deltaY = editor.deltaY;
4152
- // const position = EditorPosition.at(editor, firstTouch.x, firstTouch.y)
4153
- // EditorMoveSelection.state.position = position
4154
- // state.date = Date.now()
3969
+ return noTypeDefinitionFound();
4155
3970
  };
4156
3971
 
4157
- const LessThan = -1;
4158
- const Equal = 0;
4159
- const GreaterThan = 1;
3972
+ const getTypeDefinition = async (editor, offset) => {
3973
+ const definition = await invoke$3('ExtensionHostTypeDefinition.executeTypeDefinitionProvider', editor, offset);
3974
+ return definition;
3975
+ };
4160
3976
 
4161
- // @ts-ignore
3977
+ const getLocation = async (editor, rowIndex, columnIndex) => {
3978
+ const offset = offsetAt(editor, rowIndex, columnIndex);
3979
+ const definition = await getTypeDefinition(editor, offset);
3980
+ return definition;
3981
+ };
4162
3982
 
4163
3983
  // @ts-ignore
4164
- const compare = (positionA, positionB) => {
4165
- if (positionA.rowIndex > positionB.rowIndex) {
4166
- return GreaterThan;
4167
- }
4168
- if (positionA.rowIndex === positionB.rowIndex) {
4169
- if (positionA.columnIndex > positionB.columnIndex) {
4170
- return GreaterThan;
4171
- }
4172
- if (positionA.columnIndex < positionB.columnIndex) {
4173
- return LessThan;
4174
- }
4175
- return Equal;
4176
- }
4177
- return LessThan;
3984
+ const getErrorMessage$2 = error => {
3985
+ // if (
3986
+ // error &&
3987
+ // error.message &&
3988
+ // error.message.startsWith('Failed to execute type definition provider: ')
3989
+ // ) {
3990
+ // return error.message.replace(
3991
+ // 'Failed to execute type definition provider: ',
3992
+ // ''
3993
+ // )
3994
+ // }
3995
+ return `${error}`;
3996
+ };
3997
+ const isNoProviderFoundError = error => {
3998
+ return error &&
3999
+ // @ts-ignore
4000
+ error.message &&
4001
+ // @ts-ignore
4002
+ error.message.startsWith('Failed to execute type definition provider: No type definition provider found');
4003
+ };
4004
+ const goToTypeDefinition = (editor, explicit = true) => {
4005
+ return goTo({
4006
+ editor,
4007
+ getLocation,
4008
+ getNoLocationFoundMessage: getNoLocationFoundMessage,
4009
+ isNoProviderFoundError,
4010
+ getErrorMessage: getErrorMessage$2
4011
+ });
4178
4012
  };
4179
4013
 
4180
- // @ts-ignore
4181
- const editorMoveSelectionBackwards = (anchor, position) => {
4182
- return new Uint32Array([anchor.rowIndex, anchor.columnIndex, position.rowIndex, position.columnIndex]);
4014
+ const Editor = 3;
4015
+
4016
+ const handleContextMenu = async (editor, button, x, y) => {
4017
+ await invoke$3(/* ContextMenu.show */'ContextMenu.show', /* x */x, /* y */y, /* id */Editor);
4018
+ return editor;
4183
4019
  };
4184
4020
 
4185
4021
  // @ts-ignore
4186
- const editorMoveSelectionEqual = (anchor, position) => {
4187
- return new Uint32Array([position.rowIndex, position.columnIndex, position.rowIndex, position.columnIndex]);
4188
- };
4022
+
4023
+ // match all words, including umlauts, see https://stackoverflow.com/questions/5436824/matching-accented-characters-with-javascript-regexes/#answer-11550799
4024
+ const RE_WORD_START = /^[a-z\u00C0-\u017F\d]+/i;
4025
+ const RE_WORD_END = /[a-z\u00C0-\u017F\d]+$/i;
4189
4026
 
4190
4027
  // @ts-ignore
4191
- const editorMoveSelectionForwards = (anchor, position) => {
4192
- return new Uint32Array([anchor.rowIndex, anchor.columnIndex, position.rowIndex, position.columnIndex]);
4028
+ const getNewSelections$7 = (line, rowIndex, columnIndex) => {
4029
+ const before = line.slice(0, columnIndex);
4030
+ const after = line.slice(columnIndex);
4031
+ const beforeMatch = before.match(RE_WORD_END);
4032
+ const afterMatch = after.match(RE_WORD_START);
4033
+ const columnStart = columnIndex - (beforeMatch ? beforeMatch[0].length : 0);
4034
+ const columnEnd = columnIndex + (afterMatch ? afterMatch[0].length : 0);
4035
+ const newSelections = new Uint32Array([rowIndex, columnStart, rowIndex, columnEnd]);
4036
+ return newSelections;
4193
4037
  };
4194
4038
 
4195
4039
  // @ts-ignore
4196
- const getNewSelections$5 = (anchor, position) => {
4197
- switch (compare(position, anchor)) {
4198
- case LessThan:
4199
- return editorMoveSelectionBackwards(anchor, position);
4200
- case Equal:
4201
- return editorMoveSelectionEqual(anchor, position);
4202
- case GreaterThan:
4203
- return editorMoveSelectionForwards(anchor, position);
4204
- default:
4205
- throw new Error('unexpected comparison result');
4040
+ const selectWord = (editor, rowIndex, columnIndex) => {
4041
+ const line = getLine(editor, rowIndex);
4042
+ const newSelections = getNewSelections$7(line, rowIndex, columnIndex);
4043
+ return scheduleSelections(editor, newSelections);
4044
+ };
4045
+
4046
+ const handleDoubleClick = (editor, modifier, x, y) => {
4047
+ const position = at(editor, x, y);
4048
+ return selectWord(editor, position.rowIndex, position.columnIndex);
4049
+ };
4050
+
4051
+ const WhenExpressionEditorText = 12;
4052
+ const handleFocus = editor => {
4053
+ // TODO make change events functional,
4054
+ // when rendering, send focus changes to renderer worker
4055
+ invoke$3('Focus.setFocus', WhenExpressionEditorText);
4056
+ return editor;
4057
+ };
4058
+
4059
+ const Single = 1;
4060
+ const Double = 2;
4061
+ const Triple = 3;
4062
+
4063
+ const state$3 = {
4064
+ position: {
4065
+ rowIndex: 0,
4066
+ columnIndex: 0
4206
4067
  }
4207
4068
  };
4069
+ const getPosition$1 = () => {
4070
+ return state$3.position;
4071
+ };
4208
4072
 
4209
4073
  // @ts-ignore
4210
- const editorMoveSelection = (editor, position) => {
4211
- const anchor = getPosition$1();
4212
- const newSelections = getNewSelections$5(anchor, position);
4213
- // TODO if selection equals previous selection -> do nothing
4214
- return scheduleSelections(editor, newSelections);
4074
+ const setPosition$1 = position => {
4075
+ state$3.position = position;
4215
4076
  };
4216
4077
 
4217
- const LONG_TOUCH_THRESHOLD = 150;
4078
+ const Ctrl = 1;
4079
+ const Alt = 2;
4218
4080
 
4219
- // @ts-ignore
4220
- const handleTouchEnd = (editor, touchEvent) => {
4221
- if (touchEvent.changedTouches.length === 0) {
4222
- return;
4223
- }
4224
- const firstTouch = touchEvent.changedTouches[0];
4225
- const position = at(editor, firstTouch.x, firstTouch.y);
4226
- // @ts-ignore
4227
- if (undefined.position.rowIndex === position.rowIndex && undefined.position.columnIndex === position.columnIndex) {
4228
- // @ts-ignore
4229
- if (Date.now() - state$2.date > LONG_TOUCH_THRESHOLD) {
4230
- selectWord(editor, position.rowIndex, position.columnIndex);
4231
- } else {
4232
- // @ts-ignore
4233
- cursorSet(editor, position);
4081
+ // TODO first change cursor position, then run go to definition
4082
+ // cursor should appear at mousedown position immediately
4083
+ const handleSingleClickWithAlt = async (editor, position) => {
4084
+ const {
4085
+ rowIndex,
4086
+ columnIndex
4087
+ } = position;
4088
+ const newEditor = {
4089
+ ...editor,
4090
+ selections: new Uint32Array([rowIndex, columnIndex, rowIndex, columnIndex])
4091
+ };
4092
+ // TODO rectangular selection with alt click,
4093
+ // but also go to definition with alt click
4094
+ const newEditor2 = await goToDefinition(newEditor);
4095
+ return newEditor2;
4096
+ };
4097
+ const handleSingleClickWithCtrl = async (editor, position) => {
4098
+ const selections = editor.selections;
4099
+ for (let i = 0; i < selections.length; i += 4) {
4100
+ const [selectionStartRow, selectionStartColumn, selectionEndRow, selectionEndColumn] = getSelectionPairs(selections, i);
4101
+ if (selectionStartRow === position.rowIndex && selectionStartColumn === position.columnIndex && selectionEndRow === position.rowIndex && selectionEndColumn === position.columnIndex) {
4102
+ // selection exists -> remove
4103
+ const newSelections = new Uint32Array(selections.length - 4);
4104
+ newSelections.set(selections.subarray(0, i), 0);
4105
+ newSelections.set(selections.subarray(i + 4), i);
4106
+ return scheduleSelections(editor, newSelections);
4234
4107
  }
4235
- } else {
4236
- console.log('different position');
4237
4108
  }
4109
+ // TODO selection does not exist -> add
4110
+ // TODO insert in order
4111
+ const newSelections = new Uint32Array(selections.length + 4);
4112
+ newSelections.set(selections, 0);
4113
+ const insertIndex = selections.length;
4114
+ newSelections[insertIndex] = position.rowIndex;
4115
+ newSelections[insertIndex + 1] = position.columnIndex;
4116
+ newSelections[insertIndex + 2] = position.rowIndex;
4117
+ newSelections[insertIndex + 3] = position.columnIndex;
4118
+ return scheduleSelections(editor, newSelections);
4119
+ };
4120
+ const handleSingleClickDefault = (editor, position) => {
4121
+ setPosition$1(position);
4122
+ return {
4123
+ ...editor,
4124
+ selections: new Uint32Array([position.rowIndex, position.columnIndex, position.rowIndex, position.columnIndex]),
4125
+ focused: true
4126
+ };
4127
+ };
4128
+ const getFn = modifier => {
4129
+ switch (modifier) {
4130
+ case Alt:
4131
+ return handleSingleClickWithAlt;
4132
+ case Ctrl:
4133
+ return handleSingleClickWithCtrl;
4134
+ default:
4135
+ return handleSingleClickDefault;
4136
+ }
4137
+ };
4138
+ const handleSingleClick = async (editor, modifier, x, y) => {
4139
+ object(editor);
4140
+ number$1(modifier);
4141
+ number$1(x);
4142
+ number$1(y);
4143
+ const position = at(editor, x, y);
4144
+ const fn = getFn(modifier);
4145
+ const newEditor = await fn(editor, position);
4146
+ // switch (newEditor.completionState) {
4147
+ // case EditorCompletionState.None:
4148
+ // case EditorCompletionState.Visible:
4149
+ // case EditorCompletionState.Loading:
4150
+ // return {
4151
+ // newState: newEditor,
4152
+ // commands: [],
4153
+ // }
4154
+ // default:
4155
+ // break
4156
+ // }
4157
+ return newEditor;
4238
4158
  };
4239
4159
 
4240
4160
  // @ts-ignore
4241
- const setDeltaY = (editor, deltaY) => {
4242
- return setDeltaY$1(editor, deltaY);
4161
+
4162
+ // @ts-ignore
4163
+ const getNewSelections$6 = (line, rowIndex) => {
4164
+ // TODO handle virtual space when columnIndex is greater than line length
4165
+ return new Uint32Array([rowIndex, 0, rowIndex, line.length]);
4243
4166
  };
4244
4167
 
4245
4168
  // @ts-ignore
4246
- const setDeltaYFixedValue = (editor, deltaY) => {
4247
- return setDeltaYFixedValue$1(editor, deltaY);
4169
+ const selectLine = editor => {
4170
+ const selections = editor.selections;
4171
+ const rowIndex = selections[editor.primarySelectionIndex];
4172
+ const line = getLine(editor, rowIndex);
4173
+ const newSelections = getNewSelections$6(line, rowIndex);
4174
+ return scheduleSelections(editor, newSelections);
4248
4175
  };
4249
4176
 
4177
+ // TODO rowIndex and columnIndex should already be set because of singleClick which occurred before triple click
4250
4178
  // @ts-ignore
4251
- const setDelta = (editor, deltaMode, eventDeltaX, eventDeltaY) => {
4252
- number$1(deltaMode);
4253
- number$1(eventDeltaX);
4254
- number$1(eventDeltaY);
4255
- // @ts-ignore
4256
- const {
4257
- deltaX,
4258
- deltaY
4259
- } = editor;
4260
- if (eventDeltaX === 0) {
4261
- return setDeltaY(editor, eventDeltaY);
4262
- }
4263
- const newDeltaX = clamp(deltaX + eventDeltaX, 0, Number.POSITIVE_INFINITY);
4179
+ const handleTripleClick = (editor, modifier, x, y) => {
4180
+ object(editor);
4181
+ number$1(x);
4182
+ number$1(y);
4264
4183
  return {
4265
- ...setDeltaY(editor, eventDeltaY),
4266
- deltaX: newDeltaX
4184
+ newState: selectLine(editor),
4185
+ commands: []
4267
4186
  };
4268
4187
  };
4269
4188
 
4270
- // @ts-ignore
4271
- const handleTouchMove = (editor, touchEvent) => {
4272
- if (touchEvent.touches.length === 0) {
4273
- return;
4189
+ const handleMouseDown = (state, modifier, x, y, detail) => {
4190
+ switch (detail) {
4191
+ case Single:
4192
+ return handleSingleClick(state, modifier, x, y);
4193
+ case Double:
4194
+ return handleDoubleClick(state, modifier, x, y);
4195
+ case Triple:
4196
+ return handleTripleClick(state, modifier, x, y);
4197
+ default:
4198
+ return state;
4274
4199
  }
4275
- const firstTouch = touchEvent.touches[0];
4276
- const offsetY = state$2.deltaY + (state$2.touchOffsetY - firstTouch.y);
4277
- setDeltaYFixedValue(editor, offsetY);
4200
+ };
4201
+
4202
+ const state$2 = {
4203
+ timeout: -1,
4204
+ x: 0,
4205
+ y: 0,
4206
+ editor: undefined
4207
+ };
4208
+ const get$2 = () => {
4209
+ return state$2;
4210
+ };
4211
+ const set$2 = (editor, timeout, x, y) => {
4212
+ state$2.editor = editor;
4213
+ state$2.timeout = timeout;
4214
+ state$2.x = x;
4215
+ state$2.y = y;
4216
+ };
4217
+
4218
+ const showHover$1 = async (editor, position) => {
4219
+ // TODO race condition
4220
+ // await Viewlet.closeWidget(ViewletModuleId.EditorHover)
4221
+ // await Viewlet.openWidget(ViewletModuleId.EditorHover, position)
4222
+ };
4223
+
4224
+ // TODO several things can happen:
4225
+ // 1. highlight link when alt key is pressed
4226
+ // 2. show hover info
4227
+ // 3. selection moves
4228
+ // 4. highlight go to definition
4229
+ // 5. show color picker
4230
+ // 6. show error info
4231
+
4232
+ const onHoverIdle = async () => {
4233
+ const {
4234
+ x,
4235
+ y,
4236
+ editor
4237
+ } = get$2();
4238
+ at(editor, x, y);
4239
+ await showHover$1();
4240
+ };
4241
+ const hoverDelay = 300;
4242
+
4243
+ // @ts-ignore
4244
+ const handleMouseMove = (editor, x, y) => {
4245
+ if (!editor.hoverEnabled) {
4246
+ return editor;
4247
+ }
4248
+ const oldState = get$2();
4249
+ if (oldState.timeout !== -1) {
4250
+ clearTimeout(oldState.timeout);
4251
+ }
4252
+ const timeout = setTimeout(onHoverIdle, hoverDelay);
4253
+ set$2(editor, timeout, x, y);
4254
+ return editor;
4255
+ };
4256
+
4257
+ // @ts-ignore
4258
+ const getTokenIndex = (tokens, offset) => {
4259
+ let currentOffset = 0;
4260
+ for (let i = 0; i < tokens.length; i++) {
4261
+ const token = tokens[i];
4262
+ currentOffset += token.length;
4263
+ if (currentOffset >= offset) {
4264
+ return i;
4265
+ }
4266
+ }
4267
+ return -1;
4268
+ };
4269
+
4270
+ // @ts-ignore
4271
+ const handleMouseMoveWithAltKey = async (editor, x, y) => {
4272
+ object(editor);
4273
+ number$1(x);
4274
+ number$1(y);
4275
+ const position = at(editor, x, y);
4276
+ const documentOffset = offsetAt(editor, position.rowIndex, position.columnIndex);
4277
+ try {
4278
+ const definition = await getDefinition(editor, documentOffset);
4279
+ if (!definition) {
4280
+ return editor;
4281
+ }
4282
+
4283
+ // TODO make sure that editor is not disposed
4284
+
4285
+ const definitionStartPosition = positionAt(editor, definition.startOffset);
4286
+ const definitionEndPosition = positionAt(editor, definition.endOffset);
4287
+ // @ts-ignore
4288
+ const definitionRelativeStartX = definitionStartPosition.columnIndex;
4289
+ // @ts-ignore
4290
+ const definitionRelativeEndX = definitionEndPosition.columnIndex;
4291
+ // const definitionRelativeY = definitionStartPosition.rowIndex - editor.minLineY
4292
+
4293
+ const lineTokenMap = editor.lineCache[definitionStartPosition.rowIndex + 1];
4294
+ if (!lineTokenMap) {
4295
+ return editor;
4296
+ }
4297
+ const tokenIndex = getTokenIndex(lineTokenMap.tokens, definitionStartPosition.columnIndex);
4298
+ if (tokenIndex === -1) {
4299
+ return editor;
4300
+ }
4301
+ // .tokens
4302
+ // await RendererProcess.invoke(
4303
+ // /* Viewlet.invoke */ 'Viewlet.send',
4304
+ // /* id */ ViewletModuleId.EditorText,
4305
+ // /* method */ 'highlightAsLink',
4306
+ // /* relativeY */ definitionRelativeY,
4307
+ // /* tokenIndex */ tokenIndex,
4308
+ // )
4309
+ return editor;
4310
+ } catch (error) {
4311
+ // @ts-ignore
4312
+ if (error && error.message.startsWith('Failed to execute definition provider: No definition provider found')) {
4313
+ return editor;
4314
+ }
4315
+ throw error;
4316
+ }
4317
+ };
4318
+
4319
+ // TODO adjust relative position
4320
+ // @ts-ignore
4321
+ const getSelectionFromNativeRange = (editor, range) => {
4322
+ return new Uint32Array([range.startRowIndex, range.startColumnIndex, range.endRowIndex, range.endColumnIndex]);
4323
+ };
4324
+
4325
+ // @ts-ignore
4326
+ const getChanges$4 = (editor, data, range) => {
4327
+ const selection = getSelectionFromNativeRange(editor, range);
4328
+ const selectionRange = {
4329
+ start: {
4330
+ rowIndex: selection[0],
4331
+ columnIndex: selection[1]
4332
+ },
4333
+ end: {
4334
+ rowIndex: selection[2],
4335
+ columnIndex: selection[3]
4336
+ }
4337
+ };
4338
+ const changes = [{
4339
+ start: selectionRange.start,
4340
+ end: selectionRange.end,
4341
+ inserted: [data],
4342
+ deleted: getSelectionText(editor, selectionRange),
4343
+ origin: ContentEditableInput
4344
+ }];
4345
+ return changes;
4346
+ };
4347
+ const handleBeforeInputFromContentEditable = (editor, data, range) => {
4348
+ const changes = getChanges$4(editor, data, range);
4349
+ return scheduleDocumentAndCursorsSelections(editor, changes);
4350
+ };
4351
+
4352
+ // @ts-ignore
4353
+
4354
+ // @ts-ignore
4355
+ const editorHandleNativeSelectionChange = (editor, range) => {
4356
+ const selections = getSelectionFromNativeRange(editor, range);
4357
+ return scheduleSelections(editor, selections);
4358
+ };
4359
+
4360
+ const state$1 = {
4361
+ /**
4362
+ * @type {any}
4363
+ */
4364
+ currentEditor: undefined,
4365
+ hasListener: false,
4366
+ position: {
4367
+ rowIndex: 0,
4368
+ columnIndex: 0
4369
+ }
4370
+ };
4371
+
4372
+ // @ts-ignore
4373
+ const setEditor = editor => {
4374
+ state$1.currentEditor = editor;
4375
+ state$1.hasListener = true;
4376
+ };
4377
+ const clearEditor = () => {
4378
+ state$1.currentEditor = undefined;
4379
+ state$1.hasListener = false;
4380
+ };
4381
+
4382
+ // @ts-ignore
4383
+ const setPosition = position => {
4384
+ state$1.position = position;
4385
+ };
4386
+ const getEditor$1 = () => {
4387
+ return state$1.currentEditor;
4388
+ };
4389
+ const getPosition = () => {
4390
+ return state$1.position;
4391
+ };
4392
+ const hasListener = () => {
4393
+ return state$1.hasListener;
4394
+ };
4395
+
4396
+ // @ts-ignore
4397
+ const handlePointerCaptureLost = editor => {
4398
+ clearEditor();
4399
+ return editor;
4400
+ };
4401
+
4402
+ // @ts-ignore
4403
+
4404
+ // @ts-ignore
4405
+ const getNewPercent$1 = (size, scrollBarSize, relativeX) => {
4406
+ if (relativeX <= 0) {
4407
+ return 0;
4408
+ }
4409
+ // if (relativeY <= editor.scrollBarHeight / 2) {
4410
+ // console.log('clicked at top')
4411
+ // // clicked at top
4412
+ // return 0
4413
+ // }
4414
+ if (relativeX <= size - scrollBarSize / 2) {
4415
+ // clicked in middle
4416
+ return relativeX / (size - scrollBarSize);
4417
+ }
4418
+ // clicked at bottom
4419
+ return 1;
4420
+ };
4421
+
4422
+ // @ts-ignore
4423
+ const handleScrollBarHorizontalMove = (state, eventX) => {
4424
+ const {
4425
+ x,
4426
+ width,
4427
+ longestLineWidth,
4428
+ handleOffsetX
4429
+ } = state;
4430
+ const spaceRight = 20; // TODO make this configurable
4431
+ const normalizedEventX = clamp(eventX, x, x + width);
4432
+ if (width > longestLineWidth) {
4433
+ return {
4434
+ ...state,
4435
+ deltaX: 0,
4436
+ scrollBarWidth: 0
4437
+ };
4438
+ }
4439
+ const relativeX = normalizedEventX - x - handleOffsetX;
4440
+ const scrollBarWidth = getScrollBarWidth(width, longestLineWidth);
4441
+ const finalDeltaX = longestLineWidth - width + spaceRight;
4442
+ const newPercent = getNewPercent$1(width, scrollBarWidth, relativeX);
4443
+ const clampedPercent = clamp(newPercent, 0, 1);
4444
+ const newDeltaX = clampedPercent * finalDeltaX;
4445
+ return {
4446
+ ...state,
4447
+ deltaX: newDeltaX
4448
+ };
4449
+ };
4450
+
4451
+ // @ts-ignore
4452
+
4453
+ // TODO duplicate code with vertical pointer down event listener
4454
+
4455
+ // @ts-ignore
4456
+ const handleScrollBarHorizontalPointerDown = (state, eventX) => {
4457
+ // @ts-ignore
4458
+ const {
4459
+ x,
4460
+ deltaX,
4461
+ width,
4462
+ finalDeltaY,
4463
+ height,
4464
+ scrollBarHeight,
4465
+ longestLineWidth
4466
+ } = state;
4467
+ const relativeX = eventX - x;
4468
+ const scrollBarWidth = getScrollBarWidth(width, longestLineWidth);
4469
+ const finalDeltaX = width - scrollBarWidth;
4470
+ const currentScrollBarX = getScrollBarOffset(deltaX, finalDeltaX, width, scrollBarWidth);
4471
+ const diff = relativeX - currentScrollBarX;
4472
+ if (diff >= 0 && diff < scrollBarWidth) {
4473
+ return {
4474
+ ...state,
4475
+ handleOffsetX: diff
4476
+ };
4477
+ }
4478
+ const {
4479
+ percent,
4480
+ handleOffset
4481
+ } = getNewDeltaPercent(width, scrollBarWidth, relativeX);
4482
+ const newDeltaX = percent * finalDeltaX;
4483
+ return {
4484
+ ...state,
4485
+ handleOffsetX: handleOffset,
4486
+ deltaX: newDeltaX
4487
+ };
4488
+ };
4489
+
4490
+ // @ts-ignore
4491
+
4492
+ // @ts-ignore
4493
+ const getNewPercent = (state, relativeY) => {
4494
+ const {
4495
+ height,
4496
+ scrollBarHeight
4497
+ } = state;
4498
+ // if (relativeY <= editor.scrollBarHeight / 2) {
4499
+ // console.log('clicked at top')
4500
+ // // clicked at top
4501
+ // return 0
4502
+ // }
4503
+ if (relativeY <= height - scrollBarHeight / 2) {
4504
+ // clicked in middle
4505
+ return relativeY / (height - scrollBarHeight);
4506
+ }
4507
+ // clicked at bottom
4508
+ return 1;
4509
+ };
4510
+
4511
+ // @ts-ignore
4512
+ const handleScrollBarMove = (state, eventY) => {
4513
+ const {
4514
+ y,
4515
+ finalDeltaY,
4516
+ handleOffset
4517
+ } = state;
4518
+ const relativeY = eventY - y - handleOffset;
4519
+ const newPercent = getNewPercent(state, relativeY);
4520
+ const newDeltaY = newPercent * finalDeltaY;
4521
+ return setDeltaYFixedValue$1(state, newDeltaY);
4522
+ };
4523
+ const handleScrollBarVerticalPointerMove = handleScrollBarMove;
4524
+
4525
+ // @ts-ignore
4526
+
4527
+ // TODO scrollbar position can be in interval [0, editor.height - editor.scrollBarHeight]
4528
+ // when clicked at y <= editor.scrollbarHeight/2, position is set to zero
4529
+ // when clicked at y >= editor.height - editor.scrollBarHeight/2, position is set to (editor.height - scrollBarHeight/2)
4530
+ // when clicked at y > editor.height - editor.scrollBarHeight/2, position scrollbar at (y - scrollbarHeight/2)
4531
+ // additionally, when clicked on scrollbar, scrollbar position shouldn't move
4532
+
4533
+ // @ts-ignore
4534
+ const handleScrollBarPointerDown = (state, eventY) => {
4535
+ const {
4536
+ y,
4537
+ deltaY,
4538
+ finalDeltaY,
4539
+ height,
4540
+ scrollBarHeight
4541
+ } = state;
4542
+ const relativeY = eventY - y;
4543
+ const currentScrollBarY = getScrollBarY(deltaY, finalDeltaY, height, scrollBarHeight);
4544
+ const diff = relativeY - currentScrollBarY;
4545
+ if (diff >= 0 && diff < scrollBarHeight) {
4546
+ return {
4547
+ ...state,
4548
+ handleOffset: diff
4549
+ };
4550
+ }
4551
+ const {
4552
+ percent,
4553
+ handleOffset
4554
+ } = getNewDeltaPercent(height, scrollBarHeight, relativeY);
4555
+ const newDeltaY = percent * finalDeltaY;
4556
+ return {
4557
+ ...setDeltaYFixedValue$1(state, newDeltaY),
4558
+ handleOffset
4559
+ };
4560
+ };
4561
+
4562
+ const state = {
4563
+ touchOffsetY: 0,
4564
+ deltaY: 0
4565
+ };
4566
+
4567
+ // @ts-ignore
4568
+ const handleTouchStart = (editor, touchEvent) => {
4569
+ if (touchEvent.touches.length === 0) {
4570
+ return;
4571
+ }
4572
+ const firstTouch = touchEvent.touches[0];
4573
+ state.touchOffsetY = firstTouch.y;
4574
+ state.deltaY = editor.deltaY;
4575
+ // const position = EditorPosition.at(editor, firstTouch.x, firstTouch.y)
4576
+ // EditorMoveSelection.state.position = position
4577
+ // state.date = Date.now()
4578
+ };
4579
+
4580
+ const LessThan = -1;
4581
+ const Equal = 0;
4582
+ const GreaterThan = 1;
4583
+
4584
+ // @ts-ignore
4585
+
4586
+ // @ts-ignore
4587
+ const compare = (positionA, positionB) => {
4588
+ if (positionA.rowIndex > positionB.rowIndex) {
4589
+ return GreaterThan;
4590
+ }
4591
+ if (positionA.rowIndex === positionB.rowIndex) {
4592
+ if (positionA.columnIndex > positionB.columnIndex) {
4593
+ return GreaterThan;
4594
+ }
4595
+ if (positionA.columnIndex < positionB.columnIndex) {
4596
+ return LessThan;
4597
+ }
4598
+ return Equal;
4599
+ }
4600
+ return LessThan;
4601
+ };
4602
+
4603
+ // @ts-ignore
4604
+ const editorMoveSelectionBackwards = (anchor, position) => {
4605
+ return new Uint32Array([anchor.rowIndex, anchor.columnIndex, position.rowIndex, position.columnIndex]);
4606
+ };
4607
+
4608
+ // @ts-ignore
4609
+ const editorMoveSelectionEqual = (anchor, position) => {
4610
+ return new Uint32Array([position.rowIndex, position.columnIndex, position.rowIndex, position.columnIndex]);
4611
+ };
4612
+
4613
+ // @ts-ignore
4614
+ const editorMoveSelectionForwards = (anchor, position) => {
4615
+ return new Uint32Array([anchor.rowIndex, anchor.columnIndex, position.rowIndex, position.columnIndex]);
4616
+ };
4617
+
4618
+ // @ts-ignore
4619
+ const getNewSelections$5 = (anchor, position) => {
4620
+ switch (compare(position, anchor)) {
4621
+ case LessThan:
4622
+ return editorMoveSelectionBackwards(anchor, position);
4623
+ case Equal:
4624
+ return editorMoveSelectionEqual(anchor, position);
4625
+ case GreaterThan:
4626
+ return editorMoveSelectionForwards(anchor, position);
4627
+ default:
4628
+ throw new Error('unexpected comparison result');
4629
+ }
4630
+ };
4631
+
4632
+ // @ts-ignore
4633
+ const editorMoveSelection = (editor, position) => {
4634
+ const anchor = getPosition$1();
4635
+ const newSelections = getNewSelections$5(anchor, position);
4636
+ // TODO if selection equals previous selection -> do nothing
4637
+ return scheduleSelections(editor, newSelections);
4638
+ };
4639
+
4640
+ const LONG_TOUCH_THRESHOLD = 150;
4641
+
4642
+ // @ts-ignore
4643
+ const handleTouchEnd = (editor, touchEvent) => {
4644
+ if (touchEvent.changedTouches.length === 0) {
4645
+ return;
4646
+ }
4647
+ const firstTouch = touchEvent.changedTouches[0];
4648
+ const position = at(editor, firstTouch.x, firstTouch.y);
4649
+ // @ts-ignore
4650
+ if (undefined.position.rowIndex === position.rowIndex && undefined.position.columnIndex === position.columnIndex) {
4651
+ // @ts-ignore
4652
+ if (Date.now() - state.date > LONG_TOUCH_THRESHOLD) {
4653
+ selectWord(editor, position.rowIndex, position.columnIndex);
4654
+ } else {
4655
+ // @ts-ignore
4656
+ cursorSet(editor, position);
4657
+ }
4658
+ } else {
4659
+ console.log('different position');
4660
+ }
4661
+ };
4662
+
4663
+ // @ts-ignore
4664
+ const setDeltaY = (editor, deltaY) => {
4665
+ return setDeltaY$1(editor, deltaY);
4666
+ };
4667
+
4668
+ // @ts-ignore
4669
+ const setDeltaYFixedValue = (editor, deltaY) => {
4670
+ return setDeltaYFixedValue$1(editor, deltaY);
4671
+ };
4672
+
4673
+ // @ts-ignore
4674
+ const setDelta = (editor, deltaMode, eventDeltaX, eventDeltaY) => {
4675
+ number$1(deltaMode);
4676
+ number$1(eventDeltaX);
4677
+ number$1(eventDeltaY);
4678
+ // @ts-ignore
4679
+ const {
4680
+ deltaX,
4681
+ deltaY
4682
+ } = editor;
4683
+ if (eventDeltaX === 0) {
4684
+ return setDeltaY(editor, eventDeltaY);
4685
+ }
4686
+ const newDeltaX = clamp(deltaX + eventDeltaX, 0, Number.POSITIVE_INFINITY);
4687
+ return {
4688
+ ...setDeltaY(editor, eventDeltaY),
4689
+ deltaX: newDeltaX
4690
+ };
4691
+ };
4692
+
4693
+ // @ts-ignore
4694
+ const handleTouchMove = (editor, touchEvent) => {
4695
+ if (touchEvent.touches.length === 0) {
4696
+ return;
4697
+ }
4698
+ const firstTouch = touchEvent.touches[0];
4699
+ const offsetY = state.deltaY + (state.touchOffsetY - firstTouch.y);
4700
+ setDeltaYFixedValue(editor, offsetY);
4278
4701
  };
4279
4702
 
4280
4703
  // @ts-ignore
@@ -4565,7 +4988,7 @@ const moveSelectionPx = (editor, x, y) => {
4565
4988
  };
4566
4989
 
4567
4990
  const create$2 = () => {
4568
- const completionUid = create$4();
4991
+ const completionUid = create$5();
4569
4992
  const completionWidget = {
4570
4993
  id: Completion,
4571
4994
  oldState: {
@@ -4598,28 +5021,6 @@ const create$2 = () => {
4598
5021
  return completionWidget;
4599
5022
  };
4600
5023
 
4601
- const OnCompletion = 'onCompletion';
4602
- const OnHover = 'onHover';
4603
-
4604
- // TODO add tests for this
4605
- const activateByEvent = async event => {
4606
- await invoke$3('ExtensionHostManagement.activateByEvent', event);
4607
- };
4608
-
4609
- const execute = async ({
4610
- editor,
4611
- args,
4612
- event,
4613
- method,
4614
- noProviderFoundMessage,
4615
- noProviderFoundResult = undefined
4616
- }) => {
4617
- const fullEvent = `${event}:${editor.languageId}`;
4618
- await activateByEvent(fullEvent);
4619
- const result = await invoke$2(method, editor.uid, ...args);
4620
- return result;
4621
- };
4622
-
4623
5024
  const combineResults = results => {
4624
5025
  return results[0] ?? [];
4625
5026
  };
@@ -5081,7 +5482,7 @@ const Script = 2;
5081
5482
  const Unknown$1 = 0;
5082
5483
 
5083
5484
  const create$1 = () => {
5084
- const uid = create$4();
5485
+ const uid = create$5();
5085
5486
  const widget = {
5086
5487
  id: Find,
5087
5488
  oldState: {
@@ -6110,187 +6511,65 @@ const selectPreviousOccurrence = editor => {
6110
6511
 
6111
6512
  // @ts-ignore
6112
6513
 
6113
- // @ts-ignore
6114
- const getSelectUpChanges = (lines, selections) => {
6115
- const newSelections = new Uint32Array(selections.length);
6116
- for (let i = 0; i < selections.length; i += 4) {
6117
- const [selectionStartRow, selectionStartColumn, selectionEndRow, selectionEndColumn] = getSelectionPairs(selections, i);
6118
- newSelections[i] = Math.max(selectionStartRow - 1, 0);
6119
- newSelections[i + 1] = selectionStartColumn;
6120
- newSelections[i + 2] = selectionEndRow;
6121
- newSelections[i + 3] = selectionEndColumn;
6122
- }
6123
- return newSelections;
6124
- };
6125
-
6126
- // @ts-ignore
6127
- const selectUp = editor => {
6128
- const {
6129
- lines,
6130
- selections
6131
- } = editor;
6132
- const newSelections = getSelectUpChanges(lines, selections);
6133
- return scheduleSelections(editor, newSelections);
6134
- };
6135
-
6136
- // @ts-ignore
6137
- const selectWordLeft = editor => {
6138
- return editorSelectHorizontalLeft(editor, wordLeft);
6139
- };
6140
-
6141
- // @ts-ignore
6142
- const selectWordRight = editor => {
6143
- return editorSelectHorizontalRight(editor, wordRight);
6144
- };
6145
-
6146
- // import * as ExtensionHostSelection from '../ExtensionHost/ExtensionHostSelection.ts'
6147
-
6148
- const getNewSelections = async (editor, selections) => {
6149
- const newSelections = await invoke$3('ExtensionHostSelection.executeGrowSelection', editor, selections);
6150
- if (newSelections.length === 0) {
6151
- return selections;
6152
- }
6153
- return new Uint32Array(newSelections);
6154
- };
6155
- const selectionGrow = async editor => {
6156
- const {
6157
- selections
6158
- } = editor;
6159
- const newSelections = await getNewSelections(editor, selections);
6160
- return scheduleSelections(editor, newSelections);
6161
- };
6162
-
6163
- const setDecorations = (editor, decorations, diagnostics) => {
6164
- if (editor.decorations.length === 0 && decorations.length === 0) {
6165
- return editor;
6166
- }
6167
- return {
6168
- ...editor,
6169
- decorations,
6170
- diagnostics
6171
- };
6172
- };
6173
-
6174
- /**
6175
- * @enum number
6176
- */
6177
- const State = {
6178
- TopLevelContent: 1
6179
- };
6180
-
6181
- /**
6182
- * @enum number
6183
- */
6184
- const TokenType = {
6185
- Text: 1
6186
- };
6187
- const TokenMap = {
6188
- [TokenType.Text]: 'Text'
6189
- };
6190
- const initialLineState = {
6191
- state: State.TopLevelContent
6192
- };
6193
- const hasArrayReturn = true;
6194
- const tokenizeLine = (line, lineState) => {
6195
- return {
6196
- tokens: [TokenType.Text, line.length],
6197
- state: lineState.state
6198
- };
6199
- };
6200
-
6201
- const TokenizePlainText = {
6202
- __proto__: null,
6203
- State,
6204
- TokenMap,
6205
- TokenType,
6206
- hasArrayReturn,
6207
- initialLineState,
6208
- tokenizeLine
6209
- };
6210
-
6211
- const state$1 = {
6212
- tokenizers: Object.create(null),
6213
- tokenizePaths: Object.create(null),
6214
- listeners: [],
6215
- pending: Object.create(null),
6216
- /**
6217
- * @type {number[]}
6218
- */
6219
- connectedEditors: []
6220
- };
6221
- const has = languageId => {
6222
- return languageId in state$1.tokenizers;
6223
- };
6224
- const set$3 = (languageId, tokenizer) => {
6225
- state$1.tokenizers[languageId] = tokenizer;
6226
- };
6227
- const get$3 = languageId => {
6228
- return state$1.tokenizers[languageId];
6514
+ // @ts-ignore
6515
+ const getSelectUpChanges = (lines, selections) => {
6516
+ const newSelections = new Uint32Array(selections.length);
6517
+ for (let i = 0; i < selections.length; i += 4) {
6518
+ const [selectionStartRow, selectionStartColumn, selectionEndRow, selectionEndColumn] = getSelectionPairs(selections, i);
6519
+ newSelections[i] = Math.max(selectionStartRow - 1, 0);
6520
+ newSelections[i + 1] = selectionStartColumn;
6521
+ newSelections[i + 2] = selectionEndRow;
6522
+ newSelections[i + 3] = selectionEndColumn;
6523
+ }
6524
+ return newSelections;
6229
6525
  };
6230
- const isPending = languageId => {
6231
- return languageId in state$1.pending;
6526
+
6527
+ // @ts-ignore
6528
+ const selectUp = editor => {
6529
+ const {
6530
+ lines,
6531
+ selections
6532
+ } = editor;
6533
+ const newSelections = getSelectUpChanges(lines, selections);
6534
+ return scheduleSelections(editor, newSelections);
6232
6535
  };
6233
6536
 
6234
- let enabled$1 = false;
6235
- const setEnabled$1 = value => {
6236
- enabled$1 = value;
6537
+ // @ts-ignore
6538
+ const selectWordLeft = editor => {
6539
+ return editorSelectHorizontalLeft(editor, wordLeft);
6237
6540
  };
6238
- const getEnabled$1 = () => {
6239
- return enabled$1;
6541
+
6542
+ // @ts-ignore
6543
+ const selectWordRight = editor => {
6544
+ return editorSelectHorizontalRight(editor, wordRight);
6240
6545
  };
6241
6546
 
6242
- const {
6243
- listen: listen$6,
6244
- invoke: invoke$1
6245
- } = createRpc(SyntaxHighlightingWorker);
6547
+ // import * as ExtensionHostSelection from '../ExtensionHost/ExtensionHostSelection.ts'
6246
6548
 
6247
- const tokenMaps = Object.create(null);
6248
- const set$2 = (languageId, tokenMap) => {
6249
- tokenMaps[languageId] = tokenMap;
6549
+ const getNewSelections = async (editor, selections) => {
6550
+ const newSelections = await invoke$3('ExtensionHostSelection.executeGrowSelection', editor, selections);
6551
+ if (newSelections.length === 0) {
6552
+ return selections;
6553
+ }
6554
+ return new Uint32Array(newSelections);
6250
6555
  };
6251
- const get$2 = languageId => {
6252
- return tokenMaps[languageId] || {};
6556
+ const selectionGrow = async editor => {
6557
+ const {
6558
+ selections
6559
+ } = editor;
6560
+ const newSelections = await getNewSelections(editor, selections);
6561
+ return scheduleSelections(editor, newSelections);
6253
6562
  };
6254
6563
 
6255
- // TODO loadTokenizer should be invoked from renderer worker
6256
- const loadTokenizer = async (languageId, tokenizePath) => {
6257
- if (!tokenizePath) {
6258
- return;
6259
- }
6260
- if (getEnabled$1()) {
6261
- const tokenMap = await invoke$1('Tokenizer.load', languageId, tokenizePath);
6262
- set$2(languageId, tokenMap);
6263
- return;
6264
- }
6265
- try {
6266
- // TODO check that tokenizer is valid
6267
- // 1. tokenizeLine should be of type function
6268
- // 2. getTokenClass should be of type function
6269
- const tokenizer = await import(tokenizePath);
6270
- if (typeof tokenizer.tokenizeLine !== 'function') {
6271
- console.warn(`tokenizer.tokenizeLine should be a function in "${tokenizePath}"`);
6272
- return;
6273
- }
6274
- if (!tokenizer.TokenMap || typeof tokenizer.TokenMap !== 'object' || Array.isArray(tokenizer.TokenMap)) {
6275
- console.warn(`tokenizer.TokenMap should be an object in "${tokenizePath}"`);
6276
- return;
6277
- }
6278
- set$2(languageId, tokenizer.TokenMap);
6279
- set$3(languageId, tokenizer);
6280
- } catch (error) {
6281
- // TODO better error handling
6282
- console.error(error);
6283
- return;
6284
- }
6285
- };
6286
- const getTokenizer = languageId => {
6287
- if (has(languageId)) {
6288
- return get$3(languageId);
6289
- }
6290
- if (isPending(languageId)) {
6291
- return TokenizePlainText;
6564
+ const setDecorations = (editor, decorations, diagnostics) => {
6565
+ if (editor.decorations.length === 0 && decorations.length === 0) {
6566
+ return editor;
6292
6567
  }
6293
- return TokenizePlainText;
6568
+ return {
6569
+ ...editor,
6570
+ decorations,
6571
+ diagnostics
6572
+ };
6294
6573
  };
6295
6574
 
6296
6575
  const tokenizers = Object.create(null);
@@ -7118,467 +7397,257 @@ const editorUnindent = editor => {
7118
7397
  return;
7119
7398
  }
7120
7399
  // @ts-ignore
7121
- documentEdits.push({
7122
- type: /* singleLineEdit */1,
7123
- rowIndex: editor.cursor.rowIndex,
7124
- inserted: '',
7125
- columnIndex: 2,
7126
- deleted: 2
7127
- });
7128
- // @ts-ignore
7129
- cursorEdits.push({
7130
- rowIndex: editor.cursor.rowIndex,
7131
- columnIndex: editor.cursor.columnIndex - 2
7132
- });
7133
- // @ts-ignore
7134
- undefined(editor, documentEdits, cursorEdits);
7135
- };
7136
- // const editor = {
7137
- // textDocument: {
7138
- // lines: [' line 1'],
7139
- // },
7140
- // cursor: {
7141
- // rowIndex: 0,
7142
- // columnIndex: 8,
7143
- // },
7144
- // selections: [
7145
- // {
7146
- // start: {
7147
- // rowIndex: 0,
7148
- // columnIndex: 0,
7149
- // },
7150
- // end: {
7151
- // rowIndex: 0,
7152
- // columnIndex: 8,
7153
- // },
7154
- // },
7155
- // ],
7156
- // tokenizer: TokenizePlainText,
7157
- // }
7158
- // editorUnindent(editor)
7159
-
7160
- // editor.lines //?
7161
-
7162
- const isCompletionDetailWidget = widget => {
7163
- return widget.id === CompletionDetail$1;
7164
- };
7165
- const closeDetails = editor => {
7166
- const {
7167
- widgets
7168
- } = editor;
7169
- const index = widgets.findIndex(isCompletionDetailWidget);
7170
- if (index === -1) {
7171
- return editor;
7172
- }
7173
- const newWidgets = [...widgets.slice(0, index), ...widgets.slice(index + 1)];
7174
- return {
7175
- ...editor,
7176
- widgets: newWidgets
7177
- };
7178
- };
7179
-
7180
- const getCompletionState = editor => {
7181
- return getWidgetState(editor, Completion);
7182
- };
7183
-
7184
- const isCompletion$1 = widget => {
7185
- return widget.id === Completion;
7186
- };
7187
- const focusIndex = (editor, index) => {
7188
- const child = getCompletionState(editor);
7189
- if (index === -1) {
7190
- return editor;
7191
- }
7192
- const childIndex = editor.widgets.findIndex(isCompletion$1);
7193
- // TODO scroll up/down if necessary
7194
- const childWidget = editor.widgets[childIndex];
7195
- const newWidget = {
7196
- ...childWidget,
7197
- newState: {
7198
- ...child,
7199
- focusedIndex: index,
7200
- focused: true
7201
- }
7202
- };
7203
- const newWidgets = [...editor.widgets.slice(0, childIndex), newWidget, ...editor.widgets.slice(childIndex + 1)];
7204
- return {
7205
- ...editor,
7206
- widgets: newWidgets
7207
- };
7208
- };
7209
-
7210
- const focusFirst = editor => {
7211
- const firstIndex = 0;
7212
- return focusIndex(editor, firstIndex);
7213
- };
7214
-
7215
- const focusNext = editor => {
7216
- const child = getCompletionState(editor);
7217
- if (!child) {
7218
- return editor;
7219
- }
7220
- const nextIndex = child.focusedIndex + 1;
7221
- return focusIndex(editor, nextIndex);
7222
- };
7223
-
7224
- const focusPrevious = editor => {
7225
- const child = getCompletionState(editor);
7226
- if (!child) {
7227
- return editor;
7228
- }
7229
- const previousIndex = child.focusedIndex - 1;
7230
- return focusIndex(editor, previousIndex);
7231
- };
7232
-
7233
- const create = () => {
7234
- const completionUid = create$4();
7235
- const completionWidget = {
7236
- id: CompletionDetail$1,
7237
- oldState: {
7238
- content: '',
7239
- uid: completionUid,
7240
- x: 0,
7241
- y: 0,
7242
- width: 0,
7243
- height: 0
7244
- },
7245
- newState: {
7246
- content: '',
7247
- uid: completionUid,
7248
- x: 0,
7249
- y: 0,
7250
- width: 0,
7251
- height: 0
7252
- }
7253
- };
7254
- return completionWidget;
7255
- };
7256
-
7257
- const getCompletionDetailBounds = (completionBounds, borderSize) => {
7258
- return {
7259
- x: completionBounds.x + completionBounds.width - borderSize,
7260
- y: completionBounds.y,
7261
- width: 100,
7262
- height: 100
7263
- };
7264
- };
7265
-
7266
- const openDetails = editor => {
7267
- const child = getCompletionState(editor);
7268
- if (!child) {
7269
- return editor;
7270
- }
7271
- // TODO avoid closure
7272
- const newStateGenerator = state => {
7273
- const borderSize = 1;
7274
- const newestState = {
7275
- ...state,
7276
- content: 'abc',
7277
- ...getCompletionDetailBounds(child, borderSize)
7278
- };
7279
- return newestState;
7280
- };
7281
- return addWidgetToEditor(CompletionDetail$1, CompletionDetail, editor, create, newStateGenerator);
7282
- };
7283
-
7284
- const getEdits = async (editor, completionItem) => {
7285
- const child = getCompletionState(editor);
7400
+ documentEdits.push({
7401
+ type: /* singleLineEdit */1,
7402
+ rowIndex: editor.cursor.rowIndex,
7403
+ inserted: '',
7404
+ columnIndex: 2,
7405
+ deleted: 2
7406
+ });
7286
7407
  // @ts-ignore
7287
- const {
7288
- leadingWord,
7289
- uid
7290
- } = child;
7291
- const word = completionItem.label;
7292
- const resolvedItem = await resolveCompletion(editor, word, completionItem);
7293
- const inserted = resolvedItem ? resolvedItem.snippet : word;
7294
- // TODO type and dispose commands should be sent to renderer process at the same time
7295
- const {
7296
- selections
7297
- } = editor;
7298
- const [startRowIndex, startColumnIndex] = selections;
7299
- const leadingWordLength = leadingWord.length;
7300
- const replaceRange$1 = new Uint32Array([startRowIndex, startColumnIndex - leadingWordLength, startRowIndex, startColumnIndex]);
7301
- const changes = replaceRange(editor, replaceRange$1, [inserted], '');
7302
- return changes;
7408
+ cursorEdits.push({
7409
+ rowIndex: editor.cursor.rowIndex,
7410
+ columnIndex: editor.cursor.columnIndex - 2
7411
+ });
7412
+ // @ts-ignore
7413
+ undefined(editor, documentEdits, cursorEdits);
7303
7414
  };
7304
- const isCompletion = widget => {
7305
- return widget.id === Completion;
7415
+ // const editor = {
7416
+ // textDocument: {
7417
+ // lines: [' line 1'],
7418
+ // },
7419
+ // cursor: {
7420
+ // rowIndex: 0,
7421
+ // columnIndex: 8,
7422
+ // },
7423
+ // selections: [
7424
+ // {
7425
+ // start: {
7426
+ // rowIndex: 0,
7427
+ // columnIndex: 0,
7428
+ // },
7429
+ // end: {
7430
+ // rowIndex: 0,
7431
+ // columnIndex: 8,
7432
+ // },
7433
+ // },
7434
+ // ],
7435
+ // tokenizer: TokenizePlainText,
7436
+ // }
7437
+ // editorUnindent(editor)
7438
+
7439
+ // editor.lines //?
7440
+
7441
+ const isCompletionDetailWidget = widget => {
7442
+ return widget.id === CompletionDetail$1;
7306
7443
  };
7307
- const select = async (editor, completionItem) => {
7308
- const changes = await getEdits(editor, completionItem);
7309
- const index = editor.widgets.indexOf
7310
- // ViewletModuleId.EditorCompletion
7311
- ();
7312
- if (index !== -1) {
7313
- editor.widgets.splice(index, 1);
7314
- editor.completionState = None$1;
7315
- editor.completionUid = 0;
7316
- }
7317
- // TODO dispose completion widget
7318
- // TODO apply edit in editor worker instead of asking renderer worker
7319
- // await RendererWorker.invoke('Viewlet.dispose', state.uid)
7444
+ const closeDetails = editor => {
7320
7445
  const {
7321
7446
  widgets
7322
7447
  } = editor;
7323
- const completionWidgetIndex = editor.widgets.findIndex(isCompletion);
7324
- const newWidgets = [...widgets.slice(0, completionWidgetIndex), ...widgets.slice(completionWidgetIndex + 1)];
7325
- const intermediateEditor = await applyEdit(editor, changes);
7448
+ const index = widgets.findIndex(isCompletionDetailWidget);
7449
+ if (index === -1) {
7450
+ return editor;
7451
+ }
7452
+ const newWidgets = [...widgets.slice(0, index), ...widgets.slice(index + 1)];
7326
7453
  return {
7327
- ...intermediateEditor,
7454
+ ...editor,
7328
7455
  widgets: newWidgets
7329
7456
  };
7330
7457
  };
7331
- const selectIndex = (editor, index) => {
7332
- const child = getCompletionState(editor);
7333
- if (!child) {
7334
- return editor;
7335
- }
7336
- const {
7337
- items
7338
- } = child;
7339
- if (index === -1) {
7340
- return editor;
7341
- }
7342
- if (index > items.length) {
7343
- throw new Error('index too large');
7344
- }
7345
- const actualIndex = index;
7346
- const completionItem = items[actualIndex];
7347
- return select(editor, completionItem);
7458
+
7459
+ const getCompletionState = editor => {
7460
+ return getWidgetState(editor, Completion);
7348
7461
  };
7349
7462
 
7350
- const selectCurrent = editor => {
7463
+ const isCompletion$1 = widget => {
7464
+ return widget.id === Completion;
7465
+ };
7466
+ const focusIndex = (editor, index) => {
7351
7467
  const child = getCompletionState(editor);
7352
- if (!child) {
7468
+ if (index === -1) {
7353
7469
  return editor;
7354
7470
  }
7355
- const {
7356
- focusedIndex
7357
- } = child;
7358
- return selectIndex(editor, focusedIndex);
7471
+ const childIndex = editor.widgets.findIndex(isCompletion$1);
7472
+ // TODO scroll up/down if necessary
7473
+ const childWidget = editor.widgets[childIndex];
7474
+ const newWidget = {
7475
+ ...childWidget,
7476
+ newState: {
7477
+ ...child,
7478
+ focusedIndex: index,
7479
+ focused: true
7480
+ }
7481
+ };
7482
+ const newWidgets = [...editor.widgets.slice(0, childIndex), newWidget, ...editor.widgets.slice(childIndex + 1)];
7483
+ return {
7484
+ ...editor,
7485
+ widgets: newWidgets
7486
+ };
7359
7487
  };
7360
7488
 
7361
- const getCompletionDetailState = editor => {
7362
- return getWidgetState(editor, CompletionDetail$1);
7489
+ const focusFirst = editor => {
7490
+ const firstIndex = 0;
7491
+ return focusIndex(editor, firstIndex);
7363
7492
  };
7364
7493
 
7365
- const toggleDetails = editor => {
7366
- const child = getCompletionDetailState(editor);
7494
+ const focusNext = editor => {
7495
+ const child = getCompletionState(editor);
7367
7496
  if (!child) {
7368
- return openDetails(editor);
7369
- }
7370
- return closeDetails(editor);
7371
- };
7372
-
7373
- const executeHoverProvider = (editor, offset) => {
7374
- object(editor);
7375
- number$1(offset);
7376
- return execute({
7377
- event: OnHover,
7378
- editor,
7379
- method: HoverExecute,
7380
- args: [offset],
7381
- noProviderFoundMessage: 'No hover provider found'
7382
- });
7383
- };
7384
-
7385
- const getHover = async (editor, offset) => {
7386
- object(editor);
7387
- number$1(offset);
7388
- // TODO invoke extension host worker directly
7389
- const hover = await executeHoverProvider(editor, offset);
7390
- return hover;
7391
- };
7392
-
7393
- let _ipc;
7394
- const listen$5 = async () => {
7395
- const ipc = await create$6({
7396
- method: RendererProcess
7397
- });
7398
- handleIpc(ipc);
7399
- _ipc = ipc;
7400
- };
7401
- const invoke = async (method, ...args) => {
7402
- return invoke$5(_ipc, method, ...args);
7403
- };
7404
-
7405
- const measureTextBlockHeight = (text, fontFamily, fontSize, lineHeight, width) => {
7406
- return invoke('MeasureTextBlockHeight.measureTextBlockHeight', text, fontSize, fontFamily, lineHeight, width);
7407
- };
7408
-
7409
- const deepCopy = value => {
7410
- return structuredClone(value);
7411
- };
7412
-
7413
- const getInitialLineState = initialLineState => {
7414
- return deepCopy(initialLineState);
7415
- };
7416
-
7417
- const getLineInfo$1 = (line, tokens, TokenMap) => {
7418
- const tokensLength = tokens.length;
7419
- let end = 0;
7420
- let start = 0;
7421
- const lineInfo = [];
7422
- for (let i = 0; i < tokensLength; i += 2) {
7423
- const tokenType = tokens[i];
7424
- const tokenLength = tokens[i + 1];
7425
- end += tokenLength;
7426
- const text = line.slice(start, end);
7427
- const className = `Token ${TokenMap[tokenType] || 'Unknown'}`;
7428
- const normalizedText = text;
7429
- lineInfo.push(normalizedText, className);
7430
- start = end;
7431
- }
7432
- return lineInfo;
7433
- };
7434
-
7435
- const state = {
7436
- warned: []
7437
- };
7438
- const flattenTokensArray = tokens => {
7439
- const flattened = [];
7440
- for (const token of tokens) {
7441
- object(token);
7442
- flattened.push(token.type, token.length);
7443
- }
7444
- return flattened;
7445
- };
7446
- const warnDeprecatedArrayReturn = (languageId, fn) => {
7447
- if (state.warned.includes(fn)) {
7448
- return;
7449
- }
7450
- state.warned.push(fn);
7451
- console.warn(`tokenizers without hasArrayReturn=false are deprecated (language ${languageId})`);
7452
- };
7453
- const safeTokenizeLine = (languageId, tokenizeLine, line, lineStateAtStart, hasArrayReturn) => {
7454
- try {
7455
- const lineState = tokenizeLine(line, lineStateAtStart);
7456
- if (!lineState || !lineState.tokens || !lineState.state) {
7457
- throw new Error('invalid tokenization result');
7458
- }
7459
- if (!hasArrayReturn) {
7460
- warnDeprecatedArrayReturn(languageId, tokenizeLine);
7461
- // workaround for old tokenizers
7462
- lineState.tokens = flattenTokensArray(lineState.tokens);
7463
- }
7464
- return lineState;
7465
- } catch (error) {
7466
- console.error(error);
7467
- return {
7468
- tokens: [/* type */0, /* length */line.length],
7469
- lineState: lineStateAtStart
7470
- };
7497
+ return editor;
7471
7498
  }
7499
+ const nextIndex = child.focusedIndex + 1;
7500
+ return focusIndex(editor, nextIndex);
7472
7501
  };
7473
7502
 
7474
- const getLineInfos = (lines, tokenizer, languageId) => {
7475
- const lineInfos = [];
7476
- const {
7477
- tokenizeLine,
7478
- initialLineState,
7479
- hasArrayReturn,
7480
- TokenMap
7481
- } = tokenizer;
7482
- let currentLineState = getInitialLineState(initialLineState);
7483
- for (const line of lines) {
7484
- const result = safeTokenizeLine(languageId, tokenizeLine, line, currentLineState, hasArrayReturn);
7485
- const {
7486
- tokens
7487
- } = result;
7488
- const lineInfo = getLineInfo$1(line, tokens, TokenMap);
7489
- lineInfos.push(lineInfo);
7490
- currentLineState = result;
7503
+ const focusPrevious = editor => {
7504
+ const child = getCompletionState(editor);
7505
+ if (!child) {
7506
+ return editor;
7491
7507
  }
7492
- return lineInfos;
7508
+ const previousIndex = child.focusedIndex - 1;
7509
+ return focusIndex(editor, previousIndex);
7493
7510
  };
7494
7511
 
7495
- const tokenizeCodeBlock = async (codeBlock, languageId, tokenizerPath) => {
7496
- await loadTokenizer(languageId, tokenizerPath);
7497
- const tokenizer = getTokenizer(languageId);
7498
- const lines = splitLines$2(codeBlock);
7499
- const lineInfos = getLineInfos(lines, tokenizer, languageId);
7500
- return lineInfos;
7512
+ const create = () => {
7513
+ const completionUid = create$5();
7514
+ const completionWidget = {
7515
+ id: CompletionDetail$1,
7516
+ oldState: {
7517
+ content: '',
7518
+ uid: completionUid,
7519
+ x: 0,
7520
+ y: 0,
7521
+ width: 0,
7522
+ height: 0
7523
+ },
7524
+ newState: {
7525
+ content: '',
7526
+ uid: completionUid,
7527
+ x: 0,
7528
+ y: 0,
7529
+ width: 0,
7530
+ height: 0
7531
+ }
7532
+ };
7533
+ return completionWidget;
7501
7534
  };
7502
7535
 
7503
- const getHoverPosition = (position, selections) => {
7504
- if (position) {
7505
- return position;
7506
- }
7507
- const rowIndex = selections[0];
7508
- const columnIndex = selections[1];
7536
+ const getCompletionDetailBounds = (completionBounds, borderSize) => {
7509
7537
  return {
7510
- rowIndex,
7511
- columnIndex
7538
+ x: completionBounds.x + completionBounds.width - borderSize,
7539
+ y: completionBounds.y,
7540
+ width: 100,
7541
+ height: 100
7512
7542
  };
7513
7543
  };
7514
- const getMatchingDiagnostics = (diagnostics, rowIndex, columnIndex) => {
7515
- const matching = [];
7516
- for (const diagnostic of diagnostics) {
7517
- if (diagnostic.rowIndex === rowIndex) {
7518
- matching.push(diagnostic);
7519
- }
7520
- }
7521
- return matching;
7522
- };
7523
- const fallbackDisplayStringLanguageId = 'typescript'; // TODO remove this
7524
7544
 
7525
- const hoverDocumentationFontSize = 15;
7526
- const hoverDocumentationFontFamily = 'Fira Code';
7527
- const hoverDocumentationLineHeight = '1.33333';
7528
- const hoverBorderLeft = 1;
7529
- const hoverBorderRight = 1;
7530
- const hoverPaddingLeft = 8;
7531
- const hoverPaddingRight = 8;
7532
- const hovverFullWidth = 400;
7533
- const hoverDocumentationWidth = hovverFullWidth - hoverPaddingLeft - hoverPaddingRight - hoverBorderLeft - hoverBorderRight;
7534
- const getHoverPositionXy = (editor, rowIndex, wordStart, documentationHeight) => {
7535
- const x$1 = x(editor, rowIndex, wordStart);
7536
- const y$1 = editor.height - y(editor, rowIndex) + editor.y + 40;
7537
- return {
7538
- x: x$1,
7539
- y: y$1
7545
+ const openDetails = editor => {
7546
+ const child = getCompletionState(editor);
7547
+ if (!child) {
7548
+ return editor;
7549
+ }
7550
+ // TODO avoid closure
7551
+ const newStateGenerator = state => {
7552
+ const borderSize = 1;
7553
+ const newestState = {
7554
+ ...state,
7555
+ content: 'abc',
7556
+ ...getCompletionDetailBounds(child, borderSize)
7557
+ };
7558
+ return newestState;
7540
7559
  };
7560
+ return addWidgetToEditor(CompletionDetail$1, CompletionDetail, editor, create, newStateGenerator);
7541
7561
  };
7542
- const getEditorHoverInfo = async (editorUid, position) => {
7543
- number$1(editorUid);
7544
- const instance = get$7(editorUid);
7545
- const editor = instance.newState;
7562
+
7563
+ const getEdits = async (editor, completionItem) => {
7564
+ const child = getCompletionState(editor);
7565
+ // @ts-ignore
7566
+ const {
7567
+ leadingWord,
7568
+ uid
7569
+ } = child;
7570
+ const word = completionItem.label;
7571
+ const resolvedItem = await resolveCompletion(editor, word, completionItem);
7572
+ const inserted = resolvedItem ? resolvedItem.snippet : word;
7573
+ // TODO type and dispose commands should be sent to renderer process at the same time
7546
7574
  const {
7547
7575
  selections
7548
7576
  } = editor;
7549
- const {
7550
- rowIndex,
7551
- columnIndex
7552
- } = getHoverPosition(position, selections);
7553
- const offset = offsetAt(editor, rowIndex, columnIndex);
7554
- const hover = await getHover(editor, offset);
7555
- if (!hover) {
7556
- return undefined;
7577
+ const [startRowIndex, startColumnIndex] = selections;
7578
+ const leadingWordLength = leadingWord.length;
7579
+ const replaceRange$1 = new Uint32Array([startRowIndex, startColumnIndex - leadingWordLength, startRowIndex, startColumnIndex]);
7580
+ const changes = replaceRange(editor, replaceRange$1, [inserted], '');
7581
+ return changes;
7582
+ };
7583
+ const isCompletion = widget => {
7584
+ return widget.id === Completion;
7585
+ };
7586
+ const select = async (editor, completionItem) => {
7587
+ const changes = await getEdits(editor, completionItem);
7588
+ const index = editor.widgets.indexOf
7589
+ // ViewletModuleId.EditorCompletion
7590
+ ();
7591
+ if (index !== -1) {
7592
+ editor.widgets.splice(index, 1);
7593
+ editor.completionState = None$1;
7594
+ editor.completionUid = 0;
7557
7595
  }
7596
+ // TODO dispose completion widget
7597
+ // TODO apply edit in editor worker instead of asking renderer worker
7598
+ // await RendererWorker.invoke('Viewlet.dispose', state.uid)
7558
7599
  const {
7559
- displayString,
7560
- documentation,
7561
- displayStringLanguageId
7562
- } = hover;
7563
- const tokenizerPath = '';
7564
- const lineInfos = await tokenizeCodeBlock(displayString, displayStringLanguageId || fallbackDisplayStringLanguageId, tokenizerPath);
7565
- const wordPart = await getWordBefore(editor, rowIndex, columnIndex);
7566
- const wordStart = columnIndex - wordPart.length;
7567
- await measureTextBlockHeight(documentation, hoverDocumentationFontFamily, hoverDocumentationFontSize, hoverDocumentationLineHeight, hoverDocumentationWidth);
7568
- const {
7569
- x,
7570
- y
7571
- } = getHoverPositionXy(editor, rowIndex, wordStart);
7572
- const diagnostics = editor.diagnostics || [];
7573
- const matchingDiagnostics = getMatchingDiagnostics(diagnostics, rowIndex);
7600
+ widgets
7601
+ } = editor;
7602
+ const completionWidgetIndex = editor.widgets.findIndex(isCompletion);
7603
+ const newWidgets = [...widgets.slice(0, completionWidgetIndex), ...widgets.slice(completionWidgetIndex + 1)];
7604
+ const intermediateEditor = await applyEdit(editor, changes);
7574
7605
  return {
7575
- lineInfos,
7576
- documentation,
7577
- x,
7578
- y,
7579
- matchingDiagnostics
7606
+ ...intermediateEditor,
7607
+ widgets: newWidgets
7580
7608
  };
7581
7609
  };
7610
+ const selectIndex = (editor, index) => {
7611
+ const child = getCompletionState(editor);
7612
+ if (!child) {
7613
+ return editor;
7614
+ }
7615
+ const {
7616
+ items
7617
+ } = child;
7618
+ if (index === -1) {
7619
+ return editor;
7620
+ }
7621
+ if (index > items.length) {
7622
+ throw new Error('index too large');
7623
+ }
7624
+ const actualIndex = index;
7625
+ const completionItem = items[actualIndex];
7626
+ return select(editor, completionItem);
7627
+ };
7628
+
7629
+ const selectCurrent = editor => {
7630
+ const child = getCompletionState(editor);
7631
+ if (!child) {
7632
+ return editor;
7633
+ }
7634
+ const {
7635
+ focusedIndex
7636
+ } = child;
7637
+ return selectIndex(editor, focusedIndex);
7638
+ };
7639
+
7640
+ const getCompletionDetailState = editor => {
7641
+ return getWidgetState(editor, CompletionDetail$1);
7642
+ };
7643
+
7644
+ const toggleDetails = editor => {
7645
+ const child = getCompletionDetailState(editor);
7646
+ if (!child) {
7647
+ return openDetails(editor);
7648
+ }
7649
+ return closeDetails(editor);
7650
+ };
7582
7651
 
7583
7652
  const loadContent = async (editorUid, state, position) => {
7584
7653
  const hoverInfo = await getEditorHoverInfo(editorUid, position);
@@ -7709,7 +7778,7 @@ const getHoverVirtualDom = (lineInfos, documentation, diagnostics) => {
7709
7778
 
7710
7779
  const renderHoverDom = {
7711
7780
  isEqual(oldState, newState) {
7712
- return oldState.lineInfos === newState.lineInfos && oldState.documentation === newState.documentation && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.diagnostics === newState.diagnostics;
7781
+ return oldState.lineInfos === newState.lineInfos && oldState.documentation === newState.documentation && oldState.diagnostics === newState.diagnostics;
7713
7782
  },
7714
7783
  apply(oldState, newState) {
7715
7784
  const dom = getHoverVirtualDom(newState.lineInfos, newState.documentation, newState.diagnostics);
@@ -7718,26 +7787,22 @@ const renderHoverDom = {
7718
7787
  };
7719
7788
  const renderBounds$4 = {
7720
7789
  isEqual(oldState, newState) {
7721
- return oldState.x === newState.x && oldState.y === newState.y && oldState.resizedWidth === newState.resizedWidth;
7790
+ return oldState.x === newState.x && oldState.y === newState.y;
7722
7791
  },
7723
7792
  apply(oldState, newState) {
7724
- // @ts-ignore
7725
7793
  const {
7726
7794
  x,
7727
7795
  y,
7728
- width,
7729
- height,
7730
- resizedWidth,
7731
- uid
7796
+ height
7732
7797
  } = newState;
7733
- console.log('apply');
7734
- return [SetBounds, x, y, resizedWidth, height];
7798
+ const renderWidth = 200;
7799
+ return [SetBounds, x, y, renderWidth, height];
7735
7800
  }
7736
7801
  };
7737
- const render$9 = [renderHoverDom, renderBounds$4];
7738
- const renderHover = async (oldState, newState) => {
7802
+ const render$a = [renderHoverDom, renderBounds$4];
7803
+ const renderHover = (oldState, newState) => {
7739
7804
  const commands = [];
7740
- for (const item of render$9) {
7805
+ for (const item of render$a) {
7741
7806
  if (!item.isEqual(oldState, newState)) {
7742
7807
  commands.push(item.apply(oldState, newState));
7743
7808
  }
@@ -7841,10 +7906,10 @@ const getEnabled = () => {
7841
7906
  };
7842
7907
 
7843
7908
  const intialize = async (syntaxHighlightingEnabled, syncIncremental) => {
7844
- await listen$5();
7909
+ await listen$6();
7845
7910
  if (syntaxHighlightingEnabled) {
7846
7911
  setEnabled$1(true);
7847
- await listen$6();
7912
+ await listen$5();
7848
7913
  }
7849
7914
  if (syncIncremental) {
7850
7915
  setEnabled(true);
@@ -8132,10 +8197,10 @@ const getTokensViewport2 = (editor, startLineIndex, endLineIndex, syncIncrementa
8132
8197
  languageId,
8133
8198
  invalidStartIndex
8134
8199
  };
8135
- return invoke$1('GetTokensViewport.getTokensViewport', slimEditor, startLineIndex, endLineIndex, hasLinesToSend, id, linesToSend);
8200
+ return invoke('GetTokensViewport.getTokensViewport', slimEditor, startLineIndex, endLineIndex, hasLinesToSend, id, linesToSend);
8136
8201
  }
8137
8202
  // TODO only send needed lines of text
8138
- return invoke$1('GetTokensViewport.getTokensViewport', editor, startLineIndex, endLineIndex, true, editor.id, editor.lines);
8203
+ return invoke('GetTokensViewport.getTokensViewport', editor, startLineIndex, endLineIndex, true, editor.id, editor.lines);
8139
8204
  }
8140
8205
  return getTokensViewport(editor, startLineIndex, endLineIndex);
8141
8206
  };
@@ -8328,7 +8393,7 @@ const getLineInfosViewport = (editor, tokens, embeddedResults, minLineY, maxLine
8328
8393
  decorations,
8329
8394
  languageId
8330
8395
  } = editor;
8331
- const tokenMap = get$2(languageId);
8396
+ const tokenMap = get$3(languageId);
8332
8397
  let offset = minLineOffset;
8333
8398
  const tabSize = 2;
8334
8399
  for (let i = minLineY; i < maxLineY; i++) {
@@ -8485,7 +8550,7 @@ const getIncrementalEdits = async (oldState, newState) => {
8485
8550
  const lines = newState.lines;
8486
8551
  const oldLine = oldState.lines[rowIndex];
8487
8552
  const newLine = lines[rowIndex];
8488
- const incrementalEdits = await invoke$1('TokenizeIncremental.tokenizeIncremental', newState.uid, newState.languageId, oldLine, newLine, rowIndex, newState.minLineY);
8553
+ const incrementalEdits = await invoke('TokenizeIncremental.tokenizeIncremental', newState.uid, newState.languageId, oldLine, newLine, rowIndex, newState.minLineY);
8489
8554
  if (incrementalEdits && incrementalEdits.length === 1) {
8490
8555
  return incrementalEdits;
8491
8556
  }
@@ -8695,7 +8760,7 @@ const renderWidgets = {
8695
8760
  },
8696
8761
  multiple: true
8697
8762
  };
8698
- const render$8 = [renderLines, renderSelections, renderScrollBarX, renderScrollBarY, renderFocus$1, renderDecorations, renderGutterInfo, renderWidgets];
8763
+ const render$9 = [renderLines, renderSelections, renderScrollBarX, renderScrollBarY, renderFocus$1, renderDecorations, renderGutterInfo, renderWidgets];
8699
8764
  const renderEditor = async id => {
8700
8765
  const instance = get$7(id);
8701
8766
  if (!instance) {
@@ -8707,7 +8772,7 @@ const renderEditor = async id => {
8707
8772
  } = instance;
8708
8773
  const commands = [];
8709
8774
  set$7(id, newState, newState);
8710
- for (const item of render$8) {
8775
+ for (const item of render$9) {
8711
8776
  if (!item.isEqual(oldState, newState)) {
8712
8777
  const result = await item.apply(oldState, newState);
8713
8778
  // @ts-ignore
@@ -8919,6 +8984,7 @@ const commandMap = {
8919
8984
  'Editor.setLanguageId': setLanguageId,
8920
8985
  'Editor.setSelections': setSelections,
8921
8986
  'Editor.showHover': showHover,
8987
+ 'Editor.showHover2': showHover2,
8922
8988
  'Editor.showSourceActions': showSourceActions,
8923
8989
  'Editor.sortLinesAscending': sortLinesAscending,
8924
8990
  'Editor.tabCompletion': tabCompletion,
@@ -8945,6 +9011,7 @@ const commandMap = {
8945
9011
  'EditorCompletion.selectIndex': selectIndex,
8946
9012
  'EditorCompletion.toggleDetails': toggleDetails,
8947
9013
  'FindWidget.close': close$1,
9014
+ 'FindWidget.focusCloseButton': focusCloseButton,
8948
9015
  'FindWidget.focusFind': focusFind,
8949
9016
  'FindWidget.focusFirst': focusFirst$1,
8950
9017
  'FindWidget.focusIndex': focusIndex$1,
@@ -8966,7 +9033,6 @@ const commandMap = {
8966
9033
  'FindWidget.handleToggleReplaceFocus': handleToggleReplaceFocus,
8967
9034
  'FindWidget.loadContent': loadContent$1,
8968
9035
  'FindWidget.toggleReplace': toggleReplace,
8969
- 'FindWidget.focusCloseButton': focusCloseButton,
8970
9036
  'Font.ensure': ensure,
8971
9037
  'Hover.getHoverInfo': getEditorHoverInfo,
8972
9038
  'Hover.handleSashPointerDown': handleSashPointerDown,
@@ -9226,10 +9292,10 @@ const renderScrollBar = {
9226
9292
  return [/* method */SetScrollBar, /* scrollBarY */scrollBarY, /* scrollBarHeight */scrollBarHeight];
9227
9293
  }
9228
9294
  };
9229
- const render$7 = [renderItems, renderBounds$3, renderHeight, renderNegativeMargin, renderScrollBar];
9295
+ const render$8 = [renderItems, renderBounds$3, renderHeight, renderNegativeMargin, renderScrollBar];
9230
9296
  const renderCompletion = (oldState, newState) => {
9231
9297
  const commands = [];
9232
- for (const item of render$7) {
9298
+ for (const item of render$8) {
9233
9299
  if (!item.isEqual(oldState, newState)) {
9234
9300
  commands.push(item.apply(oldState, newState));
9235
9301
  }
@@ -9242,7 +9308,7 @@ const removeWidget = widget => {
9242
9308
  return [['Viewlet.send', widget.newState.uid, 'dispose']];
9243
9309
  };
9244
9310
 
9245
- const render$6 = widget => {
9311
+ const render$7 = widget => {
9246
9312
  const commands = renderCompletion(widget.oldState, widget.newState);
9247
9313
  const wrappedCommands = [];
9248
9314
  const uid = widget.newState.uid;
@@ -9251,8 +9317,8 @@ const render$6 = widget => {
9251
9317
  }
9252
9318
  return wrappedCommands;
9253
9319
  };
9254
- const add$3 = widget => {
9255
- const commands = render$6(widget);
9320
+ const add$4 = widget => {
9321
+ const commands = render$7(widget);
9256
9322
  const id = 'EditorCompletion';
9257
9323
  // TODO how to generate a unique integer id
9258
9324
  // that doesn't collide with ids created in renderer worker?
@@ -9262,7 +9328,7 @@ const add$3 = widget => {
9262
9328
  allCommands.push(...commands);
9263
9329
  return allCommands;
9264
9330
  };
9265
- const remove$3 = removeWidget;
9331
+ const remove$4 = removeWidget;
9266
9332
  const handleEditorType = (editor, state) => {
9267
9333
  const {
9268
9334
  unfilteredItems,
@@ -9327,11 +9393,11 @@ const handleEditorDeleteLeft = (editor, state) => {
9327
9393
 
9328
9394
  const EditorCompletionWidget = {
9329
9395
  __proto__: null,
9330
- add: add$3,
9396
+ add: add$4,
9331
9397
  handleEditorDeleteLeft,
9332
9398
  handleEditorType,
9333
- remove: remove$3,
9334
- render: render$6
9399
+ remove: remove$4,
9400
+ render: render$7
9335
9401
  };
9336
9402
 
9337
9403
  const MessagePort$1 = 1;
@@ -9882,10 +9948,10 @@ const renderBounds$2 = {
9882
9948
  return [/* method */SetBounds, /* x */x, /* y */y, /* width */width, /* height */height];
9883
9949
  }
9884
9950
  };
9885
- const render$5 = [renderContent$1, renderBounds$2, renderColor, renderOffsetX];
9951
+ const render$6 = [renderContent$1, renderBounds$2, renderColor, renderOffsetX];
9886
9952
  const renderFull$1 = (oldState, newState) => {
9887
9953
  const commands = [];
9888
- for (const item of render$5) {
9954
+ for (const item of render$6) {
9889
9955
  if (!item.isEqual(oldState, newState)) {
9890
9956
  commands.push(item.apply(oldState, newState));
9891
9957
  }
@@ -9893,7 +9959,7 @@ const renderFull$1 = (oldState, newState) => {
9893
9959
  return commands;
9894
9960
  };
9895
9961
 
9896
- const render$4 = widget => {
9962
+ const render$5 = widget => {
9897
9963
  const commands = renderFull$1(widget.oldState, widget.newState);
9898
9964
  const wrappedCommands = [];
9899
9965
  const uid = widget.newState.uid;
@@ -9906,10 +9972,10 @@ const render$4 = widget => {
9906
9972
  }
9907
9973
  return wrappedCommands;
9908
9974
  };
9909
- const add$2 = widget => {
9910
- return addWidget(widget, 'ColorPicker', render$4);
9975
+ const add$3 = widget => {
9976
+ return addWidget(widget, 'ColorPicker', render$5);
9911
9977
  };
9912
- const remove$2 = removeWidget;
9978
+ const remove$3 = removeWidget;
9913
9979
  const Commands$1 = {
9914
9980
  'ColorPicker.handleSliderPointerDown': handleSliderPointerDown,
9915
9981
  'ColorPicker.handleSliderPointerMove': handleSliderPointerMove
@@ -9918,9 +9984,9 @@ const Commands$1 = {
9918
9984
  const EditorColorPickerWidget = {
9919
9985
  __proto__: null,
9920
9986
  Commands: Commands$1,
9921
- add: add$2,
9922
- remove: remove$2,
9923
- render: render$4
9987
+ add: add$3,
9988
+ remove: remove$3,
9989
+ render: render$5
9924
9990
  };
9925
9991
 
9926
9992
  const getCompletionDetailVirtualDom = content => {
@@ -9968,12 +10034,12 @@ const renderBounds$1 = {
9968
10034
  return [/* method */SetBounds, /* x */x, /* y */y, /* width */width, /* height */height];
9969
10035
  }
9970
10036
  };
9971
- const render$3 = [renderContent, renderBounds$1];
10037
+ const render$4 = [renderContent, renderBounds$1];
9972
10038
  const renderFull = (oldState, newState) => {
9973
- return renderParts(render$3, oldState, newState);
10039
+ return renderParts(render$4, oldState, newState);
9974
10040
  };
9975
10041
 
9976
- const render$2 = widget => {
10042
+ const render$3 = widget => {
9977
10043
  const commands = renderFull(widget.oldState, widget.newState);
9978
10044
  const wrappedCommands = [];
9979
10045
  const uid = widget.newState.uid;
@@ -9986,16 +10052,16 @@ const render$2 = widget => {
9986
10052
  }
9987
10053
  return wrappedCommands;
9988
10054
  };
9989
- const add$1 = widget => {
9990
- return addWidget(widget, 'EditorCompletionDetails', render$2);
10055
+ const add$2 = widget => {
10056
+ return addWidget(widget, 'EditorCompletionDetails', render$3);
9991
10057
  };
9992
- const remove$1 = removeWidget;
10058
+ const remove$2 = removeWidget;
9993
10059
 
9994
10060
  const EditorCompletionDetailWidget = {
9995
10061
  __proto__: null,
9996
- add: add$1,
9997
- remove: remove$1,
9998
- render: render$2
10062
+ add: add$2,
10063
+ remove: remove$2,
10064
+ render: render$3
9999
10065
  };
10000
10066
 
10001
10067
  /**
@@ -10341,16 +10407,16 @@ const renderFocus = {
10341
10407
  // },
10342
10408
  // }
10343
10409
 
10344
- const render$1 = [renderDetails, renderBounds, renderValue, renderFocus];
10410
+ const render$2 = [renderDetails, renderBounds, renderValue, renderFocus];
10345
10411
  const apply = (oldState, newState) => {
10346
10412
  // TODO avoid side effect
10347
10413
  if (oldState.focus !== newState.focus) {
10348
10414
  setFocus(newState.focus);
10349
10415
  }
10350
- return renderParts(render$1, oldState, newState);
10416
+ return renderParts(render$2, oldState, newState);
10351
10417
  };
10352
10418
 
10353
- const render = widget => {
10419
+ const render$1 = widget => {
10354
10420
  const commands = apply(widget.oldState, widget.newState);
10355
10421
  const wrappedCommands = [];
10356
10422
  const uid = widget.newState.uid;
@@ -10363,10 +10429,10 @@ const render = widget => {
10363
10429
  }
10364
10430
  return wrappedCommands;
10365
10431
  };
10366
- const add = widget => {
10367
- return addWidget(widget, 'FindWidget', render);
10432
+ const add$1 = widget => {
10433
+ return addWidget(widget, 'FindWidget', render$1);
10368
10434
  };
10369
- const remove = removeWidget;
10435
+ const remove$1 = removeWidget;
10370
10436
  const Commands = {
10371
10437
  'FindWidget.close': close$1,
10372
10438
  'FindWidget.focusNext': focusNext$1,
@@ -10381,6 +10447,31 @@ const Commands = {
10381
10447
  const EditorFindWidget = {
10382
10448
  __proto__: null,
10383
10449
  Commands,
10450
+ add: add$1,
10451
+ remove: remove$1,
10452
+ render: render$1
10453
+ };
10454
+
10455
+ const render = widget => {
10456
+ const commands = renderHover(widget.oldState, widget.newState);
10457
+ const wrappedCommands = [];
10458
+ const uid = widget.newState.uid;
10459
+ for (const command of commands) {
10460
+ if (command[0] === 'Viewlet.setDom2') {
10461
+ wrappedCommands.push([command[0], uid, ...command.slice(1)]);
10462
+ } else {
10463
+ wrappedCommands.push(['Viewlet.send', uid, ...command]);
10464
+ }
10465
+ }
10466
+ return wrappedCommands;
10467
+ };
10468
+ const add = widget => {
10469
+ return addWidget(widget, 'EditorHover', render);
10470
+ };
10471
+ const remove = removeWidget;
10472
+
10473
+ const EditorHoverWidget = {
10474
+ __proto__: null,
10384
10475
  add,
10385
10476
  remove,
10386
10477
  render
@@ -10391,6 +10482,7 @@ const registerWidgets = () => {
10391
10482
  set(Completion, EditorCompletionWidget);
10392
10483
  set(CompletionDetail$1, EditorCompletionDetailWidget);
10393
10484
  set(Find, EditorFindWidget);
10485
+ set(Hover, EditorHoverWidget);
10394
10486
  };
10395
10487
 
10396
10488
  const main = async () => {