...

Source file src/github.com/rogpeppe/go-internal/internal/misspell/misspell.go

Documentation: github.com/rogpeppe/go-internal/internal/misspell

     1  // Package misspell impements utilities for basic spelling correction.
     2  package misspell
     3  
     4  import (
     5  	"unicode/utf8"
     6  )
     7  
     8  // AlmostEqual reports whether a and b have Damerau-Levenshtein distance of at
     9  // most 1. That is, it reports whether a can be transformed into b by adding,
    10  // removing or substituting a single rune, or by swapping two adjacent runes.
    11  // Invalid runes are considered equal.
    12  //
    13  // It runs in O(len(a)+len(b)) time.
    14  func AlmostEqual(a, b string) bool {
    15  	for len(a) > 0 && len(b) > 0 {
    16  		ra, tailA := shiftRune(a)
    17  		rb, tailB := shiftRune(b)
    18  		if ra == rb {
    19  			a, b = tailA, tailB
    20  			continue
    21  		}
    22  		// check for addition/deletion/substitution
    23  		if equalValid(a, tailB) || equalValid(tailA, b) || equalValid(tailA, tailB) {
    24  			return true
    25  		}
    26  		if len(tailA) == 0 || len(tailB) == 0 {
    27  			return false
    28  		}
    29  		// check for swap
    30  		a, b = tailA, tailB
    31  		Ra, tailA := shiftRune(tailA)
    32  		Rb, tailB := shiftRune(tailB)
    33  		return ra == Rb && Ra == rb && equalValid(tailA, tailB)
    34  	}
    35  	if len(a) == 0 {
    36  		return len(b) == 0 || singleRune(b)
    37  	}
    38  	return singleRune(a)
    39  }
    40  
    41  // singleRune reports whether s consists of a single UTF-8 codepoint.
    42  func singleRune(s string) bool {
    43  	_, n := utf8.DecodeRuneInString(s)
    44  	return n == len(s)
    45  }
    46  
    47  // shiftRune splits off the first UTF-8 codepoint from s and returns it and the
    48  // rest of the string. It panics if s is empty.
    49  func shiftRune(s string) (rune, string) {
    50  	if len(s) == 0 {
    51  		panic(s)
    52  	}
    53  	r, n := utf8.DecodeRuneInString(s)
    54  	return r, s[n:]
    55  }
    56  
    57  // equalValid reports whether a and b are equal, if invalid code points are considered equal.
    58  func equalValid(a, b string) bool {
    59  	var ra, rb rune
    60  	for len(a) > 0 && len(b) > 0 {
    61  		ra, a = shiftRune(a)
    62  		rb, b = shiftRune(b)
    63  		if ra != rb {
    64  			return false
    65  		}
    66  	}
    67  	return len(a) == 0 && len(b) == 0
    68  }
    69  

View as plain text