mirror of https://github.com/chzyer/readline.git
fix fwd/bck search
This commit is contained in:
parent
3b1cf6b8fb
commit
a7f498f047
35
history.go
35
history.go
|
@ -58,9 +58,19 @@ func (o *opHistory) Close() {
|
|||
}
|
||||
}
|
||||
|
||||
func (o *opHistory) FindHistoryBck(rs []rune) (int, *list.Element) {
|
||||
func (o *opHistory) FindHistoryBck(isNewSearch bool, rs []rune, start int) (int, *list.Element) {
|
||||
for elem := o.current; elem != nil; elem = elem.Prev() {
|
||||
idx := RunesIndex(o.showItem(elem.Value), rs)
|
||||
item := o.showItem(elem.Value)
|
||||
if isNewSearch {
|
||||
start += len(rs)
|
||||
}
|
||||
if elem == o.current {
|
||||
if len(item) < start {
|
||||
continue
|
||||
}
|
||||
item = item[:start]
|
||||
}
|
||||
idx := RunesIndexBck(item, rs)
|
||||
if idx < 0 {
|
||||
continue
|
||||
}
|
||||
|
@ -69,12 +79,25 @@ func (o *opHistory) FindHistoryBck(rs []rune) (int, *list.Element) {
|
|||
return -1, nil
|
||||
}
|
||||
|
||||
func (o *opHistory) FindHistoryFwd(rs []rune) (int, *list.Element) {
|
||||
func (o *opHistory) FindHistoryFwd(isNewSearch bool, rs []rune, start int) (int, *list.Element) {
|
||||
for elem := o.current; elem != nil; elem = elem.Next() {
|
||||
idx := RunesIndex(o.showItem(elem.Value), rs)
|
||||
item := o.showItem(elem.Value)
|
||||
if isNewSearch {
|
||||
start -= len(rs)
|
||||
}
|
||||
if elem == o.current {
|
||||
if len(item)-1 < start {
|
||||
continue
|
||||
}
|
||||
item = item[start:]
|
||||
}
|
||||
idx := RunesIndex(item, rs)
|
||||
if idx < 0 {
|
||||
continue
|
||||
}
|
||||
if elem == o.current {
|
||||
idx += start
|
||||
}
|
||||
return idx, elem
|
||||
}
|
||||
return -1, nil
|
||||
|
@ -119,8 +142,8 @@ func (o *opHistory) NewHistory(current []rune) {
|
|||
if back := o.history.Back(); back != nil {
|
||||
prev := back.Prev()
|
||||
if prev != nil {
|
||||
use := o.current.Value.(*HisItem)
|
||||
if equalRunes(use.Tmp, prev.Value.(*HisItem).Source) {
|
||||
use := o.showItem(o.current.Value.(*HisItem))
|
||||
if equalRunes(use, prev.Value.(*HisItem).Source) {
|
||||
o.current = o.history.Back()
|
||||
o.current.Value.(*HisItem).Clean()
|
||||
o.historyVer++
|
||||
|
|
|
@ -96,6 +96,9 @@ func (l *Operation) ioloop() {
|
|||
case MetaBackspace:
|
||||
l.buf.BackEscapeWord()
|
||||
case CharEnter, CharEnter2:
|
||||
if l.IsSearchMode() {
|
||||
l.ExitSearchMode(false)
|
||||
}
|
||||
l.buf.MoveToLineEnd()
|
||||
l.buf.WriteRune('\n')
|
||||
data := l.buf.Reset()
|
||||
|
@ -136,7 +139,9 @@ func (l *Operation) ioloop() {
|
|||
l.ExitSearchMode(false)
|
||||
l.buf.Refresh()
|
||||
}
|
||||
l.UpdateHistory(l.buf.Runes(), false)
|
||||
if !l.IsSearchMode() {
|
||||
l.UpdateHistory(l.buf.Runes(), false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
29
runebuf.go
29
runebuf.go
|
@ -198,7 +198,9 @@ func (r *RuneBuffer) Output() []byte {
|
|||
buf.Write(r.CleanOutput())
|
||||
buf.Write(r.prompt)
|
||||
buf.Write([]byte(string(r.buf)))
|
||||
buf.Write(bytes.Repeat([]byte{'\b'}, len(r.buf)-r.idx))
|
||||
if len(r.buf) > r.idx {
|
||||
buf.Write(bytes.Repeat([]byte{'\b'}, len(r.buf)-r.idx))
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
|
@ -224,6 +226,31 @@ func (r *RuneBuffer) Reset() []rune {
|
|||
return ret
|
||||
}
|
||||
|
||||
func (r *RuneBuffer) SetStyle(start, end int, style string) {
|
||||
idx := r.idx
|
||||
if end < start {
|
||||
panic("end < start")
|
||||
}
|
||||
|
||||
// goto start
|
||||
move := start - idx
|
||||
if move > 0 {
|
||||
r.w.Write([]byte(string(r.buf[r.idx : r.idx+move])))
|
||||
} else {
|
||||
r.w.Write(bytes.Repeat([]byte("\b"), -move))
|
||||
}
|
||||
r.w.Write([]byte("\033[" + style))
|
||||
r.w.Write([]byte(string(r.buf[start:end])))
|
||||
r.w.Write([]byte("\033[0m"))
|
||||
if move > 0 {
|
||||
r.w.Write(bytes.Repeat([]byte("\b"), -move+(end-start)))
|
||||
} else if -move < end-start {
|
||||
r.w.Write(bytes.Repeat([]byte("\b"), -move))
|
||||
} else {
|
||||
r.w.Write([]byte(string(r.buf[end:r.idx])))
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RuneBuffer) SetWithIdx(idx int, buf []rune) {
|
||||
r.buf = buf
|
||||
r.idx = idx
|
||||
|
|
38
search.go
38
search.go
|
@ -43,39 +43,59 @@ func (o *opSearch) IsSearchMode() bool {
|
|||
func (o *opSearch) SearchBackspace() {
|
||||
if len(o.data) > 0 {
|
||||
o.data = o.data[:len(o.data)-1]
|
||||
o.search()
|
||||
o.search(true)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *opSearch) findHistoryBy() (int, *list.Element) {
|
||||
func (o *opSearch) findHistoryBy(isNewSearch bool) (int, *list.Element) {
|
||||
if o.dir == S_DIR_BCK {
|
||||
return o.history.FindHistoryBck(o.data)
|
||||
return o.history.FindHistoryBck(isNewSearch, o.data, o.buf.idx)
|
||||
}
|
||||
return o.history.FindHistoryFwd(o.data)
|
||||
return o.history.FindHistoryFwd(isNewSearch, o.data, o.buf.idx)
|
||||
}
|
||||
|
||||
func (o *opSearch) search() bool {
|
||||
idx, elem := o.findHistoryBy()
|
||||
func (o *opSearch) search(isChange bool) bool {
|
||||
if len(o.data) == 0 {
|
||||
o.state = S_STATE_FOUND
|
||||
o.SearchRefresh(-1)
|
||||
return true
|
||||
}
|
||||
idx, elem := o.findHistoryBy(isChange)
|
||||
if elem == nil {
|
||||
o.SearchRefresh(-2)
|
||||
return false
|
||||
}
|
||||
o.history.current = elem
|
||||
o.buf.SetWithIdx(idx, o.history.showItem(o.history.current.Value))
|
||||
|
||||
item := o.history.showItem(o.history.current.Value)
|
||||
start, end := 0, 0
|
||||
if o.dir == S_DIR_BCK {
|
||||
start, end = idx, idx+len(o.data)
|
||||
} else {
|
||||
start, end = idx, idx+len(o.data)
|
||||
idx += len(o.data)
|
||||
}
|
||||
o.buf.SetWithIdx(idx, item)
|
||||
o.buf.SetStyle(start, end, "4m")
|
||||
o.SearchRefresh(idx)
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *opSearch) SearchChar(r rune) {
|
||||
o.data = append(o.data, r)
|
||||
o.search()
|
||||
o.search(true)
|
||||
}
|
||||
|
||||
func (o *opSearch) SearchMode(dir int) {
|
||||
alreadyInMode := o.inMode
|
||||
o.inMode = true
|
||||
o.dir = dir
|
||||
o.source = o.history.current
|
||||
o.SearchRefresh(-1)
|
||||
if alreadyInMode {
|
||||
o.search(false)
|
||||
} else {
|
||||
o.SearchRefresh(-1)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *opSearch) ExitSearchMode(revert bool) {
|
||||
|
|
16
utils.go
16
utils.go
|
@ -131,6 +131,22 @@ func RunesWidth(r []rune) (length int) {
|
|||
return
|
||||
}
|
||||
|
||||
func RunesIndexBck(r, sub []rune) 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] {
|
||||
found = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if found {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func RunesIndex(r, sub []rune) int {
|
||||
for i := 0; i < len(r); i++ {
|
||||
found := true
|
||||
|
|
Loading…
Reference in New Issue