| package liner |
| |
| import "unicode" |
| |
| // These character classes are mostly zero width (when combined). |
| // A few might not be, depending on the user's font. Fixing this |
| // is non-trivial, given that some terminals don't support |
| // ANSI DSR/CPR |
| var zeroWidth = []*unicode.RangeTable{ |
| unicode.Mn, |
| unicode.Me, |
| unicode.Cc, |
| unicode.Cf, |
| } |
| |
| var doubleWidth = []*unicode.RangeTable{ |
| unicode.Han, |
| unicode.Hangul, |
| unicode.Hiragana, |
| unicode.Katakana, |
| } |
| |
| // countGlyphs considers zero-width characters to be zero glyphs wide, |
| // and members of Chinese, Japanese, and Korean scripts to be 2 glyphs wide. |
| func countGlyphs(s []rune) int { |
| n := 0 |
| for _, r := range s { |
| switch { |
| case unicode.IsOneOf(zeroWidth, r): |
| case unicode.IsOneOf(doubleWidth, r): |
| n += 2 |
| default: |
| n++ |
| } |
| } |
| return n |
| } |
| |
| func countMultiLineGlyphs(s []rune, columns int, start int) int { |
| n := start |
| for _, r := range s { |
| switch { |
| case unicode.IsOneOf(zeroWidth, r): |
| case unicode.IsOneOf(doubleWidth, r): |
| n += 2 |
| // no room for a 2-glyphs-wide char in the ending |
| // so skip a column and display it at the beginning |
| if n%columns == 1 { |
| n++ |
| } |
| default: |
| n++ |
| } |
| } |
| return n |
| } |
| |
| func getPrefixGlyphs(s []rune, num int) []rune { |
| p := 0 |
| for n := 0; n < num && p < len(s); p++ { |
| if !unicode.IsOneOf(zeroWidth, s[p]) { |
| n++ |
| } |
| } |
| for p < len(s) && unicode.IsOneOf(zeroWidth, s[p]) { |
| p++ |
| } |
| return s[:p] |
| } |
| |
| func getSuffixGlyphs(s []rune, num int) []rune { |
| p := len(s) |
| for n := 0; n < num && p > 0; p-- { |
| if !unicode.IsOneOf(zeroWidth, s[p-1]) { |
| n++ |
| } |
| } |
| return s[p:] |
| } |