feat(history): add bash and fish
This commit is contained in:
+53
-5
@@ -8,6 +8,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/versenilvis/fuzzyvn"
|
||||
"github.com/versenilvis/iris/integration/shell"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -15,6 +16,7 @@ var (
|
||||
idMapCache map[string]int
|
||||
searcherCache *fuzzyvn.Searcher
|
||||
mu sync.Mutex
|
||||
lastModTime int64
|
||||
)
|
||||
|
||||
type HistResult struct {
|
||||
@@ -26,19 +28,40 @@ func init() {
|
||||
idMapCache = make(map[string]int)
|
||||
}
|
||||
|
||||
// SearchHistory reads the zsh history and searches using fuzzyvn (my own pkg)
|
||||
func SearchHistory(query string) ([]HistResult, error) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
// lazy load history if cache is empty
|
||||
if len(historyCache) == 0 {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
histFile := filepath.Join(home, ".zsh_history")
|
||||
shellName := "bash"
|
||||
if shell.Current != nil {
|
||||
shellName = shell.Current.GetName()
|
||||
}
|
||||
|
||||
var histFile string
|
||||
switch shellName {
|
||||
case "zsh":
|
||||
histFile = filepath.Join(home, ".zsh_history")
|
||||
case "fish":
|
||||
histFile = filepath.Join(home, ".local", "share", "fish", "fish_history")
|
||||
default:
|
||||
histFile = filepath.Join(home, ".bash_history")
|
||||
}
|
||||
|
||||
if info, err := os.Stat(histFile); err == nil {
|
||||
if info.ModTime().UnixNano() > lastModTime {
|
||||
historyCache = nil // force reload
|
||||
idMapCache = make(map[string]int)
|
||||
lastModTime = info.ModTime().UnixNano()
|
||||
}
|
||||
}
|
||||
|
||||
// lazy load history if cache is empty
|
||||
if len(historyCache) == 0 {
|
||||
file, err := os.Open(histFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -50,12 +73,37 @@ func SearchHistory(query string) ([]HistResult, error) {
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
cmd := line
|
||||
|
||||
if shellName == "zsh" {
|
||||
// zsh history format: : <timestamp>;<command>
|
||||
parts := strings.SplitN(line, ";", 2)
|
||||
cmd := line
|
||||
if len(parts) == 2 {
|
||||
cmd = parts[1]
|
||||
}
|
||||
} else if shellName == "bash" {
|
||||
// bash history format can include timestamps starting with #
|
||||
if strings.HasPrefix(line, "#") && len(line) > 1 {
|
||||
|
||||
isTimestamp := true
|
||||
for _, c := range line[1:] {
|
||||
if c < '0' || c > '9' {
|
||||
isTimestamp = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if isTimestamp {
|
||||
continue
|
||||
}
|
||||
}
|
||||
} else if shellName == "fish" {
|
||||
// simple parse for fish history (YAML-like)
|
||||
if strings.HasPrefix(line, "- cmd: ") {
|
||||
cmd = strings.TrimPrefix(line, "- cmd: ")
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
cmd = strings.TrimSpace(cmd)
|
||||
if cmd != "" {
|
||||
|
||||
Reference in New Issue
Block a user