Skip to content

Commit

Permalink
fix fwd/bck search
Browse files Browse the repository at this point in the history
  • Loading branch information
chzyer committed Sep 23, 2015
1 parent 3b1cf6b commit a7f498f
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 17 deletions.
35 changes: 29 additions & 6 deletions history.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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
Expand Down Expand Up @@ -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++
Expand Down
7 changes: 6 additions & 1 deletion operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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)
}
}
}

Expand Down
29 changes: 28 additions & 1 deletion runebuf.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}

Expand All @@ -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
Expand Down
38 changes: 29 additions & 9 deletions search.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
16 changes: 16 additions & 0 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit a7f498f

Please sign in to comment.