mirror of
https://github.com/junegunn/fzf.git
synced 2026-08-17 13:18:04 +08:00
Clean up comments and tests
This commit is contained in:
+1
-1
@@ -304,7 +304,7 @@ func bonusAt(input *util.Chars, idx int) int16 {
|
|||||||
|
|
||||||
func normalizeRune(r rune) rune {
|
func normalizeRune(r rune) rune {
|
||||||
// Every key of the map folds to ASCII, so a rune the bitmap rejects cannot
|
// Every key of the map folds to ASCII, so a rune the bitmap rejects cannot
|
||||||
// be in it. TestNormalizedKeysAreFlagged pins that.
|
// be in it. TestNormalizedKeysAreFlagged verifies that.
|
||||||
if !util.MayFoldToAscii(r) {
|
if !util.MayFoldToAscii(r) {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package algo
|
package algo
|
||||||
|
|
||||||
// Equivalence tests for the single- and two-character fast paths against the
|
// Equivalence tests for the single- and two-character fast paths against the
|
||||||
// general FuzzyMatchV2 algorithm, which serves as the oracle.
|
// general FuzzyMatchV2 algorithm, which serves as the reference.
|
||||||
//
|
//
|
||||||
// Two complementary strategies:
|
// Two complementary strategies:
|
||||||
// - Exhaustive: every string up to a fixed length over an alphabet that
|
// - Exhaustive: every string up to a fixed length over an alphabet that
|
||||||
|
|||||||
@@ -29,9 +29,9 @@ func foldForTest(r rune, normalize bool) rune {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The prefilter is only safe on items whose runes cannot become ASCII. This
|
// The prefilter is only safe on items whose runes cannot become ASCII. This
|
||||||
// pins util.MayFoldToAscii as a superset of the runes that actually can, over
|
// verifies util.MayFoldToAscii as a superset of the runes that actually can,
|
||||||
// the whole Unicode range and both normalization modes. If normalize.go or the
|
// over the whole Unicode range and both normalization modes. If normalize.go
|
||||||
// Go unicode tables change, this fails.
|
// or the Go unicode tables change, this fails.
|
||||||
func TestMayFoldToAsciiIsSuperset(t *testing.T) {
|
func TestMayFoldToAsciiIsSuperset(t *testing.T) {
|
||||||
missed := 0
|
missed := 0
|
||||||
for r := rune(utf8.RuneSelf); r <= unicode.MaxRune; r++ {
|
for r := rune(utf8.RuneSelf); r <= unicode.MaxRune; r++ {
|
||||||
@@ -51,8 +51,8 @@ func TestMayFoldToAsciiIsSuperset(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scripts that must stay unflagged, otherwise the prefilter never engages for
|
// Scripts that must stay unflagged, otherwise the prefilter never runs for
|
||||||
// them and Step C buys nothing.
|
// them and Step C has no effect.
|
||||||
func TestMayFoldToAsciiExcludesMajorScripts(t *testing.T) {
|
func TestMayFoldToAsciiExcludesMajorScripts(t *testing.T) {
|
||||||
for _, s := range []struct {
|
for _, s := range []struct {
|
||||||
name string
|
name string
|
||||||
@@ -62,9 +62,9 @@ func TestMayFoldToAsciiExcludesMajorScripts(t *testing.T) {
|
|||||||
{"Arabic", 0x0600, 0x06FF}, {"Thai", 0x0E00, 0x0E7F}, {"Devanagari", 0x0900, 0x097F},
|
{"Arabic", 0x0600, 0x06FF}, {"Thai", 0x0E00, 0x0E7F}, {"Devanagari", 0x0900, 0x097F},
|
||||||
{"CJK", 0x4E00, 0x9FFF}, {"Hangul", 0xAC00, 0xD7A3}, {"kana", 0x3040, 0x30FF},
|
{"CJK", 0x4E00, 0x9FFF}, {"Hangul", 0xAC00, 0xD7A3}, {"kana", 0x3040, 0x30FF},
|
||||||
{"box drawing", 0x2500, 0x257F}, {"emoji", 0x1F300, 0x1FAFF},
|
{"box drawing", 0x2500, 0x257F}, {"emoji", 0x1F300, 0x1FAFF},
|
||||||
// These sit between the Latin blocks and were swallowed by an earlier,
|
// These sit between the Latin blocks and were included in an earlier,
|
||||||
// wider grouping of foldableRanges. General Punctuation is the costly
|
// wider grouping of foldableRanges. General Punctuation matters most:
|
||||||
// one: curly quotes, en and em dashes and the ellipsis live there.
|
// curly quotes, en and em dashes and the ellipsis are in it.
|
||||||
{"Greek Extended", 0x1F00, 0x1FFF}, {"General Punctuation", 0x2000, 0x206F},
|
{"Greek Extended", 0x1F00, 0x1FFF}, {"General Punctuation", 0x2000, 0x206F},
|
||||||
{"Currency Symbols", 0x20A0, 0x20CF}, {"CJK Symbols", 0x3000, 0x303F},
|
{"Currency Symbols", 0x20A0, 0x20CF}, {"CJK Symbols", 0x3000, 0x303F},
|
||||||
} {
|
} {
|
||||||
@@ -257,7 +257,7 @@ func TestNormalizeRuneUnchangedByGuard(t *testing.T) {
|
|||||||
|
|
||||||
// Step G lets non-ASCII pattern runes use the scan, but only when no other
|
// Step G lets non-ASCII pattern runes use the scan, but only when no other
|
||||||
// rune can transform into them. Being uncased is not sufficient: U+00DF has no
|
// rune can transform into them. Being uncased is not sufficient: U+00DF has no
|
||||||
// simple uppercase yet U+1E9E lowercases onto it. This pins the guard against
|
// simple uppercase yet U+1E9E lowercases onto it. This checks the guard against
|
||||||
// the full preimage relation over all of Unicode.
|
// the full preimage relation over all of Unicode.
|
||||||
func TestRunePrefilterableGuardIsSound(t *testing.T) {
|
func TestRunePrefilterableGuardIsSound(t *testing.T) {
|
||||||
preimage := map[rune][]rune{}
|
preimage := map[rune][]rune{}
|
||||||
@@ -306,7 +306,7 @@ func TestRunePrefilterableGuardIsSound(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Step G path must actually engage and reject, otherwise the equivalence
|
// The Step G path must actually run and reject, otherwise the equivalence
|
||||||
// test above proves nothing about non-ASCII patterns.
|
// test above proves nothing about non-ASCII patterns.
|
||||||
func TestNonAsciiPatternPrefilterEngages(t *testing.T) {
|
func TestNonAsciiPatternPrefilterEngages(t *testing.T) {
|
||||||
rng := rand.New(rand.NewSource(6))
|
rng := rand.New(rand.NewSource(6))
|
||||||
@@ -413,7 +413,7 @@ func FuzzRunePrefilter(f *testing.F) {
|
|||||||
}
|
}
|
||||||
chars := util.ToChars([]byte(input))
|
chars := util.ToChars([]byte(input))
|
||||||
if chars.IsBytes() {
|
if chars.IsBytes() {
|
||||||
return // byte mode is the existing fuzzers' territory
|
return // byte mode is covered by the existing fuzzers
|
||||||
}
|
}
|
||||||
for _, cs := range []bool{false, true} {
|
for _, cs := range []bool{false, true} {
|
||||||
for _, norm := range []bool{false, true} {
|
for _, norm := range []bool{false, true} {
|
||||||
|
|||||||
+3
-3
@@ -36,9 +36,9 @@ type Chars struct {
|
|||||||
// Rune ranges that case folding or normalization can turn into ASCII, derived
|
// Rune ranges that case folding or normalization can turn into ASCII, derived
|
||||||
// from algo's normalization table and unicode.ToLower, then merged. They are a
|
// from algo's normalization table and unicode.ToLower, then merged. They are a
|
||||||
// superset of the exact set, which TestMayFoldToAsciiIsSuperset in the algo
|
// superset of the exact set, which TestMayFoldToAsciiIsSuperset in the algo
|
||||||
// package pins. Grouped tightly on purpose: a wider merge would swallow Greek
|
// package verifies. Grouped tightly on purpose: a wider merge would include
|
||||||
// Extended, General Punctuation and the currency and letterlike blocks, and
|
// Greek Extended, General Punctuation and the currency and letterlike blocks,
|
||||||
// every line holding a curly quote or an em dash would then lose the
|
// and every line holding a curly quote or an em dash would then lose the
|
||||||
// prefilter. Cyrillic, Greek, Hebrew, Arabic, Thai, Devanagari, CJK, Hangul,
|
// prefilter. Cyrillic, Greek, Hebrew, Arabic, Thai, Devanagari, CJK, Hangul,
|
||||||
// kana, emoji, punctuation and box drawing are all outside.
|
// kana, emoji, punctuation and box drawing are all outside.
|
||||||
const (
|
const (
|
||||||
|
|||||||
+10
-22
@@ -194,31 +194,19 @@ func TestCharsLinesWrapWord(t *testing.T) {
|
|||||||
t.Errorf("Expected first line 'abcdefghij', got %q", string(lines2[0]))
|
t.Errorf("Expected first line 'abcdefghij', got %q", string(lines2[0]))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tab as word boundary
|
|
||||||
chars3 := ToChars([]byte("hello\tworld"))
|
|
||||||
lines3, _ := chars3.Lines(false, 100, 7, 0, 8, true)
|
|
||||||
// "hello\t" should break at tab (width of tab at pos 5 with tabstop 8 = 3, total width = 8 > 7)
|
|
||||||
// Actually RunesWidth: 'h'=1,'e'=1,'l'=1,'l'=1,'o'=1,'\t'=3 = 8 > 7, overflowIdx=5
|
|
||||||
// Then word-wrap scans back and finds no space/tab before idx 5 (tab IS at idx 5 but we check line[k-1])
|
|
||||||
// Wait - let me think: overflowIdx=5, we check k=5 -> line[4]='o', k=4 -> line[3]='l'... no space/tab found
|
|
||||||
// Falls back to character wrap: "hello" | "\tworld"
|
|
||||||
if len(lines3) < 2 {
|
|
||||||
t.Errorf("Expected at least 2 lines for tab test, got %d: %v", len(lines3), lines3)
|
|
||||||
}
|
|
||||||
|
|
||||||
// wrapWord=false still character-wraps
|
// wrapWord=false still character-wraps
|
||||||
chars4 := ToChars([]byte("hello world"))
|
chars3 := ToChars([]byte("hello world"))
|
||||||
lines4, _ := chars4.Lines(false, 100, 8, 0, 8, false)
|
lines3, _ := chars3.Lines(false, 100, 8, 0, 8, false)
|
||||||
if len(lines4) != 2 {
|
if len(lines3) != 2 {
|
||||||
t.Errorf("Expected 2 lines with wrapWord=false, got %d: %v", len(lines4), lines4)
|
t.Errorf("Expected 2 lines with wrapWord=false, got %d: %v", len(lines3), lines3)
|
||||||
}
|
}
|
||||||
if string(lines4[0]) != "hello wo" {
|
if string(lines3[0]) != "hello wo" {
|
||||||
t.Errorf("Expected first line 'hello wo', got %q", string(lines4[0]))
|
t.Errorf("Expected first line 'hello wo', got %q", string(lines3[0]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chars is one per input line, so its size is load-bearing. It has no spare
|
// Chars is one per input line, so its size matters. It has no spare padding,
|
||||||
// padding, which is why new state goes in the flags byte rather than a field.
|
// which is why new state goes in the flags byte rather than a field.
|
||||||
// Derive the expectation from the slice header so the invariant holds on
|
// Derive the expectation from the slice header so the invariant holds on
|
||||||
// 32-bit builds too, where the header is 12 bytes and Chars is 20.
|
// 32-bit builds too, where the header is 12 bytes and Chars is 20.
|
||||||
func TestCharsSize(t *testing.T) {
|
func TestCharsSize(t *testing.T) {
|
||||||
@@ -260,8 +248,8 @@ func TestMayFoldFlag(t *testing.T) {
|
|||||||
|
|
||||||
// Runes and ToRunes alias the text in rune mode, so a consumer that mutates
|
// Runes and ToRunes alias the text in rune mode, so a consumer that mutates
|
||||||
// what they return changes the text without updating the cached fold bit. This
|
// what they return changes the text without updating the cached fold bit. This
|
||||||
// pins the aliasing so the read-only contract on those methods is not silently
|
// verifies the aliasing so the read-only contract on those methods is not
|
||||||
// dropped later.
|
// silently dropped later.
|
||||||
func TestRuneSlicesAliasTheText(t *testing.T) {
|
func TestRuneSlicesAliasTheText(t *testing.T) {
|
||||||
chars := ToChars([]byte("한글abc"))
|
chars := ToChars([]byte("한글abc"))
|
||||||
runes := chars.Runes()
|
runes := chars.Runes()
|
||||||
|
|||||||
Reference in New Issue
Block a user