mirror of
https://github.com/junegunn/fzf
synced 2026-08-08 19:41:43 +00:00
Skip the normalization map for runes that cannot normalize
normalizeRune guarded with 0x00C0..0xFF61, which does not exclude Hangul, CJK or Cyrillic, so every rune of those scripts hashed into the map only to miss. Every key of the map folds to ASCII, so the bitmap added for the rune prefilter rejects them without a lookup. - Non-ASCII queries 1.21x where every line is CJK, 1.05x on mostly-ASCII paths behind a Hangul prefix - ASCII queries unchanged, the prefilter already skips Phase 2 for them - Normalization share of query time for a non-ASCII query: 17.2% -> 0%
This commit is contained in:
+3
-1
@@ -303,7 +303,9 @@ func bonusAt(input *util.Chars, idx int) int16 {
|
||||
}
|
||||
|
||||
func normalizeRune(r rune) rune {
|
||||
if r < 0x00C0 || r > 0xFF61 {
|
||||
// Every key of the map folds to ASCII, so a rune the bitmap rejects cannot
|
||||
// be in it. TestNormalizedKeysAreFlagged pins that.
|
||||
if !util.MayFoldToAscii(r) {
|
||||
return r
|
||||
}
|
||||
|
||||
|
||||
@@ -226,6 +226,35 @@ func TestRunePrefilterEquivalenceV1(t *testing.T) {
|
||||
disableRunePrefilter = false
|
||||
}
|
||||
|
||||
// normalizeRune skips the map when util.MayFoldToAscii rejects the rune. That
|
||||
// is only sound if every key of the map is flagged, since a flagged-false rune
|
||||
// is returned unchanged.
|
||||
func TestNormalizedKeysAreFlagged(t *testing.T) {
|
||||
for k := range normalized {
|
||||
if !util.MayFoldToAscii(k) {
|
||||
t.Errorf("normalized key U+%04X (%c) is not flagged by MayFoldToAscii", k, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Guarding normalizeRune must not change what it returns, for any rune.
|
||||
func TestNormalizeRuneUnchangedByGuard(t *testing.T) {
|
||||
for r := rune(0); r <= unicode.MaxRune; r++ {
|
||||
if r >= 0xD800 && r <= 0xDFFF {
|
||||
continue
|
||||
}
|
||||
exp := r
|
||||
if r >= 0x00C0 && r <= 0xFF61 {
|
||||
if n := normalized[r]; n > 0 {
|
||||
exp = n
|
||||
}
|
||||
}
|
||||
if got := normalizeRune(r); got != exp {
|
||||
t.Fatalf("normalizeRune(U+%04X) = U+%04X, expected U+%04X", r, got, exp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// preparePattern mirrors what pattern.go guarantees the algo functions:
|
||||
// lowercased when case-insensitive, normalized when normalize is on.
|
||||
func preparePattern(pat string, caseSensitive, normalize bool) []rune {
|
||||
|
||||
Reference in New Issue
Block a user