Skip to content

Commit 94eaec6

Browse files
authored
add HistorySearchFold (chzyer#86)
* add HistorySearchFold * [history] fix test
1 parent bc5e387 commit 94eaec6

File tree

4 files changed

+63
-7
lines changed

4 files changed

+63
-7
lines changed

example/readline-demo/readline-demo.go

+2
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ func main() {
6868
AutoComplete: completer,
6969
InterruptPrompt: "^C",
7070
EOFPrompt: "exit",
71+
72+
HistorySearchFold: true,
7173
})
7274
if err != nil {
7375
panic(err)

history.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ func (o *opHistory) FindBck(isNewSearch bool, rs []rune, start int) (int, *list.
153153
item = item[:start]
154154
}
155155
}
156-
idx := runes.IndexAllBck(item, rs)
156+
idx := runes.IndexAllBckEx(item, rs, o.cfg.HistorySearchFold)
157157
if idx < 0 {
158158
continue
159159
}
@@ -178,7 +178,7 @@ func (o *opHistory) FindFwd(isNewSearch bool, rs []rune, start int) (int, *list.
178178
continue
179179
}
180180
}
181-
idx := runes.IndexAll(item, rs)
181+
idx := runes.IndexAllEx(item, rs, o.cfg.HistorySearchFold)
182182
if idx < 0 {
183183
continue
184184
}

readline.go

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ type Config struct {
3434
// specify the max length of historys, it's 500 by default, set it to -1 to disable history
3535
HistoryLimit int
3636
DisableAutoSaveHistory bool
37+
// enable case-insensitive history searching
38+
HistorySearchFold bool
3739

3840
// AutoCompleter will called once user press TAB
3941
AutoComplete AutoCompleter

runes.go

+57-5
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,50 @@ package readline
33
import (
44
"bytes"
55
"unicode"
6+
"unicode/utf8"
67
)
78

89
var runes = Runes{}
910
var TabWidth = 4
1011

1112
type Runes struct{}
1213

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+
1350
func (Runes) Equal(a, b []rune) bool {
1451
if len(a) != len(b) {
1552
return false
@@ -22,12 +59,11 @@ func (Runes) Equal(a, b []rune) bool {
2259
return true
2360
}
2461

25-
// Search in runes from end to front
26-
func (Runes) IndexAllBck(r, sub []rune) int {
62+
func (rs Runes) IndexAllBckEx(r, sub []rune, fold bool) int {
2763
for i := len(r) - len(sub); i >= 0; i-- {
2864
found := true
2965
for j := 0; j < len(sub); j++ {
30-
if r[i+j] != sub[j] {
66+
if !rs.EqualRune(r[i+j], sub[j], fold) {
3167
found = false
3268
break
3369
}
@@ -39,15 +75,24 @@ func (Runes) IndexAllBck(r, sub []rune) int {
3975
return -1
4076
}
4177

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+
4283
// Search in runes from front to end
43-
func (Runes) IndexAll(r, sub []rune) int {
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 {
4489
for i := 0; i < len(r); i++ {
4590
found := true
4691
if len(r[i:]) < len(sub) {
4792
return -1
4893
}
4994
for j := 0; j < len(sub); j++ {
50-
if r[i+j] != sub[j] {
95+
if !rs.EqualRune(r[i+j], sub[j], fold) {
5196
found = false
5297
break
5398
}
@@ -128,6 +173,13 @@ func (Runes) Copy(r []rune) []rune {
128173
return n
129174
}
130175

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+
131183
func (Runes) HasPrefix(r, prefix []rune) bool {
132184
if len(r) < len(prefix) {
133185
return false

0 commit comments

Comments
 (0)