@codemirror/autocomplete 6.8.1 → 6.9.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 +14 -0
- package/dist/index.cjs +97 -88
- package/dist/index.d.cts +25 -15
- package/dist/index.d.ts +25 -15
- package/dist/index.js +97 -86
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## 6.9.1 (2023-09-14)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Make sure the cursor is scrolled into view after inserting completion text.
|
|
6
|
+
|
|
7
|
+
Make sure scrolling completions into view doesn't get confused when the tooltip is scaled.
|
|
8
|
+
|
|
9
|
+
## 6.9.0 (2023-07-18)
|
|
10
|
+
|
|
11
|
+
### New features
|
|
12
|
+
|
|
13
|
+
Completions may now provide a `displayLabel` property that overrides the way they are displayed in the completion list.
|
|
14
|
+
|
|
1
15
|
## 6.8.1 (2023-06-23)
|
|
2
16
|
|
|
3
17
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
3
|
var state = require('@codemirror/state');
|
|
6
4
|
var view = require('@codemirror/view');
|
|
7
5
|
var language = require('@codemirror/language');
|
|
@@ -175,7 +173,7 @@ function insertCompletionText(state$1, text, from, to) {
|
|
|
175
173
|
changes: { from: range.from + fromOff, to: to == main.from ? range.to : range.from + toOff, insert: text },
|
|
176
174
|
range: state.EditorSelection.cursor(range.from + fromOff + text.length)
|
|
177
175
|
};
|
|
178
|
-
})), { userEvent: "input.complete" });
|
|
176
|
+
})), { scrollIntoView: true, userEvent: "input.complete" });
|
|
179
177
|
}
|
|
180
178
|
const SourceCache = new WeakMap();
|
|
181
179
|
function asSource(source) {
|
|
@@ -202,6 +200,8 @@ class FuzzyMatcher {
|
|
|
202
200
|
this.any = [];
|
|
203
201
|
this.precise = [];
|
|
204
202
|
this.byWord = [];
|
|
203
|
+
this.score = 0;
|
|
204
|
+
this.matched = [];
|
|
205
205
|
for (let p = 0; p < pattern.length;) {
|
|
206
206
|
let char = state.codePointAt(pattern, p), size = state.codePointSize(char);
|
|
207
207
|
this.chars.push(char);
|
|
@@ -211,34 +211,39 @@ class FuzzyMatcher {
|
|
|
211
211
|
}
|
|
212
212
|
this.astral = pattern.length != this.chars.length;
|
|
213
213
|
}
|
|
214
|
+
ret(score, matched) {
|
|
215
|
+
this.score = score;
|
|
216
|
+
this.matched = matched;
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
214
219
|
// Matches a given word (completion) against the pattern (input).
|
|
215
|
-
// Will return
|
|
216
|
-
//
|
|
217
|
-
// indicating the matched parts of `word`.
|
|
220
|
+
// Will return a boolean indicating whether there was a match and,
|
|
221
|
+
// on success, set `this.score` to the score, `this.matched` to an
|
|
222
|
+
// array of `from, to` pairs indicating the matched parts of `word`.
|
|
218
223
|
//
|
|
219
224
|
// The score is a number that is more negative the worse the match
|
|
220
225
|
// is. See `Penalty` above.
|
|
221
226
|
match(word) {
|
|
222
227
|
if (this.pattern.length == 0)
|
|
223
|
-
return
|
|
228
|
+
return this.ret(-100 /* Penalty.NotFull */, []);
|
|
224
229
|
if (word.length < this.pattern.length)
|
|
225
|
-
return
|
|
230
|
+
return false;
|
|
226
231
|
let { chars, folded, any, precise, byWord } = this;
|
|
227
232
|
// For single-character queries, only match when they occur right
|
|
228
233
|
// at the start
|
|
229
234
|
if (chars.length == 1) {
|
|
230
235
|
let first = state.codePointAt(word, 0), firstSize = state.codePointSize(first);
|
|
231
|
-
let score = firstSize == word.length ? 0 : -100 /* NotFull */;
|
|
236
|
+
let score = firstSize == word.length ? 0 : -100 /* Penalty.NotFull */;
|
|
232
237
|
if (first == chars[0]) ;
|
|
233
238
|
else if (first == folded[0])
|
|
234
|
-
score += -200 /* CaseFold */;
|
|
239
|
+
score += -200 /* Penalty.CaseFold */;
|
|
235
240
|
else
|
|
236
|
-
return
|
|
237
|
-
return
|
|
241
|
+
return false;
|
|
242
|
+
return this.ret(score, [0, firstSize]);
|
|
238
243
|
}
|
|
239
244
|
let direct = word.indexOf(this.pattern);
|
|
240
245
|
if (direct == 0)
|
|
241
|
-
return
|
|
246
|
+
return this.ret(word.length == this.pattern.length ? 0 : -100 /* Penalty.NotFull */, [0, this.pattern.length]);
|
|
242
247
|
let len = chars.length, anyTo = 0;
|
|
243
248
|
if (direct < 0) {
|
|
244
249
|
for (let i = 0, e = Math.min(word.length, 200); i < e && anyTo < len;) {
|
|
@@ -249,7 +254,7 @@ class FuzzyMatcher {
|
|
|
249
254
|
}
|
|
250
255
|
// No match, exit immediately
|
|
251
256
|
if (anyTo < len)
|
|
252
|
-
return
|
|
257
|
+
return false;
|
|
253
258
|
}
|
|
254
259
|
// This tracks the extent of the precise (non-folded, not
|
|
255
260
|
// necessarily adjacent) match
|
|
@@ -262,7 +267,7 @@ class FuzzyMatcher {
|
|
|
262
267
|
let adjacentTo = 0, adjacentStart = -1, adjacentEnd = -1;
|
|
263
268
|
let hasLower = /[a-z]/.test(word), wordAdjacent = true;
|
|
264
269
|
// 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 /* NonWord */; i < e && byWordTo < len;) {
|
|
270
|
+
for (let i = 0, e = Math.min(word.length, 200), prevType = 0 /* Tp.NonWord */; i < e && byWordTo < len;) {
|
|
266
271
|
let next = state.codePointAt(word, i);
|
|
267
272
|
if (direct < 0) {
|
|
268
273
|
if (preciseTo < len && next == chars[preciseTo])
|
|
@@ -280,9 +285,9 @@ class FuzzyMatcher {
|
|
|
280
285
|
}
|
|
281
286
|
}
|
|
282
287
|
let ch, type = next < 0xff
|
|
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 */) {
|
|
288
|
+
? (next >= 48 && next <= 57 || next >= 97 && next <= 122 ? 2 /* Tp.Lower */ : next >= 65 && next <= 90 ? 1 /* Tp.Upper */ : 0 /* Tp.NonWord */)
|
|
289
|
+
: ((ch = state.fromCodePoint(next)) != ch.toLowerCase() ? 1 /* Tp.Upper */ : ch != ch.toUpperCase() ? 2 /* Tp.Lower */ : 0 /* Tp.NonWord */);
|
|
290
|
+
if (!i || type == 1 /* Tp.Upper */ && hasLower || prevType == 0 /* Tp.NonWord */ && type != 0 /* Tp.NonWord */) {
|
|
286
291
|
if (chars[byWordTo] == next || (folded[byWordTo] == next && (byWordFolded = true)))
|
|
287
292
|
byWord[byWordTo++] = i;
|
|
288
293
|
else if (byWord.length)
|
|
@@ -292,30 +297,31 @@ class FuzzyMatcher {
|
|
|
292
297
|
i += state.codePointSize(next);
|
|
293
298
|
}
|
|
294
299
|
if (byWordTo == len && byWord[0] == 0 && wordAdjacent)
|
|
295
|
-
return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0), byWord, word);
|
|
300
|
+
return this.result(-100 /* Penalty.ByWord */ + (byWordFolded ? -200 /* Penalty.CaseFold */ : 0), byWord, word);
|
|
296
301
|
if (adjacentTo == len && adjacentStart == 0)
|
|
297
|
-
return
|
|
302
|
+
return this.ret(-200 /* Penalty.CaseFold */ - word.length + (adjacentEnd == word.length ? 0 : -100 /* Penalty.NotFull */), [0, adjacentEnd]);
|
|
298
303
|
if (direct > -1)
|
|
299
|
-
return
|
|
304
|
+
return this.ret(-700 /* Penalty.NotStart */ - word.length, [direct, direct + this.pattern.length]);
|
|
300
305
|
if (adjacentTo == len)
|
|
301
|
-
return
|
|
306
|
+
return this.ret(-200 /* Penalty.CaseFold */ + -700 /* Penalty.NotStart */ - word.length, [adjacentStart, adjacentEnd]);
|
|
302
307
|
if (byWordTo == len)
|
|
303
|
-
return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0) + -700 /* NotStart */ +
|
|
304
|
-
(wordAdjacent ? 0 : -1100 /* Gap */), byWord, word);
|
|
305
|
-
return chars.length == 2 ?
|
|
308
|
+
return this.result(-100 /* Penalty.ByWord */ + (byWordFolded ? -200 /* Penalty.CaseFold */ : 0) + -700 /* Penalty.NotStart */ +
|
|
309
|
+
(wordAdjacent ? 0 : -1100 /* Penalty.Gap */), byWord, word);
|
|
310
|
+
return chars.length == 2 ? false
|
|
311
|
+
: this.result((any[0] ? -700 /* Penalty.NotStart */ : 0) + -200 /* Penalty.CaseFold */ + -1100 /* Penalty.Gap */, any, word);
|
|
306
312
|
}
|
|
307
313
|
result(score, positions, word) {
|
|
308
|
-
let result = [
|
|
314
|
+
let result = [], i = 0;
|
|
309
315
|
for (let pos of positions) {
|
|
310
316
|
let to = pos + (this.astral ? state.codePointSize(state.codePointAt(word, pos)) : 1);
|
|
311
|
-
if (i
|
|
317
|
+
if (i && result[i - 1] == pos)
|
|
312
318
|
result[i - 1] = to;
|
|
313
319
|
else {
|
|
314
320
|
result[i++] = pos;
|
|
315
321
|
result[i++] = to;
|
|
316
322
|
}
|
|
317
323
|
}
|
|
318
|
-
return result;
|
|
324
|
+
return this.ret(score - word.length, result);
|
|
319
325
|
}
|
|
320
326
|
}
|
|
321
327
|
|
|
@@ -349,7 +355,7 @@ const completionConfig = state.Facet.define({
|
|
|
349
355
|
function joinClass(a, b) {
|
|
350
356
|
return a ? b ? a + " " + b : a : b;
|
|
351
357
|
}
|
|
352
|
-
function defaultPositionInfo(view$1, list, option, info, space) {
|
|
358
|
+
function defaultPositionInfo(view$1, list, option, info, space, tooltip) {
|
|
353
359
|
let rtl = view$1.textDirection == view.Direction.RTL, left = rtl, narrow = false;
|
|
354
360
|
let side = "top", offset, maxWidth;
|
|
355
361
|
let spaceLeft = list.left - space.left, spaceRight = space.right - list.right;
|
|
@@ -360,11 +366,11 @@ function defaultPositionInfo(view$1, list, option, info, space) {
|
|
|
360
366
|
left = true;
|
|
361
367
|
if (infoWidth <= (left ? spaceLeft : spaceRight)) {
|
|
362
368
|
offset = Math.max(space.top, Math.min(option.top, space.bottom - infoHeight)) - list.top;
|
|
363
|
-
maxWidth = Math.min(400 /* Width */, left ? spaceLeft : spaceRight);
|
|
369
|
+
maxWidth = Math.min(400 /* Info.Width */, left ? spaceLeft : spaceRight);
|
|
364
370
|
}
|
|
365
371
|
else {
|
|
366
372
|
narrow = true;
|
|
367
|
-
maxWidth = Math.min(400 /* Width */, (rtl ? list.right : space.right - list.left) - 30 /* Margin */);
|
|
373
|
+
maxWidth = Math.min(400 /* Info.Width */, (rtl ? list.right : space.right - list.left) - 30 /* Info.Margin */);
|
|
368
374
|
let spaceBelow = space.bottom - list.bottom;
|
|
369
375
|
if (spaceBelow >= infoHeight || spaceBelow > list.top) { // Below the completion
|
|
370
376
|
offset = option.bottom - list.top;
|
|
@@ -374,8 +380,10 @@ function defaultPositionInfo(view$1, list, option, info, space) {
|
|
|
374
380
|
offset = list.bottom - option.top;
|
|
375
381
|
}
|
|
376
382
|
}
|
|
383
|
+
let scaleY = (list.bottom - list.top) / tooltip.offsetHeight;
|
|
384
|
+
let scaleX = (list.right - list.left) / tooltip.offsetWidth;
|
|
377
385
|
return {
|
|
378
|
-
style: `${side}: ${offset}px; max-width: ${maxWidth}px`,
|
|
386
|
+
style: `${side}: ${offset / scaleY}px; max-width: ${maxWidth / scaleX}px`,
|
|
379
387
|
class: "cm-completionInfo-" + (narrow ? (rtl ? "left-narrow" : "right-narrow") : left ? "left" : "right")
|
|
380
388
|
};
|
|
381
389
|
}
|
|
@@ -398,8 +406,8 @@ function optionContent(config) {
|
|
|
398
406
|
render(completion, _s, match) {
|
|
399
407
|
let labelElt = document.createElement("span");
|
|
400
408
|
labelElt.className = "cm-completionLabel";
|
|
401
|
-
let
|
|
402
|
-
for (let j =
|
|
409
|
+
let label = completion.displayLabel || completion.label, off = 0;
|
|
410
|
+
for (let j = 0; j < match.length;) {
|
|
403
411
|
let from = match[j++], to = match[j++];
|
|
404
412
|
if (from > off)
|
|
405
413
|
labelElt.appendChild(document.createTextNode(label.slice(off, from)));
|
|
@@ -595,7 +603,7 @@ class CompletionTooltip {
|
|
|
595
603
|
if (selRect.top > Math.min(space.bottom, listRect.bottom) - 10 ||
|
|
596
604
|
selRect.bottom < Math.max(space.top, listRect.top) + 10)
|
|
597
605
|
return null;
|
|
598
|
-
return this.view.state.facet(completionConfig).positionInfo(this.view, listRect, selRect, infoRect, space);
|
|
606
|
+
return this.view.state.facet(completionConfig).positionInfo(this.view, listRect, selRect, infoRect, space, this.dom);
|
|
599
607
|
}
|
|
600
608
|
placeInfo(pos) {
|
|
601
609
|
if (this.info) {
|
|
@@ -669,10 +677,11 @@ function completionTooltip(stateField, applyCompletion) {
|
|
|
669
677
|
function scrollIntoView(container, element) {
|
|
670
678
|
let parent = container.getBoundingClientRect();
|
|
671
679
|
let self = element.getBoundingClientRect();
|
|
680
|
+
let scaleY = parent.height / container.offsetHeight;
|
|
672
681
|
if (self.top < parent.top)
|
|
673
|
-
container.scrollTop -= parent.top - self.top;
|
|
682
|
+
container.scrollTop -= (parent.top - self.top) / scaleY;
|
|
674
683
|
else if (self.bottom > parent.bottom)
|
|
675
|
-
container.scrollTop += self.bottom - parent.bottom;
|
|
684
|
+
container.scrollTop += (self.bottom - parent.bottom) / scaleY;
|
|
676
685
|
}
|
|
677
686
|
|
|
678
687
|
// Used to pick a preferred option when two options with the same
|
|
@@ -697,21 +706,18 @@ function sortOptions(active, state) {
|
|
|
697
706
|
};
|
|
698
707
|
for (let a of active)
|
|
699
708
|
if (a.hasResult()) {
|
|
709
|
+
let getMatch = a.result.getMatch;
|
|
700
710
|
if (a.result.filter === false) {
|
|
701
|
-
let getMatch = a.result.getMatch;
|
|
702
711
|
for (let option of a.result.options) {
|
|
703
|
-
|
|
704
|
-
if (getMatch)
|
|
705
|
-
for (let n of getMatch(option))
|
|
706
|
-
match.push(n);
|
|
707
|
-
addOption(new Option(option, a.source, match, match[0]));
|
|
712
|
+
addOption(new Option(option, a.source, getMatch ? getMatch(option) : [], 1e9 - options.length));
|
|
708
713
|
}
|
|
709
714
|
}
|
|
710
715
|
else {
|
|
711
|
-
let matcher = new FuzzyMatcher(state.sliceDoc(a.from, a.to))
|
|
716
|
+
let matcher = new FuzzyMatcher(state.sliceDoc(a.from, a.to));
|
|
712
717
|
for (let option of a.result.options)
|
|
713
|
-
if (
|
|
714
|
-
|
|
718
|
+
if (matcher.match(option.label)) {
|
|
719
|
+
let matched = !option.displayLabel ? matcher.matched : getMatch ? getMatch(option, matcher.matched) : [];
|
|
720
|
+
addOption(new Option(option, a.source, matched, matcher.score + (option.boost || 0)));
|
|
715
721
|
}
|
|
716
722
|
}
|
|
717
723
|
}
|
|
@@ -758,7 +764,7 @@ class CompletionDialog {
|
|
|
758
764
|
static build(active, state, id, prev, conf) {
|
|
759
765
|
let options = sortOptions(active, state);
|
|
760
766
|
if (!options.length) {
|
|
761
|
-
return prev && active.some(a => a.state == 1 /* Pending */) ?
|
|
767
|
+
return prev && active.some(a => a.state == 1 /* State.Pending */) ?
|
|
762
768
|
new CompletionDialog(prev.options, prev.attrs, prev.tooltip, prev.timestamp, prev.selected, true) : null;
|
|
763
769
|
}
|
|
764
770
|
let selected = state.facet(completionConfig).selectOnOpen ? 0 : -1;
|
|
@@ -795,7 +801,7 @@ class CompletionState {
|
|
|
795
801
|
state.languageDataAt("autocomplete", cur(state)).map(asSource);
|
|
796
802
|
let active = sources.map(source => {
|
|
797
803
|
let value = this.active.find(s => s.source == source) ||
|
|
798
|
-
new ActiveSource(source, this.active.some(a => a.state != 0 /* Inactive */) ? 1 /* Pending */ : 0 /* Inactive */);
|
|
804
|
+
new ActiveSource(source, this.active.some(a => a.state != 0 /* State.Inactive */) ? 1 /* State.Pending */ : 0 /* State.Inactive */);
|
|
799
805
|
return value.update(tr, conf);
|
|
800
806
|
});
|
|
801
807
|
if (active.length == this.active.length && active.every((a, i) => a == this.active[i]))
|
|
@@ -806,10 +812,10 @@ class CompletionState {
|
|
|
806
812
|
if (tr.selection || active.some(a => a.hasResult() && tr.changes.touchesRange(a.from, a.to)) ||
|
|
807
813
|
!sameResults(active, this.active))
|
|
808
814
|
open = CompletionDialog.build(active, state, this.id, open, conf);
|
|
809
|
-
else if (open && open.disabled && !active.some(a => a.state == 1 /* Pending */))
|
|
815
|
+
else if (open && open.disabled && !active.some(a => a.state == 1 /* State.Pending */))
|
|
810
816
|
open = null;
|
|
811
|
-
if (!open && active.every(a => a.state != 1 /* Pending */) && active.some(a => a.hasResult()))
|
|
812
|
-
active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /* Inactive */) : a);
|
|
817
|
+
if (!open && active.every(a => a.state != 1 /* State.Pending */) && active.some(a => a.hasResult()))
|
|
818
|
+
active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /* State.Inactive */) : a);
|
|
813
819
|
for (let effect of tr.effects)
|
|
814
820
|
if (effect.is(setSelectedEffect))
|
|
815
821
|
open = open && open.setSelected(effect.value, this.id);
|
|
@@ -863,13 +869,13 @@ class ActiveSource {
|
|
|
863
869
|
value = value.handleUserEvent(tr, event, conf);
|
|
864
870
|
else if (tr.docChanged)
|
|
865
871
|
value = value.handleChange(tr);
|
|
866
|
-
else if (tr.selection && value.state != 0 /* Inactive */)
|
|
867
|
-
value = new ActiveSource(value.source, 0 /* Inactive */);
|
|
872
|
+
else if (tr.selection && value.state != 0 /* State.Inactive */)
|
|
873
|
+
value = new ActiveSource(value.source, 0 /* State.Inactive */);
|
|
868
874
|
for (let effect of tr.effects) {
|
|
869
875
|
if (effect.is(startCompletionEffect))
|
|
870
|
-
value = new ActiveSource(value.source, 1 /* Pending */, effect.value ? cur(tr.state) : -1);
|
|
876
|
+
value = new ActiveSource(value.source, 1 /* State.Pending */, effect.value ? cur(tr.state) : -1);
|
|
871
877
|
else if (effect.is(closeCompletionEffect))
|
|
872
|
-
value = new ActiveSource(value.source, 0 /* Inactive */);
|
|
878
|
+
value = new ActiveSource(value.source, 0 /* State.Inactive */);
|
|
873
879
|
else if (effect.is(setActiveEffect))
|
|
874
880
|
for (let active of effect.value)
|
|
875
881
|
if (active.source == value.source)
|
|
@@ -878,10 +884,10 @@ class ActiveSource {
|
|
|
878
884
|
return value;
|
|
879
885
|
}
|
|
880
886
|
handleUserEvent(tr, type, conf) {
|
|
881
|
-
return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* Pending */);
|
|
887
|
+
return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* State.Pending */);
|
|
882
888
|
}
|
|
883
889
|
handleChange(tr) {
|
|
884
|
-
return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
|
|
890
|
+
return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes);
|
|
885
891
|
}
|
|
886
892
|
map(changes) {
|
|
887
893
|
return changes.empty || this.explicitPos < 0 ? this : new ActiveSource(this.source, this.state, changes.mapPos(this.explicitPos));
|
|
@@ -889,7 +895,7 @@ class ActiveSource {
|
|
|
889
895
|
}
|
|
890
896
|
class ActiveResult extends ActiveSource {
|
|
891
897
|
constructor(source, explicitPos, result, from, to) {
|
|
892
|
-
super(source, 2 /* Result */, explicitPos);
|
|
898
|
+
super(source, 2 /* State.Result */, explicitPos);
|
|
893
899
|
this.result = result;
|
|
894
900
|
this.from = from;
|
|
895
901
|
this.to = to;
|
|
@@ -902,17 +908,17 @@ class ActiveResult extends ActiveSource {
|
|
|
902
908
|
if ((this.explicitPos < 0 ? pos <= from : pos < this.from) ||
|
|
903
909
|
pos > to ||
|
|
904
910
|
type == "delete" && cur(tr.startState) == this.from)
|
|
905
|
-
return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* Pending */ : 0 /* Inactive */);
|
|
911
|
+
return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* State.Pending */ : 0 /* State.Inactive */);
|
|
906
912
|
let explicitPos = this.explicitPos < 0 ? -1 : tr.changes.mapPos(this.explicitPos), updated;
|
|
907
913
|
if (checkValid(this.result.validFor, tr.state, from, to))
|
|
908
914
|
return new ActiveResult(this.source, explicitPos, this.result, from, to);
|
|
909
915
|
if (this.result.update &&
|
|
910
916
|
(updated = this.result.update(this.result, from, to, new CompletionContext(tr.state, pos, explicitPos >= 0))))
|
|
911
917
|
return new ActiveResult(this.source, explicitPos, updated, updated.from, (_a = updated.to) !== null && _a !== void 0 ? _a : cur(tr.state));
|
|
912
|
-
return new ActiveSource(this.source, 1 /* Pending */, explicitPos);
|
|
918
|
+
return new ActiveSource(this.source, 1 /* State.Pending */, explicitPos);
|
|
913
919
|
}
|
|
914
920
|
handleChange(tr) {
|
|
915
|
-
return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
|
|
921
|
+
return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes);
|
|
916
922
|
}
|
|
917
923
|
map(mapping) {
|
|
918
924
|
return mapping.empty ? this :
|
|
@@ -998,7 +1004,7 @@ Close the currently active completion.
|
|
|
998
1004
|
*/
|
|
999
1005
|
const closeCompletion = (view) => {
|
|
1000
1006
|
let cState = view.state.field(completionState, false);
|
|
1001
|
-
if (!cState || !cState.active.some(a => a.state != 0 /* Inactive */))
|
|
1007
|
+
if (!cState || !cState.active.some(a => a.state != 0 /* State.Inactive */))
|
|
1002
1008
|
return false;
|
|
1003
1009
|
view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
1004
1010
|
return true;
|
|
@@ -1021,9 +1027,9 @@ const completionPlugin = view.ViewPlugin.fromClass(class {
|
|
|
1021
1027
|
this.debounceUpdate = -1;
|
|
1022
1028
|
this.running = [];
|
|
1023
1029
|
this.debounceAccept = -1;
|
|
1024
|
-
this.composing = 0 /* None */;
|
|
1030
|
+
this.composing = 0 /* CompositionState.None */;
|
|
1025
1031
|
for (let active of view.state.field(completionState).active)
|
|
1026
|
-
if (active.state == 1 /* Pending */)
|
|
1032
|
+
if (active.state == 1 /* State.Pending */)
|
|
1027
1033
|
this.startQuery(active);
|
|
1028
1034
|
}
|
|
1029
1035
|
update(update) {
|
|
@@ -1054,21 +1060,21 @@ const completionPlugin = view.ViewPlugin.fromClass(class {
|
|
|
1054
1060
|
}
|
|
1055
1061
|
if (this.debounceUpdate > -1)
|
|
1056
1062
|
clearTimeout(this.debounceUpdate);
|
|
1057
|
-
this.debounceUpdate = cState.active.some(a => a.state == 1 /* Pending */ && !this.running.some(q => q.active.source == a.source))
|
|
1063
|
+
this.debounceUpdate = cState.active.some(a => a.state == 1 /* State.Pending */ && !this.running.some(q => q.active.source == a.source))
|
|
1058
1064
|
? setTimeout(() => this.startUpdate(), DebounceTime) : -1;
|
|
1059
|
-
if (this.composing != 0 /* None */)
|
|
1065
|
+
if (this.composing != 0 /* CompositionState.None */)
|
|
1060
1066
|
for (let tr of update.transactions) {
|
|
1061
1067
|
if (getUserEvent(tr) == "input")
|
|
1062
|
-
this.composing = 2 /* Changed */;
|
|
1063
|
-
else if (this.composing == 2 /* Changed */ && tr.selection)
|
|
1064
|
-
this.composing = 3 /* ChangedAndMoved */;
|
|
1068
|
+
this.composing = 2 /* CompositionState.Changed */;
|
|
1069
|
+
else if (this.composing == 2 /* CompositionState.Changed */ && tr.selection)
|
|
1070
|
+
this.composing = 3 /* CompositionState.ChangedAndMoved */;
|
|
1065
1071
|
}
|
|
1066
1072
|
}
|
|
1067
1073
|
startUpdate() {
|
|
1068
1074
|
this.debounceUpdate = -1;
|
|
1069
1075
|
let { state } = this.view, cState = state.field(completionState);
|
|
1070
1076
|
for (let active of cState.active) {
|
|
1071
|
-
if (active.state == 1 /* Pending */ && !this.running.some(r => r.active.source == active.source))
|
|
1077
|
+
if (active.state == 1 /* State.Pending */ && !this.running.some(r => r.active.source == active.source))
|
|
1072
1078
|
this.startQuery(active);
|
|
1073
1079
|
}
|
|
1074
1080
|
}
|
|
@@ -1119,14 +1125,14 @@ const completionPlugin = view.ViewPlugin.fromClass(class {
|
|
|
1119
1125
|
}
|
|
1120
1126
|
}
|
|
1121
1127
|
let current = this.view.state.field(completionState).active.find(a => a.source == query.active.source);
|
|
1122
|
-
if (current && current.state == 1 /* Pending */) {
|
|
1128
|
+
if (current && current.state == 1 /* State.Pending */) {
|
|
1123
1129
|
if (query.done == null) {
|
|
1124
1130
|
// Explicitly failed. Should clear the pending status if it
|
|
1125
1131
|
// hasn't been re-set in the meantime.
|
|
1126
|
-
let active = new ActiveSource(query.active.source, 0 /* Inactive */);
|
|
1132
|
+
let active = new ActiveSource(query.active.source, 0 /* State.Inactive */);
|
|
1127
1133
|
for (let tr of query.updates)
|
|
1128
1134
|
active = active.update(tr, conf);
|
|
1129
|
-
if (active.state != 1 /* Pending */)
|
|
1135
|
+
if (active.state != 1 /* State.Pending */)
|
|
1130
1136
|
updated.push(active);
|
|
1131
1137
|
}
|
|
1132
1138
|
else {
|
|
@@ -1149,15 +1155,15 @@ const completionPlugin = view.ViewPlugin.fromClass(class {
|
|
|
1149
1155
|
}
|
|
1150
1156
|
},
|
|
1151
1157
|
compositionstart() {
|
|
1152
|
-
this.composing = 1 /* Started */;
|
|
1158
|
+
this.composing = 1 /* CompositionState.Started */;
|
|
1153
1159
|
},
|
|
1154
1160
|
compositionend() {
|
|
1155
|
-
if (this.composing == 3 /* ChangedAndMoved */) {
|
|
1161
|
+
if (this.composing == 3 /* CompositionState.ChangedAndMoved */) {
|
|
1156
1162
|
// Safari fires compositionend events synchronously, possibly
|
|
1157
1163
|
// from inside an update, so dispatch asynchronously to avoid reentrancy
|
|
1158
1164
|
setTimeout(() => this.view.dispatch({ effects: startCompletionEffect.of(false) }), 20);
|
|
1159
1165
|
}
|
|
1160
|
-
this.composing = 0 /* None */;
|
|
1166
|
+
this.composing = 0 /* CompositionState.None */;
|
|
1161
1167
|
}
|
|
1162
1168
|
}
|
|
1163
1169
|
});
|
|
@@ -1217,13 +1223,13 @@ const baseTheme = view.EditorView.baseTheme({
|
|
|
1217
1223
|
position: "absolute",
|
|
1218
1224
|
padding: "3px 9px",
|
|
1219
1225
|
width: "max-content",
|
|
1220
|
-
maxWidth: `${400 /* Width */}px`,
|
|
1226
|
+
maxWidth: `${400 /* Info.Width */}px`,
|
|
1221
1227
|
boxSizing: "border-box"
|
|
1222
1228
|
},
|
|
1223
1229
|
".cm-completionInfo.cm-completionInfo-left": { right: "100%" },
|
|
1224
1230
|
".cm-completionInfo.cm-completionInfo-right": { left: "100%" },
|
|
1225
|
-
".cm-completionInfo.cm-completionInfo-left-narrow": { right: `${30 /* Margin */}px` },
|
|
1226
|
-
".cm-completionInfo.cm-completionInfo-right-narrow": { left: `${30 /* Margin */}px` },
|
|
1231
|
+
".cm-completionInfo.cm-completionInfo-left-narrow": { right: `${30 /* Info.Margin */}px` },
|
|
1232
|
+
".cm-completionInfo.cm-completionInfo-right-narrow": { left: `${30 /* Info.Margin */}px` },
|
|
1227
1233
|
"&light .cm-snippetField": { backgroundColor: "#00000022" },
|
|
1228
1234
|
"&dark .cm-snippetField": { backgroundColor: "#ffffff22" },
|
|
1229
1235
|
".cm-snippetFieldPosition": {
|
|
@@ -1474,7 +1480,8 @@ function moveField(dir) {
|
|
|
1474
1480
|
let next = active.active + dir, last = dir > 0 && !active.ranges.some(r => r.field == next + dir);
|
|
1475
1481
|
dispatch(state.update({
|
|
1476
1482
|
selection: fieldSelection(active.ranges, next),
|
|
1477
|
-
effects: setActive.of(last ? null : new ActiveSnippet(active.ranges, next))
|
|
1483
|
+
effects: setActive.of(last ? null : new ActiveSnippet(active.ranges, next)),
|
|
1484
|
+
scrollIntoView: true
|
|
1478
1485
|
}));
|
|
1479
1486
|
return true;
|
|
1480
1487
|
};
|
|
@@ -1546,7 +1553,9 @@ const snippetPointerHandler = view.EditorView.domEventHandlers({
|
|
|
1546
1553
|
return false;
|
|
1547
1554
|
view.dispatch({
|
|
1548
1555
|
selection: fieldSelection(active.ranges, match.field),
|
|
1549
|
-
effects: setActive.of(active.ranges.some(r => r.field > match.field)
|
|
1556
|
+
effects: setActive.of(active.ranges.some(r => r.field > match.field)
|
|
1557
|
+
? new ActiveSnippet(active.ranges, match.field) : null),
|
|
1558
|
+
scrollIntoView: true
|
|
1550
1559
|
});
|
|
1551
1560
|
return true;
|
|
1552
1561
|
}
|
|
@@ -1576,7 +1585,7 @@ function storeWords(doc, wordRE, result, seen, ignoreAt) {
|
|
|
1576
1585
|
if (!seen[m[0]] && pos + m.index != ignoreAt) {
|
|
1577
1586
|
result.push({ type: "text", label: m[0] });
|
|
1578
1587
|
seen[m[0]] = true;
|
|
1579
|
-
if (result.length >= 2000 /* MaxList */)
|
|
1588
|
+
if (result.length >= 2000 /* C.MaxList */)
|
|
1580
1589
|
return;
|
|
1581
1590
|
}
|
|
1582
1591
|
}
|
|
@@ -1584,7 +1593,7 @@ function storeWords(doc, wordRE, result, seen, ignoreAt) {
|
|
|
1584
1593
|
}
|
|
1585
1594
|
}
|
|
1586
1595
|
function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|
1587
|
-
let big = doc.length >= 1000 /* MinCacheLen */;
|
|
1596
|
+
let big = doc.length >= 1000 /* C.MinCacheLen */;
|
|
1588
1597
|
let cached = big && cache.get(doc);
|
|
1589
1598
|
if (cached)
|
|
1590
1599
|
return cached;
|
|
@@ -1592,7 +1601,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|
|
1592
1601
|
if (doc.children) {
|
|
1593
1602
|
let pos = 0;
|
|
1594
1603
|
for (let ch of doc.children) {
|
|
1595
|
-
if (ch.length >= 1000 /* MinCacheLen */) {
|
|
1604
|
+
if (ch.length >= 1000 /* C.MinCacheLen */) {
|
|
1596
1605
|
for (let c of collectWords(ch, cache, wordRE, to - pos, ignoreAt - pos)) {
|
|
1597
1606
|
if (!seen[c.label]) {
|
|
1598
1607
|
seen[c.label] = true;
|
|
@@ -1609,7 +1618,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|
|
1609
1618
|
else {
|
|
1610
1619
|
storeWords(doc, wordRE, result, seen, ignoreAt);
|
|
1611
1620
|
}
|
|
1612
|
-
if (big && result.length < 2000 /* MaxList */)
|
|
1621
|
+
if (big && result.length < 2000 /* C.MaxList */)
|
|
1613
1622
|
cache.set(doc, result);
|
|
1614
1623
|
return result;
|
|
1615
1624
|
}
|
|
@@ -1625,7 +1634,7 @@ const completeAnyWord = context => {
|
|
|
1625
1634
|
if (!token && !context.explicit)
|
|
1626
1635
|
return null;
|
|
1627
1636
|
let from = token ? token.from : context.pos;
|
|
1628
|
-
let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /* Range */, from);
|
|
1637
|
+
let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /* C.Range */, from);
|
|
1629
1638
|
return { from, options, validFor: mapRE(re, s => "^" + s) };
|
|
1630
1639
|
};
|
|
1631
1640
|
|
|
@@ -1917,8 +1926,8 @@ returns `null`.
|
|
|
1917
1926
|
*/
|
|
1918
1927
|
function completionStatus(state) {
|
|
1919
1928
|
let cState = state.field(completionState, false);
|
|
1920
|
-
return cState && cState.active.some(a => a.state == 1 /* Pending */) ? "pending"
|
|
1921
|
-
: cState && cState.active.some(a => a.state != 0 /* Inactive */) ? "active" : null;
|
|
1929
|
+
return cState && cState.active.some(a => a.state == 1 /* State.Pending */) ? "pending"
|
|
1930
|
+
: cState && cState.active.some(a => a.state != 0 /* State.Inactive */) ? "active" : null;
|
|
1922
1931
|
}
|
|
1923
1932
|
const completionArrayCache = new WeakMap;
|
|
1924
1933
|
/**
|
package/dist/index.d.cts
CHANGED
|
@@ -9,11 +9,18 @@ Objects type used to represent individual completions.
|
|
|
9
9
|
interface Completion {
|
|
10
10
|
/**
|
|
11
11
|
The label to show in the completion picker. This is what input
|
|
12
|
-
is matched
|
|
12
|
+
is matched against to determine whether a completion matches (and
|
|
13
13
|
how well it matches).
|
|
14
14
|
*/
|
|
15
15
|
label: string;
|
|
16
16
|
/**
|
|
17
|
+
An optional override for the completion's visible label. When
|
|
18
|
+
using this, matched characters will only be highlighted if you
|
|
19
|
+
provide a [`getMatch`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.getMatch)
|
|
20
|
+
function.
|
|
21
|
+
*/
|
|
22
|
+
displayLabel?: string;
|
|
23
|
+
/**
|
|
17
24
|
An optional short piece of information to show (with a different
|
|
18
25
|
style) after the label.
|
|
19
26
|
*/
|
|
@@ -68,7 +75,7 @@ The type returned from
|
|
|
68
75
|
node, null to indicate there is no info, or an object with an
|
|
69
76
|
optional `destroy` method that cleans up the node.
|
|
70
77
|
*/
|
|
71
|
-
|
|
78
|
+
type CompletionInfo = Node | null | {
|
|
72
79
|
dom: Node;
|
|
73
80
|
destroy?(): void;
|
|
74
81
|
};
|
|
@@ -189,7 +196,7 @@ may return its [result](https://codemirror.net/6/docs/ref/#autocomplete.Completi
|
|
|
189
196
|
synchronously or as a promise. Returning null indicates no
|
|
190
197
|
completions are available.
|
|
191
198
|
*/
|
|
192
|
-
|
|
199
|
+
type CompletionSource = (context: CompletionContext) => CompletionResult | null | Promise<CompletionResult | null>;
|
|
193
200
|
/**
|
|
194
201
|
Interface for objects returned by completion sources.
|
|
195
202
|
*/
|
|
@@ -230,12 +237,15 @@ interface CompletionResult {
|
|
|
230
237
|
filter?: boolean;
|
|
231
238
|
/**
|
|
232
239
|
When [`filter`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.filter) is set to
|
|
233
|
-
`false
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
240
|
+
`false` or a completion has a
|
|
241
|
+
[`displayLabel`](https://codemirror.net/6/docs/ref/#autocomplete.Completion.displayLabel), this
|
|
242
|
+
may be provided to compute the ranges on the label that match
|
|
243
|
+
the input. Should return an array of numbers where each pair of
|
|
244
|
+
adjacent numbers provide the start and end of a range. The
|
|
245
|
+
second argument, the match found by the library, is only passed
|
|
246
|
+
when `filter` isn't `false`.
|
|
237
247
|
*/
|
|
238
|
-
getMatch?: (completion: Completion) => readonly number[];
|
|
248
|
+
getMatch?: (completion: Completion, matched?: readonly number[]) => readonly number[];
|
|
239
249
|
/**
|
|
240
250
|
Synchronously update the completion result after typing or
|
|
241
251
|
deletion. If given, this should not do any expensive work, since
|
|
@@ -334,13 +344,13 @@ interface CompletionConfig {
|
|
|
334
344
|
position: number;
|
|
335
345
|
}[];
|
|
336
346
|
/**
|
|
337
|
-
By default, [info](https://codemirror.net/6/docs/ref/#
|
|
338
|
-
placed to the side of the selected. This option can
|
|
339
|
-
override that. It will be given rectangles for the
|
|
340
|
-
completions, the selected option, the info element, and
|
|
341
|
-
availble [tooltip
|
|
342
|
-
and should return
|
|
343
|
-
element.
|
|
347
|
+
By default, [info](https://codemirror.net/6/docs/ref/#autocomplete.Completion.info) tooltips are
|
|
348
|
+
placed to the side of the selected completion. This option can
|
|
349
|
+
be used to override that. It will be given rectangles for the
|
|
350
|
+
list of completions, the selected option, the info element, and
|
|
351
|
+
the availble [tooltip
|
|
352
|
+
space](https://codemirror.net/6/docs/ref/#view.tooltips^config.tooltipSpace), and should return
|
|
353
|
+
style and/or class strings for the info element.
|
|
344
354
|
*/
|
|
345
355
|
positionInfo?: (view: EditorView, list: Rect, option: Rect, info: Rect, space: Rect) => {
|
|
346
356
|
style?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -9,11 +9,18 @@ Objects type used to represent individual completions.
|
|
|
9
9
|
interface Completion {
|
|
10
10
|
/**
|
|
11
11
|
The label to show in the completion picker. This is what input
|
|
12
|
-
is matched
|
|
12
|
+
is matched against to determine whether a completion matches (and
|
|
13
13
|
how well it matches).
|
|
14
14
|
*/
|
|
15
15
|
label: string;
|
|
16
16
|
/**
|
|
17
|
+
An optional override for the completion's visible label. When
|
|
18
|
+
using this, matched characters will only be highlighted if you
|
|
19
|
+
provide a [`getMatch`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.getMatch)
|
|
20
|
+
function.
|
|
21
|
+
*/
|
|
22
|
+
displayLabel?: string;
|
|
23
|
+
/**
|
|
17
24
|
An optional short piece of information to show (with a different
|
|
18
25
|
style) after the label.
|
|
19
26
|
*/
|
|
@@ -68,7 +75,7 @@ The type returned from
|
|
|
68
75
|
node, null to indicate there is no info, or an object with an
|
|
69
76
|
optional `destroy` method that cleans up the node.
|
|
70
77
|
*/
|
|
71
|
-
|
|
78
|
+
type CompletionInfo = Node | null | {
|
|
72
79
|
dom: Node;
|
|
73
80
|
destroy?(): void;
|
|
74
81
|
};
|
|
@@ -189,7 +196,7 @@ may return its [result](https://codemirror.net/6/docs/ref/#autocomplete.Completi
|
|
|
189
196
|
synchronously or as a promise. Returning null indicates no
|
|
190
197
|
completions are available.
|
|
191
198
|
*/
|
|
192
|
-
|
|
199
|
+
type CompletionSource = (context: CompletionContext) => CompletionResult | null | Promise<CompletionResult | null>;
|
|
193
200
|
/**
|
|
194
201
|
Interface for objects returned by completion sources.
|
|
195
202
|
*/
|
|
@@ -230,12 +237,15 @@ interface CompletionResult {
|
|
|
230
237
|
filter?: boolean;
|
|
231
238
|
/**
|
|
232
239
|
When [`filter`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.filter) is set to
|
|
233
|
-
`false
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
240
|
+
`false` or a completion has a
|
|
241
|
+
[`displayLabel`](https://codemirror.net/6/docs/ref/#autocomplete.Completion.displayLabel), this
|
|
242
|
+
may be provided to compute the ranges on the label that match
|
|
243
|
+
the input. Should return an array of numbers where each pair of
|
|
244
|
+
adjacent numbers provide the start and end of a range. The
|
|
245
|
+
second argument, the match found by the library, is only passed
|
|
246
|
+
when `filter` isn't `false`.
|
|
237
247
|
*/
|
|
238
|
-
getMatch?: (completion: Completion) => readonly number[];
|
|
248
|
+
getMatch?: (completion: Completion, matched?: readonly number[]) => readonly number[];
|
|
239
249
|
/**
|
|
240
250
|
Synchronously update the completion result after typing or
|
|
241
251
|
deletion. If given, this should not do any expensive work, since
|
|
@@ -334,13 +344,13 @@ interface CompletionConfig {
|
|
|
334
344
|
position: number;
|
|
335
345
|
}[];
|
|
336
346
|
/**
|
|
337
|
-
By default, [info](https://codemirror.net/6/docs/ref/#
|
|
338
|
-
placed to the side of the selected. This option can
|
|
339
|
-
override that. It will be given rectangles for the
|
|
340
|
-
completions, the selected option, the info element, and
|
|
341
|
-
availble [tooltip
|
|
342
|
-
and should return
|
|
343
|
-
element.
|
|
347
|
+
By default, [info](https://codemirror.net/6/docs/ref/#autocomplete.Completion.info) tooltips are
|
|
348
|
+
placed to the side of the selected completion. This option can
|
|
349
|
+
be used to override that. It will be given rectangles for the
|
|
350
|
+
list of completions, the selected option, the info element, and
|
|
351
|
+
the availble [tooltip
|
|
352
|
+
space](https://codemirror.net/6/docs/ref/#view.tooltips^config.tooltipSpace), and should return
|
|
353
|
+
style and/or class strings for the info element.
|
|
344
354
|
*/
|
|
345
355
|
positionInfo?: (view: EditorView, list: Rect, option: Rect, info: Rect, space: Rect) => {
|
|
346
356
|
style?: string;
|
package/dist/index.js
CHANGED
|
@@ -171,7 +171,7 @@ function insertCompletionText(state, text, from, to) {
|
|
|
171
171
|
changes: { from: range.from + fromOff, to: to == main.from ? range.to : range.from + toOff, insert: text },
|
|
172
172
|
range: EditorSelection.cursor(range.from + fromOff + text.length)
|
|
173
173
|
};
|
|
174
|
-
})), { userEvent: "input.complete" });
|
|
174
|
+
})), { scrollIntoView: true, userEvent: "input.complete" });
|
|
175
175
|
}
|
|
176
176
|
const SourceCache = /*@__PURE__*/new WeakMap();
|
|
177
177
|
function asSource(source) {
|
|
@@ -198,6 +198,8 @@ class FuzzyMatcher {
|
|
|
198
198
|
this.any = [];
|
|
199
199
|
this.precise = [];
|
|
200
200
|
this.byWord = [];
|
|
201
|
+
this.score = 0;
|
|
202
|
+
this.matched = [];
|
|
201
203
|
for (let p = 0; p < pattern.length;) {
|
|
202
204
|
let char = codePointAt(pattern, p), size = codePointSize(char);
|
|
203
205
|
this.chars.push(char);
|
|
@@ -207,34 +209,39 @@ class FuzzyMatcher {
|
|
|
207
209
|
}
|
|
208
210
|
this.astral = pattern.length != this.chars.length;
|
|
209
211
|
}
|
|
212
|
+
ret(score, matched) {
|
|
213
|
+
this.score = score;
|
|
214
|
+
this.matched = matched;
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
210
217
|
// Matches a given word (completion) against the pattern (input).
|
|
211
|
-
// Will return
|
|
212
|
-
//
|
|
213
|
-
// indicating the matched parts of `word`.
|
|
218
|
+
// Will return a boolean indicating whether there was a match and,
|
|
219
|
+
// on success, set `this.score` to the score, `this.matched` to an
|
|
220
|
+
// array of `from, to` pairs indicating the matched parts of `word`.
|
|
214
221
|
//
|
|
215
222
|
// The score is a number that is more negative the worse the match
|
|
216
223
|
// is. See `Penalty` above.
|
|
217
224
|
match(word) {
|
|
218
225
|
if (this.pattern.length == 0)
|
|
219
|
-
return
|
|
226
|
+
return this.ret(-100 /* Penalty.NotFull */, []);
|
|
220
227
|
if (word.length < this.pattern.length)
|
|
221
|
-
return
|
|
228
|
+
return false;
|
|
222
229
|
let { chars, folded, any, precise, byWord } = this;
|
|
223
230
|
// For single-character queries, only match when they occur right
|
|
224
231
|
// at the start
|
|
225
232
|
if (chars.length == 1) {
|
|
226
233
|
let first = codePointAt(word, 0), firstSize = codePointSize(first);
|
|
227
|
-
let score = firstSize == word.length ? 0 : -100 /* NotFull */;
|
|
234
|
+
let score = firstSize == word.length ? 0 : -100 /* Penalty.NotFull */;
|
|
228
235
|
if (first == chars[0]) ;
|
|
229
236
|
else if (first == folded[0])
|
|
230
|
-
score += -200 /* CaseFold */;
|
|
237
|
+
score += -200 /* Penalty.CaseFold */;
|
|
231
238
|
else
|
|
232
|
-
return
|
|
233
|
-
return
|
|
239
|
+
return false;
|
|
240
|
+
return this.ret(score, [0, firstSize]);
|
|
234
241
|
}
|
|
235
242
|
let direct = word.indexOf(this.pattern);
|
|
236
243
|
if (direct == 0)
|
|
237
|
-
return
|
|
244
|
+
return this.ret(word.length == this.pattern.length ? 0 : -100 /* Penalty.NotFull */, [0, this.pattern.length]);
|
|
238
245
|
let len = chars.length, anyTo = 0;
|
|
239
246
|
if (direct < 0) {
|
|
240
247
|
for (let i = 0, e = Math.min(word.length, 200); i < e && anyTo < len;) {
|
|
@@ -245,7 +252,7 @@ class FuzzyMatcher {
|
|
|
245
252
|
}
|
|
246
253
|
// No match, exit immediately
|
|
247
254
|
if (anyTo < len)
|
|
248
|
-
return
|
|
255
|
+
return false;
|
|
249
256
|
}
|
|
250
257
|
// This tracks the extent of the precise (non-folded, not
|
|
251
258
|
// necessarily adjacent) match
|
|
@@ -258,7 +265,7 @@ class FuzzyMatcher {
|
|
|
258
265
|
let adjacentTo = 0, adjacentStart = -1, adjacentEnd = -1;
|
|
259
266
|
let hasLower = /[a-z]/.test(word), wordAdjacent = true;
|
|
260
267
|
// 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 /* NonWord */; i < e && byWordTo < len;) {
|
|
268
|
+
for (let i = 0, e = Math.min(word.length, 200), prevType = 0 /* Tp.NonWord */; i < e && byWordTo < len;) {
|
|
262
269
|
let next = codePointAt(word, i);
|
|
263
270
|
if (direct < 0) {
|
|
264
271
|
if (preciseTo < len && next == chars[preciseTo])
|
|
@@ -276,9 +283,9 @@ class FuzzyMatcher {
|
|
|
276
283
|
}
|
|
277
284
|
}
|
|
278
285
|
let ch, type = next < 0xff
|
|
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 */) {
|
|
286
|
+
? (next >= 48 && next <= 57 || next >= 97 && next <= 122 ? 2 /* Tp.Lower */ : next >= 65 && next <= 90 ? 1 /* Tp.Upper */ : 0 /* Tp.NonWord */)
|
|
287
|
+
: ((ch = fromCodePoint(next)) != ch.toLowerCase() ? 1 /* Tp.Upper */ : ch != ch.toUpperCase() ? 2 /* Tp.Lower */ : 0 /* Tp.NonWord */);
|
|
288
|
+
if (!i || type == 1 /* Tp.Upper */ && hasLower || prevType == 0 /* Tp.NonWord */ && type != 0 /* Tp.NonWord */) {
|
|
282
289
|
if (chars[byWordTo] == next || (folded[byWordTo] == next && (byWordFolded = true)))
|
|
283
290
|
byWord[byWordTo++] = i;
|
|
284
291
|
else if (byWord.length)
|
|
@@ -288,30 +295,31 @@ class FuzzyMatcher {
|
|
|
288
295
|
i += codePointSize(next);
|
|
289
296
|
}
|
|
290
297
|
if (byWordTo == len && byWord[0] == 0 && wordAdjacent)
|
|
291
|
-
return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0), byWord, word);
|
|
298
|
+
return this.result(-100 /* Penalty.ByWord */ + (byWordFolded ? -200 /* Penalty.CaseFold */ : 0), byWord, word);
|
|
292
299
|
if (adjacentTo == len && adjacentStart == 0)
|
|
293
|
-
return
|
|
300
|
+
return this.ret(-200 /* Penalty.CaseFold */ - word.length + (adjacentEnd == word.length ? 0 : -100 /* Penalty.NotFull */), [0, adjacentEnd]);
|
|
294
301
|
if (direct > -1)
|
|
295
|
-
return
|
|
302
|
+
return this.ret(-700 /* Penalty.NotStart */ - word.length, [direct, direct + this.pattern.length]);
|
|
296
303
|
if (adjacentTo == len)
|
|
297
|
-
return
|
|
304
|
+
return this.ret(-200 /* Penalty.CaseFold */ + -700 /* Penalty.NotStart */ - word.length, [adjacentStart, adjacentEnd]);
|
|
298
305
|
if (byWordTo == len)
|
|
299
|
-
return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0) + -700 /* NotStart */ +
|
|
300
|
-
(wordAdjacent ? 0 : -1100 /* Gap */), byWord, word);
|
|
301
|
-
return chars.length == 2 ?
|
|
306
|
+
return this.result(-100 /* Penalty.ByWord */ + (byWordFolded ? -200 /* Penalty.CaseFold */ : 0) + -700 /* Penalty.NotStart */ +
|
|
307
|
+
(wordAdjacent ? 0 : -1100 /* Penalty.Gap */), byWord, word);
|
|
308
|
+
return chars.length == 2 ? false
|
|
309
|
+
: this.result((any[0] ? -700 /* Penalty.NotStart */ : 0) + -200 /* Penalty.CaseFold */ + -1100 /* Penalty.Gap */, any, word);
|
|
302
310
|
}
|
|
303
311
|
result(score, positions, word) {
|
|
304
|
-
let result = [
|
|
312
|
+
let result = [], i = 0;
|
|
305
313
|
for (let pos of positions) {
|
|
306
314
|
let to = pos + (this.astral ? codePointSize(codePointAt(word, pos)) : 1);
|
|
307
|
-
if (i
|
|
315
|
+
if (i && result[i - 1] == pos)
|
|
308
316
|
result[i - 1] = to;
|
|
309
317
|
else {
|
|
310
318
|
result[i++] = pos;
|
|
311
319
|
result[i++] = to;
|
|
312
320
|
}
|
|
313
321
|
}
|
|
314
|
-
return result;
|
|
322
|
+
return this.ret(score - word.length, result);
|
|
315
323
|
}
|
|
316
324
|
}
|
|
317
325
|
|
|
@@ -345,7 +353,7 @@ const completionConfig = /*@__PURE__*/Facet.define({
|
|
|
345
353
|
function joinClass(a, b) {
|
|
346
354
|
return a ? b ? a + " " + b : a : b;
|
|
347
355
|
}
|
|
348
|
-
function defaultPositionInfo(view, list, option, info, space) {
|
|
356
|
+
function defaultPositionInfo(view, list, option, info, space, tooltip) {
|
|
349
357
|
let rtl = view.textDirection == Direction.RTL, left = rtl, narrow = false;
|
|
350
358
|
let side = "top", offset, maxWidth;
|
|
351
359
|
let spaceLeft = list.left - space.left, spaceRight = space.right - list.right;
|
|
@@ -356,11 +364,11 @@ function defaultPositionInfo(view, list, option, info, space) {
|
|
|
356
364
|
left = true;
|
|
357
365
|
if (infoWidth <= (left ? spaceLeft : spaceRight)) {
|
|
358
366
|
offset = Math.max(space.top, Math.min(option.top, space.bottom - infoHeight)) - list.top;
|
|
359
|
-
maxWidth = Math.min(400 /* Width */, left ? spaceLeft : spaceRight);
|
|
367
|
+
maxWidth = Math.min(400 /* Info.Width */, left ? spaceLeft : spaceRight);
|
|
360
368
|
}
|
|
361
369
|
else {
|
|
362
370
|
narrow = true;
|
|
363
|
-
maxWidth = Math.min(400 /* Width */, (rtl ? list.right : space.right - list.left) - 30 /* Margin */);
|
|
371
|
+
maxWidth = Math.min(400 /* Info.Width */, (rtl ? list.right : space.right - list.left) - 30 /* Info.Margin */);
|
|
364
372
|
let spaceBelow = space.bottom - list.bottom;
|
|
365
373
|
if (spaceBelow >= infoHeight || spaceBelow > list.top) { // Below the completion
|
|
366
374
|
offset = option.bottom - list.top;
|
|
@@ -370,8 +378,10 @@ function defaultPositionInfo(view, list, option, info, space) {
|
|
|
370
378
|
offset = list.bottom - option.top;
|
|
371
379
|
}
|
|
372
380
|
}
|
|
381
|
+
let scaleY = (list.bottom - list.top) / tooltip.offsetHeight;
|
|
382
|
+
let scaleX = (list.right - list.left) / tooltip.offsetWidth;
|
|
373
383
|
return {
|
|
374
|
-
style: `${side}: ${offset}px; max-width: ${maxWidth}px`,
|
|
384
|
+
style: `${side}: ${offset / scaleY}px; max-width: ${maxWidth / scaleX}px`,
|
|
375
385
|
class: "cm-completionInfo-" + (narrow ? (rtl ? "left-narrow" : "right-narrow") : left ? "left" : "right")
|
|
376
386
|
};
|
|
377
387
|
}
|
|
@@ -394,8 +404,8 @@ function optionContent(config) {
|
|
|
394
404
|
render(completion, _s, match) {
|
|
395
405
|
let labelElt = document.createElement("span");
|
|
396
406
|
labelElt.className = "cm-completionLabel";
|
|
397
|
-
let
|
|
398
|
-
for (let j =
|
|
407
|
+
let label = completion.displayLabel || completion.label, off = 0;
|
|
408
|
+
for (let j = 0; j < match.length;) {
|
|
399
409
|
let from = match[j++], to = match[j++];
|
|
400
410
|
if (from > off)
|
|
401
411
|
labelElt.appendChild(document.createTextNode(label.slice(off, from)));
|
|
@@ -591,7 +601,7 @@ class CompletionTooltip {
|
|
|
591
601
|
if (selRect.top > Math.min(space.bottom, listRect.bottom) - 10 ||
|
|
592
602
|
selRect.bottom < Math.max(space.top, listRect.top) + 10)
|
|
593
603
|
return null;
|
|
594
|
-
return this.view.state.facet(completionConfig).positionInfo(this.view, listRect, selRect, infoRect, space);
|
|
604
|
+
return this.view.state.facet(completionConfig).positionInfo(this.view, listRect, selRect, infoRect, space, this.dom);
|
|
595
605
|
}
|
|
596
606
|
placeInfo(pos) {
|
|
597
607
|
if (this.info) {
|
|
@@ -665,10 +675,11 @@ function completionTooltip(stateField, applyCompletion) {
|
|
|
665
675
|
function scrollIntoView(container, element) {
|
|
666
676
|
let parent = container.getBoundingClientRect();
|
|
667
677
|
let self = element.getBoundingClientRect();
|
|
678
|
+
let scaleY = parent.height / container.offsetHeight;
|
|
668
679
|
if (self.top < parent.top)
|
|
669
|
-
container.scrollTop -= parent.top - self.top;
|
|
680
|
+
container.scrollTop -= (parent.top - self.top) / scaleY;
|
|
670
681
|
else if (self.bottom > parent.bottom)
|
|
671
|
-
container.scrollTop += self.bottom - parent.bottom;
|
|
682
|
+
container.scrollTop += (self.bottom - parent.bottom) / scaleY;
|
|
672
683
|
}
|
|
673
684
|
|
|
674
685
|
// Used to pick a preferred option when two options with the same
|
|
@@ -693,21 +704,18 @@ function sortOptions(active, state) {
|
|
|
693
704
|
};
|
|
694
705
|
for (let a of active)
|
|
695
706
|
if (a.hasResult()) {
|
|
707
|
+
let getMatch = a.result.getMatch;
|
|
696
708
|
if (a.result.filter === false) {
|
|
697
|
-
let getMatch = a.result.getMatch;
|
|
698
709
|
for (let option of a.result.options) {
|
|
699
|
-
|
|
700
|
-
if (getMatch)
|
|
701
|
-
for (let n of getMatch(option))
|
|
702
|
-
match.push(n);
|
|
703
|
-
addOption(new Option(option, a.source, match, match[0]));
|
|
710
|
+
addOption(new Option(option, a.source, getMatch ? getMatch(option) : [], 1e9 - options.length));
|
|
704
711
|
}
|
|
705
712
|
}
|
|
706
713
|
else {
|
|
707
|
-
let matcher = new FuzzyMatcher(state.sliceDoc(a.from, a.to))
|
|
714
|
+
let matcher = new FuzzyMatcher(state.sliceDoc(a.from, a.to));
|
|
708
715
|
for (let option of a.result.options)
|
|
709
|
-
if (
|
|
710
|
-
|
|
716
|
+
if (matcher.match(option.label)) {
|
|
717
|
+
let matched = !option.displayLabel ? matcher.matched : getMatch ? getMatch(option, matcher.matched) : [];
|
|
718
|
+
addOption(new Option(option, a.source, matched, matcher.score + (option.boost || 0)));
|
|
711
719
|
}
|
|
712
720
|
}
|
|
713
721
|
}
|
|
@@ -754,7 +762,7 @@ class CompletionDialog {
|
|
|
754
762
|
static build(active, state, id, prev, conf) {
|
|
755
763
|
let options = sortOptions(active, state);
|
|
756
764
|
if (!options.length) {
|
|
757
|
-
return prev && active.some(a => a.state == 1 /* Pending */) ?
|
|
765
|
+
return prev && active.some(a => a.state == 1 /* State.Pending */) ?
|
|
758
766
|
new CompletionDialog(prev.options, prev.attrs, prev.tooltip, prev.timestamp, prev.selected, true) : null;
|
|
759
767
|
}
|
|
760
768
|
let selected = state.facet(completionConfig).selectOnOpen ? 0 : -1;
|
|
@@ -791,7 +799,7 @@ class CompletionState {
|
|
|
791
799
|
state.languageDataAt("autocomplete", cur(state)).map(asSource);
|
|
792
800
|
let active = sources.map(source => {
|
|
793
801
|
let value = this.active.find(s => s.source == source) ||
|
|
794
|
-
new ActiveSource(source, this.active.some(a => a.state != 0 /* Inactive */) ? 1 /* Pending */ : 0 /* Inactive */);
|
|
802
|
+
new ActiveSource(source, this.active.some(a => a.state != 0 /* State.Inactive */) ? 1 /* State.Pending */ : 0 /* State.Inactive */);
|
|
795
803
|
return value.update(tr, conf);
|
|
796
804
|
});
|
|
797
805
|
if (active.length == this.active.length && active.every((a, i) => a == this.active[i]))
|
|
@@ -802,10 +810,10 @@ class CompletionState {
|
|
|
802
810
|
if (tr.selection || active.some(a => a.hasResult() && tr.changes.touchesRange(a.from, a.to)) ||
|
|
803
811
|
!sameResults(active, this.active))
|
|
804
812
|
open = CompletionDialog.build(active, state, this.id, open, conf);
|
|
805
|
-
else if (open && open.disabled && !active.some(a => a.state == 1 /* Pending */))
|
|
813
|
+
else if (open && open.disabled && !active.some(a => a.state == 1 /* State.Pending */))
|
|
806
814
|
open = null;
|
|
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);
|
|
815
|
+
if (!open && active.every(a => a.state != 1 /* State.Pending */) && active.some(a => a.hasResult()))
|
|
816
|
+
active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /* State.Inactive */) : a);
|
|
809
817
|
for (let effect of tr.effects)
|
|
810
818
|
if (effect.is(setSelectedEffect))
|
|
811
819
|
open = open && open.setSelected(effect.value, this.id);
|
|
@@ -859,13 +867,13 @@ class ActiveSource {
|
|
|
859
867
|
value = value.handleUserEvent(tr, event, conf);
|
|
860
868
|
else if (tr.docChanged)
|
|
861
869
|
value = value.handleChange(tr);
|
|
862
|
-
else if (tr.selection && value.state != 0 /* Inactive */)
|
|
863
|
-
value = new ActiveSource(value.source, 0 /* Inactive */);
|
|
870
|
+
else if (tr.selection && value.state != 0 /* State.Inactive */)
|
|
871
|
+
value = new ActiveSource(value.source, 0 /* State.Inactive */);
|
|
864
872
|
for (let effect of tr.effects) {
|
|
865
873
|
if (effect.is(startCompletionEffect))
|
|
866
|
-
value = new ActiveSource(value.source, 1 /* Pending */, effect.value ? cur(tr.state) : -1);
|
|
874
|
+
value = new ActiveSource(value.source, 1 /* State.Pending */, effect.value ? cur(tr.state) : -1);
|
|
867
875
|
else if (effect.is(closeCompletionEffect))
|
|
868
|
-
value = new ActiveSource(value.source, 0 /* Inactive */);
|
|
876
|
+
value = new ActiveSource(value.source, 0 /* State.Inactive */);
|
|
869
877
|
else if (effect.is(setActiveEffect))
|
|
870
878
|
for (let active of effect.value)
|
|
871
879
|
if (active.source == value.source)
|
|
@@ -874,10 +882,10 @@ class ActiveSource {
|
|
|
874
882
|
return value;
|
|
875
883
|
}
|
|
876
884
|
handleUserEvent(tr, type, conf) {
|
|
877
|
-
return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* Pending */);
|
|
885
|
+
return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* State.Pending */);
|
|
878
886
|
}
|
|
879
887
|
handleChange(tr) {
|
|
880
|
-
return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
|
|
888
|
+
return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes);
|
|
881
889
|
}
|
|
882
890
|
map(changes) {
|
|
883
891
|
return changes.empty || this.explicitPos < 0 ? this : new ActiveSource(this.source, this.state, changes.mapPos(this.explicitPos));
|
|
@@ -885,7 +893,7 @@ class ActiveSource {
|
|
|
885
893
|
}
|
|
886
894
|
class ActiveResult extends ActiveSource {
|
|
887
895
|
constructor(source, explicitPos, result, from, to) {
|
|
888
|
-
super(source, 2 /* Result */, explicitPos);
|
|
896
|
+
super(source, 2 /* State.Result */, explicitPos);
|
|
889
897
|
this.result = result;
|
|
890
898
|
this.from = from;
|
|
891
899
|
this.to = to;
|
|
@@ -898,17 +906,17 @@ class ActiveResult extends ActiveSource {
|
|
|
898
906
|
if ((this.explicitPos < 0 ? pos <= from : pos < this.from) ||
|
|
899
907
|
pos > to ||
|
|
900
908
|
type == "delete" && cur(tr.startState) == this.from)
|
|
901
|
-
return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* Pending */ : 0 /* Inactive */);
|
|
909
|
+
return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* State.Pending */ : 0 /* State.Inactive */);
|
|
902
910
|
let explicitPos = this.explicitPos < 0 ? -1 : tr.changes.mapPos(this.explicitPos), updated;
|
|
903
911
|
if (checkValid(this.result.validFor, tr.state, from, to))
|
|
904
912
|
return new ActiveResult(this.source, explicitPos, this.result, from, to);
|
|
905
913
|
if (this.result.update &&
|
|
906
914
|
(updated = this.result.update(this.result, from, to, new CompletionContext(tr.state, pos, explicitPos >= 0))))
|
|
907
915
|
return new ActiveResult(this.source, explicitPos, updated, updated.from, (_a = updated.to) !== null && _a !== void 0 ? _a : cur(tr.state));
|
|
908
|
-
return new ActiveSource(this.source, 1 /* Pending */, explicitPos);
|
|
916
|
+
return new ActiveSource(this.source, 1 /* State.Pending */, explicitPos);
|
|
909
917
|
}
|
|
910
918
|
handleChange(tr) {
|
|
911
|
-
return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
|
|
919
|
+
return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes);
|
|
912
920
|
}
|
|
913
921
|
map(mapping) {
|
|
914
922
|
return mapping.empty ? this :
|
|
@@ -994,7 +1002,7 @@ Close the currently active completion.
|
|
|
994
1002
|
*/
|
|
995
1003
|
const closeCompletion = (view) => {
|
|
996
1004
|
let cState = view.state.field(completionState, false);
|
|
997
|
-
if (!cState || !cState.active.some(a => a.state != 0 /* Inactive */))
|
|
1005
|
+
if (!cState || !cState.active.some(a => a.state != 0 /* State.Inactive */))
|
|
998
1006
|
return false;
|
|
999
1007
|
view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
1000
1008
|
return true;
|
|
@@ -1017,9 +1025,9 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
1017
1025
|
this.debounceUpdate = -1;
|
|
1018
1026
|
this.running = [];
|
|
1019
1027
|
this.debounceAccept = -1;
|
|
1020
|
-
this.composing = 0 /* None */;
|
|
1028
|
+
this.composing = 0 /* CompositionState.None */;
|
|
1021
1029
|
for (let active of view.state.field(completionState).active)
|
|
1022
|
-
if (active.state == 1 /* Pending */)
|
|
1030
|
+
if (active.state == 1 /* State.Pending */)
|
|
1023
1031
|
this.startQuery(active);
|
|
1024
1032
|
}
|
|
1025
1033
|
update(update) {
|
|
@@ -1050,21 +1058,21 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
1050
1058
|
}
|
|
1051
1059
|
if (this.debounceUpdate > -1)
|
|
1052
1060
|
clearTimeout(this.debounceUpdate);
|
|
1053
|
-
this.debounceUpdate = cState.active.some(a => a.state == 1 /* Pending */ && !this.running.some(q => q.active.source == a.source))
|
|
1061
|
+
this.debounceUpdate = cState.active.some(a => a.state == 1 /* State.Pending */ && !this.running.some(q => q.active.source == a.source))
|
|
1054
1062
|
? setTimeout(() => this.startUpdate(), DebounceTime) : -1;
|
|
1055
|
-
if (this.composing != 0 /* None */)
|
|
1063
|
+
if (this.composing != 0 /* CompositionState.None */)
|
|
1056
1064
|
for (let tr of update.transactions) {
|
|
1057
1065
|
if (getUserEvent(tr) == "input")
|
|
1058
|
-
this.composing = 2 /* Changed */;
|
|
1059
|
-
else if (this.composing == 2 /* Changed */ && tr.selection)
|
|
1060
|
-
this.composing = 3 /* ChangedAndMoved */;
|
|
1066
|
+
this.composing = 2 /* CompositionState.Changed */;
|
|
1067
|
+
else if (this.composing == 2 /* CompositionState.Changed */ && tr.selection)
|
|
1068
|
+
this.composing = 3 /* CompositionState.ChangedAndMoved */;
|
|
1061
1069
|
}
|
|
1062
1070
|
}
|
|
1063
1071
|
startUpdate() {
|
|
1064
1072
|
this.debounceUpdate = -1;
|
|
1065
1073
|
let { state } = this.view, cState = state.field(completionState);
|
|
1066
1074
|
for (let active of cState.active) {
|
|
1067
|
-
if (active.state == 1 /* Pending */ && !this.running.some(r => r.active.source == active.source))
|
|
1075
|
+
if (active.state == 1 /* State.Pending */ && !this.running.some(r => r.active.source == active.source))
|
|
1068
1076
|
this.startQuery(active);
|
|
1069
1077
|
}
|
|
1070
1078
|
}
|
|
@@ -1115,14 +1123,14 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
1115
1123
|
}
|
|
1116
1124
|
}
|
|
1117
1125
|
let current = this.view.state.field(completionState).active.find(a => a.source == query.active.source);
|
|
1118
|
-
if (current && current.state == 1 /* Pending */) {
|
|
1126
|
+
if (current && current.state == 1 /* State.Pending */) {
|
|
1119
1127
|
if (query.done == null) {
|
|
1120
1128
|
// Explicitly failed. Should clear the pending status if it
|
|
1121
1129
|
// hasn't been re-set in the meantime.
|
|
1122
|
-
let active = new ActiveSource(query.active.source, 0 /* Inactive */);
|
|
1130
|
+
let active = new ActiveSource(query.active.source, 0 /* State.Inactive */);
|
|
1123
1131
|
for (let tr of query.updates)
|
|
1124
1132
|
active = active.update(tr, conf);
|
|
1125
|
-
if (active.state != 1 /* Pending */)
|
|
1133
|
+
if (active.state != 1 /* State.Pending */)
|
|
1126
1134
|
updated.push(active);
|
|
1127
1135
|
}
|
|
1128
1136
|
else {
|
|
@@ -1145,15 +1153,15 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
1145
1153
|
}
|
|
1146
1154
|
},
|
|
1147
1155
|
compositionstart() {
|
|
1148
|
-
this.composing = 1 /* Started */;
|
|
1156
|
+
this.composing = 1 /* CompositionState.Started */;
|
|
1149
1157
|
},
|
|
1150
1158
|
compositionend() {
|
|
1151
|
-
if (this.composing == 3 /* ChangedAndMoved */) {
|
|
1159
|
+
if (this.composing == 3 /* CompositionState.ChangedAndMoved */) {
|
|
1152
1160
|
// Safari fires compositionend events synchronously, possibly
|
|
1153
1161
|
// from inside an update, so dispatch asynchronously to avoid reentrancy
|
|
1154
1162
|
setTimeout(() => this.view.dispatch({ effects: startCompletionEffect.of(false) }), 20);
|
|
1155
1163
|
}
|
|
1156
|
-
this.composing = 0 /* None */;
|
|
1164
|
+
this.composing = 0 /* CompositionState.None */;
|
|
1157
1165
|
}
|
|
1158
1166
|
}
|
|
1159
1167
|
});
|
|
@@ -1213,13 +1221,13 @@ const baseTheme = /*@__PURE__*/EditorView.baseTheme({
|
|
|
1213
1221
|
position: "absolute",
|
|
1214
1222
|
padding: "3px 9px",
|
|
1215
1223
|
width: "max-content",
|
|
1216
|
-
maxWidth: `${400 /* Width */}px`,
|
|
1224
|
+
maxWidth: `${400 /* Info.Width */}px`,
|
|
1217
1225
|
boxSizing: "border-box"
|
|
1218
1226
|
},
|
|
1219
1227
|
".cm-completionInfo.cm-completionInfo-left": { right: "100%" },
|
|
1220
1228
|
".cm-completionInfo.cm-completionInfo-right": { left: "100%" },
|
|
1221
|
-
".cm-completionInfo.cm-completionInfo-left-narrow": { right: `${30 /* Margin */}px` },
|
|
1222
|
-
".cm-completionInfo.cm-completionInfo-right-narrow": { left: `${30 /* Margin */}px` },
|
|
1229
|
+
".cm-completionInfo.cm-completionInfo-left-narrow": { right: `${30 /* Info.Margin */}px` },
|
|
1230
|
+
".cm-completionInfo.cm-completionInfo-right-narrow": { left: `${30 /* Info.Margin */}px` },
|
|
1223
1231
|
"&light .cm-snippetField": { backgroundColor: "#00000022" },
|
|
1224
1232
|
"&dark .cm-snippetField": { backgroundColor: "#ffffff22" },
|
|
1225
1233
|
".cm-snippetFieldPosition": {
|
|
@@ -1470,7 +1478,8 @@ function moveField(dir) {
|
|
|
1470
1478
|
let next = active.active + dir, last = dir > 0 && !active.ranges.some(r => r.field == next + dir);
|
|
1471
1479
|
dispatch(state.update({
|
|
1472
1480
|
selection: fieldSelection(active.ranges, next),
|
|
1473
|
-
effects: setActive.of(last ? null : new ActiveSnippet(active.ranges, next))
|
|
1481
|
+
effects: setActive.of(last ? null : new ActiveSnippet(active.ranges, next)),
|
|
1482
|
+
scrollIntoView: true
|
|
1474
1483
|
}));
|
|
1475
1484
|
return true;
|
|
1476
1485
|
};
|
|
@@ -1542,7 +1551,9 @@ const snippetPointerHandler = /*@__PURE__*/EditorView.domEventHandlers({
|
|
|
1542
1551
|
return false;
|
|
1543
1552
|
view.dispatch({
|
|
1544
1553
|
selection: fieldSelection(active.ranges, match.field),
|
|
1545
|
-
effects: setActive.of(active.ranges.some(r => r.field > match.field)
|
|
1554
|
+
effects: setActive.of(active.ranges.some(r => r.field > match.field)
|
|
1555
|
+
? new ActiveSnippet(active.ranges, match.field) : null),
|
|
1556
|
+
scrollIntoView: true
|
|
1546
1557
|
});
|
|
1547
1558
|
return true;
|
|
1548
1559
|
}
|
|
@@ -1572,7 +1583,7 @@ function storeWords(doc, wordRE, result, seen, ignoreAt) {
|
|
|
1572
1583
|
if (!seen[m[0]] && pos + m.index != ignoreAt) {
|
|
1573
1584
|
result.push({ type: "text", label: m[0] });
|
|
1574
1585
|
seen[m[0]] = true;
|
|
1575
|
-
if (result.length >= 2000 /* MaxList */)
|
|
1586
|
+
if (result.length >= 2000 /* C.MaxList */)
|
|
1576
1587
|
return;
|
|
1577
1588
|
}
|
|
1578
1589
|
}
|
|
@@ -1580,7 +1591,7 @@ function storeWords(doc, wordRE, result, seen, ignoreAt) {
|
|
|
1580
1591
|
}
|
|
1581
1592
|
}
|
|
1582
1593
|
function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|
1583
|
-
let big = doc.length >= 1000 /* MinCacheLen */;
|
|
1594
|
+
let big = doc.length >= 1000 /* C.MinCacheLen */;
|
|
1584
1595
|
let cached = big && cache.get(doc);
|
|
1585
1596
|
if (cached)
|
|
1586
1597
|
return cached;
|
|
@@ -1588,7 +1599,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|
|
1588
1599
|
if (doc.children) {
|
|
1589
1600
|
let pos = 0;
|
|
1590
1601
|
for (let ch of doc.children) {
|
|
1591
|
-
if (ch.length >= 1000 /* MinCacheLen */) {
|
|
1602
|
+
if (ch.length >= 1000 /* C.MinCacheLen */) {
|
|
1592
1603
|
for (let c of collectWords(ch, cache, wordRE, to - pos, ignoreAt - pos)) {
|
|
1593
1604
|
if (!seen[c.label]) {
|
|
1594
1605
|
seen[c.label] = true;
|
|
@@ -1605,7 +1616,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|
|
1605
1616
|
else {
|
|
1606
1617
|
storeWords(doc, wordRE, result, seen, ignoreAt);
|
|
1607
1618
|
}
|
|
1608
|
-
if (big && result.length < 2000 /* MaxList */)
|
|
1619
|
+
if (big && result.length < 2000 /* C.MaxList */)
|
|
1609
1620
|
cache.set(doc, result);
|
|
1610
1621
|
return result;
|
|
1611
1622
|
}
|
|
@@ -1621,7 +1632,7 @@ const completeAnyWord = context => {
|
|
|
1621
1632
|
if (!token && !context.explicit)
|
|
1622
1633
|
return null;
|
|
1623
1634
|
let from = token ? token.from : context.pos;
|
|
1624
|
-
let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /* Range */, from);
|
|
1635
|
+
let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /* C.Range */, from);
|
|
1625
1636
|
return { from, options, validFor: mapRE(re, s => "^" + s) };
|
|
1626
1637
|
};
|
|
1627
1638
|
|
|
@@ -1913,8 +1924,8 @@ returns `null`.
|
|
|
1913
1924
|
*/
|
|
1914
1925
|
function completionStatus(state) {
|
|
1915
1926
|
let cState = state.field(completionState, false);
|
|
1916
|
-
return cState && cState.active.some(a => a.state == 1 /* Pending */) ? "pending"
|
|
1917
|
-
: cState && cState.active.some(a => a.state != 0 /* Inactive */) ? "active" : null;
|
|
1927
|
+
return cState && cState.active.some(a => a.state == 1 /* State.Pending */) ? "pending"
|
|
1928
|
+
: cState && cState.active.some(a => a.state != 0 /* State.Inactive */) ? "active" : null;
|
|
1918
1929
|
}
|
|
1919
1930
|
const completionArrayCache = /*@__PURE__*/new WeakMap;
|
|
1920
1931
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codemirror/autocomplete",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.9.1",
|
|
4
4
|
"description": "Autocompletion for the CodeMirror code editor",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "cm-runtests",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@codemirror/language": "^6.0.0",
|
|
30
30
|
"@codemirror/state": "^6.0.0",
|
|
31
|
-
"@codemirror/view": "^6.
|
|
31
|
+
"@codemirror/view": "^6.17.0",
|
|
32
32
|
"@lezer/common": "^1.0.0"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|