github.com/puellanivis/breton@v0.2.16/lib/display/width/width.go (about)

     1  package width
     2  
     3  import (
     4  	"unicode"
     5  
     6  	"golang.org/x/text/width"
     7  )
     8  
     9  // AmbiguousIsWide sets if an unknown ambiguous character is assumed to be width == 2.
    10  var AmbiguousIsWide = false
    11  
    12  func guessWidth(r rune) int {
    13  	if unicode.Is(unicode.Cc, r) {
    14  		// NUL is width 0, all other C0/C1 codes shall return -1
    15  		if r == 0 {
    16  			return 0
    17  		}
    18  
    19  		return -1
    20  	}
    21  
    22  	// assume SOFT HYPHEN has a width of 1 (because monospaced-fonts)
    23  	if r == '\u00AD' {
    24  		return 1
    25  	}
    26  
    27  	if unicode.Is(ZeroWidth, r) {
    28  		return 0
    29  	}
    30  
    31  	if AmbiguousIsWide || unicode.Is(DoubleWidth, r) {
    32  		return 2
    33  	}
    34  
    35  	return 1
    36  }
    37  
    38  // Rune returns the expected display width of a rune. The logic largely matches what PuTTY does.
    39  //
    40  // Control Characters other than NUL return a value of -1.
    41  func Rune(r rune) int {
    42  	switch width.LookupRune(r).Kind() {
    43  	case width.EastAsianAmbiguous, width.Neutral:
    44  		return guessWidth(r)
    45  
    46  	case width.EastAsianWide, width.EastAsianFullwidth:
    47  		return 2
    48  
    49  		// case width.EastAsianNarrow, width.EastAsianHalfwidth, width.EastAsianNeutral:
    50  	}
    51  
    52  	return 1
    53  }
    54  
    55  // String returns the sum display length expected of the string given.
    56  //
    57  // If any rune in the string returns a width of -1, this function will return -1.
    58  func String(s string) int {
    59  	var n int
    60  
    61  	for _, r := range s {
    62  		w := Rune(r)
    63  		if w < 0 {
    64  			return -1
    65  		}
    66  
    67  		n += w
    68  	}
    69  
    70  	return n
    71  }