123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- package liner
- import (
- "unicode"
- "github.com/mattn/go-runewidth"
- )
- // 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,
- }
- // 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 {
- // speed up the common case
- if r < 127 {
- n++
- continue
- }
- n += runewidth.RuneWidth(r)
- }
- return n
- }
- func countMultiLineGlyphs(s []rune, columns int, start int) int {
- n := start
- for _, r := range s {
- if r < 127 {
- n++
- continue
- }
- switch runewidth.RuneWidth(r) {
- case 0:
- case 1:
- n++
- case 2:
- 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++
- }
- }
- }
- return n
- }
- func getPrefixGlyphs(s []rune, num int) []rune {
- p := 0
- for n := 0; n < num && p < len(s); p++ {
- // speed up the common case
- if s[p] < 127 {
- n++
- continue
- }
- 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-- {
- // speed up the common case
- if s[p-1] < 127 {
- n++
- continue
- }
- if !unicode.IsOneOf(zeroWidth, s[p-1]) {
- n++
- }
- }
- return s[p:]
- }
|