debt - move scoring into completion model, honor the text range of each completion item
This commit is contained in:
parent
23b0b3da56
commit
2bc4681760
2 changed files with 48 additions and 37 deletions
|
@ -166,23 +166,6 @@ class Delegate implements IDelegate<CompletionItem> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function computeScore(suggestion: string, currentWord: string, currentWordLowerCase: string): number {
|
|
||||||
const suggestionLowerCase = suggestion.toLowerCase();
|
|
||||||
let score = 0;
|
|
||||||
|
|
||||||
for (let i = 0; i < currentWord.length && i < suggestion.length; i++) {
|
|
||||||
if (currentWord[i] === suggestion[i]) {
|
|
||||||
score += 2;
|
|
||||||
} else if (currentWordLowerCase[i] === suggestionLowerCase[i]) {
|
|
||||||
score += 1;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return score;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum State {
|
enum State {
|
||||||
Hidden,
|
Hidden,
|
||||||
Loading,
|
Loading,
|
||||||
|
@ -592,21 +575,10 @@ export class SuggestWidget implements IContentWidget, IDisposable {
|
||||||
this.completionModel = null;
|
this.completionModel = null;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
const currentWord = e.currentWord;
|
// TODO@joao,joh move this to a better place
|
||||||
const currentWordLowerCase = currentWord.toLowerCase();
|
|
||||||
let snippetCount = 0;
|
let snippetCount = 0;
|
||||||
let textCount = 0;
|
let textCount = 0;
|
||||||
let bestSuggestionIndex = -1;
|
|
||||||
let bestScore = -1;
|
|
||||||
|
|
||||||
this.completionModel.items.forEach((item, index) => {
|
this.completionModel.items.forEach((item, index) => {
|
||||||
const score = computeScore(item.suggestion.label, currentWord, currentWordLowerCase);
|
|
||||||
|
|
||||||
if (score > bestScore) {
|
|
||||||
bestScore = score;
|
|
||||||
bestSuggestionIndex = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (item.suggestion.type) {
|
switch (item.suggestion.type) {
|
||||||
case 'snippet': snippetCount++; break;
|
case 'snippet': snippetCount++; break;
|
||||||
case 'text': textCount++; break;
|
case 'text': textCount++; break;
|
||||||
|
@ -614,8 +586,8 @@ export class SuggestWidget implements IContentWidget, IDisposable {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.list.splice(0, this.list.length, ...this.completionModel.items);
|
this.list.splice(0, this.list.length, ...this.completionModel.items);
|
||||||
this.list.setFocus(bestSuggestionIndex);
|
this.list.setFocus(this.completionModel.topScoreIdx);
|
||||||
this.list.reveal(bestSuggestionIndex, 0);
|
this.list.reveal(this.completionModel.topScoreIdx, 0);
|
||||||
|
|
||||||
this.setState(State.Open);
|
this.setState(State.Open);
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,9 @@ export class CompletionModel {
|
||||||
|
|
||||||
private _lineContext: LineContext;
|
private _lineContext: LineContext;
|
||||||
private _items: CompletionItem[] = [];
|
private _items: CompletionItem[] = [];
|
||||||
|
|
||||||
private _filteredItems: CompletionItem[] = undefined;
|
private _filteredItems: CompletionItem[] = undefined;
|
||||||
|
private _topScoreIdx: number;
|
||||||
|
|
||||||
constructor(raw: ISuggestionItem[], leadingLineContent: string) {
|
constructor(raw: ISuggestionItem[], leadingLineContent: string) {
|
||||||
this.raw = raw;
|
this.raw = raw;
|
||||||
|
@ -61,21 +63,31 @@ export class CompletionModel {
|
||||||
|
|
||||||
get items(): CompletionItem[] {
|
get items(): CompletionItem[] {
|
||||||
if (!this._filteredItems) {
|
if (!this._filteredItems) {
|
||||||
this._filter();
|
this._filterAndScore();
|
||||||
}
|
}
|
||||||
return this._filteredItems;
|
return this._filteredItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get topScoreIdx(): number {
|
||||||
|
if (!this._filteredItems) {
|
||||||
|
this._filterAndScore();
|
||||||
|
}
|
||||||
|
return this._topScoreIdx;
|
||||||
|
}
|
||||||
|
|
||||||
private _filter(): void {
|
private _filterAndScore(): void {
|
||||||
this._filteredItems = [];
|
this._filteredItems = [];
|
||||||
|
this._topScoreIdx = -1;
|
||||||
|
let topScore = -1;
|
||||||
const {leadingLineContent, characterCountDelta} = this._lineContext;
|
const {leadingLineContent, characterCountDelta} = this._lineContext;
|
||||||
for (let item of this._items) {
|
|
||||||
|
//TODO@joh - sort by 'overwriteBefore' such that we can 'reuse' the word (wordLowerCase)
|
||||||
|
for (const item of this._items) {
|
||||||
|
|
||||||
const start = leadingLineContent.length - (item.suggestion.overwriteBefore + characterCountDelta);
|
const start = leadingLineContent.length - (item.suggestion.overwriteBefore + characterCountDelta);
|
||||||
const word = leadingLineContent.substr(start);
|
const word = leadingLineContent.substr(start);
|
||||||
|
|
||||||
const {filter, suggestion} = item;
|
const {filter, suggestion} = item;
|
||||||
|
|
||||||
let match = false;
|
let match = false;
|
||||||
|
|
||||||
// compute highlights based on 'label'
|
// compute highlights based on 'label'
|
||||||
|
@ -87,9 +99,36 @@ export class CompletionModel {
|
||||||
match = !isFalsyOrEmpty(filter(word, suggestion.filterText));
|
match = !isFalsyOrEmpty(filter(word, suggestion.filterText));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match) {
|
if (!match) {
|
||||||
this._filteredItems.push(item);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._filteredItems.push(item);
|
||||||
|
|
||||||
|
// compute score against word
|
||||||
|
const wordLowerCase = word.toLowerCase();
|
||||||
|
const score = CompletionModel._score(suggestion.label, word, wordLowerCase);
|
||||||
|
if (score > topScore) {
|
||||||
|
topScore = score;
|
||||||
|
this._topScoreIdx = this._filteredItems.length - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static _score(suggestion: string, currentWord: string, currentWordLowerCase: string): number {
|
||||||
|
const suggestionLowerCase = suggestion.toLowerCase();
|
||||||
|
let score = 0;
|
||||||
|
|
||||||
|
for (let i = 0, len = Math.min(currentWord.length, suggestion.length); i < len; i++) {
|
||||||
|
if (currentWord[i] === suggestion[i]) {
|
||||||
|
score += 2;
|
||||||
|
} else if (currentWordLowerCase[i] === suggestionLowerCase[i]) {
|
||||||
|
score += 1;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return score;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue