99 lines
2.2 KiB
Go
99 lines
2.2 KiB
Go
package search
|
|
|
|
import (
|
|
"database/sql"
|
|
"flag"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
dim = "\033[2m"
|
|
reset = "\033[0m"
|
|
)
|
|
|
|
func Run(d *sql.DB, args []string) error {
|
|
fs := flag.NewFlagSet("search", flag.ExitOnError)
|
|
host := fs.String("host", "", "filter by hostname")
|
|
dir := fs.String("dir", "", "filter by working directory")
|
|
after := fs.String("after", "", "filter entries after timestamp")
|
|
before := fs.String("before", "", "filter entries before timestamp")
|
|
limit := fs.Int("limit", 0, "max results (0 = unlimited)")
|
|
reverse := fs.Bool("reverse", false, "newest first")
|
|
compact := fs.Bool("compact", false, "compact output with color")
|
|
fs.Parse(args)
|
|
|
|
query := strings.Join(fs.Args(), " ")
|
|
|
|
var where []string
|
|
var params []any
|
|
|
|
if query != "" {
|
|
where = append(where, "command LIKE ?")
|
|
params = append(params, "%"+query+"%")
|
|
}
|
|
if *host != "" {
|
|
where = append(where, "hostname = ?")
|
|
params = append(params, *host)
|
|
}
|
|
if *dir != "" {
|
|
where = append(where, "working_dir = ?")
|
|
params = append(params, *dir)
|
|
}
|
|
if *after != "" {
|
|
where = append(where, "timestamp > ?")
|
|
params = append(params, *after)
|
|
}
|
|
if *before != "" {
|
|
where = append(where, "timestamp < ?")
|
|
params = append(params, *before)
|
|
}
|
|
|
|
inner := "SELECT timestamp, hostname, working_dir, command FROM history"
|
|
if len(where) > 0 {
|
|
inner += " WHERE " + strings.Join(where, " AND ")
|
|
}
|
|
inner += " ORDER BY timestamp DESC"
|
|
if *limit > 0 {
|
|
inner += " LIMIT ?"
|
|
params = append(params, *limit)
|
|
}
|
|
|
|
outerOrder := "ASC"
|
|
if *reverse {
|
|
outerOrder = "DESC"
|
|
}
|
|
q := "SELECT * FROM (" + inner + ") ORDER BY timestamp " + outerOrder
|
|
|
|
rows, err := d.Query(q, params...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer rows.Close()
|
|
|
|
for rows.Next() {
|
|
var ts, h, wd, cmd string
|
|
if err := rows.Scan(&ts, &h, &wd, &cmd); err != nil {
|
|
return err
|
|
}
|
|
if t, err := time.Parse(time.RFC3339, ts); err == nil {
|
|
ts = t.Format("2006-01-02 15:04")
|
|
}
|
|
if *compact {
|
|
fmt.Printf("%s%s %s %s%s %s\n", dim, ts, h, shortenDir(wd), reset, cmd)
|
|
} else {
|
|
fmt.Printf("%s %s %s %s\n", ts, h, wd, cmd)
|
|
}
|
|
}
|
|
return rows.Err()
|
|
}
|
|
|
|
func shortenDir(dir string) string {
|
|
parts := strings.Split(dir, "/")
|
|
if len(parts) <= 3 {
|
|
return dir
|
|
}
|
|
return "../" + parts[len(parts)-2] + "/" + parts[len(parts)-1]
|
|
}
|