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