Andrew Wilkins | 4ffbbd7 | 2015-05-23 15:16:09 +0000 | [diff] [blame] | 1 | package liner |
| 2 | |
| 3 | import "unicode" |
| 4 | |
| 5 | // These character classes are mostly zero width (when combined). |
| 6 | // A few might not be, depending on the user's font. Fixing this |
| 7 | // is non-trivial, given that some terminals don't support |
| 8 | // ANSI DSR/CPR |
| 9 | var zeroWidth = []*unicode.RangeTable{ |
| 10 | unicode.Mn, |
| 11 | unicode.Me, |
| 12 | unicode.Cc, |
| 13 | unicode.Cf, |
| 14 | } |
| 15 | |
| 16 | var doubleWidth = []*unicode.RangeTable{ |
| 17 | unicode.Han, |
| 18 | unicode.Hangul, |
| 19 | unicode.Hiragana, |
| 20 | unicode.Katakana, |
| 21 | } |
| 22 | |
| 23 | // countGlyphs considers zero-width characters to be zero glyphs wide, |
| 24 | // and members of Chinese, Japanese, and Korean scripts to be 2 glyphs wide. |
| 25 | func countGlyphs(s []rune) int { |
| 26 | n := 0 |
| 27 | for _, r := range s { |
| 28 | switch { |
| 29 | case unicode.IsOneOf(zeroWidth, r): |
| 30 | case unicode.IsOneOf(doubleWidth, r): |
| 31 | n += 2 |
| 32 | default: |
| 33 | n++ |
| 34 | } |
| 35 | } |
| 36 | return n |
| 37 | } |
| 38 | |
Andrew Wilkins | 6436a4a | 2016-03-15 05:36:43 +0000 | [diff] [blame^] | 39 | func countMultiLineGlyphs(s []rune, columns int, start int) int { |
| 40 | n := start |
| 41 | for _, r := range s { |
| 42 | switch { |
| 43 | case unicode.IsOneOf(zeroWidth, r): |
| 44 | case unicode.IsOneOf(doubleWidth, r): |
| 45 | n += 2 |
| 46 | // no room for a 2-glyphs-wide char in the ending |
| 47 | // so skip a column and display it at the beginning |
| 48 | if n%columns == 1 { |
| 49 | n++ |
| 50 | } |
| 51 | default: |
| 52 | n++ |
| 53 | } |
| 54 | } |
| 55 | return n |
| 56 | } |
| 57 | |
Andrew Wilkins | 4ffbbd7 | 2015-05-23 15:16:09 +0000 | [diff] [blame] | 58 | func getPrefixGlyphs(s []rune, num int) []rune { |
| 59 | p := 0 |
| 60 | for n := 0; n < num && p < len(s); p++ { |
| 61 | if !unicode.IsOneOf(zeroWidth, s[p]) { |
| 62 | n++ |
| 63 | } |
| 64 | } |
| 65 | for p < len(s) && unicode.IsOneOf(zeroWidth, s[p]) { |
| 66 | p++ |
| 67 | } |
| 68 | return s[:p] |
| 69 | } |
| 70 | |
| 71 | func getSuffixGlyphs(s []rune, num int) []rune { |
| 72 | p := len(s) |
| 73 | for n := 0; n < num && p > 0; p-- { |
| 74 | if !unicode.IsOneOf(zeroWidth, s[p-1]) { |
| 75 | n++ |
| 76 | } |
| 77 | } |
| 78 | return s[p:] |
| 79 | } |