From 077fdc8d3b4eba2d6dad556114b941bbe1343299 Mon Sep 17 00:00:00 2001 From: Hans Pinckaers Date: Mon, 4 Sep 2023 20:47:08 +0200 Subject: [PATCH 01/11] Add typo-resistency to filter graceful --- src/util/filter.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/util/filter.ts b/src/util/filter.ts index ba206aecce6..4f3992a006f 100644 --- a/src/util/filter.ts +++ b/src/util/filter.ts @@ -94,6 +94,23 @@ function fuzzyScoreWithPermutations(pattern: string, lowPattern: string, pattern } } } + + // Maybe the last few letters of a pattern contain typos + // For example, `conson` could be a typo for `console` + for (let slidePos = 1; slidePos < 3; slidePos++) { + if (slidePos < pattern.length) { + const newPattern = pattern.slice(0, pattern.length - slidePos) + if (newPattern) { + const candidate = fuzzyScore(newPattern, newPattern.toLowerCase(), patternPos, word, lowWord, wordPos, options) + if (candidate) { + candidate[0] -= 3 // permutation penalty + if (!top || candidate[0] > top[0]) { + top = candidate + } + } + } + } + } } return top From 99e9a16977c0acd95419ced386c2dc493d60b7c0 Mon Sep 17 00:00:00 2001 From: Hans Pinckaers Date: Mon, 4 Sep 2023 22:17:08 +0200 Subject: [PATCH 02/11] Consolidate in one loop --- src/util/filter.ts | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/src/util/filter.ts b/src/util/filter.ts index 4f3992a006f..20141f75340 100644 --- a/src/util/filter.ts +++ b/src/util/filter.ts @@ -81,32 +81,25 @@ function fuzzyScoreWithPermutations(pattern: string, lowPattern: string, pattern // permutations of the pattern to find a better match. The // permutations only swap neighbouring characters, e.g // `cnoso` becomes `conso`, `cnsoo`, `cnoos`. - const tries = Math.min(7, pattern.length - 1) - for (let movingPatternPos = patternPos + 1; movingPatternPos < tries; movingPatternPos++) { - const newPattern = nextTypoPermutation(pattern, movingPatternPos) + // + // For the last 2 permutations try remove the final characters, + // Maybe the last few letters of a pattern contain typos + // For example, `conson` could be a typo for `console` + const maxTriesPermutation = Math.min(7, pattern.length - 1); + const maxTries = maxTriesPermutation + 2; + for (let i = 1; i < maxTries; i++) { + let newPattern: string; + if (i <= maxTriesPermutation) { + newPattern = nextTypoPermutation(pattern, patternPos + i); + } else { + newPattern = pattern.slice(0, pattern.length - (i - maxTriesPermutation)); + } if (newPattern) { - const candidate = fuzzyScore(newPattern, newPattern.toLowerCase(), patternPos, word, lowWord, wordPos, options) + const candidate = fuzzyScore(newPattern, newPattern.toLowerCase(), patternPos, word, lowWord, wordPos, options); if (candidate) { - candidate[0] -= 3 // permutation penalty + candidate[0] -= 3; // permutation penalty if (!top || candidate[0] > top[0]) { - top = candidate - } - } - } - } - - // Maybe the last few letters of a pattern contain typos - // For example, `conson` could be a typo for `console` - for (let slidePos = 1; slidePos < 3; slidePos++) { - if (slidePos < pattern.length) { - const newPattern = pattern.slice(0, pattern.length - slidePos) - if (newPattern) { - const candidate = fuzzyScore(newPattern, newPattern.toLowerCase(), patternPos, word, lowWord, wordPos, options) - if (candidate) { - candidate[0] -= 3 // permutation penalty - if (!top || candidate[0] > top[0]) { - top = candidate - } + top = candidate; } } } From 61e74756226f7d486f99d91f6a20b090739aceca Mon Sep 17 00:00:00 2001 From: Hans Pinckaers Date: Mon, 4 Sep 2023 22:19:28 +0200 Subject: [PATCH 03/11] Remove semicolons --- src/util/filter.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/util/filter.ts b/src/util/filter.ts index 20141f75340..13e51c69993 100644 --- a/src/util/filter.ts +++ b/src/util/filter.ts @@ -85,21 +85,21 @@ function fuzzyScoreWithPermutations(pattern: string, lowPattern: string, pattern // For the last 2 permutations try remove the final characters, // Maybe the last few letters of a pattern contain typos // For example, `conson` could be a typo for `console` - const maxTriesPermutation = Math.min(7, pattern.length - 1); - const maxTries = maxTriesPermutation + 2; + const maxTriesPermutation = Math.min(7, pattern.length - 1) + const maxTries = maxTriesPermutation + pattern.length for (let i = 1; i < maxTries; i++) { - let newPattern: string; + let newPattern: string if (i <= maxTriesPermutation) { - newPattern = nextTypoPermutation(pattern, patternPos + i); + newPattern = nextTypoPermutation(pattern, patternPos + i) } else { - newPattern = pattern.slice(0, pattern.length - (i - maxTriesPermutation)); + newPattern = pattern.slice(0, pattern.length - (i - maxTriesPermutation)) } if (newPattern) { - const candidate = fuzzyScore(newPattern, newPattern.toLowerCase(), patternPos, word, lowWord, wordPos, options); + const candidate = fuzzyScore(newPattern, newPattern.toLowerCase(), patternPos, word, lowWord, wordPos, options) if (candidate) { - candidate[0] -= 3; // permutation penalty + candidate[0] -= 3 // permutation penalty if (!top || candidate[0] > top[0]) { - top = candidate; + top = candidate } } } From 052b1180fe1f8f7238529a4afe4d95eaec296ef8 Mon Sep 17 00:00:00 2001 From: Hans Pinckaers Date: Mon, 4 Sep 2023 22:20:28 +0200 Subject: [PATCH 04/11] Fix comments --- src/util/filter.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/util/filter.ts b/src/util/filter.ts index 13e51c69993..49f345e02c3 100644 --- a/src/util/filter.ts +++ b/src/util/filter.ts @@ -82,11 +82,11 @@ function fuzzyScoreWithPermutations(pattern: string, lowPattern: string, pattern // permutations only swap neighbouring characters, e.g // `cnoso` becomes `conso`, `cnsoo`, `cnoos`. // - // For the last 2 permutations try remove the final characters, - // Maybe the last few letters of a pattern contain typos - // For example, `conson` could be a typo for `console` + // For the last 2 permutations try to remove the last characters, + // maybe the last few letters are typos. For example, + // `conson` could be a typo for `console` const maxTriesPermutation = Math.min(7, pattern.length - 1) - const maxTries = maxTriesPermutation + pattern.length + const maxTries = maxTriesPermutation + 2 for (let i = 1; i < maxTries; i++) { let newPattern: string if (i <= maxTriesPermutation) { From 5bfe45790a84cd07434dde641f7769074c7ff730 Mon Sep 17 00:00:00 2001 From: Hans Pinckaers Date: Tue, 5 Sep 2023 09:58:11 +0200 Subject: [PATCH 05/11] Also check for typos in the word, stop when typing a non-alpha char --- src/completion/complete.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/completion/complete.ts b/src/completion/complete.ts index baaefb88ae9..21cfc3ce02b 100644 --- a/src/completion/complete.ts +++ b/src/completion/complete.ts @@ -5,7 +5,7 @@ import { createLogger } from '../logger' import type Document from '../model/document' import { waitWithToken } from '../util' import { isFalsyOrEmpty } from '../util/array' -import { anyScore, FuzzyScore, fuzzyScore, fuzzyScoreGracefulAggressive, FuzzyScorer } from '../util/filter' +import { anyScore, FuzzyScore, fuzzyScore, fuzzyScoreGraceful, fuzzyScoreGracefulAggressive, FuzzyScorer } from '../util/filter' import * as Is from '../util/is' import { clamp } from '../util/numbers' import { CancellationToken, CancellationTokenSource, Disposable, Emitter, Event } from '../util/protocol' From 30f35d26e10c5ea15ddd806459f0d7d6d16b9bcb Mon Sep 17 00:00:00 2001 From: Hans Pinckaers Date: Tue, 5 Sep 2023 10:02:31 +0200 Subject: [PATCH 06/11] Also check for typos in the word, stop when typing a non-alpha char --- src/util/filter.ts | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/util/filter.ts b/src/util/filter.ts index 49f345e02c3..ae84fb9984b 100644 --- a/src/util/filter.ts +++ b/src/util/filter.ts @@ -85,27 +85,43 @@ function fuzzyScoreWithPermutations(pattern: string, lowPattern: string, pattern // For the last 2 permutations try to remove the last characters, // maybe the last few letters are typos. For example, // `conson` could be a typo for `console` - const maxTriesPermutation = Math.min(7, pattern.length - 1) - const maxTries = maxTriesPermutation + 2 - for (let i = 1; i < maxTries; i++) { - let newPattern: string - if (i <= maxTriesPermutation) { - newPattern = nextTypoPermutation(pattern, patternPos + i) - } else { - newPattern = pattern.slice(0, pattern.length - (i - maxTriesPermutation)) + const maxTriesPermutation = Math.min(7, pattern.length - 1); + const maxTries = maxTriesPermutation + pattern.length; + + // Loop for existing permutations + for (let i = 1; i <= maxTriesPermutation; i++) { + const newPattern = nextTypoPermutation(pattern, patternPos + i); + checkAndUpdateTopCandidate(newPattern, 3); + } + + const lastChar = pattern.charAt(pattern.length - 1); + + if ((/[a-zA-Z0-9]/.test(lastChar))) { + // Loop for removing characters at all positions + for (let i = 0; i < pattern.length; i++) { + const newPattern = pattern.slice(0, i) + pattern.slice(i + 1); + checkAndUpdateTopCandidate(newPattern, 1); } + + // Loop for removing last characters + for (let i = 1; i < pattern.length; i++) { + const newPattern = pattern.slice(0, pattern.length - i); + checkAndUpdateTopCandidate(newPattern, i+1); + } + } + + function checkAndUpdateTopCandidate(newPattern: string, penalty: int) { if (newPattern) { - const candidate = fuzzyScore(newPattern, newPattern.toLowerCase(), patternPos, word, lowWord, wordPos, options) + const candidate = fuzzyScore(newPattern, newPattern.toLowerCase(), patternPos, word, lowWord, wordPos, options); if (candidate) { - candidate[0] -= 3 // permutation penalty + candidate[0] -= penalty; // permutation penalty if (!top || candidate[0] > top[0]) { - top = candidate + top = candidate; } } } } } - return top } From 1b60717e3ab118cfd0dd3774703e013bccccd75e Mon Sep 17 00:00:00 2001 From: Hans Pinckaers Date: Tue, 5 Sep 2023 10:02:49 +0200 Subject: [PATCH 07/11] Revert "Also check for typos in the word, stop when typing a non-alpha char" This reverts commit 5bfe45790a84cd07434dde641f7769074c7ff730. --- src/completion/complete.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/completion/complete.ts b/src/completion/complete.ts index 21cfc3ce02b..baaefb88ae9 100644 --- a/src/completion/complete.ts +++ b/src/completion/complete.ts @@ -5,7 +5,7 @@ import { createLogger } from '../logger' import type Document from '../model/document' import { waitWithToken } from '../util' import { isFalsyOrEmpty } from '../util/array' -import { anyScore, FuzzyScore, fuzzyScore, fuzzyScoreGraceful, fuzzyScoreGracefulAggressive, FuzzyScorer } from '../util/filter' +import { anyScore, FuzzyScore, fuzzyScore, fuzzyScoreGracefulAggressive, FuzzyScorer } from '../util/filter' import * as Is from '../util/is' import { clamp } from '../util/numbers' import { CancellationToken, CancellationTokenSource, Disposable, Emitter, Event } from '../util/protocol' From a350c9eb77c2f529559de246dcb92ec28c554a73 Mon Sep 17 00:00:00 2001 From: Hans Pinckaers Date: Wed, 13 Sep 2023 21:20:36 +0200 Subject: [PATCH 08/11] Fix type --- src/util/filter.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/util/filter.ts b/src/util/filter.ts index ae84fb9984b..920e0db8ec5 100644 --- a/src/util/filter.ts +++ b/src/util/filter.ts @@ -100,17 +100,17 @@ function fuzzyScoreWithPermutations(pattern: string, lowPattern: string, pattern // Loop for removing characters at all positions for (let i = 0; i < pattern.length; i++) { const newPattern = pattern.slice(0, i) + pattern.slice(i + 1); - checkAndUpdateTopCandidate(newPattern, 1); + checkAndUpdateTopCandidate(newPattern, 4); } // Loop for removing last characters - for (let i = 1; i < pattern.length; i++) { + for (let i = 1; i < 3; i++) { const newPattern = pattern.slice(0, pattern.length - i); - checkAndUpdateTopCandidate(newPattern, i+1); + checkAndUpdateTopCandidate(newPattern, i+4); } } - function checkAndUpdateTopCandidate(newPattern: string, penalty: int) { + function checkAndUpdateTopCandidate(newPattern: string, penalty: number) { if (newPattern) { const candidate = fuzzyScore(newPattern, newPattern.toLowerCase(), patternPos, word, lowWord, wordPos, options); if (candidate) { From ad9947fce426e5cb01b75bf46b942f113f675380 Mon Sep 17 00:00:00 2001 From: Heyward Fann Date: Thu, 27 Nov 2025 10:13:07 +0800 Subject: [PATCH 09/11] Update src/util/filter.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/util/filter.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/util/filter.ts b/src/util/filter.ts index 920e0db8ec5..cd2a3858e13 100644 --- a/src/util/filter.ts +++ b/src/util/filter.ts @@ -86,7 +86,6 @@ function fuzzyScoreWithPermutations(pattern: string, lowPattern: string, pattern // maybe the last few letters are typos. For example, // `conson` could be a typo for `console` const maxTriesPermutation = Math.min(7, pattern.length - 1); - const maxTries = maxTriesPermutation + pattern.length; // Loop for existing permutations for (let i = 1; i <= maxTriesPermutation; i++) { From 0b321c6f4c9650f5adb4b928bac820ba42d0a89b Mon Sep 17 00:00:00 2001 From: Heyward Fann Date: Thu, 27 Nov 2025 10:13:22 +0800 Subject: [PATCH 10/11] Update src/util/filter.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/util/filter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/filter.ts b/src/util/filter.ts index cd2a3858e13..f5fe4013271 100644 --- a/src/util/filter.ts +++ b/src/util/filter.ts @@ -105,7 +105,7 @@ function fuzzyScoreWithPermutations(pattern: string, lowPattern: string, pattern // Loop for removing last characters for (let i = 1; i < 3; i++) { const newPattern = pattern.slice(0, pattern.length - i); - checkAndUpdateTopCandidate(newPattern, i+4); + checkAndUpdateTopCandidate(newPattern, i + 4); } } From 8f09c11893bd77415292905f41d32a1422290ece Mon Sep 17 00:00:00 2001 From: Heyward Fann Date: Thu, 27 Nov 2025 10:16:01 +0800 Subject: [PATCH 11/11] Update src/util/filter.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/util/filter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/filter.ts b/src/util/filter.ts index f5fe4013271..2d3d379bd4a 100644 --- a/src/util/filter.ts +++ b/src/util/filter.ts @@ -95,7 +95,7 @@ function fuzzyScoreWithPermutations(pattern: string, lowPattern: string, pattern const lastChar = pattern.charAt(pattern.length - 1); - if ((/[a-zA-Z0-9]/.test(lastChar))) { + if (/[a-zA-Z0-9]/.test(lastChar)) { // Loop for removing characters at all positions for (let i = 0; i < pattern.length; i++) { const newPattern = pattern.slice(0, i) + pattern.slice(i + 1);