summaryrefslogtreecommitdiff
path: root/vendor/github.com/chzyer/readline/search.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/chzyer/readline/search.go')
-rw-r--r--vendor/github.com/chzyer/readline/search.go164
1 files changed, 164 insertions, 0 deletions
diff --git a/vendor/github.com/chzyer/readline/search.go b/vendor/github.com/chzyer/readline/search.go
new file mode 100644
index 000000000..52e8ff099
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/search.go
@@ -0,0 +1,164 @@
+package readline
+
+import (
+ "bytes"
+ "container/list"
+ "fmt"
+ "io"
+)
+
+const (
+ S_STATE_FOUND = iota
+ S_STATE_FAILING
+)
+
+const (
+ S_DIR_BCK = iota
+ S_DIR_FWD
+)
+
+type opSearch struct {
+ inMode bool
+ state int
+ dir int
+ source *list.Element
+ w io.Writer
+ buf *RuneBuffer
+ data []rune
+ history *opHistory
+ cfg *Config
+ markStart int
+ markEnd int
+ width int
+}
+
+func newOpSearch(w io.Writer, buf *RuneBuffer, history *opHistory, cfg *Config, width int) *opSearch {
+ return &opSearch{
+ w: w,
+ buf: buf,
+ cfg: cfg,
+ history: history,
+ width: width,
+ }
+}
+
+func (o *opSearch) OnWidthChange(newWidth int) {
+ o.width = newWidth
+}
+
+func (o *opSearch) IsSearchMode() bool {
+ return o.inMode
+}
+
+func (o *opSearch) SearchBackspace() {
+ if len(o.data) > 0 {
+ o.data = o.data[:len(o.data)-1]
+ o.search(true)
+ }
+}
+
+func (o *opSearch) findHistoryBy(isNewSearch bool) (int, *list.Element) {
+ if o.dir == S_DIR_BCK {
+ return o.history.FindBck(isNewSearch, o.data, o.buf.idx)
+ }
+ return o.history.FindFwd(isNewSearch, o.data, o.buf.idx)
+}
+
+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
+
+ 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.markStart, o.markEnd = start, end
+ o.SearchRefresh(idx)
+ return true
+}
+
+func (o *opSearch) SearchChar(r rune) {
+ o.data = append(o.data, r)
+ o.search(true)
+}
+
+func (o *opSearch) SearchMode(dir int) bool {
+ if o.width == 0 {
+ return false
+ }
+ alreadyInMode := o.inMode
+ o.inMode = true
+ o.dir = dir
+ o.source = o.history.current
+ if alreadyInMode {
+ o.search(false)
+ } else {
+ o.SearchRefresh(-1)
+ }
+ return true
+}
+
+func (o *opSearch) ExitSearchMode(revert bool) {
+ if revert {
+ o.history.current = o.source
+ o.buf.Set(o.history.showItem(o.history.current.Value))
+ }
+ o.markStart, o.markEnd = 0, 0
+ o.state = S_STATE_FOUND
+ o.inMode = false
+ o.source = nil
+ o.data = nil
+}
+
+func (o *opSearch) SearchRefresh(x int) {
+ if x == -2 {
+ o.state = S_STATE_FAILING
+ } else if x >= 0 {
+ o.state = S_STATE_FOUND
+ }
+ if x < 0 {
+ x = o.buf.idx
+ }
+ x = o.buf.CurrentWidth(x)
+ x += o.buf.PromptLen()
+ x = x % o.width
+
+ if o.markStart > 0 {
+ o.buf.SetStyle(o.markStart, o.markEnd, "4")
+ }
+
+ lineCnt := o.buf.CursorLineCount()
+ buf := bytes.NewBuffer(nil)
+ buf.Write(bytes.Repeat([]byte("\n"), lineCnt))
+ buf.WriteString("\033[J")
+ if o.state == S_STATE_FAILING {
+ buf.WriteString("failing ")
+ }
+ if o.dir == S_DIR_BCK {
+ buf.WriteString("bck")
+ } else if o.dir == S_DIR_FWD {
+ buf.WriteString("fwd")
+ }
+ buf.WriteString("-i-search: ")
+ buf.WriteString(string(o.data)) // keyword
+ buf.WriteString("\033[4m \033[0m") // _
+ fmt.Fprintf(buf, "\r\033[%dA", lineCnt) // move prev
+ if x > 0 {
+ fmt.Fprintf(buf, "\033[%dC", x) // move forward
+ }
+ o.w.Write(buf.Bytes())
+}