From a2c4c99af4e33ff08b77023f1dd61cfb28ae9b02 Mon Sep 17 00:00:00 2001 From: lawl Date: Sat, 5 Jun 2021 19:59:47 +0200 Subject: [PATCH] WIP: implement reverse search --- go.mod | 2 +- history.go | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.go | 11 ++++++-- 3 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 history.go diff --git a/go.mod b/go.mod index 931bcd0..f15853b 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module hs9001 go 1.16 require ( - github.com/peterh/liner v1.2.1 + github.com/peterh/liner v1.2.1 github.com/tj/go-naturaldate v1.3.0 modernc.org/sqlite v1.10.0 ) diff --git a/history.go b/history.go new file mode 100644 index 0000000..e5d4824 --- /dev/null +++ b/history.go @@ -0,0 +1,77 @@ +package main + +import ( + "database/sql" + "fmt" + "io" + "log" + "os" + "strings" + "time" + + "github.com/tj/go-naturaldate" +) + +type history struct { + conn *sql.DB +} + +func (h *history) GetHistoryByPrefix(prefix string) (ph []string) { + beginTimestamp, err := naturaldate.Parse("50 years ago", time.Now()) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to convert time string: %s\n", err.Error()) + } + endTimeStamp, err := naturaldate.Parse("now", time.Now()) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to convert time string: %s\n", err.Error()) + } + results := search(h.conn, prefix+"%", "%", beginTimestamp, endTimeStamp, -9001) + for e := results.Front(); e != nil; e = e.Next() { + entry, ok := e.Value.(*HistoryEntry) + if !ok { + log.Panic("Failed to retrieve entries") + } + ph = append(ph, entry.cmd) + } + return +} +func (h *history) GetHistoryByPattern(pattern string) (ph []string, pos []int) { + beginTimestamp, err := naturaldate.Parse("50 years ago", time.Now()) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to convert time string: %s\n", err.Error()) + } + endTimeStamp, err := naturaldate.Parse("now", time.Now()) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to convert time string: %s\n", err.Error()) + } + results := search(h.conn, "%"+pattern+"%", "%", beginTimestamp, endTimeStamp, -9001) + for e := results.Front(); e != nil; e = e.Next() { + entry, ok := e.Value.(*HistoryEntry) + if !ok { + log.Panic("Failed to retrieve entries") + } + //mt.Printf("\nAppending: [%s] %s -- %d\n", pattern, entry.cmd, strings.Index(entry.cmd, pattern)) + ph = append(ph, entry.cmd) + pos = append(pos, strings.Index(strings.ToLower(entry.cmd), strings.ToLower(pattern))) + } + return +} + +func (h *history) ReadHistory(r io.Reader) (num int, err error) { + panic("not implemented") +} +func (h *history) WriteHistory(w io.Writer) (num int, err error) { + panic("not implemented") +} +func (h *history) AppendHistory(item string) { + panic("not implemented") +} +func (h *history) ClearHistory() { + panic("not implemented") +} +func (h *history) RLock() { + //noop +} +func (h *history) RUnlock() { + //noop +} diff --git a/main.go b/main.go index bd8a42d..bb796df 100644 --- a/main.go +++ b/main.go @@ -10,6 +10,7 @@ import ( "os" "path/filepath" "regexp" + "strconv" "strings" "time" @@ -271,6 +272,7 @@ func main() { line := liner.NewLiner() defer line.Close() line.SetCtrlCAborts(true) + line.SetHistoryProvider(&history{conn: conn}) line.SetCompleter(func(line string) (c []string) { beginTimestamp, err := naturaldate.Parse("50 years ago", time.Now()) if err != nil { @@ -291,14 +293,19 @@ func main() { return }) - if name, err := line.Prompt("What is your command? "); err == nil { - log.Print("Got: ", name) + rdlineline := os.Getenv("READLINE_LINE") + rdlinepos := os.Getenv("READLINE_POS") + rdlineposint, _ := strconv.Atoi(rdlinepos) + + if name, err := line.PromptWithSuggestionReverse("", rdlineline, rdlineposint); err == nil { + fmt.Fprintf(os.Stderr, "%s\n", name) } case "bash-enable": fmt.Printf(` if [ -n "$PS1" ] ; then PROMPT_COMMAND='hs9001 add -ret $? "$(history 1)"' + bind -x '"\C-r": " READLINE_LINE=$(hs9001 bash-ctrlr 3>&1 1>&2 2>&3) READLINE_POINT=0"' fi `) case "bash-disable":