Skip to content
This repository has been archived by the owner on Dec 15, 2022. It is now read-only.

Implement the Provider API 4.1.0 with the new RFC #1102

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 123 additions & 22 deletions lib/autocomplete-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,12 @@ class AutocompleteManager {

if (provider.filterSuggestions) {
providerSuggestions = this.filterSuggestions(providerSuggestions, options)
if (apiVersion <= 4) {
providerSuggestions = this.sortSuggestions(providerSuggestions, options)
}
}
if (provider.sortSuggestions) {
providerSuggestions = this.sortSuggestions(providerSuggestions, options)
}
return providerSuggestions
}))
Expand All @@ -363,30 +369,60 @@ class AutocompleteManager {
)
}

filterSuggestions (suggestions, {prefix}) {
filterSuggestions (suggestions, {prefix, editor}) {
const results = []
const fuzzaldrinProvider = this.useAlternateScoring ? fuzzaldrinPlus : fuzzaldrin
for (let i = 0; i < suggestions.length; i++) {
// sortScore mostly preserves in the original sorting. The function is
// chosen such that suggestions with a very high match score can break out.
let score
const suggestion = suggestions[i]
suggestion.sortScore = Math.max((-i / 10) + 3, 0) + 1
suggestion.score = null

const text = (suggestion.snippet || suggestion.text)
const suggestionPrefix = suggestion.replacementPrefix != null ? suggestion.replacementPrefix : prefix
let text = (suggestion.filterText || suggestion.snippet || suggestion.text)
if (typeof text === 'object') {
text = text.newText
}
let suggestionPrefix
if (typeof (suggestion.snippet || suggestion.text) === 'object') {
suggestionPrefix = editor.getTextInBufferRange((suggestion.snippet || suggestion.text).range)
} else {
suggestionPrefix = suggestion.replacementPrefix != null ? suggestion.replacementPrefix : prefix
}
const prefixIsEmpty = !suggestionPrefix || suggestionPrefix === ' '
const firstCharIsMatch = !prefixIsEmpty && suggestionPrefix[0].toLowerCase() === text[0].toLowerCase()

if (prefixIsEmpty) {
results.push(suggestion)
}
if (firstCharIsMatch && (score = fuzzaldrinProvider.score(text, suggestionPrefix)) > 0) {
suggestion.score = score * suggestion.sortScore
if (firstCharIsMatch && fuzzaldrinProvider.score(text, suggestionPrefix) > 0) {
results.push(suggestion)
}
}
return results
}

sortSuggestions (suggestions, {prefix}) {
const fuzzaldrinProvider = this.useAlternateScoring ? fuzzaldrinPlus : fuzzaldrin
for (let i = 0; i < suggestions.length; i++) {
let score
const suggestion = suggestions[i]
suggestion.sortScore = Math.max((-i / 10) + 3, 0) + 1
suggestion.score = null

let text = (suggestion.sortText || suggestion.snippet || suggestion.text)
if (typeof text === 'object') {
text = text.newText
}
let suggestionPrefix
if (typeof (suggestion.snippet || suggestion.text) === 'object') {
suggestionPrefix = editor.getTextInBufferRange((suggestion.snippet || suggestion.text).range)
} else {
suggestionPrefix = suggestion.replacementPrefix != null ? suggestion.replacementPrefix : prefix
}
if (score = fuzzaldrinProvider.score(text, suggestionPrefix) > 0) {
suggestion.score = score * suggestion.sortScore
}
}

results.sort(this.reverseSortOnScoreComparator)
return results
Expand Down Expand Up @@ -619,23 +655,44 @@ See https://github.com/atom/autocomplete-plus/wiki/Provider-API`
return this.editor.transact(() => {
for (let i = 0; i < cursors.length; i++) {
const cursor = cursors[i]
const endPosition = cursor.getBufferPosition()
const beginningPosition = [endPosition.row, endPosition.column - suggestion.replacementPrefix.length]

if (this.editor.getTextInBufferRange([beginningPosition, endPosition]) === suggestion.replacementPrefix) {
const suffix = this.consumeSuffix ? this.getSuffix(this.editor, endPosition, suggestion) : ''
if (suffix.length) { cursor.moveRight(suffix.length) }
cursor.selection.selectLeft(suggestion.replacementPrefix.length + suffix.length)

if ((suggestion.snippet != null) && (this.snippetsManager != null)) {
this.snippetsManager.insertSnippet(suggestion.snippet, this.editor, cursor)
} else {
cursor.selection.insertText(suggestion.text != null ? suggestion.text : suggestion.snippet, {
autoIndentNewline: this.editor.shouldAutoIndent(),
autoDecreaseIndent: this.editor.shouldAutoIndent()
let replacementRange, newText
if (typeof suggestion.text === 'object' || typeof suggestion.snippet === 'object') {
replacementRange = (suggestion.text || suggestion.snippet).range
newText = (suggestion.text || suggestion.snippet).newText
} else {
const beginningPosition = cursor.getBufferPosition().translate([0, -suggestion.replacementPrefix.length])
const suffix = this.consumeSuffix ? this.getSuffix(this.editor, cursor.getBufferPosition(), suggestion) : ''
replacementRange = new Range(
beginningPosition,
cursor.getBufferPosition().translate([0, suffix.length])
)
newText = (suggestion.text || suggestion.snippet)
}

if (suggestion.additionalTextEdits) {
for (const textEdit of suggestion.additionalTextEdits) {
cursor.setBufferPosition(textEdit.range.start)
cursor.selection.selectToBufferPosition(textEdit.range.end)
cursor.selection.insertText(newText, {
autoIndent: false,
autoIndentNewline: false,
autoDecreaseIndent: false,
})
}
}

cursor.setBufferPosition(replacementRange.end)
cursor.selection.selectToBufferPosition(replacementRange.start)

if ((suggestion.snippet != null) && (this.snippetsManager != null)) {
this.snippetsManager.insertSnippet(newText, this.editor, cursor)
} else {
cursor.selection.insertText(newText, {
autoIndent: false,
autoIndentNewline: false,
autoDecreaseIndent: false,
})
}
}
}
)
Expand Down Expand Up @@ -718,7 +775,7 @@ See https://github.com/atom/autocomplete-plus/wiki/Provider-API`
// bufferChanged handler decides to show suggestions, it will cancel the
// hideSuggestionList request. If there is no bufferChanged event,
// suggestionList will be hidden.
if (!textChanged) this.requestHideSuggestionList()
if (!textChanged) setTimeout(() => this.requestHideSuggestionList(), 100);
}

// Private: Gets called when the user saves the document. Cancels the
Expand All @@ -736,6 +793,26 @@ See https://github.com/atom/autocomplete-plus/wiki/Provider-API`
})
if (!changeOccurredNearLastCursor) return

if (this.shouldDisplaySuggestions) {
// The suggestion list is already shown, check if the newly typed character
// is a commit character for the currently selected suggestion.
for (const change of changes) {
if (!change.newRange.containsPoint(lastCursorPosition)) {
return false
}

const selectedSuggestion = this.suggestionList.suggestionListElement.getSelectedItem()
const commitCharacters = selectedSuggestion && selectedSuggestion.commitCharacters || []
for (const char of commitCharacters) {
if (change.newText.startsWith(char)) {
this.addCommitCharacter(selectedSuggestion, char)
this.confirm(selectedSuggestion)
return
}
}
}
}

let shouldActivate = false
if (this.autoActivationEnabled || this.suggestionList.isActive() && !this.compositionInProgress) {
shouldActivate = changes.some(({oldText, newText}) => {
Expand Down Expand Up @@ -767,6 +844,30 @@ See https://github.com/atom/autocomplete-plus/wiki/Provider-API`
}
}

addCommitCharacter (suggestion, character) {
if (suggestion.snippet != null) {
if (typeof suggestion.snippet === 'object') {
suggestion.snippet.newText += character
suggestion.snippet.range = new Range(
suggestion.snippet.range.start,
suggestion.snippet.range.end.translate([0, character.length]),
)
} else {
suggestion.snippet += character
}
} else {
if (typeof suggestion.text === 'object') {
suggestion.text.newText += character
suggestion.text.range = new Range(
suggestion.text.range.start,
suggestion.text.range.end.translate([0, character.length]),
)
} else {
suggestion.text += character
}
}
}

shouldSuppressActivationForEditorClasses () {
for (let i = 0; i < this.suppressForClasses.length; i++) {
const classNames = this.suppressForClasses[i]
Expand Down
4 changes: 4 additions & 0 deletions lib/suggestion-list-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ module.exports = class SuggestionListElement {
})
)
this.setDescriptionMoreLink(item)
} else if (item.descriptionHTML && item.descriptionHTML.length > 0) {
this.descriptionContainer.style.display = 'block'
this.descriptionContent.innerHTML = createDOMPurify().sanitize(item.descriptionHTML)
this.setDescriptionMoreLink(item)
} else if (item.description && item.description.length > 0) {
this.descriptionContainer.style.display = 'block'
this.descriptionContent.textContent = item.description
Expand Down