@codemirror/autocomplete 6.7.1 → 6.8.1
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/CHANGELOG.md +12 -0
- package/dist/index.cjs +309 -291
- package/dist/index.d.cts +557 -0
- package/dist/index.d.ts +12 -2
- package/dist/index.js +310 -292
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Annotation, StateEffect, EditorSelection, codePointAt, codePointSize, fromCodePoint, Facet, combineConfig, StateField, Prec, Text, MapMode, RangeValue, RangeSet, CharCategory } from '@codemirror/state';
|
|
2
|
-
import { Direction,
|
|
2
|
+
import { Direction, logException, showTooltip, EditorView, ViewPlugin, getTooltip, Decoration, WidgetType, keymap } from '@codemirror/view';
|
|
3
3
|
import { syntaxTree, indentUnit } from '@codemirror/language';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -216,7 +216,7 @@ class FuzzyMatcher {
|
|
|
216
216
|
// is. See `Penalty` above.
|
|
217
217
|
match(word) {
|
|
218
218
|
if (this.pattern.length == 0)
|
|
219
|
-
return [-100 /*
|
|
219
|
+
return [-100 /* NotFull */];
|
|
220
220
|
if (word.length < this.pattern.length)
|
|
221
221
|
return null;
|
|
222
222
|
let { chars, folded, any, precise, byWord } = this;
|
|
@@ -224,17 +224,17 @@ class FuzzyMatcher {
|
|
|
224
224
|
// at the start
|
|
225
225
|
if (chars.length == 1) {
|
|
226
226
|
let first = codePointAt(word, 0), firstSize = codePointSize(first);
|
|
227
|
-
let score = firstSize == word.length ? 0 : -100 /*
|
|
227
|
+
let score = firstSize == word.length ? 0 : -100 /* NotFull */;
|
|
228
228
|
if (first == chars[0]) ;
|
|
229
229
|
else if (first == folded[0])
|
|
230
|
-
score += -200 /*
|
|
230
|
+
score += -200 /* CaseFold */;
|
|
231
231
|
else
|
|
232
232
|
return null;
|
|
233
233
|
return [score, 0, firstSize];
|
|
234
234
|
}
|
|
235
235
|
let direct = word.indexOf(this.pattern);
|
|
236
236
|
if (direct == 0)
|
|
237
|
-
return [word.length == this.pattern.length ? 0 : -100 /*
|
|
237
|
+
return [word.length == this.pattern.length ? 0 : -100 /* NotFull */, 0, this.pattern.length];
|
|
238
238
|
let len = chars.length, anyTo = 0;
|
|
239
239
|
if (direct < 0) {
|
|
240
240
|
for (let i = 0, e = Math.min(word.length, 200); i < e && anyTo < len;) {
|
|
@@ -258,7 +258,7 @@ class FuzzyMatcher {
|
|
|
258
258
|
let adjacentTo = 0, adjacentStart = -1, adjacentEnd = -1;
|
|
259
259
|
let hasLower = /[a-z]/.test(word), wordAdjacent = true;
|
|
260
260
|
// Go over the option's text, scanning for the various kinds of matches
|
|
261
|
-
for (let i = 0, e = Math.min(word.length, 200), prevType = 0 /*
|
|
261
|
+
for (let i = 0, e = Math.min(word.length, 200), prevType = 0 /* NonWord */; i < e && byWordTo < len;) {
|
|
262
262
|
let next = codePointAt(word, i);
|
|
263
263
|
if (direct < 0) {
|
|
264
264
|
if (preciseTo < len && next == chars[preciseTo])
|
|
@@ -276,9 +276,9 @@ class FuzzyMatcher {
|
|
|
276
276
|
}
|
|
277
277
|
}
|
|
278
278
|
let ch, type = next < 0xff
|
|
279
|
-
? (next >= 48 && next <= 57 || next >= 97 && next <= 122 ? 2 /*
|
|
280
|
-
: ((ch = fromCodePoint(next)) != ch.toLowerCase() ? 1 /*
|
|
281
|
-
if (!i || type == 1 /*
|
|
279
|
+
? (next >= 48 && next <= 57 || next >= 97 && next <= 122 ? 2 /* Lower */ : next >= 65 && next <= 90 ? 1 /* Upper */ : 0 /* NonWord */)
|
|
280
|
+
: ((ch = fromCodePoint(next)) != ch.toLowerCase() ? 1 /* Upper */ : ch != ch.toUpperCase() ? 2 /* Lower */ : 0 /* NonWord */);
|
|
281
|
+
if (!i || type == 1 /* Upper */ && hasLower || prevType == 0 /* NonWord */ && type != 0 /* NonWord */) {
|
|
282
282
|
if (chars[byWordTo] == next || (folded[byWordTo] == next && (byWordFolded = true)))
|
|
283
283
|
byWord[byWordTo++] = i;
|
|
284
284
|
else if (byWord.length)
|
|
@@ -288,17 +288,17 @@ class FuzzyMatcher {
|
|
|
288
288
|
i += codePointSize(next);
|
|
289
289
|
}
|
|
290
290
|
if (byWordTo == len && byWord[0] == 0 && wordAdjacent)
|
|
291
|
-
return this.result(-100 /*
|
|
291
|
+
return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0), byWord, word);
|
|
292
292
|
if (adjacentTo == len && adjacentStart == 0)
|
|
293
|
-
return [-200 /*
|
|
293
|
+
return [-200 /* CaseFold */ - word.length + (adjacentEnd == word.length ? 0 : -100 /* NotFull */), 0, adjacentEnd];
|
|
294
294
|
if (direct > -1)
|
|
295
|
-
return [-700 /*
|
|
295
|
+
return [-700 /* NotStart */ - word.length, direct, direct + this.pattern.length];
|
|
296
296
|
if (adjacentTo == len)
|
|
297
|
-
return [-200 /*
|
|
297
|
+
return [-200 /* CaseFold */ + -700 /* NotStart */ - word.length, adjacentStart, adjacentEnd];
|
|
298
298
|
if (byWordTo == len)
|
|
299
|
-
return this.result(-100 /*
|
|
300
|
-
(wordAdjacent ? 0 : -1100 /*
|
|
301
|
-
return chars.length == 2 ? null : this.result((any[0] ? -700 /*
|
|
299
|
+
return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0) + -700 /* NotStart */ +
|
|
300
|
+
(wordAdjacent ? 0 : -1100 /* Gap */), byWord, word);
|
|
301
|
+
return chars.length == 2 ? null : this.result((any[0] ? -700 /* NotStart */ : 0) + -200 /* CaseFold */ + -1100 /* Gap */, any, word);
|
|
302
302
|
}
|
|
303
303
|
result(score, positions, word) {
|
|
304
304
|
let result = [score - word.length], i = 1;
|
|
@@ -356,11 +356,11 @@ function defaultPositionInfo(view, list, option, info, space) {
|
|
|
356
356
|
left = true;
|
|
357
357
|
if (infoWidth <= (left ? spaceLeft : spaceRight)) {
|
|
358
358
|
offset = Math.max(space.top, Math.min(option.top, space.bottom - infoHeight)) - list.top;
|
|
359
|
-
maxWidth = Math.min(400 /*
|
|
359
|
+
maxWidth = Math.min(400 /* Width */, left ? spaceLeft : spaceRight);
|
|
360
360
|
}
|
|
361
361
|
else {
|
|
362
362
|
narrow = true;
|
|
363
|
-
maxWidth = Math.min(400 /*
|
|
363
|
+
maxWidth = Math.min(400 /* Width */, (rtl ? list.right : space.right - list.left) - 30 /* Margin */);
|
|
364
364
|
let spaceBelow = space.bottom - list.bottom;
|
|
365
365
|
if (spaceBelow >= infoHeight || spaceBelow > list.top) { // Below the completion
|
|
366
366
|
offset = option.bottom - list.top;
|
|
@@ -376,232 +376,6 @@ function defaultPositionInfo(view, list, option, info, space) {
|
|
|
376
376
|
};
|
|
377
377
|
}
|
|
378
378
|
|
|
379
|
-
/**
|
|
380
|
-
Returns a command that moves the completion selection forward or
|
|
381
|
-
backward by the given amount.
|
|
382
|
-
*/
|
|
383
|
-
function moveCompletionSelection(forward, by = "option") {
|
|
384
|
-
return (view) => {
|
|
385
|
-
let cState = view.state.field(completionState, false);
|
|
386
|
-
if (!cState || !cState.open || cState.open.disabled ||
|
|
387
|
-
Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay)
|
|
388
|
-
return false;
|
|
389
|
-
let step = 1, tooltip;
|
|
390
|
-
if (by == "page" && (tooltip = getTooltip(view, cState.open.tooltip)))
|
|
391
|
-
step = Math.max(2, Math.floor(tooltip.dom.offsetHeight /
|
|
392
|
-
tooltip.dom.querySelector("li").offsetHeight) - 1);
|
|
393
|
-
let { length } = cState.open.options;
|
|
394
|
-
let selected = cState.open.selected > -1 ? cState.open.selected + step * (forward ? 1 : -1) : forward ? 0 : length - 1;
|
|
395
|
-
if (selected < 0)
|
|
396
|
-
selected = by == "page" ? 0 : length - 1;
|
|
397
|
-
else if (selected >= length)
|
|
398
|
-
selected = by == "page" ? length - 1 : 0;
|
|
399
|
-
view.dispatch({ effects: setSelectedEffect.of(selected) });
|
|
400
|
-
return true;
|
|
401
|
-
};
|
|
402
|
-
}
|
|
403
|
-
/**
|
|
404
|
-
Accept the current completion.
|
|
405
|
-
*/
|
|
406
|
-
const acceptCompletion = (view) => {
|
|
407
|
-
let cState = view.state.field(completionState, false);
|
|
408
|
-
if (view.state.readOnly || !cState || !cState.open || cState.open.selected < 0 ||
|
|
409
|
-
Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay)
|
|
410
|
-
return false;
|
|
411
|
-
if (!cState.open.disabled)
|
|
412
|
-
return applyCompletion(view, cState.open.options[cState.open.selected]);
|
|
413
|
-
return true;
|
|
414
|
-
};
|
|
415
|
-
/**
|
|
416
|
-
Explicitly start autocompletion.
|
|
417
|
-
*/
|
|
418
|
-
const startCompletion = (view) => {
|
|
419
|
-
let cState = view.state.field(completionState, false);
|
|
420
|
-
if (!cState)
|
|
421
|
-
return false;
|
|
422
|
-
view.dispatch({ effects: startCompletionEffect.of(true) });
|
|
423
|
-
return true;
|
|
424
|
-
};
|
|
425
|
-
/**
|
|
426
|
-
Close the currently active completion.
|
|
427
|
-
*/
|
|
428
|
-
const closeCompletion = (view) => {
|
|
429
|
-
let cState = view.state.field(completionState, false);
|
|
430
|
-
if (!cState || !cState.active.some(a => a.state != 0 /* State.Inactive */))
|
|
431
|
-
return false;
|
|
432
|
-
view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
433
|
-
return true;
|
|
434
|
-
};
|
|
435
|
-
class RunningQuery {
|
|
436
|
-
constructor(active, context) {
|
|
437
|
-
this.active = active;
|
|
438
|
-
this.context = context;
|
|
439
|
-
this.time = Date.now();
|
|
440
|
-
this.updates = [];
|
|
441
|
-
// Note that 'undefined' means 'not done yet', whereas 'null' means
|
|
442
|
-
// 'query returned null'.
|
|
443
|
-
this.done = undefined;
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
const DebounceTime = 50, MaxUpdateCount = 50, MinAbortTime = 1000;
|
|
447
|
-
const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
448
|
-
constructor(view) {
|
|
449
|
-
this.view = view;
|
|
450
|
-
this.debounceUpdate = -1;
|
|
451
|
-
this.running = [];
|
|
452
|
-
this.debounceAccept = -1;
|
|
453
|
-
this.composing = 0 /* CompositionState.None */;
|
|
454
|
-
for (let active of view.state.field(completionState).active)
|
|
455
|
-
if (active.state == 1 /* State.Pending */)
|
|
456
|
-
this.startQuery(active);
|
|
457
|
-
}
|
|
458
|
-
update(update) {
|
|
459
|
-
let cState = update.state.field(completionState);
|
|
460
|
-
if (!update.selectionSet && !update.docChanged && update.startState.field(completionState) == cState)
|
|
461
|
-
return;
|
|
462
|
-
let doesReset = update.transactions.some(tr => {
|
|
463
|
-
return (tr.selection || tr.docChanged) && !getUserEvent(tr);
|
|
464
|
-
});
|
|
465
|
-
for (let i = 0; i < this.running.length; i++) {
|
|
466
|
-
let query = this.running[i];
|
|
467
|
-
if (doesReset ||
|
|
468
|
-
query.updates.length + update.transactions.length > MaxUpdateCount && Date.now() - query.time > MinAbortTime) {
|
|
469
|
-
for (let handler of query.context.abortListeners) {
|
|
470
|
-
try {
|
|
471
|
-
handler();
|
|
472
|
-
}
|
|
473
|
-
catch (e) {
|
|
474
|
-
logException(this.view.state, e);
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
query.context.abortListeners = null;
|
|
478
|
-
this.running.splice(i--, 1);
|
|
479
|
-
}
|
|
480
|
-
else {
|
|
481
|
-
query.updates.push(...update.transactions);
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
if (this.debounceUpdate > -1)
|
|
485
|
-
clearTimeout(this.debounceUpdate);
|
|
486
|
-
this.debounceUpdate = cState.active.some(a => a.state == 1 /* State.Pending */ && !this.running.some(q => q.active.source == a.source))
|
|
487
|
-
? setTimeout(() => this.startUpdate(), DebounceTime) : -1;
|
|
488
|
-
if (this.composing != 0 /* CompositionState.None */)
|
|
489
|
-
for (let tr of update.transactions) {
|
|
490
|
-
if (getUserEvent(tr) == "input")
|
|
491
|
-
this.composing = 2 /* CompositionState.Changed */;
|
|
492
|
-
else if (this.composing == 2 /* CompositionState.Changed */ && tr.selection)
|
|
493
|
-
this.composing = 3 /* CompositionState.ChangedAndMoved */;
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
startUpdate() {
|
|
497
|
-
this.debounceUpdate = -1;
|
|
498
|
-
let { state } = this.view, cState = state.field(completionState);
|
|
499
|
-
for (let active of cState.active) {
|
|
500
|
-
if (active.state == 1 /* State.Pending */ && !this.running.some(r => r.active.source == active.source))
|
|
501
|
-
this.startQuery(active);
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
startQuery(active) {
|
|
505
|
-
let { state } = this.view, pos = cur(state);
|
|
506
|
-
let context = new CompletionContext(state, pos, active.explicitPos == pos);
|
|
507
|
-
let pending = new RunningQuery(active, context);
|
|
508
|
-
this.running.push(pending);
|
|
509
|
-
Promise.resolve(active.source(context)).then(result => {
|
|
510
|
-
if (!pending.context.aborted) {
|
|
511
|
-
pending.done = result || null;
|
|
512
|
-
this.scheduleAccept();
|
|
513
|
-
}
|
|
514
|
-
}, err => {
|
|
515
|
-
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
516
|
-
logException(this.view.state, err);
|
|
517
|
-
});
|
|
518
|
-
}
|
|
519
|
-
scheduleAccept() {
|
|
520
|
-
if (this.running.every(q => q.done !== undefined))
|
|
521
|
-
this.accept();
|
|
522
|
-
else if (this.debounceAccept < 0)
|
|
523
|
-
this.debounceAccept = setTimeout(() => this.accept(), DebounceTime);
|
|
524
|
-
}
|
|
525
|
-
// For each finished query in this.running, try to create a result
|
|
526
|
-
// or, if appropriate, restart the query.
|
|
527
|
-
accept() {
|
|
528
|
-
var _a;
|
|
529
|
-
if (this.debounceAccept > -1)
|
|
530
|
-
clearTimeout(this.debounceAccept);
|
|
531
|
-
this.debounceAccept = -1;
|
|
532
|
-
let updated = [];
|
|
533
|
-
let conf = this.view.state.facet(completionConfig);
|
|
534
|
-
for (let i = 0; i < this.running.length; i++) {
|
|
535
|
-
let query = this.running[i];
|
|
536
|
-
if (query.done === undefined)
|
|
537
|
-
continue;
|
|
538
|
-
this.running.splice(i--, 1);
|
|
539
|
-
if (query.done) {
|
|
540
|
-
let active = new ActiveResult(query.active.source, query.active.explicitPos, query.done, query.done.from, (_a = query.done.to) !== null && _a !== void 0 ? _a : cur(query.updates.length ? query.updates[0].startState : this.view.state));
|
|
541
|
-
// Replay the transactions that happened since the start of
|
|
542
|
-
// the request and see if that preserves the result
|
|
543
|
-
for (let tr of query.updates)
|
|
544
|
-
active = active.update(tr, conf);
|
|
545
|
-
if (active.hasResult()) {
|
|
546
|
-
updated.push(active);
|
|
547
|
-
continue;
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
let current = this.view.state.field(completionState).active.find(a => a.source == query.active.source);
|
|
551
|
-
if (current && current.state == 1 /* State.Pending */) {
|
|
552
|
-
if (query.done == null) {
|
|
553
|
-
// Explicitly failed. Should clear the pending status if it
|
|
554
|
-
// hasn't been re-set in the meantime.
|
|
555
|
-
let active = new ActiveSource(query.active.source, 0 /* State.Inactive */);
|
|
556
|
-
for (let tr of query.updates)
|
|
557
|
-
active = active.update(tr, conf);
|
|
558
|
-
if (active.state != 1 /* State.Pending */)
|
|
559
|
-
updated.push(active);
|
|
560
|
-
}
|
|
561
|
-
else {
|
|
562
|
-
// Cleared by subsequent transactions. Restart.
|
|
563
|
-
this.startQuery(current);
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
if (updated.length)
|
|
568
|
-
this.view.dispatch({ effects: setActiveEffect.of(updated) });
|
|
569
|
-
}
|
|
570
|
-
}, {
|
|
571
|
-
eventHandlers: {
|
|
572
|
-
blur(event) {
|
|
573
|
-
let state = this.view.state.field(completionState, false);
|
|
574
|
-
if (state && state.tooltip && this.view.state.facet(completionConfig).closeOnBlur) {
|
|
575
|
-
let dialog = state.open && getTooltip(this.view, state.open.tooltip);
|
|
576
|
-
if (!dialog || !dialog.dom.contains(event.relatedTarget))
|
|
577
|
-
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
578
|
-
}
|
|
579
|
-
},
|
|
580
|
-
compositionstart() {
|
|
581
|
-
this.composing = 1 /* CompositionState.Started */;
|
|
582
|
-
},
|
|
583
|
-
compositionend() {
|
|
584
|
-
if (this.composing == 3 /* CompositionState.ChangedAndMoved */) {
|
|
585
|
-
// Safari fires compositionend events synchronously, possibly
|
|
586
|
-
// from inside an update, so dispatch asynchronously to avoid reentrancy
|
|
587
|
-
setTimeout(() => this.view.dispatch({ effects: startCompletionEffect.of(false) }), 20);
|
|
588
|
-
}
|
|
589
|
-
this.composing = 0 /* CompositionState.None */;
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
});
|
|
593
|
-
function applyCompletion(view, option) {
|
|
594
|
-
const apply = option.completion.apply || option.completion.label;
|
|
595
|
-
let result = view.state.field(completionState).active.find(a => a.source == option.source);
|
|
596
|
-
if (!(result instanceof ActiveResult))
|
|
597
|
-
return false;
|
|
598
|
-
if (typeof apply == "string")
|
|
599
|
-
view.dispatch(Object.assign(Object.assign({}, insertCompletionText(view.state, apply, result.from, result.to)), { annotations: pickedCompletion.of(option.completion) }));
|
|
600
|
-
else
|
|
601
|
-
apply(view, option.completion, result.from, result.to);
|
|
602
|
-
return true;
|
|
603
|
-
}
|
|
604
|
-
|
|
605
379
|
function optionContent(config) {
|
|
606
380
|
let content = config.addToOptions.slice();
|
|
607
381
|
if (config.icons)
|
|
@@ -661,10 +435,12 @@ function rangeAroundSelected(total, selected, max) {
|
|
|
661
435
|
return { from: total - (off + 1) * max, to: total - off * max };
|
|
662
436
|
}
|
|
663
437
|
class CompletionTooltip {
|
|
664
|
-
constructor(view, stateField) {
|
|
438
|
+
constructor(view, stateField, applyCompletion) {
|
|
665
439
|
this.view = view;
|
|
666
440
|
this.stateField = stateField;
|
|
441
|
+
this.applyCompletion = applyCompletion;
|
|
667
442
|
this.info = null;
|
|
443
|
+
this.infoDestroy = null;
|
|
668
444
|
this.placeInfoReq = {
|
|
669
445
|
read: () => this.measureInfo(),
|
|
670
446
|
write: (pos) => this.placeInfo(pos),
|
|
@@ -685,7 +461,7 @@ class CompletionTooltip {
|
|
|
685
461
|
this.dom.addEventListener("mousedown", (e) => {
|
|
686
462
|
for (let dom = e.target, match; dom && dom != this.dom; dom = dom.parentNode) {
|
|
687
463
|
if (dom.nodeName == "LI" && (match = /-(\d+)$/.exec(dom.id)) && +match[1] < options.length) {
|
|
688
|
-
applyCompletion(view, options[+match[1]]);
|
|
464
|
+
this.applyCompletion(view, options[+match[1]]);
|
|
689
465
|
e.preventDefault();
|
|
690
466
|
return;
|
|
691
467
|
}
|
|
@@ -744,33 +520,39 @@ class CompletionTooltip {
|
|
|
744
520
|
});
|
|
745
521
|
}
|
|
746
522
|
if (this.updateSelectedOption(open.selected)) {
|
|
747
|
-
|
|
748
|
-
this.info.remove();
|
|
749
|
-
this.info = null;
|
|
750
|
-
}
|
|
523
|
+
this.destroyInfo();
|
|
751
524
|
let { completion } = open.options[open.selected];
|
|
752
525
|
let { info } = completion;
|
|
753
526
|
if (!info)
|
|
754
527
|
return;
|
|
755
|
-
let infoResult = typeof info ===
|
|
528
|
+
let infoResult = typeof info === "string" ? document.createTextNode(info) : info(completion);
|
|
756
529
|
if (!infoResult)
|
|
757
530
|
return;
|
|
758
|
-
if (
|
|
759
|
-
infoResult.then(
|
|
760
|
-
if (
|
|
761
|
-
this.addInfoPane(
|
|
531
|
+
if ("then" in infoResult) {
|
|
532
|
+
infoResult.then(obj => {
|
|
533
|
+
if (obj && this.view.state.field(this.stateField, false) == cState)
|
|
534
|
+
this.addInfoPane(obj, completion);
|
|
762
535
|
}).catch(e => logException(this.view.state, e, "completion info"));
|
|
763
536
|
}
|
|
764
537
|
else {
|
|
765
|
-
this.addInfoPane(infoResult);
|
|
538
|
+
this.addInfoPane(infoResult, completion);
|
|
766
539
|
}
|
|
767
540
|
}
|
|
768
541
|
}
|
|
769
|
-
addInfoPane(content) {
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
542
|
+
addInfoPane(content, completion) {
|
|
543
|
+
this.destroyInfo();
|
|
544
|
+
let wrap = this.info = document.createElement("div");
|
|
545
|
+
wrap.className = "cm-tooltip cm-completionInfo";
|
|
546
|
+
if (content.nodeType != null) {
|
|
547
|
+
wrap.appendChild(content);
|
|
548
|
+
this.infoDestroy = null;
|
|
549
|
+
}
|
|
550
|
+
else {
|
|
551
|
+
let { dom, destroy } = content;
|
|
552
|
+
wrap.appendChild(dom);
|
|
553
|
+
this.infoDestroy = destroy || null;
|
|
554
|
+
}
|
|
555
|
+
this.dom.appendChild(wrap);
|
|
774
556
|
this.view.requestMeasure(this.placeInfoReq);
|
|
775
557
|
}
|
|
776
558
|
updateSelectedOption(selected) {
|
|
@@ -863,11 +645,22 @@ class CompletionTooltip {
|
|
|
863
645
|
ul.classList.add("cm-completionListIncompleteBottom");
|
|
864
646
|
return ul;
|
|
865
647
|
}
|
|
648
|
+
destroyInfo() {
|
|
649
|
+
if (this.info) {
|
|
650
|
+
if (this.infoDestroy)
|
|
651
|
+
this.infoDestroy();
|
|
652
|
+
this.info.remove();
|
|
653
|
+
this.info = null;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
destroy() {
|
|
657
|
+
this.destroyInfo();
|
|
658
|
+
}
|
|
866
659
|
}
|
|
867
660
|
// We allocate a new function instance every time the completion
|
|
868
661
|
// changes to force redrawing/repositioning of the tooltip
|
|
869
|
-
function completionTooltip(stateField) {
|
|
870
|
-
return (view) => new CompletionTooltip(view, stateField);
|
|
662
|
+
function completionTooltip(stateField, applyCompletion) {
|
|
663
|
+
return (view) => new CompletionTooltip(view, stateField, applyCompletion);
|
|
871
664
|
}
|
|
872
665
|
function scrollIntoView(container, element) {
|
|
873
666
|
let parent = container.getBoundingClientRect();
|
|
@@ -934,9 +727,10 @@ function sortOptions(active, state) {
|
|
|
934
727
|
let result = [], prev = null;
|
|
935
728
|
let compare = state.facet(completionConfig).compareCompletions;
|
|
936
729
|
for (let opt of options.sort((a, b) => (b.score - a.score) || compare(a.completion, b.completion))) {
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
prev.
|
|
730
|
+
let cur = opt.completion;
|
|
731
|
+
if (!prev || prev.label != cur.label || prev.detail != cur.detail ||
|
|
732
|
+
(prev.type != null && cur.type != null && prev.type != cur.type) ||
|
|
733
|
+
prev.apply != cur.apply || prev.boost != cur.boost)
|
|
940
734
|
result.push(opt);
|
|
941
735
|
else if (score(opt.completion) > score(prev))
|
|
942
736
|
result[result.length - 1] = opt;
|
|
@@ -960,7 +754,7 @@ class CompletionDialog {
|
|
|
960
754
|
static build(active, state, id, prev, conf) {
|
|
961
755
|
let options = sortOptions(active, state);
|
|
962
756
|
if (!options.length) {
|
|
963
|
-
return prev && active.some(a => a.state == 1 /*
|
|
757
|
+
return prev && active.some(a => a.state == 1 /* Pending */) ?
|
|
964
758
|
new CompletionDialog(prev.options, prev.attrs, prev.tooltip, prev.timestamp, prev.selected, true) : null;
|
|
965
759
|
}
|
|
966
760
|
let selected = state.facet(completionConfig).selectOnOpen ? 0 : -1;
|
|
@@ -974,7 +768,7 @@ class CompletionDialog {
|
|
|
974
768
|
}
|
|
975
769
|
return new CompletionDialog(options, makeAttrs(id, selected), {
|
|
976
770
|
pos: active.reduce((a, b) => b.hasResult() ? Math.min(a, b.from) : a, 1e8),
|
|
977
|
-
create: completionTooltip(completionState),
|
|
771
|
+
create: completionTooltip(completionState, applyCompletion),
|
|
978
772
|
above: conf.aboveCursor,
|
|
979
773
|
}, prev ? prev.timestamp : Date.now(), selected, false);
|
|
980
774
|
}
|
|
@@ -997,7 +791,7 @@ class CompletionState {
|
|
|
997
791
|
state.languageDataAt("autocomplete", cur(state)).map(asSource);
|
|
998
792
|
let active = sources.map(source => {
|
|
999
793
|
let value = this.active.find(s => s.source == source) ||
|
|
1000
|
-
new ActiveSource(source, this.active.some(a => a.state != 0 /*
|
|
794
|
+
new ActiveSource(source, this.active.some(a => a.state != 0 /* Inactive */) ? 1 /* Pending */ : 0 /* Inactive */);
|
|
1001
795
|
return value.update(tr, conf);
|
|
1002
796
|
});
|
|
1003
797
|
if (active.length == this.active.length && active.every((a, i) => a == this.active[i]))
|
|
@@ -1008,10 +802,10 @@ class CompletionState {
|
|
|
1008
802
|
if (tr.selection || active.some(a => a.hasResult() && tr.changes.touchesRange(a.from, a.to)) ||
|
|
1009
803
|
!sameResults(active, this.active))
|
|
1010
804
|
open = CompletionDialog.build(active, state, this.id, open, conf);
|
|
1011
|
-
else if (open && open.disabled && !active.some(a => a.state == 1 /*
|
|
805
|
+
else if (open && open.disabled && !active.some(a => a.state == 1 /* Pending */))
|
|
1012
806
|
open = null;
|
|
1013
|
-
if (!open && active.every(a => a.state != 1 /*
|
|
1014
|
-
active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /*
|
|
807
|
+
if (!open && active.every(a => a.state != 1 /* Pending */) && active.some(a => a.hasResult()))
|
|
808
|
+
active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /* Inactive */) : a);
|
|
1015
809
|
for (let effect of tr.effects)
|
|
1016
810
|
if (effect.is(setSelectedEffect))
|
|
1017
811
|
open = open && open.setSelected(effect.value, this.id);
|
|
@@ -1065,13 +859,13 @@ class ActiveSource {
|
|
|
1065
859
|
value = value.handleUserEvent(tr, event, conf);
|
|
1066
860
|
else if (tr.docChanged)
|
|
1067
861
|
value = value.handleChange(tr);
|
|
1068
|
-
else if (tr.selection && value.state != 0 /*
|
|
1069
|
-
value = new ActiveSource(value.source, 0 /*
|
|
862
|
+
else if (tr.selection && value.state != 0 /* Inactive */)
|
|
863
|
+
value = new ActiveSource(value.source, 0 /* Inactive */);
|
|
1070
864
|
for (let effect of tr.effects) {
|
|
1071
865
|
if (effect.is(startCompletionEffect))
|
|
1072
|
-
value = new ActiveSource(value.source, 1 /*
|
|
866
|
+
value = new ActiveSource(value.source, 1 /* Pending */, effect.value ? cur(tr.state) : -1);
|
|
1073
867
|
else if (effect.is(closeCompletionEffect))
|
|
1074
|
-
value = new ActiveSource(value.source, 0 /*
|
|
868
|
+
value = new ActiveSource(value.source, 0 /* Inactive */);
|
|
1075
869
|
else if (effect.is(setActiveEffect))
|
|
1076
870
|
for (let active of effect.value)
|
|
1077
871
|
if (active.source == value.source)
|
|
@@ -1080,10 +874,10 @@ class ActiveSource {
|
|
|
1080
874
|
return value;
|
|
1081
875
|
}
|
|
1082
876
|
handleUserEvent(tr, type, conf) {
|
|
1083
|
-
return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /*
|
|
877
|
+
return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* Pending */);
|
|
1084
878
|
}
|
|
1085
879
|
handleChange(tr) {
|
|
1086
|
-
return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /*
|
|
880
|
+
return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
|
|
1087
881
|
}
|
|
1088
882
|
map(changes) {
|
|
1089
883
|
return changes.empty || this.explicitPos < 0 ? this : new ActiveSource(this.source, this.state, changes.mapPos(this.explicitPos));
|
|
@@ -1091,7 +885,7 @@ class ActiveSource {
|
|
|
1091
885
|
}
|
|
1092
886
|
class ActiveResult extends ActiveSource {
|
|
1093
887
|
constructor(source, explicitPos, result, from, to) {
|
|
1094
|
-
super(source, 2 /*
|
|
888
|
+
super(source, 2 /* Result */, explicitPos);
|
|
1095
889
|
this.result = result;
|
|
1096
890
|
this.from = from;
|
|
1097
891
|
this.to = to;
|
|
@@ -1104,17 +898,17 @@ class ActiveResult extends ActiveSource {
|
|
|
1104
898
|
if ((this.explicitPos < 0 ? pos <= from : pos < this.from) ||
|
|
1105
899
|
pos > to ||
|
|
1106
900
|
type == "delete" && cur(tr.startState) == this.from)
|
|
1107
|
-
return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /*
|
|
901
|
+
return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* Pending */ : 0 /* Inactive */);
|
|
1108
902
|
let explicitPos = this.explicitPos < 0 ? -1 : tr.changes.mapPos(this.explicitPos), updated;
|
|
1109
903
|
if (checkValid(this.result.validFor, tr.state, from, to))
|
|
1110
904
|
return new ActiveResult(this.source, explicitPos, this.result, from, to);
|
|
1111
905
|
if (this.result.update &&
|
|
1112
906
|
(updated = this.result.update(this.result, from, to, new CompletionContext(tr.state, pos, explicitPos >= 0))))
|
|
1113
907
|
return new ActiveResult(this.source, explicitPos, updated, updated.from, (_a = updated.to) !== null && _a !== void 0 ? _a : cur(tr.state));
|
|
1114
|
-
return new ActiveSource(this.source, 1 /*
|
|
908
|
+
return new ActiveSource(this.source, 1 /* Pending */, explicitPos);
|
|
1115
909
|
}
|
|
1116
910
|
handleChange(tr) {
|
|
1117
|
-
return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /*
|
|
911
|
+
return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
|
|
1118
912
|
}
|
|
1119
913
|
map(mapping) {
|
|
1120
914
|
return mapping.empty ? this :
|
|
@@ -1139,6 +933,230 @@ const completionState = /*@__PURE__*/StateField.define({
|
|
|
1139
933
|
EditorView.contentAttributes.from(f, state => state.attrs)
|
|
1140
934
|
]
|
|
1141
935
|
});
|
|
936
|
+
function applyCompletion(view, option) {
|
|
937
|
+
const apply = option.completion.apply || option.completion.label;
|
|
938
|
+
let result = view.state.field(completionState).active.find(a => a.source == option.source);
|
|
939
|
+
if (!(result instanceof ActiveResult))
|
|
940
|
+
return false;
|
|
941
|
+
if (typeof apply == "string")
|
|
942
|
+
view.dispatch(Object.assign(Object.assign({}, insertCompletionText(view.state, apply, result.from, result.to)), { annotations: pickedCompletion.of(option.completion) }));
|
|
943
|
+
else
|
|
944
|
+
apply(view, option.completion, result.from, result.to);
|
|
945
|
+
return true;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
/**
|
|
949
|
+
Returns a command that moves the completion selection forward or
|
|
950
|
+
backward by the given amount.
|
|
951
|
+
*/
|
|
952
|
+
function moveCompletionSelection(forward, by = "option") {
|
|
953
|
+
return (view) => {
|
|
954
|
+
let cState = view.state.field(completionState, false);
|
|
955
|
+
if (!cState || !cState.open || cState.open.disabled ||
|
|
956
|
+
Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay)
|
|
957
|
+
return false;
|
|
958
|
+
let step = 1, tooltip;
|
|
959
|
+
if (by == "page" && (tooltip = getTooltip(view, cState.open.tooltip)))
|
|
960
|
+
step = Math.max(2, Math.floor(tooltip.dom.offsetHeight /
|
|
961
|
+
tooltip.dom.querySelector("li").offsetHeight) - 1);
|
|
962
|
+
let { length } = cState.open.options;
|
|
963
|
+
let selected = cState.open.selected > -1 ? cState.open.selected + step * (forward ? 1 : -1) : forward ? 0 : length - 1;
|
|
964
|
+
if (selected < 0)
|
|
965
|
+
selected = by == "page" ? 0 : length - 1;
|
|
966
|
+
else if (selected >= length)
|
|
967
|
+
selected = by == "page" ? length - 1 : 0;
|
|
968
|
+
view.dispatch({ effects: setSelectedEffect.of(selected) });
|
|
969
|
+
return true;
|
|
970
|
+
};
|
|
971
|
+
}
|
|
972
|
+
/**
|
|
973
|
+
Accept the current completion.
|
|
974
|
+
*/
|
|
975
|
+
const acceptCompletion = (view) => {
|
|
976
|
+
let cState = view.state.field(completionState, false);
|
|
977
|
+
if (view.state.readOnly || !cState || !cState.open || cState.open.selected < 0 || cState.open.disabled ||
|
|
978
|
+
Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay)
|
|
979
|
+
return false;
|
|
980
|
+
return applyCompletion(view, cState.open.options[cState.open.selected]);
|
|
981
|
+
};
|
|
982
|
+
/**
|
|
983
|
+
Explicitly start autocompletion.
|
|
984
|
+
*/
|
|
985
|
+
const startCompletion = (view) => {
|
|
986
|
+
let cState = view.state.field(completionState, false);
|
|
987
|
+
if (!cState)
|
|
988
|
+
return false;
|
|
989
|
+
view.dispatch({ effects: startCompletionEffect.of(true) });
|
|
990
|
+
return true;
|
|
991
|
+
};
|
|
992
|
+
/**
|
|
993
|
+
Close the currently active completion.
|
|
994
|
+
*/
|
|
995
|
+
const closeCompletion = (view) => {
|
|
996
|
+
let cState = view.state.field(completionState, false);
|
|
997
|
+
if (!cState || !cState.active.some(a => a.state != 0 /* Inactive */))
|
|
998
|
+
return false;
|
|
999
|
+
view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
1000
|
+
return true;
|
|
1001
|
+
};
|
|
1002
|
+
class RunningQuery {
|
|
1003
|
+
constructor(active, context) {
|
|
1004
|
+
this.active = active;
|
|
1005
|
+
this.context = context;
|
|
1006
|
+
this.time = Date.now();
|
|
1007
|
+
this.updates = [];
|
|
1008
|
+
// Note that 'undefined' means 'not done yet', whereas 'null' means
|
|
1009
|
+
// 'query returned null'.
|
|
1010
|
+
this.done = undefined;
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
const DebounceTime = 50, MaxUpdateCount = 50, MinAbortTime = 1000;
|
|
1014
|
+
const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
1015
|
+
constructor(view) {
|
|
1016
|
+
this.view = view;
|
|
1017
|
+
this.debounceUpdate = -1;
|
|
1018
|
+
this.running = [];
|
|
1019
|
+
this.debounceAccept = -1;
|
|
1020
|
+
this.composing = 0 /* None */;
|
|
1021
|
+
for (let active of view.state.field(completionState).active)
|
|
1022
|
+
if (active.state == 1 /* Pending */)
|
|
1023
|
+
this.startQuery(active);
|
|
1024
|
+
}
|
|
1025
|
+
update(update) {
|
|
1026
|
+
let cState = update.state.field(completionState);
|
|
1027
|
+
if (!update.selectionSet && !update.docChanged && update.startState.field(completionState) == cState)
|
|
1028
|
+
return;
|
|
1029
|
+
let doesReset = update.transactions.some(tr => {
|
|
1030
|
+
return (tr.selection || tr.docChanged) && !getUserEvent(tr);
|
|
1031
|
+
});
|
|
1032
|
+
for (let i = 0; i < this.running.length; i++) {
|
|
1033
|
+
let query = this.running[i];
|
|
1034
|
+
if (doesReset ||
|
|
1035
|
+
query.updates.length + update.transactions.length > MaxUpdateCount && Date.now() - query.time > MinAbortTime) {
|
|
1036
|
+
for (let handler of query.context.abortListeners) {
|
|
1037
|
+
try {
|
|
1038
|
+
handler();
|
|
1039
|
+
}
|
|
1040
|
+
catch (e) {
|
|
1041
|
+
logException(this.view.state, e);
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
query.context.abortListeners = null;
|
|
1045
|
+
this.running.splice(i--, 1);
|
|
1046
|
+
}
|
|
1047
|
+
else {
|
|
1048
|
+
query.updates.push(...update.transactions);
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
if (this.debounceUpdate > -1)
|
|
1052
|
+
clearTimeout(this.debounceUpdate);
|
|
1053
|
+
this.debounceUpdate = cState.active.some(a => a.state == 1 /* Pending */ && !this.running.some(q => q.active.source == a.source))
|
|
1054
|
+
? setTimeout(() => this.startUpdate(), DebounceTime) : -1;
|
|
1055
|
+
if (this.composing != 0 /* None */)
|
|
1056
|
+
for (let tr of update.transactions) {
|
|
1057
|
+
if (getUserEvent(tr) == "input")
|
|
1058
|
+
this.composing = 2 /* Changed */;
|
|
1059
|
+
else if (this.composing == 2 /* Changed */ && tr.selection)
|
|
1060
|
+
this.composing = 3 /* ChangedAndMoved */;
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
startUpdate() {
|
|
1064
|
+
this.debounceUpdate = -1;
|
|
1065
|
+
let { state } = this.view, cState = state.field(completionState);
|
|
1066
|
+
for (let active of cState.active) {
|
|
1067
|
+
if (active.state == 1 /* Pending */ && !this.running.some(r => r.active.source == active.source))
|
|
1068
|
+
this.startQuery(active);
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
startQuery(active) {
|
|
1072
|
+
let { state } = this.view, pos = cur(state);
|
|
1073
|
+
let context = new CompletionContext(state, pos, active.explicitPos == pos);
|
|
1074
|
+
let pending = new RunningQuery(active, context);
|
|
1075
|
+
this.running.push(pending);
|
|
1076
|
+
Promise.resolve(active.source(context)).then(result => {
|
|
1077
|
+
if (!pending.context.aborted) {
|
|
1078
|
+
pending.done = result || null;
|
|
1079
|
+
this.scheduleAccept();
|
|
1080
|
+
}
|
|
1081
|
+
}, err => {
|
|
1082
|
+
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
1083
|
+
logException(this.view.state, err);
|
|
1084
|
+
});
|
|
1085
|
+
}
|
|
1086
|
+
scheduleAccept() {
|
|
1087
|
+
if (this.running.every(q => q.done !== undefined))
|
|
1088
|
+
this.accept();
|
|
1089
|
+
else if (this.debounceAccept < 0)
|
|
1090
|
+
this.debounceAccept = setTimeout(() => this.accept(), DebounceTime);
|
|
1091
|
+
}
|
|
1092
|
+
// For each finished query in this.running, try to create a result
|
|
1093
|
+
// or, if appropriate, restart the query.
|
|
1094
|
+
accept() {
|
|
1095
|
+
var _a;
|
|
1096
|
+
if (this.debounceAccept > -1)
|
|
1097
|
+
clearTimeout(this.debounceAccept);
|
|
1098
|
+
this.debounceAccept = -1;
|
|
1099
|
+
let updated = [];
|
|
1100
|
+
let conf = this.view.state.facet(completionConfig);
|
|
1101
|
+
for (let i = 0; i < this.running.length; i++) {
|
|
1102
|
+
let query = this.running[i];
|
|
1103
|
+
if (query.done === undefined)
|
|
1104
|
+
continue;
|
|
1105
|
+
this.running.splice(i--, 1);
|
|
1106
|
+
if (query.done) {
|
|
1107
|
+
let active = new ActiveResult(query.active.source, query.active.explicitPos, query.done, query.done.from, (_a = query.done.to) !== null && _a !== void 0 ? _a : cur(query.updates.length ? query.updates[0].startState : this.view.state));
|
|
1108
|
+
// Replay the transactions that happened since the start of
|
|
1109
|
+
// the request and see if that preserves the result
|
|
1110
|
+
for (let tr of query.updates)
|
|
1111
|
+
active = active.update(tr, conf);
|
|
1112
|
+
if (active.hasResult()) {
|
|
1113
|
+
updated.push(active);
|
|
1114
|
+
continue;
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
let current = this.view.state.field(completionState).active.find(a => a.source == query.active.source);
|
|
1118
|
+
if (current && current.state == 1 /* Pending */) {
|
|
1119
|
+
if (query.done == null) {
|
|
1120
|
+
// Explicitly failed. Should clear the pending status if it
|
|
1121
|
+
// hasn't been re-set in the meantime.
|
|
1122
|
+
let active = new ActiveSource(query.active.source, 0 /* Inactive */);
|
|
1123
|
+
for (let tr of query.updates)
|
|
1124
|
+
active = active.update(tr, conf);
|
|
1125
|
+
if (active.state != 1 /* Pending */)
|
|
1126
|
+
updated.push(active);
|
|
1127
|
+
}
|
|
1128
|
+
else {
|
|
1129
|
+
// Cleared by subsequent transactions. Restart.
|
|
1130
|
+
this.startQuery(current);
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
if (updated.length)
|
|
1135
|
+
this.view.dispatch({ effects: setActiveEffect.of(updated) });
|
|
1136
|
+
}
|
|
1137
|
+
}, {
|
|
1138
|
+
eventHandlers: {
|
|
1139
|
+
blur(event) {
|
|
1140
|
+
let state = this.view.state.field(completionState, false);
|
|
1141
|
+
if (state && state.tooltip && this.view.state.facet(completionConfig).closeOnBlur) {
|
|
1142
|
+
let dialog = state.open && getTooltip(this.view, state.open.tooltip);
|
|
1143
|
+
if (!dialog || !dialog.dom.contains(event.relatedTarget))
|
|
1144
|
+
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
1145
|
+
}
|
|
1146
|
+
},
|
|
1147
|
+
compositionstart() {
|
|
1148
|
+
this.composing = 1 /* Started */;
|
|
1149
|
+
},
|
|
1150
|
+
compositionend() {
|
|
1151
|
+
if (this.composing == 3 /* ChangedAndMoved */) {
|
|
1152
|
+
// Safari fires compositionend events synchronously, possibly
|
|
1153
|
+
// from inside an update, so dispatch asynchronously to avoid reentrancy
|
|
1154
|
+
setTimeout(() => this.view.dispatch({ effects: startCompletionEffect.of(false) }), 20);
|
|
1155
|
+
}
|
|
1156
|
+
this.composing = 0 /* None */;
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
});
|
|
1142
1160
|
|
|
1143
1161
|
const baseTheme = /*@__PURE__*/EditorView.baseTheme({
|
|
1144
1162
|
".cm-tooltip.cm-tooltip-autocomplete": {
|
|
@@ -1195,13 +1213,13 @@ const baseTheme = /*@__PURE__*/EditorView.baseTheme({
|
|
|
1195
1213
|
position: "absolute",
|
|
1196
1214
|
padding: "3px 9px",
|
|
1197
1215
|
width: "max-content",
|
|
1198
|
-
maxWidth: `${400 /*
|
|
1216
|
+
maxWidth: `${400 /* Width */}px`,
|
|
1199
1217
|
boxSizing: "border-box"
|
|
1200
1218
|
},
|
|
1201
1219
|
".cm-completionInfo.cm-completionInfo-left": { right: "100%" },
|
|
1202
1220
|
".cm-completionInfo.cm-completionInfo-right": { left: "100%" },
|
|
1203
|
-
".cm-completionInfo.cm-completionInfo-left-narrow": { right: `${30 /*
|
|
1204
|
-
".cm-completionInfo.cm-completionInfo-right-narrow": { left: `${30 /*
|
|
1221
|
+
".cm-completionInfo.cm-completionInfo-left-narrow": { right: `${30 /* Margin */}px` },
|
|
1222
|
+
".cm-completionInfo.cm-completionInfo-right-narrow": { left: `${30 /* Margin */}px` },
|
|
1205
1223
|
"&light .cm-snippetField": { backgroundColor: "#00000022" },
|
|
1206
1224
|
"&dark .cm-snippetField": { backgroundColor: "#ffffff22" },
|
|
1207
1225
|
".cm-snippetFieldPosition": {
|
|
@@ -1554,7 +1572,7 @@ function storeWords(doc, wordRE, result, seen, ignoreAt) {
|
|
|
1554
1572
|
if (!seen[m[0]] && pos + m.index != ignoreAt) {
|
|
1555
1573
|
result.push({ type: "text", label: m[0] });
|
|
1556
1574
|
seen[m[0]] = true;
|
|
1557
|
-
if (result.length >= 2000 /*
|
|
1575
|
+
if (result.length >= 2000 /* MaxList */)
|
|
1558
1576
|
return;
|
|
1559
1577
|
}
|
|
1560
1578
|
}
|
|
@@ -1562,7 +1580,7 @@ function storeWords(doc, wordRE, result, seen, ignoreAt) {
|
|
|
1562
1580
|
}
|
|
1563
1581
|
}
|
|
1564
1582
|
function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|
1565
|
-
let big = doc.length >= 1000 /*
|
|
1583
|
+
let big = doc.length >= 1000 /* MinCacheLen */;
|
|
1566
1584
|
let cached = big && cache.get(doc);
|
|
1567
1585
|
if (cached)
|
|
1568
1586
|
return cached;
|
|
@@ -1570,7 +1588,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|
|
1570
1588
|
if (doc.children) {
|
|
1571
1589
|
let pos = 0;
|
|
1572
1590
|
for (let ch of doc.children) {
|
|
1573
|
-
if (ch.length >= 1000 /*
|
|
1591
|
+
if (ch.length >= 1000 /* MinCacheLen */) {
|
|
1574
1592
|
for (let c of collectWords(ch, cache, wordRE, to - pos, ignoreAt - pos)) {
|
|
1575
1593
|
if (!seen[c.label]) {
|
|
1576
1594
|
seen[c.label] = true;
|
|
@@ -1587,7 +1605,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|
|
1587
1605
|
else {
|
|
1588
1606
|
storeWords(doc, wordRE, result, seen, ignoreAt);
|
|
1589
1607
|
}
|
|
1590
|
-
if (big && result.length < 2000 /*
|
|
1608
|
+
if (big && result.length < 2000 /* MaxList */)
|
|
1591
1609
|
cache.set(doc, result);
|
|
1592
1610
|
return result;
|
|
1593
1611
|
}
|
|
@@ -1603,7 +1621,7 @@ const completeAnyWord = context => {
|
|
|
1603
1621
|
if (!token && !context.explicit)
|
|
1604
1622
|
return null;
|
|
1605
1623
|
let from = token ? token.from : context.pos;
|
|
1606
|
-
let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /*
|
|
1624
|
+
let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /* Range */, from);
|
|
1607
1625
|
return { from, options, validFor: mapRE(re, s => "^" + s) };
|
|
1608
1626
|
};
|
|
1609
1627
|
|
|
@@ -1895,8 +1913,8 @@ returns `null`.
|
|
|
1895
1913
|
*/
|
|
1896
1914
|
function completionStatus(state) {
|
|
1897
1915
|
let cState = state.field(completionState, false);
|
|
1898
|
-
return cState && cState.active.some(a => a.state == 1 /*
|
|
1899
|
-
: cState && cState.active.some(a => a.state != 0 /*
|
|
1916
|
+
return cState && cState.active.some(a => a.state == 1 /* Pending */) ? "pending"
|
|
1917
|
+
: cState && cState.active.some(a => a.state != 0 /* Inactive */) ? "active" : null;
|
|
1900
1918
|
}
|
|
1901
1919
|
const completionArrayCache = /*@__PURE__*/new WeakMap;
|
|
1902
1920
|
/**
|