@adecore/editor 0.22.0 → 0.23.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/attribution.d.ts +9 -8
- package/dist/attribution.js +44 -9
- package/dist/bidi.d.ts +44 -0
- package/dist/bidi.js +26 -0
- package/dist/column-selection.js +2 -1
- package/dist/controller.d.ts +6 -1
- package/dist/controller.js +93 -3
- package/dist/editor.css +81 -1
- package/dist/engine.js +184 -41
- package/dist/fake.d.ts +43 -5
- package/dist/fake.js +117 -13
- package/dist/find-search.d.ts +26 -0
- package/dist/find-search.js +130 -0
- package/dist/find.d.ts +50 -2
- package/dist/find.js +575 -25
- package/dist/geometry-stops.d.ts +6 -0
- package/dist/geometry-stops.js +47 -0
- package/dist/grammar-preparation.d.ts +29 -0
- package/dist/grammar-preparation.js +147 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -0
- package/dist/keymap-table.d.ts +10 -1
- package/dist/keymap-table.js +37 -1
- package/dist/keymap.d.ts +1 -0
- package/dist/keymap.js +4 -1
- package/dist/layout-changes.d.ts +6 -0
- package/dist/layout-changes.js +27 -0
- package/dist/layout.d.ts +45 -2
- package/dist/layout.js +202 -58
- package/dist/offsets.d.ts +1 -0
- package/dist/offsets.js +23 -0
- package/dist/outline.js +5 -4
- package/dist/paint.d.ts +11 -3
- package/dist/paint.js +180 -34
- package/dist/search-client.d.ts +27 -0
- package/dist/search-client.js +210 -0
- package/dist/search-protocol.d.ts +103 -0
- package/dist/search-protocol.js +3 -0
- package/dist/search-worker.d.ts +11 -0
- package/dist/search-worker.js +137 -0
- package/dist/semantic.d.ts +2 -1
- package/dist/semantic.js +6 -1
- package/dist/shiki-document.d.ts +8 -0
- package/dist/shiki-document.js +93 -0
- package/dist/shiki-worker.d.ts +65 -0
- package/dist/shiki-worker.js +265 -0
- package/dist/shiki.d.ts +1 -0
- package/dist/shiki.js +96 -33
- package/dist/testing.d.ts +1 -0
- package/dist/tokens.d.ts +2 -0
- package/dist/tokens.js +37 -7
- package/dist/touch.d.ts +27 -0
- package/dist/touch.js +100 -0
- package/dist/types.d.ts +84 -2
- package/dist/uniform-geometry.d.ts +7 -0
- package/dist/uniform-geometry.js +49 -0
- package/dist/view.d.ts +68 -17
- package/dist/view.js +424 -97
- package/dist/worker-client.d.ts +37 -0
- package/dist/worker-client.js +195 -0
- package/package.json +17 -2
- package/src/attribution.ts +50 -14
- package/src/bidi.ts +32 -0
- package/src/column-selection.ts +2 -1
- package/src/controller.ts +97 -3
- package/src/editor.css +81 -1
- package/src/engine.ts +216 -42
- package/src/fake.ts +152 -14
- package/src/find-search.ts +165 -0
- package/src/find.ts +622 -21
- package/src/geometry-stops.ts +51 -0
- package/src/grammar-preparation.ts +158 -0
- package/src/index.ts +10 -0
- package/src/keymap-table.ts +44 -2
- package/src/keymap.ts +5 -1
- package/src/layout-changes.ts +33 -0
- package/src/layout.ts +262 -63
- package/src/offsets.ts +24 -0
- package/src/outline.ts +5 -4
- package/src/paint.ts +202 -36
- package/src/search-client.ts +306 -0
- package/src/search-protocol.ts +100 -0
- package/src/search-worker.ts +171 -0
- package/src/semantic.ts +8 -2
- package/src/shiki-document.ts +143 -0
- package/src/shiki-worker.ts +344 -0
- package/src/shiki.ts +103 -33
- package/src/testing.ts +2 -0
- package/src/tokens.ts +36 -7
- package/src/touch.ts +134 -0
- package/src/types.ts +174 -8
- package/src/uniform-geometry.ts +57 -0
- package/src/view.ts +500 -102
- package/src/worker-client.ts +212 -0
package/dist/fake.js
CHANGED
|
@@ -76,7 +76,7 @@ export class FakeEditor {
|
|
|
76
76
|
this.replaceText(text);
|
|
77
77
|
}
|
|
78
78
|
/* The text becomes `text`, and listeners of the text hear the one stretch that differs, as the real editor reports it. */
|
|
79
|
-
replaceText(text, source = 'external') {
|
|
79
|
+
replaceText(text, source = 'external', selections) {
|
|
80
80
|
const span = changedSpan(this.text, text);
|
|
81
81
|
const before = this.text;
|
|
82
82
|
this.text = text;
|
|
@@ -85,7 +85,12 @@ export class FakeEditor {
|
|
|
85
85
|
}
|
|
86
86
|
// As in the real editor the caret lands behind what was typed, and listeners of the caret hear it before those of the text.
|
|
87
87
|
if (source !== 'external') {
|
|
88
|
-
|
|
88
|
+
if (selections === undefined) {
|
|
89
|
+
this.moveCaret(positionIn(text, span.start + span.text.length));
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
this.setSelections(selections);
|
|
93
|
+
}
|
|
89
94
|
}
|
|
90
95
|
this.followTracked(span.start, span.end, span.text.length);
|
|
91
96
|
this.ghost = null;
|
|
@@ -180,6 +185,9 @@ export class FakeEditor {
|
|
|
180
185
|
this.replaceOptions.push(options);
|
|
181
186
|
return this.readOnly ? 0 : this.findState.count;
|
|
182
187
|
}
|
|
188
|
+
async replaceAllAsync(replacement, options = {}) {
|
|
189
|
+
return this.replaceAll(replacement, options);
|
|
190
|
+
}
|
|
183
191
|
setReplacePreview(replacement) {
|
|
184
192
|
this.replacePreview = replacement;
|
|
185
193
|
}
|
|
@@ -210,10 +218,18 @@ export class FakeEditor {
|
|
|
210
218
|
/* What the host handed it last; null while it reads the structure itself. */
|
|
211
219
|
blocks = null;
|
|
212
220
|
scopes = new Set();
|
|
213
|
-
/*
|
|
214
|
-
changeMarks
|
|
215
|
-
|
|
216
|
-
|
|
221
|
+
/* The marks of every layer, in the order the layers last became non-empty. */
|
|
222
|
+
get changeMarks() {
|
|
223
|
+
return [...this.changeLayers.values()].flat();
|
|
224
|
+
}
|
|
225
|
+
changeLayers = new Map();
|
|
226
|
+
setChangeMarks(marks, layer = '') {
|
|
227
|
+
if (marks.length === 0) {
|
|
228
|
+
this.changeLayers.delete(layer);
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
this.changeLayers.set(layer, marks);
|
|
232
|
+
}
|
|
217
233
|
}
|
|
218
234
|
/* The tinted lines the host set last. */
|
|
219
235
|
lineHighlights = [];
|
|
@@ -222,6 +238,32 @@ export class FakeEditor {
|
|
|
222
238
|
}
|
|
223
239
|
/* What the host drew as code outside the document: the text and how, and into which element. */
|
|
224
240
|
codeBlocks = [];
|
|
241
|
+
lineNumbers = null;
|
|
242
|
+
lineTokens = null;
|
|
243
|
+
setLineNumbers(labels) {
|
|
244
|
+
this.lineNumbers = labels;
|
|
245
|
+
}
|
|
246
|
+
lineLabels = null;
|
|
247
|
+
setLineLabels(labels) {
|
|
248
|
+
this.lineLabels = labels;
|
|
249
|
+
}
|
|
250
|
+
/* What the input points at, as the last call left it. */
|
|
251
|
+
inputPopup = null;
|
|
252
|
+
setInputPopup(popup) {
|
|
253
|
+
this.inputPopup = popup;
|
|
254
|
+
}
|
|
255
|
+
/* Every sentence said, oldest first. */
|
|
256
|
+
announcements = [];
|
|
257
|
+
announce(message) {
|
|
258
|
+
this.announcements.push(message);
|
|
259
|
+
}
|
|
260
|
+
messages = {};
|
|
261
|
+
setMessages(messages) {
|
|
262
|
+
this.messages = { ...this.messages, ...messages };
|
|
263
|
+
}
|
|
264
|
+
setLineTokens(tokens) {
|
|
265
|
+
this.lineTokens = tokens;
|
|
266
|
+
}
|
|
225
267
|
renderCode(container, text, options = {}) {
|
|
226
268
|
this.codeBlocks.push({ container, text, options });
|
|
227
269
|
}
|
|
@@ -265,11 +307,20 @@ export class FakeEditor {
|
|
|
265
307
|
const before = this.drawnWidgets.get(owner) ?? new Set();
|
|
266
308
|
for (const widget of widgets) {
|
|
267
309
|
if (!before.has(widget.id)) {
|
|
268
|
-
widget.render({});
|
|
310
|
+
widget.render(this.element.ownerDocument?.createElement('div') ?? {});
|
|
269
311
|
}
|
|
270
312
|
}
|
|
271
313
|
this.drawnWidgets.set(owner, new Set(widgets.map((widget) => widget.id)));
|
|
272
314
|
}
|
|
315
|
+
replacementsByOwner = new Map();
|
|
316
|
+
setReplacements(replacements, owner = 'default') {
|
|
317
|
+
if (replacements.length === 0) {
|
|
318
|
+
this.replacementsByOwner.delete(owner);
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
this.replacementsByOwner.set(owner, replacements);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
273
324
|
lineActionsByOwner = new Map();
|
|
274
325
|
setLineActions(actions, owner = 'default') {
|
|
275
326
|
if (actions.length === 0) {
|
|
@@ -367,6 +418,7 @@ export class FakeEditor {
|
|
|
367
418
|
charSize = { width: 8, height: 20 };
|
|
368
419
|
carets = new Set();
|
|
369
420
|
hovers = new Set();
|
|
421
|
+
lineHeights = new Set();
|
|
370
422
|
views = new Set();
|
|
371
423
|
keys = new Set();
|
|
372
424
|
setMarkers(markers) {
|
|
@@ -377,6 +429,28 @@ export class FakeEditor {
|
|
|
377
429
|
setInlayHints(hints) {
|
|
378
430
|
this.inlayHints = hints;
|
|
379
431
|
}
|
|
432
|
+
inlayHovers = new Set();
|
|
433
|
+
inlayHandlers = new Set();
|
|
434
|
+
/* The hint, or part of one, the last `setInlayLink` drew as a link. */
|
|
435
|
+
inlayLink = null;
|
|
436
|
+
onInlayHover(listener) {
|
|
437
|
+
return subscribe(this.inlayHovers, listener);
|
|
438
|
+
}
|
|
439
|
+
/* The pointer resting on a hint or a part of one, or leaving them. */
|
|
440
|
+
hoverInlay(id, part = null) {
|
|
441
|
+
emit(this.inlayHovers, id === null ? null : { id, part, rect: { left: 0, top: 0, right: 40, bottom: 20 } });
|
|
442
|
+
}
|
|
443
|
+
onInlayClick(handler) {
|
|
444
|
+
return subscribe(this.inlayHandlers, handler);
|
|
445
|
+
}
|
|
446
|
+
/* A press on a hint as the editor sees it first; true when a handler took it. */
|
|
447
|
+
clickInlay(click) {
|
|
448
|
+
const full = { part: null, mod: false, alt: false, shift: false, clicks: 1, touch: false, ...click };
|
|
449
|
+
return [...this.inlayHandlers].some((handler) => handler(full));
|
|
450
|
+
}
|
|
451
|
+
setInlayLink(target) {
|
|
452
|
+
this.inlayLink = target;
|
|
453
|
+
}
|
|
380
454
|
/* The suggestion after the caret now, which any change of the text takes away as the real editor does. */
|
|
381
455
|
ghost = null;
|
|
382
456
|
setGhostText(ghost) {
|
|
@@ -408,6 +482,26 @@ export class FakeEditor {
|
|
|
408
482
|
}
|
|
409
483
|
/* The selection a person made; without one the caret. */
|
|
410
484
|
selection = null;
|
|
485
|
+
/* A test supplies the measured height; this fake has no layout. */
|
|
486
|
+
contentHeight = 0;
|
|
487
|
+
setScrollTop(top) {
|
|
488
|
+
if (Number.isFinite(top) && this.getScrollTop() !== Math.max(0, top)) {
|
|
489
|
+
this.scrollTop = Math.max(0, top);
|
|
490
|
+
emit(this.views);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
getLineHeight(line) {
|
|
494
|
+
return Number.isInteger(line) && line >= 0 && line < this.text.split('\n').length ? this.charSize.height : 0;
|
|
495
|
+
}
|
|
496
|
+
getBaseLineHeight() {
|
|
497
|
+
return this.charSize.height;
|
|
498
|
+
}
|
|
499
|
+
onLineHeights(listener) {
|
|
500
|
+
return subscribe(this.lineHeights, listener);
|
|
501
|
+
}
|
|
502
|
+
getContentHeight() {
|
|
503
|
+
return this.contentHeight;
|
|
504
|
+
}
|
|
411
505
|
getSelection() {
|
|
412
506
|
return this.selection ?? { start: this.caret, end: this.caret };
|
|
413
507
|
}
|
|
@@ -512,7 +606,8 @@ export class FakeEditor {
|
|
|
512
606
|
const full = { ctrlKey: false, metaKey: false, altKey: false, shiftKey: false, preventDefault: () => undefined, ...event };
|
|
513
607
|
return [...this.keys].some((handler) => handler(full));
|
|
514
608
|
}
|
|
515
|
-
|
|
609
|
+
/* The fake keeps no undo history, so `mergeUndo` changes nothing here. It keeps no selection direction either, so a test of `mapSelections` keeping a backward selection needs the real editor. */
|
|
610
|
+
applyEdits(edits, options = {}) {
|
|
516
611
|
if (this.readOnly || edits.length === 0) {
|
|
517
612
|
return false;
|
|
518
613
|
}
|
|
@@ -539,11 +634,14 @@ export class FakeEditor {
|
|
|
539
634
|
return offset + delta;
|
|
540
635
|
};
|
|
541
636
|
const moved = others.map((range) => ({ anchor: follow(range.anchor), head: follow(range.head) }));
|
|
542
|
-
this.
|
|
543
|
-
this.
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
637
|
+
const mapped = options.mapSelections && this.getSelections().map((range) => options.mapSelections(range));
|
|
638
|
+
this.replaceText(text, 'command', mapped);
|
|
639
|
+
if (mapped === undefined) {
|
|
640
|
+
this.otherSelections = moved.map((range) => ({
|
|
641
|
+
start: positionIn(text, Math.min(range.anchor, range.head)),
|
|
642
|
+
end: positionIn(text, Math.max(range.anchor, range.head))
|
|
643
|
+
}));
|
|
644
|
+
}
|
|
547
645
|
emit(this.changes);
|
|
548
646
|
return true;
|
|
549
647
|
}
|
|
@@ -557,6 +655,9 @@ export class FakeEditor {
|
|
|
557
655
|
this.readOnly = readOnly;
|
|
558
656
|
this.readOnlyReason = reason;
|
|
559
657
|
}
|
|
658
|
+
isReadOnly() {
|
|
659
|
+
return this.readOnly;
|
|
660
|
+
}
|
|
560
661
|
/* The commands run, in order; the fake has no commands of its own to carry out. */
|
|
561
662
|
commands = [];
|
|
562
663
|
runCommand(command) {
|
|
@@ -572,8 +673,11 @@ export class FakeEditor {
|
|
|
572
673
|
this.textChanges.clear();
|
|
573
674
|
this.carets.clear();
|
|
574
675
|
this.hovers.clear();
|
|
676
|
+
this.inlayHovers.clear();
|
|
677
|
+
this.inlayHandlers.clear();
|
|
575
678
|
this.attributionHovers.clear();
|
|
576
679
|
this.views.clear();
|
|
680
|
+
this.lineHeights.clear();
|
|
577
681
|
this.keys.clear();
|
|
578
682
|
this.saves.clear();
|
|
579
683
|
this.blurs.clear();
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type EditorSearchClient } from './search-client.ts';
|
|
2
|
+
export interface FindSearchOptions {
|
|
3
|
+
readonly createClient: () => EditorSearchClient | null;
|
|
4
|
+
readonly schedule?: (callback: () => void, delay: number) => () => void;
|
|
5
|
+
readonly now?: () => number;
|
|
6
|
+
}
|
|
7
|
+
type SearchKind = 'live' | 'preview' | 'command';
|
|
8
|
+
export declare function scheduleFind(callback: () => void, delay: number): () => void;
|
|
9
|
+
export declare class FindSearchQueue {
|
|
10
|
+
private client;
|
|
11
|
+
private active;
|
|
12
|
+
private pending;
|
|
13
|
+
private cancelTimer;
|
|
14
|
+
private started;
|
|
15
|
+
private disposed;
|
|
16
|
+
private epoch;
|
|
17
|
+
private readonly options;
|
|
18
|
+
constructor(options: FindSearchOptions);
|
|
19
|
+
get busy(): boolean;
|
|
20
|
+
request<Result>(run: (client: EditorSearchClient, isCurrent: () => boolean) => Promise<Result>, kind?: SearchKind, valid?: () => boolean): Promise<Result>;
|
|
21
|
+
private now;
|
|
22
|
+
private pump;
|
|
23
|
+
release(): void;
|
|
24
|
+
dispose(): void;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { EditorSearchError } from './search-client.js';
|
|
2
|
+
export function scheduleFind(callback, delay) {
|
|
3
|
+
const timer = setTimeout(callback, delay);
|
|
4
|
+
return () => clearTimeout(timer);
|
|
5
|
+
}
|
|
6
|
+
function superseded() {
|
|
7
|
+
return new EditorSearchError('superseded', 'The find operation is no longer current.');
|
|
8
|
+
}
|
|
9
|
+
/* Commands finish atomically; short background requests reuse the worker before newer work starts. */
|
|
10
|
+
export class FindSearchQueue {
|
|
11
|
+
client;
|
|
12
|
+
active;
|
|
13
|
+
pending = [];
|
|
14
|
+
cancelTimer;
|
|
15
|
+
started = 0;
|
|
16
|
+
disposed = false;
|
|
17
|
+
epoch = 0;
|
|
18
|
+
options;
|
|
19
|
+
constructor(options) {
|
|
20
|
+
this.options = options;
|
|
21
|
+
}
|
|
22
|
+
get busy() {
|
|
23
|
+
return this.active !== undefined || this.pending.length > 0;
|
|
24
|
+
}
|
|
25
|
+
request(run, kind = 'live', valid) {
|
|
26
|
+
if (this.disposed) {
|
|
27
|
+
return Promise.reject(new EditorSearchError('disposed', 'The find session was disposed.'));
|
|
28
|
+
}
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
this.pending = this.pending.filter((job) => {
|
|
31
|
+
if (job.kind !== 'command' && (job.kind === kind || (kind !== 'preview' && job.kind === 'preview'))) {
|
|
32
|
+
job.cancelled = true;
|
|
33
|
+
job.reject(superseded());
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
return true;
|
|
37
|
+
});
|
|
38
|
+
this.pending.push({ kind, valid, run, resolve: (value) => resolve(value), reject, cancelled: false });
|
|
39
|
+
this.pending.sort((left, right) => priority(left.kind) - priority(right.kind));
|
|
40
|
+
if (this.active === undefined) {
|
|
41
|
+
this.pump();
|
|
42
|
+
}
|
|
43
|
+
else if ((kind !== 'preview' || this.active.valid?.() === false) &&
|
|
44
|
+
(this.active.kind !== 'command' || this.active.valid?.() === false) &&
|
|
45
|
+
this.cancelTimer === undefined) {
|
|
46
|
+
this.cancelTimer = (this.options.schedule ?? scheduleFind)(() => {
|
|
47
|
+
this.cancelTimer = undefined;
|
|
48
|
+
if (this.pending.length > 0 && this.active !== undefined && (this.active.kind !== 'command' || this.active.valid?.() === false)) {
|
|
49
|
+
this.active.cancelled = true;
|
|
50
|
+
this.active.reject(superseded());
|
|
51
|
+
this.client?.cancel();
|
|
52
|
+
}
|
|
53
|
+
}, Math.max(0, 200 - (this.now() - this.started)));
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
now() {
|
|
58
|
+
return this.options.now?.() ?? performance.now();
|
|
59
|
+
}
|
|
60
|
+
pump() {
|
|
61
|
+
if (this.disposed || this.active !== undefined) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const job = this.pending.shift();
|
|
65
|
+
if (job === undefined) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.active = job;
|
|
69
|
+
this.started = this.now();
|
|
70
|
+
const epoch = this.epoch;
|
|
71
|
+
const alive = () => !this.disposed && epoch === this.epoch && !job.cancelled;
|
|
72
|
+
const isCurrent = () => alive() && job.valid?.() !== false;
|
|
73
|
+
void Promise.resolve()
|
|
74
|
+
.then(() => {
|
|
75
|
+
if (!isCurrent()) {
|
|
76
|
+
throw superseded();
|
|
77
|
+
}
|
|
78
|
+
this.client ??= this.options.createClient();
|
|
79
|
+
if (this.client === null) {
|
|
80
|
+
throw new EditorSearchError('unavailable', 'Regex search needs a search worker.');
|
|
81
|
+
}
|
|
82
|
+
const client = this.client;
|
|
83
|
+
const guarded = {
|
|
84
|
+
search: (...args) => (isCurrent() ? client.search(...args) : Promise.reject(superseded())),
|
|
85
|
+
match: (...args) => (isCurrent() ? client.match(...args) : Promise.reject(superseded())),
|
|
86
|
+
next: (...args) => (isCurrent() ? client.next(...args) : Promise.reject(superseded())),
|
|
87
|
+
replacements: (...args) => (isCurrent() ? client.replacements(...args) : Promise.reject(superseded())),
|
|
88
|
+
cancel: () => client.cancel(),
|
|
89
|
+
release: () => client.release(),
|
|
90
|
+
dispose: () => client.dispose()
|
|
91
|
+
};
|
|
92
|
+
return job.run(guarded, isCurrent);
|
|
93
|
+
})
|
|
94
|
+
.then((value) => {
|
|
95
|
+
if (alive()) {
|
|
96
|
+
job.resolve(value);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
job.reject(superseded());
|
|
100
|
+
}
|
|
101
|
+
}, job.reject)
|
|
102
|
+
.finally(() => {
|
|
103
|
+
this.active = undefined;
|
|
104
|
+
this.cancelTimer?.();
|
|
105
|
+
this.cancelTimer = undefined;
|
|
106
|
+
this.pump();
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
release() {
|
|
110
|
+
this.epoch++;
|
|
111
|
+
this.active?.reject(superseded());
|
|
112
|
+
for (const job of this.pending) {
|
|
113
|
+
job.cancelled = true;
|
|
114
|
+
job.reject(superseded());
|
|
115
|
+
}
|
|
116
|
+
this.pending = [];
|
|
117
|
+
this.cancelTimer?.();
|
|
118
|
+
this.cancelTimer = undefined;
|
|
119
|
+
this.client?.release();
|
|
120
|
+
}
|
|
121
|
+
dispose() {
|
|
122
|
+
this.disposed = true;
|
|
123
|
+
this.release();
|
|
124
|
+
this.client?.dispose();
|
|
125
|
+
this.client = undefined;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function priority(kind) {
|
|
129
|
+
return kind === 'command' ? 0 : kind === 'live' ? 1 : 2;
|
|
130
|
+
}
|
package/dist/find.d.ts
CHANGED
|
@@ -1,18 +1,45 @@
|
|
|
1
|
-
import type { DocumentChange, DocumentModel } from '@adecore/editor-core';
|
|
1
|
+
import type { DocumentChange, DocumentModel, FindMatch } from '@adecore/editor-core';
|
|
2
|
+
import { type FindSearchOptions } from './find-search.ts';
|
|
2
3
|
import type { EditorFindQuery, EditorFindState } from './types.ts';
|
|
3
4
|
export interface FindMark {
|
|
4
5
|
from: number;
|
|
5
6
|
to: number;
|
|
6
7
|
}
|
|
7
8
|
export declare const FIND_LIMIT = 10000;
|
|
9
|
+
export interface FindControllerOptions extends FindSearchOptions {
|
|
10
|
+
readonly changed: (reveal?: boolean) => void;
|
|
11
|
+
}
|
|
8
12
|
export declare class FindController {
|
|
9
13
|
private query;
|
|
10
14
|
private marks;
|
|
15
|
+
private cache?;
|
|
11
16
|
private index;
|
|
17
|
+
private outside;
|
|
18
|
+
private seeking;
|
|
19
|
+
private replacing;
|
|
20
|
+
private replaceEpoch;
|
|
21
|
+
private replaced;
|
|
22
|
+
private replaceFailed;
|
|
12
23
|
private bounds;
|
|
13
24
|
pendingAnchor: number | undefined;
|
|
14
25
|
private readonly model;
|
|
15
|
-
|
|
26
|
+
private readonly options;
|
|
27
|
+
private readonly search;
|
|
28
|
+
private regexCache;
|
|
29
|
+
private snapshotMemo;
|
|
30
|
+
private retained;
|
|
31
|
+
private epoch;
|
|
32
|
+
private searching;
|
|
33
|
+
private failed;
|
|
34
|
+
private captureFailed;
|
|
35
|
+
private pendingStep;
|
|
36
|
+
private cancelSearch;
|
|
37
|
+
private cancelMatch;
|
|
38
|
+
private preview;
|
|
39
|
+
private disposed;
|
|
40
|
+
private revision;
|
|
41
|
+
private cursorRequests;
|
|
42
|
+
constructor(model: DocumentModel, options?: FindControllerOptions);
|
|
16
43
|
get activeQuery(): EditorFindQuery | null;
|
|
17
44
|
get active(): boolean;
|
|
18
45
|
get matches(): readonly FindMark[];
|
|
@@ -23,8 +50,29 @@ export declare class FindController {
|
|
|
23
50
|
to: number;
|
|
24
51
|
} | null;
|
|
25
52
|
get currentMark(): FindMark | null;
|
|
53
|
+
matchesBetween(from: number, to: number): readonly FindMark[];
|
|
54
|
+
get currentMatch(): FindMatch | null;
|
|
55
|
+
get completeMatches(): readonly FindMatch[] | null;
|
|
56
|
+
private get cachedMatches();
|
|
57
|
+
private cacheKey;
|
|
26
58
|
set(query: EditorFindQuery | null): void;
|
|
27
59
|
mapBounds(changes: readonly DocumentChange[]): void;
|
|
28
60
|
refresh(): void;
|
|
29
61
|
step(direction: 1 | -1): void;
|
|
62
|
+
private get freshRegex();
|
|
63
|
+
private resetRegex;
|
|
64
|
+
private refreshRegex;
|
|
65
|
+
private startRegex;
|
|
66
|
+
private snapshot;
|
|
67
|
+
setPreview(active: boolean): void;
|
|
68
|
+
private preparePreview;
|
|
69
|
+
ensureMatch(command?: boolean): Promise<FindMatch | null>;
|
|
70
|
+
private chooseCurrent;
|
|
71
|
+
private seek;
|
|
72
|
+
nextFromCursor(query: EditorFindQuery, offset: number, direction: 1 | -1): Promise<FindMark | null>;
|
|
73
|
+
reportReplaceFailed(failure: NonNullable<EditorFindState['replaceFailed']>): void;
|
|
74
|
+
reportReplaced(count: number): void;
|
|
75
|
+
replaceOne(replacement: string, preserveCase: boolean, canApply: () => boolean): Promise<boolean>;
|
|
76
|
+
replaceAll(replacement: string, preserveCase: boolean, canApply: () => boolean): Promise<number>;
|
|
77
|
+
dispose(): void;
|
|
30
78
|
}
|