提交 d58c8124 编写于 作者: J Johannes Rieken

landmark

上级 eb34efe9
......@@ -381,7 +381,11 @@ export function matchesFuzzy2(pattern: string, word: string): IMatch[] | undefin
wordPos += 1;
}
return result.length > 0 ? result : undefined;
if (patternPos !== pattern.length) {
return undefined;
}
return result;
}
export function matchesFuzzy3(pattern: string, word: string) {
......@@ -435,7 +439,7 @@ function _doMatchesFuzzy3(
wordPos += 1;
}
if (positions.length === 0) {
if (patternPos !== lowPattern.length) {
return undefined;
}
......@@ -470,3 +474,103 @@ function _doMatchesFuzzy3(
const _separator = /[-_. ]/;
export function matchesFuzzy4(pattern: string, word: string): [IMatch[], number] {
const lowPattern = pattern.toLowerCase();
const lowWord = word.toLowerCase();
const [landmarkWord, landmarkPositions] = computeLandmarks(word, lowWord);
let landmarkPos = 0;
let wordPos = 0;
let patternPos = 1;
let charLowPattern = lowPattern.charAt(0);
let result: IMatch[] = [];
let lastMatch: IMatch;
let score = 0;
if (charLowPattern === lowWord.charAt(0)) {
lastMatch = { start: wordPos, end: wordPos + 1 };
result.push(lastMatch);
wordPos = 1;
landmarkPos = 1;
if (pattern.charAt(0) === word.charAt(0)) {
score += 10;
}
} else if ((landmarkPos = landmarkWord.indexOf(charLowPattern)) >= 0) {
wordPos = landmarkPositions[landmarkPos];
score += 10 - Math.min(9, wordPos * 3);
lastMatch = { start: wordPos, end: wordPos + 1 };
result.push(lastMatch);
wordPos += 1;
landmarkPos += 1;
} else {
return undefined;
}
while (patternPos < lowPattern.length && wordPos < lowWord.length) {
charLowPattern = lowPattern.charAt(patternPos);
let match = false;
if (landmarkPos < landmarkWord.length && charLowPattern === landmarkWord.charAt(landmarkPos)) {
let newWordPos = landmarkPositions[landmarkPos];
match = true;
score += 10 - (newWordPos - wordPos);
wordPos = newWordPos;
landmarkPos += 1;
patternPos += 1;
} else if (charLowPattern === lowWord.charAt(wordPos)) {
match = true;
patternPos += 1;
}
if (match) {
if (lastMatch && lastMatch.end === wordPos) {
lastMatch.end += 1;
score += 1;
} else {
lastMatch = { start: wordPos, end: wordPos + 1 };
result.push(lastMatch);
}
}
wordPos += 1;
if (wordPos >= landmarkPositions[landmarkPos]) {
landmarkPos += 1;
}
}
if (patternPos !== lowPattern.length) {
return undefined;
}
// substract uncovered remainder
score -= lowWord.length - wordPos;
return [result, score];
}
function computeLandmarks(word: string, lowWord: string): [string, number[]] {
let result: string = '';
let positions: number[] = [];
let lastCh: string;
for (let pos = 0; pos < word.length; pos++) {
const ch = word.charAt(pos);
if (!result // first character is a landmark
|| (lastCh === '_' || lastCh === '-' || lastCh === ' ') // last was separator
|| ch !== lowWord.charAt(pos) // upper-case
) {
result += ch;
positions.push(pos);
}
lastCh = ch;
}
result = result.toLowerCase();
return [result, positions];
}
......@@ -5,7 +5,7 @@
'use strict';
import * as assert from 'assert';
import { fuzzyContiguousFilter, matchesFuzzy2, matchesFuzzy3 } from 'vs/base/common/filters';
import { fuzzyContiguousFilter, matchesFuzzy2, matchesFuzzy3, matchesFuzzy4 } from 'vs/base/common/filters';
const fuzz = require.__$__nodeRequire('fuzzaldrin-plus');
const data = <{ label: string }[]>require.__$__nodeRequire(require.toUrl('./filters.perf.data.json'));
......@@ -36,7 +36,7 @@ perfSuite('Performance - fuzzyMatch', function () {
}
}
}
console.log(Date.now() - t1, count, (count / (Date.now() - t1)).toPrecision(5));
console.log('fuzzyContiguousFilter', Date.now() - t1, count);
assert.ok(count > 0);
});
......@@ -53,7 +53,7 @@ perfSuite('Performance - fuzzyMatch', function () {
}
}
}
console.log(Date.now() - t1, count, (count / (Date.now() - t1)).toPrecision(5));
console.log('matchesFuzzy2', Date.now() - t1, count);
assert.ok(count > 0);
});
......@@ -70,7 +70,24 @@ perfSuite('Performance - fuzzyMatch', function () {
}
}
}
console.log(Date.now() - t1, count, (count / (Date.now() - t1)).toPrecision(5));
console.log('matchesFuzzy3', Date.now() - t1, count);
assert.ok(count > 0);
});
test('matchesFuzzy4', function () {
const t1 = Date.now();
let count = 0;
for (const pattern of patterns) {
for (const item of data) {
if (item.label) {
const matches = matchesFuzzy4(pattern, item.label);
if (matches) {
count += 1;
}
}
}
}
console.log('matchesFuzzy4', Date.now() - t1, count);
assert.ok(count > 0);
});
......@@ -88,7 +105,7 @@ perfSuite('Performance - fuzzyMatch', function () {
}
}
}
console.log(Date.now() - t1, count, (count / (Date.now() - t1)).toPrecision(5));
console.log('fuzzaldrin', Date.now() - t1, count);
assert.ok(count > 0);
});
});
......
......@@ -5,7 +5,7 @@
'use strict';
import * as assert from 'assert';
import { IFilter, or, matchesPrefix, matchesStrictPrefix, matchesCamelCase, matchesSubString, matchesContiguousSubString, matchesWords, matchesFuzzy3 } from 'vs/base/common/filters';
import { IFilter, or, matchesPrefix, matchesStrictPrefix, matchesCamelCase, matchesSubString, matchesContiguousSubString, matchesWords, matchesFuzzy3, matchesFuzzy4 } from 'vs/base/common/filters';
function filterOk(filter: IFilter, word: string, wordToMatchAgainst: string, highlights?: { start: number; end: number; }[]) {
let r = filter(word, wordToMatchAgainst);
......@@ -223,5 +223,76 @@ suite('Filters', () => {
[matches] = matchesFuzzy3('Cat', 'concat');
assert.deepEqual(matches, [{ start: 0, end: 1 }, { start: 4, end: 6 }]);
[matches] = matchesFuzzy4('LLL', 'SVisualLoggerLogsList');
assert.deepEqual(matches, [{ start: 7, end: 8 }, { start: 13, end: 14 }, { start: 17, end: 18 }]);
[matches] = matchesFuzzy4('foobar', 'foobar');
assert.deepEqual(matches, [{ start: 0, end: 6 }]);
[matches] = matchesFuzzy4('tk', 'The Black Knight');
assert.deepEqual(matches, [{ start: 0, end: 1 }, { start: 10, end: 11 }]);
[matches] = matchesFuzzy4('Cat', 'charAt');
assert.deepEqual(matches, [{ start: 0, end: 1 }, { start: 4, end: 6 }]);
[matches] = matchesFuzzy4('Cat', 'charCodeAt');
assert.deepEqual(matches, [{ start: 0, end: 1 }, { start: 2, end: 3 }, { start: 9, end: 10 }]);
[matches] = matchesFuzzy4('Cat', 'concat');
assert.deepEqual(matches, [{ start: 0, end: 1 }, { start: 4, end: 6 }]);
});
test('matchFuzzy', function () {
function assertTopScore(pattern: string, expected: number, ...words: string[]) {
let topScore = Number.MIN_VALUE;
let topIdx = 0;
for (let i = 0; i < words.length; i++) {
const word = words[i];
const match = matchesFuzzy4(pattern, word);
if (match) {
const [, score] = match;
console.log(`${pattern} -> ${word}, ${score}`);
if (score > topScore) {
topScore = score;
topIdx = i;
}
}
}
// assert.equal(topIdx, expected);
console.log(topIdx, expected);
}
assertTopScore('Foo', 1, 'foo', 'Foo', 'foo');
assertTopScore('CC', 1, 'camelCase', 'CamelCase');
assertTopScore('cC', 0, 'camelCase', 'CamelCase');
assertTopScore('cC', 1, 'ccfoo', 'camelCase');
assertTopScore('cC', 1, 'ccfoo', 'camelCase', 'foo-cC-bar');
// issue #17836
assertTopScore('p', 0, 'parse', 'posix', 'sep', 'pafdsa', 'path', 'p');
assertTopScore('pa', 0, 'parse', 'posix', 'sep', 'pafdsa', 'path', 'p');
// issue #14583
assertTopScore('log', 3, 'HTMLOptGroupElement', 'ScrollLogicalPosition', 'SVGFEMorphologyElement', 'log');
assertTopScore('e', 2, 'AbstractWorker', 'ActiveXObject', 'else');
// issue #14446
assertTopScore('workbench.sideb', 1, 'workbench.editor.defaultSideBySideLayout', 'workbench.sideBar.location');
// issue #11423
assertTopScore('editor.r', 2, 'diffEditor.renderSideBySide', 'editor.overviewRulerlanes', 'editor.renderControlCharacter', 'editor.renderWhitespace');
assertTopScore('editor.R', 1, 'diffEditor.renderSideBySide', 'editor.overviewRulerlanes', 'editor.renderControlCharacter', 'editor.renderWhitespace');
assertTopScore('Editor.r', 0, 'diffEditor.renderSideBySide', 'editor.overviewRulerlanes', 'editor.renderControlCharacter', 'editor.renderWhitespace');
assertTopScore('-mo', 1, '-ms-ime-mode', '-moz-columns');
// dupe, issue #14861
assertTopScore('convertModelPosition', 0, 'convertModelPositionToViewPosition', 'convertViewToModelPosition');
// dupe, issue #14942
assertTopScore('is', 0, 'isValidViewletId', 'import statement');
});
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册