refactor search function. rename -being and -end to -after and -before

This commit is contained in:
lawl 2021-06-05 22:41:34 +02:00
parent a2c4c99af4
commit e5c1beb937
2 changed files with 78 additions and 78 deletions

View File

@ -2,14 +2,9 @@ package main
import ( import (
"database/sql" "database/sql"
"fmt"
"io" "io"
"log" "log"
"os"
"strings" "strings"
"time"
"github.com/tj/go-naturaldate"
) )
type history struct { type history struct {
@ -17,15 +12,11 @@ type history struct {
} }
func (h *history) GetHistoryByPrefix(prefix string) (ph []string) { func (h *history) GetHistoryByPrefix(prefix string) (ph []string) {
beginTimestamp, err := naturaldate.Parse("50 years ago", time.Now()) opts := searchopts{}
if err != nil { opts.order = "DESC"
fmt.Fprintf(os.Stderr, "Failed to convert time string: %s\n", err.Error()) cmdqry := prefix + "%"
} opts.command = &cmdqry
endTimeStamp, err := naturaldate.Parse("now", time.Now()) results := search(h.conn, opts)
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() { for e := results.Front(); e != nil; e = e.Next() {
entry, ok := e.Value.(*HistoryEntry) entry, ok := e.Value.(*HistoryEntry)
if !ok { if !ok {
@ -36,21 +27,16 @@ func (h *history) GetHistoryByPrefix(prefix string) (ph []string) {
return return
} }
func (h *history) GetHistoryByPattern(pattern string) (ph []string, pos []int) { func (h *history) GetHistoryByPattern(pattern string) (ph []string, pos []int) {
beginTimestamp, err := naturaldate.Parse("50 years ago", time.Now()) opts := searchopts{}
if err != nil { opts.order = "DESC"
fmt.Fprintf(os.Stderr, "Failed to convert time string: %s\n", err.Error()) cmdqry := "%" + pattern + "%"
} opts.command = &cmdqry
endTimeStamp, err := naturaldate.Parse("now", time.Now()) results := search(h.conn, opts)
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() { for e := results.Front(); e != nil; e = e.Next() {
entry, ok := e.Value.(*HistoryEntry) entry, ok := e.Value.(*HistoryEntry)
if !ok { if !ok {
log.Panic("Failed to retrieve entries") 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) ph = append(ph, entry.cmd)
pos = append(pos, strings.Index(strings.ToLower(entry.cmd), strings.ToLower(pattern))) pos = append(pos, strings.Index(strings.ToLower(entry.cmd), strings.ToLower(pattern)))
} }

120
main.go
View File

@ -150,28 +150,47 @@ func importFromStdin(conn *sql.DB) {
} }
} }
func search(conn *sql.DB, q string, workdir string, beginTime time.Time, endTime time.Time, retval int) list.List { type searchopts struct {
command *string
workdir *string
after *time.Time
before *time.Time
retval *int
order string
}
func search(conn *sql.DB, opts searchopts) list.List {
args := make([]interface{}, 0)
var sb strings.Builder var sb strings.Builder
sb.WriteString("SELECT id, command, workdir, user, hostname, retval ") sb.WriteString("SELECT id, command, workdir, user, hostname, retval ")
sb.WriteString("FROM history ") sb.WriteString("FROM history ")
sb.WriteString("WHERE timestamp BETWEEN datetime(?, 'unixepoch') ") sb.WriteString("WHERE 1=1 ") //1=1 so we can append as many AND foo as we want, or none
sb.WriteString("AND datetime(?, 'unixepoch') ")
if opts.command != nil {
sb.WriteString("AND command LIKE ? ") sb.WriteString("AND command LIKE ? ")
sb.WriteString("AND workdir LIKE ? ") args = append(args, opts.command)
if retval != -9001 {
sb.WriteString("AND retval = ? ")
} }
sb.WriteString("ORDER BY timestamp ASC ") if opts.workdir != nil {
sb.WriteString("AND workdir LIKE ? ")
args = append(args, opts.workdir)
}
if opts.after != nil {
sb.WriteString("AND timestamp > datetime(?, 'unixepoch') ")
args = append(args, opts.after.Unix())
}
if opts.before != nil {
sb.WriteString("AND timestamp < datetime(?, 'unixepoch') ")
args = append(args, opts.before.Unix())
}
if opts.retval != nil {
sb.WriteString("AND retval = ? ")
args = append(args, opts.retval)
}
sb.WriteString("ORDER BY timestamp ")
sb.WriteString("ASC ")
queryStmt := sb.String() queryStmt := sb.String()
args := make([]interface{}, 0)
args = append(args, beginTime.Unix())
args = append(args, endTime.Unix())
args = append(args, q)
args = append(args, workdir)
if retval != -9001 {
args = append(args, retval)
}
rows, err := conn.Query(queryStmt, args...) rows, err := conn.Query(queryStmt, args...)
if err != nil { if err != nil {
log.Panic(err) log.Panic(err)
@ -273,25 +292,6 @@ func main() {
defer line.Close() defer line.Close()
line.SetCtrlCAborts(true) line.SetCtrlCAborts(true)
line.SetHistoryProvider(&history{conn: conn}) line.SetHistoryProvider(&history{conn: conn})
line.SetCompleter(func(line string) (c []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(conn, "%"+line+"%", "%", 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")
}
c = append(c, entry.cmd)
}
return
})
rdlineline := os.Getenv("READLINE_LINE") rdlineline := os.Getenv("READLINE_LINE")
rdlinepos := os.Getenv("READLINE_POS") rdlinepos := os.Getenv("READLINE_POS")
@ -333,13 +333,13 @@ func main() {
fallthrough fallthrough
case "delete": case "delete":
var workDir string var workDir string
var beginTime string var afterTime string
var endTime string var beforeTime string
var distinct bool = true var distinct bool = true
var retVal int var retVal int
searchCmd.StringVar(&workDir, "cwd", "%", "Search only within this workdir") searchCmd.StringVar(&workDir, "cwd", "", "Search only within this workdir")
searchCmd.StringVar(&beginTime, "begin", "50 years ago", "Start searching from this timeframe") searchCmd.StringVar(&afterTime, "after", "", "Start searching from this timeframe")
searchCmd.StringVar(&endTime, "end", "now", "End searching from this timeframe") searchCmd.StringVar(&beforeTime, "before", "", "End searching from this timeframe")
searchCmd.BoolVar(&distinct, "distinct", true, "Remove consecutive duplicate commands from output") searchCmd.BoolVar(&distinct, "distinct", true, "Remove consecutive duplicate commands from output")
searchCmd.IntVar(&retVal, "ret", -9001, "Only query commands that returned with this exit code. -9001=all (default)") searchCmd.IntVar(&retVal, "ret", -9001, "Only query commands that returned with this exit code. -9001=all (default)")
@ -347,25 +347,39 @@ func main() {
args := searchCmd.Args() args := searchCmd.Args()
beginTimestamp, err := naturaldate.Parse(beginTime, time.Now())
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to convert time string: %s\n", err.Error())
}
endTimeStamp, err := naturaldate.Parse(endTime, time.Now())
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to convert time string: %s\n", err.Error())
}
q := strings.Join(args, " ") q := strings.Join(args, " ")
if workDir != "%" {
workDir, err = filepath.Abs(workDir) opts := searchopts{}
opts.order = "ASC"
if q != "" {
cmd := "%" + q + "%"
opts.command = &cmd
}
if workDir != "" {
wd, err := filepath.Abs(workDir)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Failed parse working directory path: %s\n", err.Error()) fmt.Fprintf(os.Stderr, "Failed parse working directory path: %s\n", err.Error())
} }
opts.workdir = &wd
} }
if afterTime != "" {
results := search(conn, "%"+q+"%", workDir, beginTimestamp, endTimeStamp, retVal) afterTimestamp, err := naturaldate.Parse(afterTime, time.Now())
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to convert time string: %s\n", err.Error())
}
opts.after = &afterTimestamp
}
if beforeTime != "" {
beforeTimestamp, err := naturaldate.Parse(beforeTime, time.Now())
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to convert time string: %s\n", err.Error())
}
opts.before = &beforeTimestamp
}
if retVal != -9001 {
opts.retval = &retVal
}
results := search(conn, opts)
previousCmd := "" previousCmd := ""
for e := results.Front(); e != nil; e = e.Next() { for e := results.Front(); e != nil; e = e.Next() {