@codemirror/autocomplete 6.7.1 → 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 +6 -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.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();
|
|
@@ -960,7 +753,7 @@ class CompletionDialog {
|
|
|
960
753
|
static build(active, state, id, prev, conf) {
|
|
961
754
|
let options = sortOptions(active, state);
|
|
962
755
|
if (!options.length) {
|
|
963
|
-
return prev && active.some(a => a.state == 1 /*
|
|
756
|
+
return prev && active.some(a => a.state == 1 /* Pending */) ?
|
|
964
757
|
new CompletionDialog(prev.options, prev.attrs, prev.tooltip, prev.timestamp, prev.selected, true) : null;
|
|
965
758
|
}
|
|
966
759
|
let selected = state.facet(completionConfig).selectOnOpen ? 0 : -1;
|
|
@@ -974,7 +767,7 @@ class CompletionDialog {
|
|
|
974
767
|
}
|
|
975
768
|
return new CompletionDialog(options, makeAttrs(id, selected), {
|
|
976
769
|
pos: active.reduce((a, b) => b.hasResult() ? Math.min(a, b.from) : a, 1e8),
|
|
977
|
-
create: completionTooltip(completionState),
|
|
770
|
+
create: completionTooltip(completionState, applyCompletion),
|
|
978
771
|
above: conf.aboveCursor,
|
|
979
772
|
}, prev ? prev.timestamp : Date.now(), selected, false);
|
|
980
773
|
}
|
|
@@ -997,7 +790,7 @@ class CompletionState {
|
|
|
997
790
|
state.languageDataAt("autocomplete", cur(state)).map(asSource);
|
|
998
791
|
let active = sources.map(source => {
|
|
999
792
|
let value = this.active.find(s => s.source == source) ||
|
|
1000
|
-
new ActiveSource(source, this.active.some(a => a.state != 0 /*
|
|
793
|
+
new ActiveSource(source, this.active.some(a => a.state != 0 /* Inactive */) ? 1 /* Pending */ : 0 /* Inactive */);
|
|
1001
794
|
return value.update(tr, conf);
|
|
1002
795
|
});
|
|
1003
796
|
if (active.length == this.active.length && active.every((a, i) => a == this.active[i]))
|
|
@@ -1008,10 +801,10 @@ class CompletionState {
|
|
|
1008
801
|
if (tr.selection || active.some(a => a.hasResult() && tr.changes.touchesRange(a.from, a.to)) ||
|
|
1009
802
|
!sameResults(active, this.active))
|
|
1010
803
|
open = CompletionDialog.build(active, state, this.id, open, conf);
|
|
1011
|
-
else if (open && open.disabled && !active.some(a => a.state == 1 /*
|
|
804
|
+
else if (open && open.disabled && !active.some(a => a.state == 1 /* Pending */))
|
|
1012
805
|
open = null;
|
|
1013
|
-
if (!open && active.every(a => a.state != 1 /*
|
|
1014
|
-
active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /*
|
|
806
|
+
if (!open && active.every(a => a.state != 1 /* Pending */) && active.some(a => a.hasResult()))
|
|
807
|
+
active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /* Inactive */) : a);
|
|
1015
808
|
for (let effect of tr.effects)
|
|
1016
809
|
if (effect.is(setSelectedEffect))
|
|
1017
810
|
open = open && open.setSelected(effect.value, this.id);
|
|
@@ -1065,13 +858,13 @@ class ActiveSource {
|
|
|
1065
858
|
value = value.handleUserEvent(tr, event, conf);
|
|
1066
859
|
else if (tr.docChanged)
|
|
1067
860
|
value = value.handleChange(tr);
|
|
1068
|
-
else if (tr.selection && value.state != 0 /*
|
|
1069
|
-
value = new ActiveSource(value.source, 0 /*
|
|
861
|
+
else if (tr.selection && value.state != 0 /* Inactive */)
|
|
862
|
+
value = new ActiveSource(value.source, 0 /* Inactive */);
|
|
1070
863
|
for (let effect of tr.effects) {
|
|
1071
864
|
if (effect.is(startCompletionEffect))
|
|
1072
|
-
value = new ActiveSource(value.source, 1 /*
|
|
865
|
+
value = new ActiveSource(value.source, 1 /* Pending */, effect.value ? cur(tr.state) : -1);
|
|
1073
866
|
else if (effect.is(closeCompletionEffect))
|
|
1074
|
-
value = new ActiveSource(value.source, 0 /*
|
|
867
|
+
value = new ActiveSource(value.source, 0 /* Inactive */);
|
|
1075
868
|
else if (effect.is(setActiveEffect))
|
|
1076
869
|
for (let active of effect.value)
|
|
1077
870
|
if (active.source == value.source)
|
|
@@ -1080,10 +873,10 @@ class ActiveSource {
|
|
|
1080
873
|
return value;
|
|
1081
874
|
}
|
|
1082
875
|
handleUserEvent(tr, type, conf) {
|
|
1083
|
-
return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /*
|
|
876
|
+
return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* Pending */);
|
|
1084
877
|
}
|
|
1085
878
|
handleChange(tr) {
|
|
1086
|
-
return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /*
|
|
879
|
+
return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
|
|
1087
880
|
}
|
|
1088
881
|
map(changes) {
|
|
1089
882
|
return changes.empty || this.explicitPos < 0 ? this : new ActiveSource(this.source, this.state, changes.mapPos(this.explicitPos));
|
|
@@ -1091,7 +884,7 @@ class ActiveSource {
|
|
|
1091
884
|
}
|
|
1092
885
|
class ActiveResult extends ActiveSource {
|
|
1093
886
|
constructor(source, explicitPos, result, from, to) {
|
|
1094
|
-
super(source, 2 /*
|
|
887
|
+
super(source, 2 /* Result */, explicitPos);
|
|
1095
888
|
this.result = result;
|
|
1096
889
|
this.from = from;
|
|
1097
890
|
this.to = to;
|
|
@@ -1104,17 +897,17 @@ class ActiveResult extends ActiveSource {
|
|
|
1104
897
|
if ((this.explicitPos < 0 ? pos <= from : pos < this.from) ||
|
|
1105
898
|
pos > to ||
|
|
1106
899
|
type == "delete" && cur(tr.startState) == this.from)
|
|
1107
|
-
return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /*
|
|
900
|
+
return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* Pending */ : 0 /* Inactive */);
|
|
1108
901
|
let explicitPos = this.explicitPos < 0 ? -1 : tr.changes.mapPos(this.explicitPos), updated;
|
|
1109
902
|
if (checkValid(this.result.validFor, tr.state, from, to))
|
|
1110
903
|
return new ActiveResult(this.source, explicitPos, this.result, from, to);
|
|
1111
904
|
if (this.result.update &&
|
|
1112
905
|
(updated = this.result.update(this.result, from, to, new CompletionContext(tr.state, pos, explicitPos >= 0))))
|
|
1113
906
|
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 /*
|
|
907
|
+
return new ActiveSource(this.source, 1 /* Pending */, explicitPos);
|
|
1115
908
|
}
|
|
1116
909
|
handleChange(tr) {
|
|
1117
|
-
return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /*
|
|
910
|
+
return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
|
|
1118
911
|
}
|
|
1119
912
|
map(mapping) {
|
|
1120
913
|
return mapping.empty ? this :
|
|
@@ -1139,6 +932,232 @@ const completionState = /*@__PURE__*/StateField.define({
|
|
|
1139
932
|
EditorView.contentAttributes.from(f, state => state.attrs)
|
|
1140
933
|
]
|
|
1141
934
|
});
|
|
935
|
+
function applyCompletion(view, option) {
|
|
936
|
+
const apply = option.completion.apply || option.completion.label;
|
|
937
|
+
let result = view.state.field(completionState).active.find(a => a.source == option.source);
|
|
938
|
+
if (!(result instanceof ActiveResult))
|
|
939
|
+
return false;
|
|
940
|
+
if (typeof apply == "string")
|
|
941
|
+
view.dispatch(Object.assign(Object.assign({}, insertCompletionText(view.state, apply, result.from, result.to)), { annotations: pickedCompletion.of(option.completion) }));
|
|
942
|
+
else
|
|
943
|
+
apply(view, option.completion, result.from, result.to);
|
|
944
|
+
return true;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
/**
|
|
948
|
+
Returns a command that moves the completion selection forward or
|
|
949
|
+
backward by the given amount.
|
|
950
|
+
*/
|
|
951
|
+
function moveCompletionSelection(forward, by = "option") {
|
|
952
|
+
return (view) => {
|
|
953
|
+
let cState = view.state.field(completionState, false);
|
|
954
|
+
if (!cState || !cState.open || cState.open.disabled ||
|
|
955
|
+
Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay)
|
|
956
|
+
return false;
|
|
957
|
+
let step = 1, tooltip;
|
|
958
|
+
if (by == "page" && (tooltip = getTooltip(view, cState.open.tooltip)))
|
|
959
|
+
step = Math.max(2, Math.floor(tooltip.dom.offsetHeight /
|
|
960
|
+
tooltip.dom.querySelector("li").offsetHeight) - 1);
|
|
961
|
+
let { length } = cState.open.options;
|
|
962
|
+
let selected = cState.open.selected > -1 ? cState.open.selected + step * (forward ? 1 : -1) : forward ? 0 : length - 1;
|
|
963
|
+
if (selected < 0)
|
|
964
|
+
selected = by == "page" ? 0 : length - 1;
|
|
965
|
+
else if (selected >= length)
|
|
966
|
+
selected = by == "page" ? length - 1 : 0;
|
|
967
|
+
view.dispatch({ effects: setSelectedEffect.of(selected) });
|
|
968
|
+
return true;
|
|
969
|
+
};
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
972
|
+
Accept the current completion.
|
|
973
|
+
*/
|
|
974
|
+
const acceptCompletion = (view) => {
|
|
975
|
+
let cState = view.state.field(completionState, false);
|
|
976
|
+
if (view.state.readOnly || !cState || !cState.open || cState.open.selected < 0 ||
|
|
977
|
+
Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay)
|
|
978
|
+
return false;
|
|
979
|
+
if (!cState.open.disabled)
|
|
980
|
+
return applyCompletion(view, cState.open.options[cState.open.selected]);
|
|
981
|
+
return true;
|
|
982
|
+
};
|
|
983
|
+
/**
|
|
984
|
+
Explicitly start autocompletion.
|
|
985
|
+
*/
|
|
986
|
+
const startCompletion = (view) => {
|
|
987
|
+
let cState = view.state.field(completionState, false);
|
|
988
|
+
if (!cState)
|
|
989
|
+
return false;
|
|
990
|
+
view.dispatch({ effects: startCompletionEffect.of(true) });
|
|
991
|
+
return true;
|
|
992
|
+
};
|
|
993
|
+
/**
|
|
994
|
+
Close the currently active completion.
|
|
995
|
+
*/
|
|
996
|
+
const closeCompletion = (view) => {
|
|
997
|
+
let cState = view.state.field(completionState, false);
|
|
998
|
+
if (!cState || !cState.active.some(a => a.state != 0 /* Inactive */))
|
|
999
|
+
return false;
|
|
1000
|
+
view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
1001
|
+
return true;
|
|
1002
|
+
};
|
|
1003
|
+
class RunningQuery {
|
|
1004
|
+
constructor(active, context) {
|
|
1005
|
+
this.active = active;
|
|
1006
|
+
this.context = context;
|
|
1007
|
+
this.time = Date.now();
|
|
1008
|
+
this.updates = [];
|
|
1009
|
+
// Note that 'undefined' means 'not done yet', whereas 'null' means
|
|
1010
|
+
// 'query returned null'.
|
|
1011
|
+
this.done = undefined;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
const DebounceTime = 50, MaxUpdateCount = 50, MinAbortTime = 1000;
|
|
1015
|
+
const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
1016
|
+
constructor(view) {
|
|
1017
|
+
this.view = view;
|
|
1018
|
+
this.debounceUpdate = -1;
|
|
1019
|
+
this.running = [];
|
|
1020
|
+
this.debounceAccept = -1;
|
|
1021
|
+
this.composing = 0 /* None */;
|
|
1022
|
+
for (let active of view.state.field(completionState).active)
|
|
1023
|
+
if (active.state == 1 /* Pending */)
|
|
1024
|
+
this.startQuery(active);
|
|
1025
|
+
}
|
|
1026
|
+
update(update) {
|
|
1027
|
+
let cState = update.state.field(completionState);
|
|
1028
|
+
if (!update.selectionSet && !update.docChanged && update.startState.field(completionState) == cState)
|
|
1029
|
+
return;
|
|
1030
|
+
let doesReset = update.transactions.some(tr => {
|
|
1031
|
+
return (tr.selection || tr.docChanged) && !getUserEvent(tr);
|
|
1032
|
+
});
|
|
1033
|
+
for (let i = 0; i < this.running.length; i++) {
|
|
1034
|
+
let query = this.running[i];
|
|
1035
|
+
if (doesReset ||
|
|
1036
|
+
query.updates.length + update.transactions.length > MaxUpdateCount && Date.now() - query.time > MinAbortTime) {
|
|
1037
|
+
for (let handler of query.context.abortListeners) {
|
|
1038
|
+
try {
|
|
1039
|
+
handler();
|
|
1040
|
+
}
|
|
1041
|
+
catch (e) {
|
|
1042
|
+
logException(this.view.state, e);
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
query.context.abortListeners = null;
|
|
1046
|
+
this.running.splice(i--, 1);
|
|
1047
|
+
}
|
|
1048
|
+
else {
|
|
1049
|
+
query.updates.push(...update.transactions);
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
if (this.debounceUpdate > -1)
|
|
1053
|
+
clearTimeout(this.debounceUpdate);
|
|
1054
|
+
this.debounceUpdate = cState.active.some(a => a.state == 1 /* Pending */ && !this.running.some(q => q.active.source == a.source))
|
|
1055
|
+
? setTimeout(() => this.startUpdate(), DebounceTime) : -1;
|
|
1056
|
+
if (this.composing != 0 /* None */)
|
|
1057
|
+
for (let tr of update.transactions) {
|
|
1058
|
+
if (getUserEvent(tr) == "input")
|
|
1059
|
+
this.composing = 2 /* Changed */;
|
|
1060
|
+
else if (this.composing == 2 /* Changed */ && tr.selection)
|
|
1061
|
+
this.composing = 3 /* ChangedAndMoved */;
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
startUpdate() {
|
|
1065
|
+
this.debounceUpdate = -1;
|
|
1066
|
+
let { state } = this.view, cState = state.field(completionState);
|
|
1067
|
+
for (let active of cState.active) {
|
|
1068
|
+
if (active.state == 1 /* Pending */ && !this.running.some(r => r.active.source == active.source))
|
|
1069
|
+
this.startQuery(active);
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
startQuery(active) {
|
|
1073
|
+
let { state } = this.view, pos = cur(state);
|
|
1074
|
+
let context = new CompletionContext(state, pos, active.explicitPos == pos);
|
|
1075
|
+
let pending = new RunningQuery(active, context);
|
|
1076
|
+
this.running.push(pending);
|
|
1077
|
+
Promise.resolve(active.source(context)).then(result => {
|
|
1078
|
+
if (!pending.context.aborted) {
|
|
1079
|
+
pending.done = result || null;
|
|
1080
|
+
this.scheduleAccept();
|
|
1081
|
+
}
|
|
1082
|
+
}, err => {
|
|
1083
|
+
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
1084
|
+
logException(this.view.state, err);
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
scheduleAccept() {
|
|
1088
|
+
if (this.running.every(q => q.done !== undefined))
|
|
1089
|
+
this.accept();
|
|
1090
|
+
else if (this.debounceAccept < 0)
|
|
1091
|
+
this.debounceAccept = setTimeout(() => this.accept(), DebounceTime);
|
|
1092
|
+
}
|
|
1093
|
+
// For each finished query in this.running, try to create a result
|
|
1094
|
+
// or, if appropriate, restart the query.
|
|
1095
|
+
accept() {
|
|
1096
|
+
var _a;
|
|
1097
|
+
if (this.debounceAccept > -1)
|
|
1098
|
+
clearTimeout(this.debounceAccept);
|
|
1099
|
+
this.debounceAccept = -1;
|
|
1100
|
+
let updated = [];
|
|
1101
|
+
let conf = this.view.state.facet(completionConfig);
|
|
1102
|
+
for (let i = 0; i < this.running.length; i++) {
|
|
1103
|
+
let query = this.running[i];
|
|
1104
|
+
if (query.done === undefined)
|
|
1105
|
+
continue;
|
|
1106
|
+
this.running.splice(i--, 1);
|
|
1107
|
+
if (query.done) {
|
|
1108
|
+
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));
|
|
1109
|
+
// Replay the transactions that happened since the start of
|
|
1110
|
+
// the request and see if that preserves the result
|
|
1111
|
+
for (let tr of query.updates)
|
|
1112
|
+
active = active.update(tr, conf);
|
|
1113
|
+
if (active.hasResult()) {
|
|
1114
|
+
updated.push(active);
|
|
1115
|
+
continue;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
let current = this.view.state.field(completionState).active.find(a => a.source == query.active.source);
|
|
1119
|
+
if (current && current.state == 1 /* Pending */) {
|
|
1120
|
+
if (query.done == null) {
|
|
1121
|
+
// Explicitly failed. Should clear the pending status if it
|
|
1122
|
+
// hasn't been re-set in the meantime.
|
|
1123
|
+
let active = new ActiveSource(query.active.source, 0 /* Inactive */);
|
|
1124
|
+
for (let tr of query.updates)
|
|
1125
|
+
active = active.update(tr, conf);
|
|
1126
|
+
if (active.state != 1 /* Pending */)
|
|
1127
|
+
updated.push(active);
|
|
1128
|
+
}
|
|
1129
|
+
else {
|
|
1130
|
+
// Cleared by subsequent transactions. Restart.
|
|
1131
|
+
this.startQuery(current);
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
if (updated.length)
|
|
1136
|
+
this.view.dispatch({ effects: setActiveEffect.of(updated) });
|
|
1137
|
+
}
|
|
1138
|
+
}, {
|
|
1139
|
+
eventHandlers: {
|
|
1140
|
+
blur(event) {
|
|
1141
|
+
let state = this.view.state.field(completionState, false);
|
|
1142
|
+
if (state && state.tooltip && this.view.state.facet(completionConfig).closeOnBlur) {
|
|
1143
|
+
let dialog = state.open && getTooltip(this.view, state.open.tooltip);
|
|
1144
|
+
if (!dialog || !dialog.dom.contains(event.relatedTarget))
|
|
1145
|
+
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
1146
|
+
}
|
|
1147
|
+
},
|
|
1148
|
+
compositionstart() {
|
|
1149
|
+
this.composing = 1 /* Started */;
|
|
1150
|
+
},
|
|
1151
|
+
compositionend() {
|
|
1152
|
+
if (this.composing == 3 /* ChangedAndMoved */) {
|
|
1153
|
+
// Safari fires compositionend events synchronously, possibly
|
|
1154
|
+
// from inside an update, so dispatch asynchronously to avoid reentrancy
|
|
1155
|
+
setTimeout(() => this.view.dispatch({ effects: startCompletionEffect.of(false) }), 20);
|
|
1156
|
+
}
|
|
1157
|
+
this.composing = 0 /* None */;
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
});
|
|
1142
1161
|
|
|
1143
1162
|
const baseTheme = /*@__PURE__*/EditorView.baseTheme({
|
|
1144
1163
|
".cm-tooltip.cm-tooltip-autocomplete": {
|
|
@@ -1195,13 +1214,13 @@ const baseTheme = /*@__PURE__*/EditorView.baseTheme({
|
|
|
1195
1214
|
position: "absolute",
|
|
1196
1215
|
padding: "3px 9px",
|
|
1197
1216
|
width: "max-content",
|
|
1198
|
-
maxWidth: `${400 /*
|
|
1217
|
+
maxWidth: `${400 /* Width */}px`,
|
|
1199
1218
|
boxSizing: "border-box"
|
|
1200
1219
|
},
|
|
1201
1220
|
".cm-completionInfo.cm-completionInfo-left": { right: "100%" },
|
|
1202
1221
|
".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 /*
|
|
1222
|
+
".cm-completionInfo.cm-completionInfo-left-narrow": { right: `${30 /* Margin */}px` },
|
|
1223
|
+
".cm-completionInfo.cm-completionInfo-right-narrow": { left: `${30 /* Margin */}px` },
|
|
1205
1224
|
"&light .cm-snippetField": { backgroundColor: "#00000022" },
|
|
1206
1225
|
"&dark .cm-snippetField": { backgroundColor: "#ffffff22" },
|
|
1207
1226
|
".cm-snippetFieldPosition": {
|
|
@@ -1554,7 +1573,7 @@ function storeWords(doc, wordRE, result, seen, ignoreAt) {
|
|
|
1554
1573
|
if (!seen[m[0]] && pos + m.index != ignoreAt) {
|
|
1555
1574
|
result.push({ type: "text", label: m[0] });
|
|
1556
1575
|
seen[m[0]] = true;
|
|
1557
|
-
if (result.length >= 2000 /*
|
|
1576
|
+
if (result.length >= 2000 /* MaxList */)
|
|
1558
1577
|
return;
|
|
1559
1578
|
}
|
|
1560
1579
|
}
|
|
@@ -1562,7 +1581,7 @@ function storeWords(doc, wordRE, result, seen, ignoreAt) {
|
|
|
1562
1581
|
}
|
|
1563
1582
|
}
|
|
1564
1583
|
function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|
1565
|
-
let big = doc.length >= 1000 /*
|
|
1584
|
+
let big = doc.length >= 1000 /* MinCacheLen */;
|
|
1566
1585
|
let cached = big && cache.get(doc);
|
|
1567
1586
|
if (cached)
|
|
1568
1587
|
return cached;
|
|
@@ -1570,7 +1589,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|
|
1570
1589
|
if (doc.children) {
|
|
1571
1590
|
let pos = 0;
|
|
1572
1591
|
for (let ch of doc.children) {
|
|
1573
|
-
if (ch.length >= 1000 /*
|
|
1592
|
+
if (ch.length >= 1000 /* MinCacheLen */) {
|
|
1574
1593
|
for (let c of collectWords(ch, cache, wordRE, to - pos, ignoreAt - pos)) {
|
|
1575
1594
|
if (!seen[c.label]) {
|
|
1576
1595
|
seen[c.label] = true;
|
|
@@ -1587,7 +1606,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|
|
1587
1606
|
else {
|
|
1588
1607
|
storeWords(doc, wordRE, result, seen, ignoreAt);
|
|
1589
1608
|
}
|
|
1590
|
-
if (big && result.length < 2000 /*
|
|
1609
|
+
if (big && result.length < 2000 /* MaxList */)
|
|
1591
1610
|
cache.set(doc, result);
|
|
1592
1611
|
return result;
|
|
1593
1612
|
}
|
|
@@ -1603,7 +1622,7 @@ const completeAnyWord = context => {
|
|
|
1603
1622
|
if (!token && !context.explicit)
|
|
1604
1623
|
return null;
|
|
1605
1624
|
let from = token ? token.from : context.pos;
|
|
1606
|
-
let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /*
|
|
1625
|
+
let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /* Range */, from);
|
|
1607
1626
|
return { from, options, validFor: mapRE(re, s => "^" + s) };
|
|
1608
1627
|
};
|
|
1609
1628
|
|
|
@@ -1895,8 +1914,8 @@ returns `null`.
|
|
|
1895
1914
|
*/
|
|
1896
1915
|
function completionStatus(state) {
|
|
1897
1916
|
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 /*
|
|
1917
|
+
return cState && cState.active.some(a => a.state == 1 /* Pending */) ? "pending"
|
|
1918
|
+
: cState && cState.active.some(a => a.state != 0 /* Inactive */) ? "active" : null;
|
|
1900
1919
|
}
|
|
1901
1920
|
const completionArrayCache = /*@__PURE__*/new WeakMap;
|
|
1902
1921
|
/**
|