Path: blob/main/vendor/github.com/chzyer/readline/search.go
2875 views
package readline12import (3"bytes"4"container/list"5"fmt"6"io"7)89const (10S_STATE_FOUND = iota11S_STATE_FAILING12)1314const (15S_DIR_BCK = iota16S_DIR_FWD17)1819type opSearch struct {20inMode bool21state int22dir int23source *list.Element24w io.Writer25buf *RuneBuffer26data []rune27history *opHistory28cfg *Config29markStart int30markEnd int31width int32}3334func newOpSearch(w io.Writer, buf *RuneBuffer, history *opHistory, cfg *Config, width int) *opSearch {35return &opSearch{36w: w,37buf: buf,38cfg: cfg,39history: history,40width: width,41}42}4344func (o *opSearch) OnWidthChange(newWidth int) {45o.width = newWidth46}4748func (o *opSearch) IsSearchMode() bool {49return o.inMode50}5152func (o *opSearch) SearchBackspace() {53if len(o.data) > 0 {54o.data = o.data[:len(o.data)-1]55o.search(true)56}57}5859func (o *opSearch) findHistoryBy(isNewSearch bool) (int, *list.Element) {60if o.dir == S_DIR_BCK {61return o.history.FindBck(isNewSearch, o.data, o.buf.idx)62}63return o.history.FindFwd(isNewSearch, o.data, o.buf.idx)64}6566func (o *opSearch) search(isChange bool) bool {67if len(o.data) == 0 {68o.state = S_STATE_FOUND69o.SearchRefresh(-1)70return true71}72idx, elem := o.findHistoryBy(isChange)73if elem == nil {74o.SearchRefresh(-2)75return false76}77o.history.current = elem7879item := o.history.showItem(o.history.current.Value)80start, end := 0, 081if o.dir == S_DIR_BCK {82start, end = idx, idx+len(o.data)83} else {84start, end = idx, idx+len(o.data)85idx += len(o.data)86}87o.buf.SetWithIdx(idx, item)88o.markStart, o.markEnd = start, end89o.SearchRefresh(idx)90return true91}9293func (o *opSearch) SearchChar(r rune) {94o.data = append(o.data, r)95o.search(true)96}9798func (o *opSearch) SearchMode(dir int) bool {99if o.width == 0 {100return false101}102alreadyInMode := o.inMode103o.inMode = true104o.dir = dir105o.source = o.history.current106if alreadyInMode {107o.search(false)108} else {109o.SearchRefresh(-1)110}111return true112}113114func (o *opSearch) ExitSearchMode(revert bool) {115if revert {116o.history.current = o.source117o.buf.Set(o.history.showItem(o.history.current.Value))118}119o.markStart, o.markEnd = 0, 0120o.state = S_STATE_FOUND121o.inMode = false122o.source = nil123o.data = nil124}125126func (o *opSearch) SearchRefresh(x int) {127if x == -2 {128o.state = S_STATE_FAILING129} else if x >= 0 {130o.state = S_STATE_FOUND131}132if x < 0 {133x = o.buf.idx134}135x = o.buf.CurrentWidth(x)136x += o.buf.PromptLen()137x = x % o.width138139if o.markStart > 0 {140o.buf.SetStyle(o.markStart, o.markEnd, "4")141}142143lineCnt := o.buf.CursorLineCount()144buf := bytes.NewBuffer(nil)145buf.Write(bytes.Repeat([]byte("\n"), lineCnt))146buf.WriteString("\033[J")147if o.state == S_STATE_FAILING {148buf.WriteString("failing ")149}150if o.dir == S_DIR_BCK {151buf.WriteString("bck")152} else if o.dir == S_DIR_FWD {153buf.WriteString("fwd")154}155buf.WriteString("-i-search: ")156buf.WriteString(string(o.data)) // keyword157buf.WriteString("\033[4m \033[0m") // _158fmt.Fprintf(buf, "\r\033[%dA", lineCnt) // move prev159if x > 0 {160fmt.Fprintf(buf, "\033[%dC", x) // move forward161}162o.w.Write(buf.Bytes())163}164165166