Skip to content

Commit ee22fa2

Browse files
committed
Add support for CompletionResult.map
FEATURE: Completion results can now define a `map` method that can be used to adjust position-dependent information for document changes. Issue codemirror/dev#1347
1 parent e29c830 commit ee22fa2

File tree

2 files changed

+21
-11
lines changed

2 files changed

+21
-11
lines changed

src/completion.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {EditorView} from "@codemirror/view"
2-
import {EditorState, StateEffect, Annotation, EditorSelection, TransactionSpec} from "@codemirror/state"
2+
import {EditorState, StateEffect, Annotation, EditorSelection, TransactionSpec, ChangeDesc} from "@codemirror/state"
33
import {syntaxTree} from "@codemirror/language"
44
import {SyntaxNode} from "@lezer/common"
55

@@ -232,6 +232,12 @@ export interface CompletionResult {
232232
/// [`validFor`](#autocomplete.CompletionResult.validFor)) that the
233233
/// completion still applies in the new state.
234234
update?: (current: CompletionResult, from: number, to: number, context: CompletionContext) => CompletionResult | null
235+
/// When results contain position-dependent information in, for
236+
/// example, `apply` methods, you can provide this method to update
237+
/// the result for transactions that happen after the query. It is
238+
/// not necessary to update `from` and `to`—those are tracked
239+
/// automatically.
240+
map?: (current: CompletionResult, changes: ChangeDesc) => CompletionResult | null
235241
/// Set a default set of [commit
236242
/// characters](#autocomplete.Completion.commitCharacters) for all
237243
/// options in this result.

src/state.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -240,18 +240,20 @@ export class ActiveResult extends ActiveSource {
240240
hasResult(): this is ActiveResult { return true }
241241

242242
handleUserEvent(tr: Transaction, type: "input" | "delete", conf: Required<CompletionConfig>): ActiveSource {
243+
let result = this.result as CompletionResult | null
244+
if (result!.map && !tr.changes.empty) result = result!.map(result!, tr.changes)
243245
let from = tr.changes.mapPos(this.from), to = tr.changes.mapPos(this.to, 1)
244246
let pos = cur(tr.state)
245247
if ((this.explicitPos < 0 ? pos <= from : pos < this.from) ||
246-
pos > to ||
248+
pos > to || !result ||
247249
type == "delete" && cur(tr.startState) == this.from)
248250
return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? State.Pending : State.Inactive)
249-
let explicitPos = this.explicitPos < 0 ? -1 : tr.changes.mapPos(this.explicitPos), updated
250-
if (checkValid(this.result.validFor, tr.state, from, to))
251-
return new ActiveResult(this.source, explicitPos, this.result, from, to)
252-
if (this.result.update &&
253-
(updated = this.result.update(this.result, from, to, new CompletionContext(tr.state, pos, explicitPos >= 0))))
254-
return new ActiveResult(this.source, explicitPos, updated, updated.from, updated.to ?? cur(tr.state))
251+
let explicitPos = this.explicitPos < 0 ? -1 : tr.changes.mapPos(this.explicitPos)
252+
if (checkValid(result.validFor, tr.state, from, to))
253+
return new ActiveResult(this.source, explicitPos, result, from, to)
254+
if (result.update &&
255+
(result = result.update(result, from, to, new CompletionContext(tr.state, pos, explicitPos >= 0))))
256+
return new ActiveResult(this.source, explicitPos, result, result.from, result.to ?? cur(tr.state))
255257
return new ActiveSource(this.source, State.Pending, explicitPos)
256258
}
257259

@@ -260,9 +262,11 @@ export class ActiveResult extends ActiveSource {
260262
}
261263

262264
map(mapping: ChangeDesc) {
263-
return mapping.empty ? this :
264-
new ActiveResult(this.source, this.explicitPos < 0 ? -1 : mapping.mapPos(this.explicitPos), this.result,
265-
mapping.mapPos(this.from), mapping.mapPos(this.to, 1))
265+
if (mapping.empty) return this
266+
let result = this.result.map ? this.result.map(this.result, mapping) : this.result
267+
if (!result) return new ActiveSource(this.source, State.Inactive)
268+
return new ActiveResult(this.source, this.explicitPos < 0 ? -1 : mapping.mapPos(this.explicitPos), this.result,
269+
mapping.mapPos(this.from), mapping.mapPos(this.to, 1))
266270
}
267271
}
268272

0 commit comments

Comments
 (0)