Compare commits

...

2 Commits

Author SHA1 Message Date
chzyer 5ac508ded8 [history] fix test 2016-10-03 14:49:32 +08:00
chzyer 5073debd7e add HistorySearchFold 2016-10-03 14:46:51 +08:00
4 changed files with 63 additions and 7 deletions

View File

@ -68,6 +68,8 @@ func main() {
AutoComplete: completer,
InterruptPrompt: "^C",
EOFPrompt: "exit",
HistorySearchFold: true,
})
if err != nil {
panic(err)

View File

@ -153,7 +153,7 @@ func (o *opHistory) FindBck(isNewSearch bool, rs []rune, start int) (int, *list.
item = item[:start]
}
}
idx := runes.IndexAllBck(item, rs)
idx := runes.IndexAllBckEx(item, rs, o.cfg.HistorySearchFold)
if idx < 0 {
continue
}
@ -178,7 +178,7 @@ func (o *opHistory) FindFwd(isNewSearch bool, rs []rune, start int) (int, *list.
continue
}
}
idx := runes.IndexAll(item, rs)
idx := runes.IndexAllEx(item, rs, o.cfg.HistorySearchFold)
if idx < 0 {
continue
}

View File

@ -34,6 +34,8 @@ type Config struct {
// specify the max length of historys, it's 500 by default, set it to -1 to disable history
HistoryLimit int
DisableAutoSaveHistory bool
// enable case-insensitive history searching
HistorySearchFold bool
// AutoCompleter will called once user press TAB
AutoComplete AutoCompleter

View File

@ -3,6 +3,7 @@ package readline
import (
"bytes"
"unicode"
"unicode/utf8"
)
var runes = Runes{}
@ -10,6 +11,42 @@ var TabWidth = 4
type Runes struct{}
func (Runes) EqualRune(a, b rune, fold bool) bool {
if a == b {
return true
}
if !fold {
return false
}
if a > b {
a, b = b, a
}
if b < utf8.RuneSelf && 'A' <= a && a <= 'Z' {
if b == a+'a'-'A' {
return true
}
}
return false
}
func (r Runes) EqualRuneFold(a, b rune) bool {
return r.EqualRune(a, b, true)
}
func (r Runes) EqualFold(a, b []rune) bool {
if len(a) != len(b) {
return false
}
for i := 0; i < len(a); i++ {
if r.EqualRuneFold(a[i], b[i]) {
continue
}
return false
}
return true
}
func (Runes) Equal(a, b []rune) bool {
if len(a) != len(b) {
return false
@ -22,12 +59,11 @@ func (Runes) Equal(a, b []rune) bool {
return true
}
// Search in runes from end to front
func (Runes) IndexAllBck(r, sub []rune) int {
func (rs Runes) IndexAllBckEx(r, sub []rune, fold bool) int {
for i := len(r) - len(sub); i >= 0; i-- {
found := true
for j := 0; j < len(sub); j++ {
if r[i+j] != sub[j] {
if !rs.EqualRune(r[i+j], sub[j], fold) {
found = false
break
}
@ -39,15 +75,24 @@ func (Runes) IndexAllBck(r, sub []rune) int {
return -1
}
// Search in runes from end to front
func (rs Runes) IndexAllBck(r, sub []rune) int {
return rs.IndexAllBckEx(r, sub, false)
}
// Search in runes from front to end
func (Runes) IndexAll(r, sub []rune) int {
func (rs Runes) IndexAll(r, sub []rune) int {
return rs.IndexAllEx(r, sub, false)
}
func (rs Runes) IndexAllEx(r, sub []rune, fold bool) int {
for i := 0; i < len(r); i++ {
found := true
if len(r[i:]) < len(sub) {
return -1
}
for j := 0; j < len(sub); j++ {
if r[i+j] != sub[j] {
if !rs.EqualRune(r[i+j], sub[j], fold) {
found = false
break
}
@ -128,6 +173,13 @@ func (Runes) Copy(r []rune) []rune {
return n
}
func (Runes) HasPrefixFold(r, prefix []rune) bool {
if len(r) < len(prefix) {
return false
}
return runes.EqualFold(r[:len(prefix)], prefix)
}
func (Runes) HasPrefix(r, prefix []rune) bool {
if len(r) < len(prefix) {
return false