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 }