package uniseg // EastAsianAmbiguousWidth specifies the monospace width for East Asian // characters classified as Ambiguous. The default is 1 but some rare fonts // render them with a width of 2. var EastAsianAmbiguousWidth = 1 // runeWidth returns the monospace width for the given rune. The provided // grapheme property is a value mapped by the [graphemeCodePoints] table. // // Every rune has a width of 1, except for runes with the following properties // (evaluated in this order): // // - Control, CR, LF, Extend, ZWJ: Width of 0 // - \u2e3a, TWO-EM DASH: Width of 3 // - \u2e3b, THREE-EM DASH: Width of 4 // - East-Asian width Fullwidth and Wide: Width of 2 (Ambiguous and Neutral // have a width of 1) // - Regional Indicator: Width of 2 // - Extended Pictographic: Width of 2, unless Emoji Presentation is "No". func runeWidth(r rune, graphemeProperty int) int { switch graphemeProperty { case prControl, prCR, prLF, prExtend, prZWJ: return 0 case prRegionalIndicator: return 2 case prExtendedPictographic: if property(emojiPresentation, r) == prEmojiPresentation { return 2 } return 1 } switch r { case 0x2e3a: return 3 case 0x2e3b: return 4 } switch propertyEastAsianWidth(r) { case prW, prF: return 2 case prA: return EastAsianAmbiguousWidth } return 1 } // StringWidth returns the monospace width for the given string, that is, the // number of same-size cells to be occupied by the string. func StringWidth(s string) (width int) { state := -1 for len(s) > 0 { var w int _, s, w, state = FirstGraphemeClusterInString(s, state) width += w } return }