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
父節點 a2c4c99af4
當前提交 e5c1beb937
共有 2 個文件被更改,包括 78 次插入78 次删除

查看文件

@ -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)))
} }

122
main.go
查看文件

@ -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') ")
sb.WriteString("AND command LIKE ? ") if opts.command != nil {
sb.WriteString("AND workdir LIKE ? ") sb.WriteString("AND command LIKE ? ")
if retval != -9001 { args = append(args, opts.command)
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() {