@adecore/editor 0.42.0 → 0.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/controller.d.ts +9 -2
- package/dist/controller.js +82 -8
- package/dist/editor.css +13 -0
- package/dist/engine.js +30 -3
- package/dist/fake.d.ts +19 -2
- package/dist/fake.js +65 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/keymap-table.d.ts +20 -1
- package/dist/keymap-table.js +24 -3
- package/dist/keymap.js +14 -0
- package/dist/layout.d.ts +2 -0
- package/dist/layout.js +6 -1
- package/dist/outline.d.ts +1 -0
- package/dist/outline.js +10 -0
- package/dist/paint.js +12 -2
- package/dist/types.d.ts +18 -2
- package/dist/view.d.ts +11 -0
- package/dist/view.js +73 -8
- package/package.json +2 -2
- package/src/controller.ts +110 -9
- package/src/editor.css +13 -0
- package/src/engine.ts +37 -3
- package/src/fake.ts +85 -3
- package/src/index.ts +3 -0
- package/src/keymap-table.ts +44 -4
- package/src/keymap.ts +14 -0
- package/src/layout.ts +9 -1
- package/src/outline.ts +13 -0
- package/src/paint.ts +11 -2
- package/src/types.ts +37 -2
- package/src/view.ts +95 -9
package/dist/controller.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Keymap } from './keymap-table.ts';
|
|
2
|
-
import type { EditorClickHandler, EditorInlayClickHandler, EditorContextMenu, EditorKeyHandler, EditorRunCommand, EditorSelectionRanges, KeyChord } from './types.ts';
|
|
2
|
+
import type { EditorClickHandler, EditorInlayClickHandler, EditorContextMenu, EditorCopy, EditorKeyHandler, EditorPasteOptions, EditorRunCommand, EditorSelectionRanges, KeyChord } from './types.ts';
|
|
3
3
|
import type { EditorView } from './view.ts';
|
|
4
4
|
export interface ControllerOptions {
|
|
5
5
|
keymap?: Keymap;
|
|
@@ -10,12 +10,16 @@ export interface ControllerOptions {
|
|
|
10
10
|
zoom(step: -1 | 0 | 1): void;
|
|
11
11
|
wheelZooms(): boolean;
|
|
12
12
|
}
|
|
13
|
+
export declare function rememberCopy(text: string, wholeLines: boolean): void;
|
|
13
14
|
export declare class InputController {
|
|
14
15
|
private readonly native;
|
|
15
16
|
private readonly pointer;
|
|
16
17
|
private readonly touch;
|
|
17
18
|
private readonly cleanup;
|
|
18
19
|
private readonly keyHandlers;
|
|
20
|
+
private readonly navigateListeners;
|
|
21
|
+
private readonly copyListeners;
|
|
22
|
+
private wordSources;
|
|
19
23
|
private readonly gesture;
|
|
20
24
|
private readonly clickHandlers;
|
|
21
25
|
private readonly inlayHandlers;
|
|
@@ -41,14 +45,17 @@ export declare class InputController {
|
|
|
41
45
|
private applyEdits;
|
|
42
46
|
private replaceSelections;
|
|
43
47
|
private unfoldCarets;
|
|
44
|
-
|
|
48
|
+
pasteText(text: string, options?: EditorPasteOptions): boolean;
|
|
49
|
+
onCopy(listener: (copy: EditorCopy) => void): () => void;
|
|
45
50
|
private commandOptions;
|
|
51
|
+
setWordSources(source: (() => readonly string[]) | null): void;
|
|
46
52
|
private viewCommand;
|
|
47
53
|
private wheel;
|
|
48
54
|
command(name: EditorRunCommand): boolean;
|
|
49
55
|
setSelectionRanges(provider: EditorSelectionRanges | null): void;
|
|
50
56
|
private expandThrough;
|
|
51
57
|
private modelCommand;
|
|
58
|
+
onNavigate(listener: (from: number) => void): () => void;
|
|
52
59
|
private typeText;
|
|
53
60
|
private movePages;
|
|
54
61
|
private toggleColumnMode;
|
package/dist/controller.js
CHANGED
|
@@ -16,9 +16,12 @@ const MODIFYING = new Set([
|
|
|
16
16
|
'deleteLine',
|
|
17
17
|
'moveLineUp',
|
|
18
18
|
'moveLineDown',
|
|
19
|
+
'moveStatementUp',
|
|
20
|
+
'moveStatementDown',
|
|
19
21
|
'toggleLineComment',
|
|
20
22
|
'toggleBlockComment',
|
|
21
23
|
'startNewLine',
|
|
24
|
+
'completeCurrentStatement',
|
|
22
25
|
'startNewLineBefore',
|
|
23
26
|
'splitLine',
|
|
24
27
|
'joinLines',
|
|
@@ -34,8 +37,11 @@ const MODIFYING = new Set([
|
|
|
34
37
|
'reverseLines',
|
|
35
38
|
'uniqueLines',
|
|
36
39
|
'convertIndentsToSpaces',
|
|
37
|
-
'convertIndentsToTabs'
|
|
40
|
+
'convertIndentsToTabs',
|
|
41
|
+
'hippieCompletion',
|
|
42
|
+
'hippieBackwardCompletion'
|
|
38
43
|
]);
|
|
44
|
+
const CODE_BLOCK_COMMANDS = new Set(['codeBlockStart', 'codeBlockEnd', 'codeBlockStartWithSelection', 'codeBlockEndWithSelection']);
|
|
39
45
|
const VIEW_COMMANDS = new Set([
|
|
40
46
|
'collapseRegion',
|
|
41
47
|
'expandRegion',
|
|
@@ -54,11 +60,23 @@ const VIEW_COMMANDS = new Set([
|
|
|
54
60
|
'toggleColumnMode',
|
|
55
61
|
'increaseFontSize',
|
|
56
62
|
'decreaseFontSize',
|
|
57
|
-
'resetFontSize'
|
|
63
|
+
'resetFontSize',
|
|
64
|
+
'methodUp',
|
|
65
|
+
'methodDown',
|
|
66
|
+
'nextChange',
|
|
67
|
+
'previousChange',
|
|
68
|
+
'pasteAsPlainText'
|
|
58
69
|
]);
|
|
59
70
|
const ZOOM_STEPS = { increaseFontSize: 1, decreaseFontSize: -1, resetFontSize: 0 };
|
|
60
71
|
/* The clipboard text of the last copy or cut of a bare caret, which pastes back as whole lines. Shared, since it can be pasted in another editor. */
|
|
61
72
|
let lineClip = null;
|
|
73
|
+
/*
|
|
74
|
+
* Makes `text` the copy that pastes back as whole lines (or not), for a paste from a history that kept what the
|
|
75
|
+
* copy was. The clipboard itself is the caller's.
|
|
76
|
+
*/
|
|
77
|
+
export function rememberCopy(text, wholeLines) {
|
|
78
|
+
lineClip = wholeLines ? text : null;
|
|
79
|
+
}
|
|
62
80
|
function selectionSignature(selections) {
|
|
63
81
|
return selections.map((selection) => `${selection.anchor}:${selection.head}`).join(',');
|
|
64
82
|
}
|
|
@@ -76,6 +94,9 @@ export class InputController {
|
|
|
76
94
|
touch;
|
|
77
95
|
cleanup = [];
|
|
78
96
|
keyHandlers = new Set();
|
|
97
|
+
navigateListeners = new Set();
|
|
98
|
+
copyListeners = new Set();
|
|
99
|
+
wordSources = null;
|
|
79
100
|
gesture;
|
|
80
101
|
clickHandlers = new Set();
|
|
81
102
|
inlayHandlers = new Set();
|
|
@@ -186,7 +207,7 @@ export class InputController {
|
|
|
186
207
|
});
|
|
187
208
|
this.listen(input, 'paste', (event) => {
|
|
188
209
|
event.preventDefault();
|
|
189
|
-
this.
|
|
210
|
+
this.pasteText(event.clipboardData?.getData('text/plain') ?? '');
|
|
190
211
|
});
|
|
191
212
|
this.listen(input, 'copy', (event) => this.copy(event, false));
|
|
192
213
|
this.listen(input, 'cut', (event) => this.copy(event, true));
|
|
@@ -245,6 +266,8 @@ export class InputController {
|
|
|
245
266
|
}
|
|
246
267
|
this.cleanup.length = 0;
|
|
247
268
|
this.keyHandlers.clear();
|
|
269
|
+
this.navigateListeners.clear();
|
|
270
|
+
this.copyListeners.clear();
|
|
248
271
|
}
|
|
249
272
|
blockedByReadOnly() {
|
|
250
273
|
return this.view.blockedByReadOnly();
|
|
@@ -278,15 +301,25 @@ export class InputController {
|
|
|
278
301
|
this.view.ensureVisible(selection.head);
|
|
279
302
|
}
|
|
280
303
|
}
|
|
281
|
-
paste
|
|
304
|
+
/* Pastes as a paste from the clipboard does; false when a read-only editor refused. */
|
|
305
|
+
pasteText(text, options = {}) {
|
|
282
306
|
if (this.blockedByReadOnly()) {
|
|
283
|
-
return;
|
|
307
|
+
return false;
|
|
284
308
|
}
|
|
285
309
|
this.unfoldCarets();
|
|
286
310
|
this.historyGroup++;
|
|
287
|
-
this.view.model.paste(this.native.normalizeNewlines(text), {
|
|
311
|
+
const pasted = this.view.model.paste(this.native.normalizeNewlines(text), {
|
|
312
|
+
...this.commandOptions(),
|
|
313
|
+
...(options.reindent === false ? { indentOnPaste: false } : {}),
|
|
314
|
+
wholeLines: options.wholeLines ?? (text !== '' && text === lineClip)
|
|
315
|
+
});
|
|
288
316
|
this.historyGroup++;
|
|
289
317
|
this.view.revealCaret();
|
|
318
|
+
return pasted;
|
|
319
|
+
}
|
|
320
|
+
/* Told what a copy or cut put on the clipboard. */
|
|
321
|
+
onCopy(listener) {
|
|
322
|
+
return subscribe(this.copyListeners, listener);
|
|
290
323
|
}
|
|
291
324
|
commandOptions() {
|
|
292
325
|
const { settings } = this.view;
|
|
@@ -300,14 +333,21 @@ export class InputController {
|
|
|
300
333
|
tabOutOfClosers: keys.tabOutOfClosers,
|
|
301
334
|
smartEnter: keys.smartIndentOnEnter,
|
|
302
335
|
indentOnPaste: keys.indentOnPaste,
|
|
336
|
+
indentGuides: settings.guides,
|
|
303
337
|
smartSemicolon: keys.smartSemicolon,
|
|
304
338
|
smartArrow: keys.smartArrow,
|
|
305
339
|
language: settings.language ?? 'plaintext',
|
|
306
340
|
camelCase: keys.camelHumps,
|
|
307
341
|
visualLine: (offset) => this.view.rowOf(offset),
|
|
308
|
-
lineSpan: (line) => this.view.lineSpan(line)
|
|
342
|
+
lineSpan: (line) => this.view.lineSpan(line),
|
|
343
|
+
structure: () => this.view.structureRanges(),
|
|
344
|
+
...(this.wordSources === null ? {} : { wordSources: this.wordSources })
|
|
309
345
|
};
|
|
310
346
|
}
|
|
347
|
+
/* The texts Hippie completion takes words from after those of this document; null takes them away. */
|
|
348
|
+
setWordSources(source) {
|
|
349
|
+
this.wordSources = source;
|
|
350
|
+
}
|
|
311
351
|
/* Folding is the view's, since it knows where the ranges are. */
|
|
312
352
|
viewCommand(name) {
|
|
313
353
|
const { view } = this;
|
|
@@ -315,6 +355,25 @@ export class InputController {
|
|
|
315
355
|
this.options.zoom(ZOOM_STEPS[name]);
|
|
316
356
|
return true;
|
|
317
357
|
}
|
|
358
|
+
if (name === 'methodUp' || name === 'methodDown') {
|
|
359
|
+
const from = view.model.getPrimary().head;
|
|
360
|
+
const moved = view.goToMethod(name === 'methodUp' ? -1 : 1);
|
|
361
|
+
if (moved) {
|
|
362
|
+
emit(this.navigateListeners, from);
|
|
363
|
+
}
|
|
364
|
+
return moved;
|
|
365
|
+
}
|
|
366
|
+
if (name === 'pasteAsPlainText') {
|
|
367
|
+
// The clipboard is read once a person asks, and an editor with no way to read it does nothing.
|
|
368
|
+
if (this.blockedByReadOnly() || globalThis.navigator?.clipboard?.readText === undefined) {
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
371
|
+
void navigator.clipboard.readText().then((text) => this.pasteText(text, { reindent: false }), () => undefined);
|
|
372
|
+
return true;
|
|
373
|
+
}
|
|
374
|
+
if (name === 'nextChange' || name === 'previousChange') {
|
|
375
|
+
return view.goToChange(name === 'nextChange' ? 1 : -1);
|
|
376
|
+
}
|
|
318
377
|
if (view.settings.folding === false && name !== 'toggleColumnMode') {
|
|
319
378
|
return false;
|
|
320
379
|
}
|
|
@@ -413,7 +472,10 @@ export class InputController {
|
|
|
413
472
|
}
|
|
414
473
|
}
|
|
415
474
|
}
|
|
416
|
-
const
|
|
475
|
+
const before = model.getPrimary().head;
|
|
476
|
+
const folded = name === 'moveLineUp' || name === 'moveLineDown' || name === 'moveStatementUp' || name === 'moveStatementDown'
|
|
477
|
+
? this.view.getFolds().collapsed
|
|
478
|
+
: [];
|
|
417
479
|
const result = model.execute(name, {
|
|
418
480
|
...this.commandOptions(),
|
|
419
481
|
onLinesMoved: (moves) => this.view.refoldMoved(folded, moves)
|
|
@@ -424,9 +486,19 @@ export class InputController {
|
|
|
424
486
|
if (name === 'smartEnd' || name === 'selectSmartEnd') {
|
|
425
487
|
this.view.markRowEnd(model.getPrimary().head);
|
|
426
488
|
}
|
|
489
|
+
if (name === 'hippieCompletion' || name === 'hippieBackwardCompletion') {
|
|
490
|
+
this.view.setHippieSource(model.hippieSource);
|
|
491
|
+
}
|
|
427
492
|
this.view.revealCaret();
|
|
493
|
+
if (CODE_BLOCK_COMMANDS.has(name) && model.getPrimary().head !== before) {
|
|
494
|
+
emit(this.navigateListeners, before);
|
|
495
|
+
}
|
|
428
496
|
return result;
|
|
429
497
|
}
|
|
498
|
+
/* Told the offset the primary caret left when a command that navigates moved it. */
|
|
499
|
+
onNavigate(listener) {
|
|
500
|
+
return subscribe(this.navigateListeners, listener);
|
|
501
|
+
}
|
|
430
502
|
typeText(text) {
|
|
431
503
|
if (this.blockedByReadOnly()) {
|
|
432
504
|
return;
|
|
@@ -651,6 +723,7 @@ export class InputController {
|
|
|
651
723
|
if (event.isComposing || this.native.composing) {
|
|
652
724
|
return;
|
|
653
725
|
}
|
|
726
|
+
this.view.setHippieSource(null);
|
|
654
727
|
const added = this.gesture.keydown(event);
|
|
655
728
|
if (added !== null) {
|
|
656
729
|
event.preventDefault();
|
|
@@ -726,6 +799,7 @@ export class InputController {
|
|
|
726
799
|
: selections.map((selection) => model.slice(Math.min(selection.anchor, selection.head), Math.max(selection.anchor, selection.head))).join('\n');
|
|
727
800
|
event.clipboardData?.setData('text/plain', text);
|
|
728
801
|
lineClip = empty ? text : null;
|
|
802
|
+
emit(this.copyListeners, { text, wholeLines: empty, cut });
|
|
729
803
|
if (!cut || this.blockedByReadOnly()) {
|
|
730
804
|
return;
|
|
731
805
|
}
|
package/dist/editor.css
CHANGED
|
@@ -652,11 +652,16 @@
|
|
|
652
652
|
.se-find-match,
|
|
653
653
|
.se-find-current,
|
|
654
654
|
.se-occurrence,
|
|
655
|
+
.se-hippie-source,
|
|
655
656
|
.se-bracket-match,
|
|
656
657
|
.se-bracket-unmatched {
|
|
657
658
|
position: absolute;
|
|
658
659
|
border-radius: var(--radius-xs);
|
|
659
660
|
}
|
|
661
|
+
.se-hippie-source {
|
|
662
|
+
background: color-mix(in srgb, var(--accent) 22%, transparent);
|
|
663
|
+
border-radius: var(--radius-sm);
|
|
664
|
+
}
|
|
660
665
|
.se-find-match {
|
|
661
666
|
background: var(--find-match);
|
|
662
667
|
}
|
|
@@ -747,6 +752,14 @@
|
|
|
747
752
|
white-space: pre;
|
|
748
753
|
cursor: default;
|
|
749
754
|
}
|
|
755
|
+
.se-swatch {
|
|
756
|
+
height: 12px;
|
|
757
|
+
margin-top: calc((var(--code-line-height, 20px) - 12px) / 2);
|
|
758
|
+
padding: 0;
|
|
759
|
+
border-radius: var(--radius-sm);
|
|
760
|
+
box-shadow: inset 0 0 0 1px var(--border);
|
|
761
|
+
cursor: pointer;
|
|
762
|
+
}
|
|
750
763
|
.se-inlay-link {
|
|
751
764
|
text-decoration: underline;
|
|
752
765
|
text-underline-offset: 2px;
|
package/dist/engine.js
CHANGED
|
@@ -35,6 +35,8 @@ class SmartEditor {
|
|
|
35
35
|
lensRevisions = new Map();
|
|
36
36
|
tokenizerRequest = 0;
|
|
37
37
|
settingText = false;
|
|
38
|
+
/* The hints of each owner, in the order the owners first set theirs. */
|
|
39
|
+
inlayOwners = new Map();
|
|
38
40
|
disposed = false;
|
|
39
41
|
engine;
|
|
40
42
|
constructor(engine, element, options) {
|
|
@@ -302,14 +304,21 @@ class SmartEditor {
|
|
|
302
304
|
...(marker.message === undefined ? {} : { message: marker.message })
|
|
303
305
|
})));
|
|
304
306
|
}
|
|
305
|
-
setInlayHints(hints) {
|
|
306
|
-
|
|
307
|
+
setInlayHints(hints, owner = DEFAULT_WIDGET_OWNER) {
|
|
308
|
+
if (hints.length === 0) {
|
|
309
|
+
this.inlayOwners.delete(owner);
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
this.inlayOwners.set(owner, hints);
|
|
313
|
+
}
|
|
314
|
+
this.view.setInlays([...this.inlayOwners.values()].flat().map((hint, index) => ({
|
|
307
315
|
id: hint.id ?? `hint-${index}`,
|
|
308
316
|
at: this.offsetAt(hint.position),
|
|
309
317
|
text: hint.label,
|
|
310
318
|
...(hint.parts === undefined ? {} : { parts: hint.parts }),
|
|
311
319
|
...(hint.paddingLeft ? { gapLeft: INLAY_GAP } : {}),
|
|
312
|
-
...(hint.paddingRight ? { gapRight: INLAY_GAP } : {})
|
|
320
|
+
...(hint.paddingRight ? { gapRight: INLAY_GAP } : {}),
|
|
321
|
+
...(hint.swatch === undefined ? {} : { swatch: hint.swatch })
|
|
313
322
|
})));
|
|
314
323
|
}
|
|
315
324
|
onInlayHover(listener) {
|
|
@@ -681,6 +690,24 @@ class SmartEditor {
|
|
|
681
690
|
setFoldHints(hints) {
|
|
682
691
|
this.view.setFoldHints(hints === null ? null : this.foldHintsByOffset(hints));
|
|
683
692
|
}
|
|
693
|
+
setDeclarations(positions) {
|
|
694
|
+
this.view.setDeclarations(positions === null ? null : positions.map((position) => this.offsetAt(position)));
|
|
695
|
+
}
|
|
696
|
+
onNavigate(listener) {
|
|
697
|
+
return this.controller.onNavigate((from) => listener(this.positionAt(from)));
|
|
698
|
+
}
|
|
699
|
+
hasFocus() {
|
|
700
|
+
return this.view.focused;
|
|
701
|
+
}
|
|
702
|
+
setWordSources(source) {
|
|
703
|
+
this.controller.setWordSources(source);
|
|
704
|
+
}
|
|
705
|
+
onCopy(listener) {
|
|
706
|
+
return this.controller.onCopy(listener);
|
|
707
|
+
}
|
|
708
|
+
paste(text, options) {
|
|
709
|
+
return this.controller.pasteText(text, options);
|
|
710
|
+
}
|
|
684
711
|
foldHintsByOffset(hints) {
|
|
685
712
|
const lineOf = (line) => this.model.getLine(Math.min(line, this.model.getLineCount() - 1));
|
|
686
713
|
const within = (line, character) => Math.min(line.end, line.start + Math.max(0, character));
|
package/dist/fake.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Editor, EditorAttributionHover, EditorAttributionMark, EditorBlock, EditorCodeBlockOptions, EditorLineAction, EditorReplacement, EditorLineHighlight, LineToken, EditorChangeMark, EditorCodeVision, EditorClick, EditorClickHandler, EditorContextMenu, EditorContentChange, EditorEngine, EditorFindQuery, EditorFindState, EditorReplaceOptions, EditorGutterAction, EditorGutterMarker, EditorHighlight, EditorHover, EditorIndentation, EditorGhostText, EditorInlayClick, EditorInlayClickHandler, EditorInlayHint, EditorInlayTarget, EditorKeyHandler, EditorInputPopup, EditorMarker, EditorMessages, EditorOptions, EditorPosition, EditorRemoteCursor, EditorRange, EditorReveal, EditorRect, EditorRunCommand, EditorSelectionRanges, EditorFoldHints, EditorFoldOutline, EditorFolds, EditorSemanticToken, EditorSmartKeys, EditorApplyEditsOptions, EditorTextChange, EditorTrackedRange, EditorTheme, EditorWhitespaceCleanup, EditorWidget } from './types.ts';
|
|
1
|
+
import type { Editor, EditorAttributionHover, EditorAttributionMark, EditorBlock, EditorCodeBlockOptions, EditorLineAction, EditorReplacement, EditorLineHighlight, LineToken, EditorChangeMark, EditorCodeVision, EditorClick, EditorClickHandler, EditorContextMenu, EditorContentChange, EditorEngine, EditorFindQuery, EditorFindState, EditorReplaceOptions, EditorGutterAction, EditorGutterMarker, EditorHighlight, EditorHover, EditorIndentation, EditorGhostText, EditorInlayClick, EditorInlayClickHandler, EditorInlayHint, EditorInlayTarget, EditorKeyHandler, EditorInputPopup, EditorMarker, EditorMessages, EditorOptions, EditorPosition, EditorRemoteCursor, EditorRange, EditorReveal, EditorRect, EditorRunCommand, EditorSelectionRanges, EditorFoldHints, EditorFoldOutline, EditorFolds, EditorSemanticToken, EditorSmartKeys, EditorApplyEditsOptions, EditorCopy, EditorPasteOptions, EditorTextChange, EditorTrackedRange, EditorTheme, EditorWhitespaceCleanup, EditorWidget } from './types.ts';
|
|
2
2
|
import { type Listener } from './listeners.ts';
|
|
3
3
|
export declare class FakeEditor implements Editor {
|
|
4
4
|
readonly element: HTMLElement;
|
|
@@ -142,6 +142,22 @@ export declare class FakeEditor implements Editor {
|
|
|
142
142
|
todoWords: readonly string[] | undefined;
|
|
143
143
|
setTodoWords(words: readonly string[]): void;
|
|
144
144
|
setFoldHints(hints: EditorFoldHints | null): void;
|
|
145
|
+
declarations: readonly EditorPosition[] | null;
|
|
146
|
+
setDeclarations(positions: readonly EditorPosition[] | null): void;
|
|
147
|
+
private readonly navigations;
|
|
148
|
+
onNavigate(listener: (from: EditorPosition) => void): () => void;
|
|
149
|
+
navigate(from: EditorPosition): void;
|
|
150
|
+
hasFocus(): boolean;
|
|
151
|
+
private readonly copies;
|
|
152
|
+
onCopy(listener: (copy: EditorCopy) => void): () => void;
|
|
153
|
+
copy(text: string, wholeLines?: boolean, cut?: boolean): void;
|
|
154
|
+
readonly pastes: Array<{
|
|
155
|
+
text: string;
|
|
156
|
+
options: EditorPasteOptions | undefined;
|
|
157
|
+
}>;
|
|
158
|
+
paste(text: string, options?: EditorPasteOptions): boolean;
|
|
159
|
+
wordSources: (() => readonly string[]) | null;
|
|
160
|
+
setWordSources(source: (() => readonly string[]) | null): void;
|
|
145
161
|
setSmartKeys(keys: Partial<EditorSmartKeys>): void;
|
|
146
162
|
setIndentation(indentation: EditorIndentation): void;
|
|
147
163
|
markers: readonly EditorMarker[];
|
|
@@ -161,7 +177,8 @@ export declare class FakeEditor implements Editor {
|
|
|
161
177
|
private readonly keys;
|
|
162
178
|
setMarkers(markers: readonly EditorMarker[]): void;
|
|
163
179
|
inlayHints: readonly EditorInlayHint[];
|
|
164
|
-
|
|
180
|
+
private readonly inlayOwners;
|
|
181
|
+
setInlayHints(hints: readonly EditorInlayHint[], owner?: string): void;
|
|
165
182
|
private readonly inlayHovers;
|
|
166
183
|
private readonly inlayHandlers;
|
|
167
184
|
inlayLink: {
|
package/dist/fake.js
CHANGED
|
@@ -581,6 +581,59 @@ export class FakeEditor {
|
|
|
581
581
|
setFoldHints(hints) {
|
|
582
582
|
this.foldHints = hints;
|
|
583
583
|
}
|
|
584
|
+
declarations = null;
|
|
585
|
+
setDeclarations(positions) {
|
|
586
|
+
this.declarations = positions;
|
|
587
|
+
}
|
|
588
|
+
navigations = new Set();
|
|
589
|
+
onNavigate(listener) {
|
|
590
|
+
return subscribe(this.navigations, listener);
|
|
591
|
+
}
|
|
592
|
+
/* Stands for a command that navigated: tells the listeners the caret left `from`. */
|
|
593
|
+
navigate(from) {
|
|
594
|
+
emit(this.navigations, from);
|
|
595
|
+
}
|
|
596
|
+
hasFocus() {
|
|
597
|
+
return this.focused;
|
|
598
|
+
}
|
|
599
|
+
copies = new Set();
|
|
600
|
+
onCopy(listener) {
|
|
601
|
+
return subscribe(this.copies, listener);
|
|
602
|
+
}
|
|
603
|
+
/* Stands for a copy or cut of a person: tells the listeners what went on the clipboard. */
|
|
604
|
+
copy(text, wholeLines = false, cut = false) {
|
|
605
|
+
emit(this.copies, { text, wholeLines, cut });
|
|
606
|
+
}
|
|
607
|
+
/* Every paste a host asked for, with its options. */
|
|
608
|
+
pastes = [];
|
|
609
|
+
/* Puts the text at every caret, one line per caret when the lines are as many as the carets, and leaves the carets behind it. */
|
|
610
|
+
paste(text, options) {
|
|
611
|
+
this.assertLive();
|
|
612
|
+
this.pastes.push({ text, options });
|
|
613
|
+
if (this.readOnly || text === '') {
|
|
614
|
+
return false;
|
|
615
|
+
}
|
|
616
|
+
const lines = text.split('\n');
|
|
617
|
+
const selections = [...this.selections].sort((left, right) => Math.min(left.anchor, left.head) - Math.min(right.anchor, right.head));
|
|
618
|
+
const perCaret = lines.length === selections.length;
|
|
619
|
+
const edits = selections.map((selection, index) => ({
|
|
620
|
+
from: Math.min(selection.anchor, selection.head),
|
|
621
|
+
to: Math.max(selection.anchor, selection.head),
|
|
622
|
+
text: perCaret ? lines[index] : text
|
|
623
|
+
}));
|
|
624
|
+
return this.edit(edits, 'command', false, () => {
|
|
625
|
+
let shift = 0;
|
|
626
|
+
return edits.map((edit) => {
|
|
627
|
+
const caret = edit.from + shift + edit.text.length;
|
|
628
|
+
shift += edit.text.length - (edit.to - edit.from);
|
|
629
|
+
return { anchor: caret, head: caret };
|
|
630
|
+
});
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
wordSources = null;
|
|
634
|
+
setWordSources(source) {
|
|
635
|
+
this.wordSources = source;
|
|
636
|
+
}
|
|
584
637
|
setSmartKeys(keys) {
|
|
585
638
|
this.smartKeys = keys;
|
|
586
639
|
}
|
|
@@ -601,10 +654,17 @@ export class FakeEditor {
|
|
|
601
654
|
setMarkers(markers) {
|
|
602
655
|
this.markers = markers;
|
|
603
656
|
}
|
|
604
|
-
/* What the host drew as hints last. */
|
|
657
|
+
/* What the host drew as hints last, every owner's together. */
|
|
605
658
|
inlayHints = [];
|
|
606
|
-
|
|
607
|
-
|
|
659
|
+
inlayOwners = new Map();
|
|
660
|
+
setInlayHints(hints, owner = 'default') {
|
|
661
|
+
if (hints.length === 0) {
|
|
662
|
+
this.inlayOwners.delete(owner);
|
|
663
|
+
}
|
|
664
|
+
else {
|
|
665
|
+
this.inlayOwners.set(owner, hints);
|
|
666
|
+
}
|
|
667
|
+
this.inlayHints = [...this.inlayOwners.values()].flat();
|
|
608
668
|
}
|
|
609
669
|
inlayHovers = new Set();
|
|
610
670
|
inlayHandlers = new Set();
|
|
@@ -872,6 +932,8 @@ export class FakeEditor {
|
|
|
872
932
|
this.changes.clear();
|
|
873
933
|
this.textChanges.clear();
|
|
874
934
|
this.carets.clear();
|
|
935
|
+
this.navigations.clear();
|
|
936
|
+
this.copies.clear();
|
|
875
937
|
this.hovers.clear();
|
|
876
938
|
this.inlayHovers.clear();
|
|
877
939
|
this.inlayHandlers.clear();
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export { findDocComments, MAX_DOC_COMMENTS, type DocComment } from '@adecore/edi
|
|
|
4
4
|
export { DEFAULT_TODO_WORDS, findTodos, type TodoMatch, type TodoOptions } from '@adecore/editor-core';
|
|
5
5
|
export { detectIndentation, type DetectedIndentation } from '@adecore/editor-core';
|
|
6
6
|
export { createSmartEditorEngine } from './engine.ts';
|
|
7
|
+
export { rememberCopy } from './controller.ts';
|
|
7
8
|
export { DEFAULT_SMART_KEYS } from './smart-keys.ts';
|
|
8
9
|
export { shikiScopeColors, shikiTokenizers } from './shiki.ts';
|
|
9
|
-
export type { Editor, EditorAttributionHover, EditorAttributionMark, EditorMarkColor, EditorBlock, EditorChangeKind, EditorChangeMark, EditorCodeVision, EditorCodeVisionEntry, EditorClick, EditorCodeBlockOptions, EditorClickHandler, EditorCommand, EditorContextMenu, EditorEngine, EditorFindQuery, EditorFoldHints, EditorFoldRangeHint, EditorFoldOutline, EditorFoldRange, EditorFoldSymbol, EditorFolds, EditorFindState, EditorReplaceOptions, EditorGutterAction, EditorGutterIcon, EditorGutterMarker, EditorReplacement, EditorIndentation, EditorContentChange, EditorHighlight, EditorHighlightKind, EditorHover, EditorGhostText, EditorInlayClick, EditorInlayClickHandler, EditorInlayHint, EditorInlayTarget, EditorKeyHandler, EditorLineAction, EditorLineHighlight, EditorMarker, EditorInputPopup, EditorMessages, EditorMarkerSeverity, EditorReveal, EditorRect, EditorSmartKeys, EditorOptions, EditorPosition, EditorRemoteCursor, EditorRange, EditorApplyEditsOptions, EditorTextChange, EditorTrackedRange, EditorRunCommand, EditorSelectionRanges, EditorTheme, EditorViewCommand, EditorWhitespaceCleanup, EditorWidget, EditorZoom, FoldRole, KeyChord, LineToken, LineTokenKind, ScopeColorSource, ScopeColors, ScopeStyle, EditorSemanticToken, LineTokenizer, SmartEditorEngineOptions, TokenizedLine, TokenizerSource } from './types.ts';
|
|
10
|
+
export type { Editor, EditorAttributionHover, EditorAttributionMark, EditorMarkColor, EditorBlock, EditorChangeKind, EditorChangeMark, EditorCodeVision, EditorCodeVisionEntry, EditorClick, EditorCodeBlockOptions, EditorClickHandler, EditorCommand, EditorContextMenu, EditorEngine, EditorFindQuery, EditorFoldHints, EditorFoldRangeHint, EditorFoldOutline, EditorFoldRange, EditorFoldSymbol, EditorFolds, EditorFindState, EditorReplaceOptions, EditorGutterAction, EditorGutterIcon, EditorGutterMarker, EditorReplacement, EditorIndentation, EditorContentChange, EditorHighlight, EditorHighlightKind, EditorHover, EditorGhostText, EditorInlayClick, EditorInlayClickHandler, EditorInlayHint, EditorInlayTarget, EditorKeyHandler, EditorLineAction, EditorLineHighlight, EditorMarker, EditorInputPopup, EditorMessages, EditorMarkerSeverity, EditorReveal, EditorRect, EditorSmartKeys, EditorOptions, EditorPosition, EditorRemoteCursor, EditorRange, EditorApplyEditsOptions, EditorCopy, EditorPasteOptions, EditorTextChange, EditorTrackedRange, EditorRunCommand, EditorSelectionRanges, EditorTheme, EditorViewCommand, EditorWhitespaceCleanup, EditorWidget, EditorZoom, FoldRole, KeyChord, LineToken, LineTokenKind, ScopeColorSource, ScopeColors, ScopeStyle, EditorSemanticToken, LineTokenizer, SmartEditorEngineOptions, TokenizedLine, TokenizerSource } from './types.ts';
|
package/dist/index.js
CHANGED
|
@@ -4,5 +4,6 @@ export { findDocComments, MAX_DOC_COMMENTS } from '@adecore/editor-core';
|
|
|
4
4
|
export { DEFAULT_TODO_WORDS, findTodos } from '@adecore/editor-core';
|
|
5
5
|
export { detectIndentation } from '@adecore/editor-core';
|
|
6
6
|
export { createSmartEditorEngine } from './engine.js';
|
|
7
|
+
export { rememberCopy } from './controller.js';
|
|
7
8
|
export { DEFAULT_SMART_KEYS } from './smart-keys.js';
|
|
8
9
|
export { shikiScopeColors, shikiTokenizers } from './shiki.js';
|
package/dist/keymap-table.d.ts
CHANGED
|
@@ -18,10 +18,15 @@ export declare const KEYMAP: {
|
|
|
18
18
|
readonly deleteLine: KeyBinding;
|
|
19
19
|
readonly moveLineUp: KeyBinding;
|
|
20
20
|
readonly moveLineDown: KeyBinding;
|
|
21
|
+
readonly moveStatementUp: KeyBinding;
|
|
22
|
+
readonly moveStatementDown: KeyBinding;
|
|
21
23
|
readonly toggleLineComment: KeyBinding;
|
|
22
24
|
readonly toggleBlockComment: KeyBinding;
|
|
23
25
|
readonly joinLines: KeyBinding;
|
|
24
26
|
readonly startNewLine: KeyBinding;
|
|
27
|
+
readonly completeCurrentStatement: KeyBinding;
|
|
28
|
+
readonly hippieCompletion: KeyBinding;
|
|
29
|
+
readonly hippieBackwardCompletion: KeyBinding;
|
|
25
30
|
readonly startNewLineBefore: KeyBinding;
|
|
26
31
|
readonly splitLine: KeyBinding;
|
|
27
32
|
readonly toggleCase: KeyBinding;
|
|
@@ -34,6 +39,18 @@ export declare const KEYMAP: {
|
|
|
34
39
|
readonly expandSelection: KeyBinding;
|
|
35
40
|
readonly shrinkSelection: KeyBinding;
|
|
36
41
|
readonly matchBrace: KeyBinding;
|
|
42
|
+
readonly methodUp: KeyBinding;
|
|
43
|
+
readonly methodDown: KeyBinding;
|
|
44
|
+
readonly lastEditLocation: KeyBinding;
|
|
45
|
+
readonly nextEditLocation: KeyBinding;
|
|
46
|
+
readonly pasteFromHistory: KeyBinding;
|
|
47
|
+
readonly pasteAsPlainText: KeyBinding;
|
|
48
|
+
readonly nextChange: KeyBinding;
|
|
49
|
+
readonly previousChange: KeyBinding;
|
|
50
|
+
readonly codeBlockStart: KeyBinding;
|
|
51
|
+
readonly codeBlockEnd: KeyBinding;
|
|
52
|
+
readonly codeBlockStartWithSelection: KeyBinding;
|
|
53
|
+
readonly codeBlockEndWithSelection: KeyBinding;
|
|
37
54
|
readonly selectNextOccurrence: KeyBinding;
|
|
38
55
|
readonly unselectOccurrence: KeyBinding;
|
|
39
56
|
readonly selectAllOccurrences: KeyBinding;
|
|
@@ -80,6 +97,7 @@ export declare const KEYMAP: {
|
|
|
80
97
|
readonly renameSymbol: KeyBinding;
|
|
81
98
|
readonly organizeImports: KeyBinding;
|
|
82
99
|
readonly formatDocument: KeyBinding;
|
|
100
|
+
readonly wrapWithAbbreviation: KeyBinding;
|
|
83
101
|
readonly selectionToChat: KeyBinding;
|
|
84
102
|
readonly inlineEdit: KeyBinding;
|
|
85
103
|
readonly suggestInline: KeyBinding;
|
|
@@ -91,6 +109,7 @@ export declare const KEYMAP: {
|
|
|
91
109
|
readonly peekDefinition: KeyBinding;
|
|
92
110
|
readonly peekReferences: KeyBinding;
|
|
93
111
|
readonly callHierarchy: KeyBinding;
|
|
112
|
+
readonly typeHierarchy: KeyBinding;
|
|
94
113
|
readonly toggleRenderedDocs: KeyBinding;
|
|
95
114
|
readonly historyBack: KeyBinding;
|
|
96
115
|
readonly historyForward: KeyBinding;
|
|
@@ -104,7 +123,7 @@ export declare const KEYMAP: {
|
|
|
104
123
|
readonly replace: KeyBinding;
|
|
105
124
|
};
|
|
106
125
|
export type KeymapId = keyof typeof KEYMAP;
|
|
107
|
-
export type OptionalKeymapId = 'toggleRenderedDocs' | 'increaseFontSize' | 'decreaseFontSize' | 'resetFontSize' | 'sortLines' | 'reverseLines' | 'uniqueLines' | 'convertIndentsToSpaces' | 'convertIndentsToTabs';
|
|
126
|
+
export type OptionalKeymapId = 'toggleRenderedDocs' | 'increaseFontSize' | 'decreaseFontSize' | 'resetFontSize' | 'sortLines' | 'reverseLines' | 'uniqueLines' | 'convertIndentsToSpaces' | 'convertIndentsToTabs' | 'completeCurrentStatement' | 'hippieCompletion' | 'hippieBackwardCompletion' | 'moveStatementUp' | 'moveStatementDown' | 'lastEditLocation' | 'nextEditLocation' | 'methodUp' | 'methodDown' | 'pasteFromHistory' | 'pasteAsPlainText' | 'nextChange' | 'previousChange' | 'codeBlockStart' | 'codeBlockEnd' | 'codeBlockStartWithSelection' | 'codeBlockEndWithSelection' | 'wrapWithAbbreviation' | 'typeHierarchy';
|
|
108
127
|
export type Keymap = Readonly<Record<Exclude<KeymapId, OptionalKeymapId>, KeyBinding> & Partial<Record<OptionalKeymapId, KeyBinding>>>;
|
|
109
128
|
export type KeymapOverrides = Partial<Record<KeymapId, Partial<KeyBinding>>>;
|
|
110
129
|
export declare const KEYMAP_IDS: KeymapId[];
|
package/dist/keymap-table.js
CHANGED
|
@@ -15,10 +15,15 @@ export const KEYMAP = {
|
|
|
15
15
|
deleteLine: bind('Mod+Backspace', 'Mod+Y'),
|
|
16
16
|
moveLineUp: bind('Alt+Shift+ArrowUp'),
|
|
17
17
|
moveLineDown: bind('Alt+Shift+ArrowDown'),
|
|
18
|
+
moveStatementUp: bind('Mod+Shift+ArrowUp'),
|
|
19
|
+
moveStatementDown: bind('Mod+Shift+ArrowDown'),
|
|
18
20
|
toggleLineComment: bind('Mod+/'),
|
|
19
21
|
toggleBlockComment: bind('Mod+Alt+/', 'Mod+Shift+/'),
|
|
20
22
|
joinLines: bind('Ctrl+Shift+J'),
|
|
21
23
|
startNewLine: bind('Shift+Enter'),
|
|
24
|
+
completeCurrentStatement: bind('Mod+Shift+Enter'),
|
|
25
|
+
hippieCompletion: bind('Alt+/'),
|
|
26
|
+
hippieBackwardCompletion: bind('Alt+Shift+/'),
|
|
22
27
|
startNewLineBefore: bind('Mod+Alt+Enter'),
|
|
23
28
|
splitLine: bind('Mod+Enter'),
|
|
24
29
|
toggleCase: bind('Mod+Shift+U'),
|
|
@@ -30,8 +35,21 @@ export const KEYMAP = {
|
|
|
30
35
|
convertIndentsToSpaces: bind(null),
|
|
31
36
|
convertIndentsToTabs: bind(null),
|
|
32
37
|
expandSelection: bind('Alt+ArrowUp', 'Ctrl+W'),
|
|
33
|
-
|
|
38
|
+
// Off macOS Alt+ArrowDown is Next Method, as in IntelliJ, so Shrink Selection takes its own chord there.
|
|
39
|
+
shrinkSelection: bind('Alt+ArrowDown', 'Ctrl+Shift+W'),
|
|
34
40
|
matchBrace: bind('Ctrl+M', 'Ctrl+Shift+M'),
|
|
41
|
+
methodUp: bind('Ctrl+Shift+ArrowUp', 'Alt+ArrowUp'),
|
|
42
|
+
methodDown: bind('Ctrl+Shift+ArrowDown', 'Alt+ArrowDown'),
|
|
43
|
+
lastEditLocation: bind('Mod+Shift+Backspace'),
|
|
44
|
+
nextEditLocation: bind(null),
|
|
45
|
+
pasteFromHistory: bind('Mod+Shift+V'),
|
|
46
|
+
pasteAsPlainText: bind('Mod+Alt+Shift+V'),
|
|
47
|
+
nextChange: bind('Ctrl+Alt+Shift+ArrowDown'),
|
|
48
|
+
previousChange: bind('Ctrl+Alt+Shift+ArrowUp'),
|
|
49
|
+
codeBlockStart: bind('Mod+Alt+[', 'Ctrl+['),
|
|
50
|
+
codeBlockEnd: bind('Mod+Alt+]', 'Ctrl+]'),
|
|
51
|
+
codeBlockStartWithSelection: bind('Mod+Alt+Shift+[', 'Ctrl+Shift+['),
|
|
52
|
+
codeBlockEndWithSelection: bind('Mod+Alt+Shift+]', 'Ctrl+Shift+]'),
|
|
35
53
|
selectNextOccurrence: bind('Ctrl+G', 'Alt+J'),
|
|
36
54
|
unselectOccurrence: bind('Ctrl+Shift+G', 'Alt+Shift+J'),
|
|
37
55
|
selectAllOccurrences: bind('Meta+Ctrl+G', 'Ctrl+Alt+Shift+J'),
|
|
@@ -51,9 +69,10 @@ export const KEYMAP = {
|
|
|
51
69
|
smartEnd: bind('Meta+ArrowRight', null),
|
|
52
70
|
selectSmartEnd: bind('Meta+Shift+ArrowRight', null),
|
|
53
71
|
textStart: bind('Meta+ArrowUp', null),
|
|
54
|
-
|
|
72
|
+
// IntelliJ binds Cmd+Shift+ArrowUp and ArrowDown to Move Statement on macOS, where Cmd+Shift+Home and End still select to the text edges.
|
|
73
|
+
selectTextStart: bind(null),
|
|
55
74
|
textEnd: bind('Meta+ArrowDown', null),
|
|
56
|
-
selectTextEnd: bind(
|
|
75
|
+
selectTextEnd: bind(null),
|
|
57
76
|
collapse: bind('Mod+-'),
|
|
58
77
|
expand: bind('Mod+='),
|
|
59
78
|
collapseAll: bind('Mod+Shift+-'),
|
|
@@ -81,6 +100,7 @@ export const KEYMAP = {
|
|
|
81
100
|
renameSymbol: bind('Shift+F6'),
|
|
82
101
|
organizeImports: bind('Ctrl+Alt+O'),
|
|
83
102
|
formatDocument: bind('Mod+Alt+L'),
|
|
103
|
+
wrapWithAbbreviation: bind('Mod+Alt+J'),
|
|
84
104
|
selectionToChat: bind(null),
|
|
85
105
|
inlineEdit: bind(null),
|
|
86
106
|
suggestInline: bind(null),
|
|
@@ -92,6 +112,7 @@ export const KEYMAP = {
|
|
|
92
112
|
peekDefinition: bind('Alt+Space', 'Ctrl+Shift+I'),
|
|
93
113
|
peekReferences: bind('Alt+F7'),
|
|
94
114
|
callHierarchy: bind('Ctrl+Alt+H'),
|
|
115
|
+
typeHierarchy: bind('Ctrl+H'),
|
|
95
116
|
toggleRenderedDocs: bind('Ctrl+Alt+Q'),
|
|
96
117
|
historyBack: bind('Mod+[', 'Ctrl+Alt+ArrowLeft'),
|
|
97
118
|
historyForward: bind('Mod+]', 'Ctrl+Alt+ArrowRight'),
|
package/dist/keymap.js
CHANGED
|
@@ -16,10 +16,15 @@ const ACTIONS = {
|
|
|
16
16
|
deleteLine: command('deleteLine'),
|
|
17
17
|
moveLineUp: command('moveLineUp'),
|
|
18
18
|
moveLineDown: command('moveLineDown'),
|
|
19
|
+
moveStatementUp: command('moveStatementUp'),
|
|
20
|
+
moveStatementDown: command('moveStatementDown'),
|
|
19
21
|
toggleLineComment: command('toggleLineComment'),
|
|
20
22
|
toggleBlockComment: command('toggleBlockComment'),
|
|
21
23
|
joinLines: command('joinLines'),
|
|
22
24
|
startNewLine: command('startNewLine'),
|
|
25
|
+
completeCurrentStatement: command('completeCurrentStatement'),
|
|
26
|
+
hippieCompletion: command('hippieCompletion'),
|
|
27
|
+
hippieBackwardCompletion: command('hippieBackwardCompletion'),
|
|
23
28
|
startNewLineBefore: command('startNewLineBefore'),
|
|
24
29
|
splitLine: command('splitLine'),
|
|
25
30
|
toggleCase: command('toggleCase'),
|
|
@@ -32,6 +37,15 @@ const ACTIONS = {
|
|
|
32
37
|
expandSelection: command('expandSelection'),
|
|
33
38
|
shrinkSelection: command('shrinkSelection'),
|
|
34
39
|
matchBrace: { type: 'bracket' },
|
|
40
|
+
methodUp: view('methodUp'),
|
|
41
|
+
methodDown: view('methodDown'),
|
|
42
|
+
pasteAsPlainText: view('pasteAsPlainText'),
|
|
43
|
+
nextChange: view('nextChange'),
|
|
44
|
+
previousChange: view('previousChange'),
|
|
45
|
+
codeBlockStart: command('codeBlockStart'),
|
|
46
|
+
codeBlockEnd: command('codeBlockEnd'),
|
|
47
|
+
codeBlockStartWithSelection: command('codeBlockStartWithSelection'),
|
|
48
|
+
codeBlockEndWithSelection: command('codeBlockEndWithSelection'),
|
|
35
49
|
selectNextOccurrence: command('selectNextOccurrence'),
|
|
36
50
|
unselectOccurrence: command('unselectOccurrence'),
|
|
37
51
|
selectAllOccurrences: command('selectAllOccurrences'),
|