github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/utils/readline/unicode.go (about) 1 package readline 2 3 import "github.com/mattn/go-runewidth" 4 5 type UnicodeT struct { 6 rl *Instance 7 value []rune 8 rPos int 9 cPos int 10 } 11 12 func (u *UnicodeT) Set(rl *Instance, r []rune) { 13 u.rl = rl 14 u.value = r 15 u.cPos = u.cellPos() 16 } 17 18 func (u *UnicodeT) Runes() []rune { 19 return u.value 20 } 21 22 func (u *UnicodeT) String() string { 23 return string(u.value) 24 } 25 26 func (u *UnicodeT) RuneLen() int { 27 return len(u.value) 28 } 29 30 func (u *UnicodeT) RunePos() int { 31 return u.rPos 32 } 33 34 func (u *UnicodeT) _offByOne(i int) int { 35 if len(u.value) == 0 { 36 return 0 37 } 38 if u.rl != nil && u.rl.modeViMode != vimInsert && i == len(u.value) { 39 i = len(u.value) - 1 40 } 41 return i 42 } 43 44 func (u *UnicodeT) SetRunePos(i int) { 45 if i < 0 { 46 i = 0 47 } 48 if i > len(u.value) { 49 i = len(u.value) 50 } 51 52 u.rPos = u._offByOne(i) 53 u.cPos = u.cellPos() 54 } 55 56 func (u *UnicodeT) Duplicate() *UnicodeT { 57 dup := new(UnicodeT) 58 dup.value = make([]rune, len(u.value)) 59 copy(dup.value, u.value) 60 dup.rPos = u.rPos 61 dup.cPos = u.cPos 62 return dup 63 } 64 65 func (u *UnicodeT) CellLen() int { 66 return runewidth.StringWidth(u.String()) 67 } 68 69 func (u *UnicodeT) cellPos() int { 70 var cPos, i, last int 71 for ; i < len(u.value) && i < u.rPos; i++ { 72 w := runewidth.RuneWidth(u.value[i]) 73 cPos += w 74 last = w 75 } 76 if last == 2 { 77 cPos-- 78 } 79 80 return cPos 81 } 82 83 func (u *UnicodeT) CellPos() int { 84 return u.cPos 85 } 86 87 func (u *UnicodeT) SetCellPos(cPos int) { 88 u._setCellPos(cPos) 89 i := u._offByOne(u.rPos) 90 if i != u.rPos { 91 u.rPos-- 92 u.cPos -= runewidth.RuneWidth(u.value[u.rPos]) 93 } 94 } 95 96 func (u *UnicodeT) _setCellPos(cPos int) { 97 if len(u.value) == 0 { 98 return 99 } 100 101 u.cPos = 0 102 var last int 103 for u.rPos = 0; u.rPos < len(u.value); u.rPos++ { 104 if u.cPos >= cPos { 105 if last == 2 { 106 u.cPos-- 107 } 108 return 109 } 110 w := runewidth.RuneWidth(u.value[u.rPos]) 111 u.cPos += w 112 last = w 113 } 114 115 if last == 2 { 116 u.cPos-- 117 } 118 u.rPos = len(u.value) 119 if u.rPos < 0 { 120 u.rPos = 0 121 } 122 }