Code change:
// Default Filter return enableSeparateSubstringMatching ? fuzzySeparateFilter(word, wordToMatchAgainst) : fuzzyContiguousFilter(word, wordToMatchAgainst); } <ins> export function matchesFuzzy2(pattern: string, word: string): IMatch[] | undefined { pattern = pattern.toLowerCase(); word = word.toLowerCase(); let result: IMatch[] = []; let lastMatch: IMatch; let patternPos = 0; let wordPos = 0; while (patternPos < pattern.length && wordPos < word.length) { if (pattern.charAt(patternPos) === word.charAt(wordPos)) { patternPos += 1; if (lastMatch && lastMatch.end === wordPos) { lastMatch.end += 1; } else { lastMatch = { start: wordPos, end: wordPos + 1 }; result.push(lastMatch); } } wordPos += 1; } if (patternPos !== pattern.length) { return undefined; } return result; } export function matchesFuzzy3(pattern: string, word: string) { return _doMatchesFuzzy3( pattern, pattern.toLowerCase(), 0, word, word.toLowerCase(), 0, [], 0 ); } function _doMatchesFuzzy3( pattern: string, lowPattern: string, patternPos: number, word: string, lowWord: string, wordPos: number, positions: number[], score: number ): [IMatch[], number] { let retryPoints: number[] = []; let lastDidMatch = false; while (patternPos < lowPattern.length && wordPos < lowWord.length) { const charLowPattern = lowPattern.charAt(patternPos); const charLowWord = lowWord.charAt(wordPos); if (charLowPattern === charLowWord) { if (positions.length === 0) { score = -Math.min(wordPos, 3) * 3; // penalty -> gaps at start } else if (lastDidMatch) { score += 1; // bonus -> subsequent match } if (charLowWord !== word.charAt(wordPos)) { score += 10; // bonus -> upper-case } else if (wordPos > 0 && word.charAt(wordPos).match(_separator)) { score += 10; // bonus -> after a separator } else { // keep this as a retry point retryPoints.push(patternPos, wordPos + 1, positions.length, score); } patternPos += 1; positions.push(wordPos); lastDidMatch = true; } else { lastDidMatch = false; score -= 1; // penalty -> gaps in match } wordPos += 1; } if (patternPos !== lowPattern.length) { return undefined; } const matches: IMatch[] = []; let lastMatch: IMatch; for (const pos of positions) { if (lastMatch && lastMatch.end === pos) { lastMatch.end += 1; } else { lastMatch = { start: pos, end: pos + 1 }; matches.push(lastMatch); } } let result: [IMatch[], number] = [matches, score]; // try alternative matches for (let i = 0; i < retryPoints.length; i += 4) { const alt = _doMatchesFuzzy3( pattern, lowPattern, retryPoints[i], word, lowWord, retryPoints[i + 1], positions.slice(0, retryPoints[i + 2]), retryPoints[i + 3] ); if (alt && alt[1] > result[1]) { result = alt; } } return result; } 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]; } // function print(m: number[][]) { // 	for (const n of m) { // 		console.log(n.join('|')); // 	} // } export function matchesFuzzy5(pattern: string, word: string) { // create matrix const matrix: number[][] = [[0]]; for (let i = 1; i <= pattern.length; i++) { matrix.push([-i]); } for (let i = 1; i <= word.length; i++) { matrix[0].push(-i); } for (let i = 0; i < pattern.length; i++) { let match = false; for (let j = 0; j < word.length; j++) { let diagScore = 0; if (pattern[i] === word[j]) { diagScore = 1 + matrix[i][j]; match = true; } else { diagScore = -1 + matrix[i][j]; } let upScore = -1 + matrix[i][j + 1]; let leftScore = -1 + matrix[i + 1][j]; matrix[i + 1][j + 1] = Math.max(diagScore, upScore, leftScore); } if (!match) { return undefined; } } // print(matrix); return []; } export function createMatches(position: number[]): IMatch[] { let ret: IMatch[] = []; let last: IMatch; for (const pos of position) { if (last && last.end === pos) { last.end += 1; } else { last = { start: pos, end: pos + 1 }; ret.push(last); } } return ret; } export function fuzzyMatchAndScore(pattern: string, word: string): [number, number[]] { let matches: number[] = []; let score = _matchRecursive( pattern, pattern.toLowerCase(), pattern.toUpperCase(), 0, word, word.toLowerCase(), 0, matches ); if (score <= 0) { return undefined; } score -= Math.min(matches[0], 3) * 3; // penalty for first matching character score -= (1 + matches[matches.length - 1]) - (pattern.length); // penalty for all non matching characters between first and last return [score, matches]; } export function _matchRecursive( pattern: string, lowPattern: string, upPattern: string, patternPos: number, word: string, lowWord: string, wordPos: number, matches: number[] ): number { if (patternPos >= lowPattern.length) { return 0; } const lowPatternChar = lowPattern.charAt(patternPos); let idx = -1; let value = 0; if ((patternPos === wordPos && lowPatternChar === lowWord.charAt(wordPos)) && ((value = _matchRecursive(pattern, lowPattern, upPattern, patternPos + 1, word, lowWord, wordPos + 1, matches)) >= 0) ) { matches.unshift(wordPos); return (pattern.charAt(patternPos) === word.charAt(wordPos) ? 17 : 11) + value; } if ((idx = lowWord.indexOf(`_${lowPatternChar}`, wordPos)) >= 0 && ((value = _matchRecursive(pattern, lowPattern, upPattern, patternPos + 1, word, lowWord, idx + 2, matches)) >= 0) ) { matches.unshift(idx + 1); return (pattern.charAt(patternPos) === word.charAt(idx + 1) ? 17 : 11) + value; } if ((idx = word.indexOf(upPattern.charAt(patternPos), wordPos)) >= 0 && ((value = _matchRecursive(pattern, lowPattern, upPattern, patternPos + 1, word, lowWord, idx + 1, matches)) >= 0) ) { matches.unshift(idx); return (pattern.charAt(patternPos) === word.charAt(idx) ? 17 : 11) + value; } if (patternPos > 0 && (idx = lowWord.indexOf(lowPatternChar, wordPos)) >= 0 && ((value = _matchRecursive(pattern, lowPattern, upPattern, patternPos + 1, word, lowWord, idx + 1, matches)) >= 0) ) { matches.unshift(idx); return 1 + value; } return -1; } </ins>

Related discussion:
text: <!-- Do you have a question? Please ask it on --- VSCode Version: 1.10.1 OS Version: macOS Is it possible for VSCode to support the following kinds of auto complete, please see screenshots Word completion: <img width="357" alt="screen shot 2017-03-07 at 10 23 19 am" src=""Member function completion: <img width="359" alt="screen shot 2017-03-07 at 10 20 22 am" src=""All auto-completions come with fuzzy matching. Steps to Reproduce:
Agree, actually fuzzy matching only works with camel Case, but in sublime and atom you can get completion by typing any middle letter of the target word. I still miss this feature in vscode
I like, tho will be some work and maybe some adjustment for folks that are used to our current filtering and ranking
This got implemented with <img width="280" alt="screen shot 2017-03-20 at 17 38 54" src=""
And this is valid for all languages then?
Yes, we have changed the default matcher to be more fuzzy.
VSCode: 11.0-insider I appear to be getting stuck in a recursive loop, and according to DevTools (I clicked Pause in the Debugger) it is happening in . I tested this with . I was able to reproduce this with a simple HTML file: After typing the opening and IntelliSense appears, trying to type an additional character will freeze the whole VSCode.
Thanks for the heads-up. You are right, there are situations in which it keeps recursing forever. I have implemented a different approach today and just pushed the last changes. Will be in tomorrows insiders.