Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
kardolus
GitHub Repository: kardolus/chatgpt-cli
Path: blob/main/vendor/github.com/chzyer/readline/runes.go
2875 views
1
package readline
2
3
import (
4
"bytes"
5
"unicode"
6
"unicode/utf8"
7
)
8
9
var runes = Runes{}
10
var TabWidth = 4
11
12
type Runes struct{}
13
14
func (Runes) EqualRune(a, b rune, fold bool) bool {
15
if a == b {
16
return true
17
}
18
if !fold {
19
return false
20
}
21
if a > b {
22
a, b = b, a
23
}
24
if b < utf8.RuneSelf && 'A' <= a && a <= 'Z' {
25
if b == a+'a'-'A' {
26
return true
27
}
28
}
29
return false
30
}
31
32
func (r Runes) EqualRuneFold(a, b rune) bool {
33
return r.EqualRune(a, b, true)
34
}
35
36
func (r Runes) EqualFold(a, b []rune) bool {
37
if len(a) != len(b) {
38
return false
39
}
40
for i := 0; i < len(a); i++ {
41
if r.EqualRuneFold(a[i], b[i]) {
42
continue
43
}
44
return false
45
}
46
47
return true
48
}
49
50
func (Runes) Equal(a, b []rune) bool {
51
if len(a) != len(b) {
52
return false
53
}
54
for i := 0; i < len(a); i++ {
55
if a[i] != b[i] {
56
return false
57
}
58
}
59
return true
60
}
61
62
func (rs Runes) IndexAllBckEx(r, sub []rune, fold bool) int {
63
for i := len(r) - len(sub); i >= 0; i-- {
64
found := true
65
for j := 0; j < len(sub); j++ {
66
if !rs.EqualRune(r[i+j], sub[j], fold) {
67
found = false
68
break
69
}
70
}
71
if found {
72
return i
73
}
74
}
75
return -1
76
}
77
78
// Search in runes from end to front
79
func (rs Runes) IndexAllBck(r, sub []rune) int {
80
return rs.IndexAllBckEx(r, sub, false)
81
}
82
83
// Search in runes from front to end
84
func (rs Runes) IndexAll(r, sub []rune) int {
85
return rs.IndexAllEx(r, sub, false)
86
}
87
88
func (rs Runes) IndexAllEx(r, sub []rune, fold bool) int {
89
for i := 0; i < len(r); i++ {
90
found := true
91
if len(r[i:]) < len(sub) {
92
return -1
93
}
94
for j := 0; j < len(sub); j++ {
95
if !rs.EqualRune(r[i+j], sub[j], fold) {
96
found = false
97
break
98
}
99
}
100
if found {
101
return i
102
}
103
}
104
return -1
105
}
106
107
func (Runes) Index(r rune, rs []rune) int {
108
for i := 0; i < len(rs); i++ {
109
if rs[i] == r {
110
return i
111
}
112
}
113
return -1
114
}
115
116
func (Runes) ColorFilter(r []rune) []rune {
117
newr := make([]rune, 0, len(r))
118
for pos := 0; pos < len(r); pos++ {
119
if r[pos] == '\033' && r[pos+1] == '[' {
120
idx := runes.Index('m', r[pos+2:])
121
if idx == -1 {
122
continue
123
}
124
pos += idx + 2
125
continue
126
}
127
newr = append(newr, r[pos])
128
}
129
return newr
130
}
131
132
var zeroWidth = []*unicode.RangeTable{
133
unicode.Mn,
134
unicode.Me,
135
unicode.Cc,
136
unicode.Cf,
137
}
138
139
var doubleWidth = []*unicode.RangeTable{
140
unicode.Han,
141
unicode.Hangul,
142
unicode.Hiragana,
143
unicode.Katakana,
144
}
145
146
func (Runes) Width(r rune) int {
147
if r == '\t' {
148
return TabWidth
149
}
150
if unicode.IsOneOf(zeroWidth, r) {
151
return 0
152
}
153
if unicode.IsOneOf(doubleWidth, r) {
154
return 2
155
}
156
return 1
157
}
158
159
func (Runes) WidthAll(r []rune) (length int) {
160
for i := 0; i < len(r); i++ {
161
length += runes.Width(r[i])
162
}
163
return
164
}
165
166
func (Runes) Backspace(r []rune) []byte {
167
return bytes.Repeat([]byte{'\b'}, runes.WidthAll(r))
168
}
169
170
func (Runes) Copy(r []rune) []rune {
171
n := make([]rune, len(r))
172
copy(n, r)
173
return n
174
}
175
176
func (Runes) HasPrefixFold(r, prefix []rune) bool {
177
if len(r) < len(prefix) {
178
return false
179
}
180
return runes.EqualFold(r[:len(prefix)], prefix)
181
}
182
183
func (Runes) HasPrefix(r, prefix []rune) bool {
184
if len(r) < len(prefix) {
185
return false
186
}
187
return runes.Equal(r[:len(prefix)], prefix)
188
}
189
190
func (Runes) Aggregate(candicate [][]rune) (same []rune, size int) {
191
for i := 0; i < len(candicate[0]); i++ {
192
for j := 0; j < len(candicate)-1; j++ {
193
if i >= len(candicate[j]) || i >= len(candicate[j+1]) {
194
goto aggregate
195
}
196
if candicate[j][i] != candicate[j+1][i] {
197
goto aggregate
198
}
199
}
200
size = i + 1
201
}
202
aggregate:
203
if size > 0 {
204
same = runes.Copy(candicate[0][:size])
205
for i := 0; i < len(candicate); i++ {
206
n := runes.Copy(candicate[i])
207
copy(n, n[size:])
208
candicate[i] = n[:len(n)-size]
209
}
210
}
211
return
212
}
213
214
func (Runes) TrimSpaceLeft(in []rune) []rune {
215
firstIndex := len(in)
216
for i, r := range in {
217
if unicode.IsSpace(r) == false {
218
firstIndex = i
219
break
220
}
221
}
222
return in[firstIndex:]
223
}
224
225