feat(spec): scan shell aliases like .zshrc, .bashrc, ...

This commit is contained in:
verse91
2026-04-11 21:00:31 +07:00
parent 81b80d079c
commit 4c70c24299
+56 -9
View File
@@ -3,6 +3,7 @@ package core
import ( import (
"os" "os"
"path/filepath" "path/filepath"
"regexp"
"strings" "strings"
"sync" "sync"
) )
@@ -43,11 +44,50 @@ type Suggestion struct {
} }
var ( var (
registry = map[string]*Spec{} registry = map[string]*Spec{}
pathCmds = make(map[string]bool) pathCmds = make(map[string]bool)
pathOnce sync.Once shellAliases = make(map[string]string) // alias name -> target command
pathOnce sync.Once
) )
var aliasRegex = regexp.MustCompile(`^alias\s+([a-zA-Z0-9_\-]+)=['"]?([^'"]+)['"]?`)
// scanShellAliases parses shell config files for aliases
func scanShellAliases() {
home, err := os.UserHomeDir()
if err != nil {
return
}
files := []string{".zshrc", ".bashrc", ".bash_profile", ".bash_aliases"}
for _, f := range files {
content, err := os.ReadFile(filepath.Join(home, f))
if err != nil {
continue
}
lines := strings.Split(string(content), "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
matches := aliasRegex.FindStringSubmatch(line)
if len(matches) == 3 {
name := matches[1]
target := matches[2]
fields := strings.Fields(target)
if len(fields) > 0 {
shellAliases[name] = fields[0]
}
}
}
}
}
// scanExternalCommands populates pathCmds and shellAliases
func scanExternalCommands() {
scanPath()
scanShellAliases()
}
// scanPath populates pathCmds with all executable files found in $PATH // scanPath populates pathCmds with all executable files found in $PATH
func scanPath() { func scanPath() {
pathVar := os.Getenv("PATH") pathVar := os.Getenv("PATH")
@@ -89,6 +129,8 @@ func Register(s *Spec) {
// //
// priority: file/dir -> subcommands -> options // priority: file/dir -> subcommands -> options
func Lookup(input string) []Suggestion { func Lookup(input string) []Suggestion {
pathOnce.Do(scanExternalCommands)
tokens := tokenize(input) tokens := tokenize(input)
if len(tokens) == 0 { if len(tokens) == 0 {
return topLevelSuggestions(input) return topLevelSuggestions(input)
@@ -99,8 +141,13 @@ func Lookup(input string) []Suggestion {
return topLevelSuggestions(tokens[0]) return topLevelSuggestions(tokens[0])
} }
root := tokens[0] rootCmdName := tokens[0]
spec, exists := registry[root] // resolve shell alias (e.g. g -> git)
if target, ok := shellAliases[rootCmdName]; ok {
rootCmdName = target
}
spec, exists := registry[rootCmdName]
if !exists { if !exists {
// no spec found for this command, return nothing to avoid clutter // no spec found for this command, return nothing to avoid clutter
return nil return nil
@@ -189,7 +236,7 @@ func Lookup(input string) []Suggestion {
results = append(results, Suggestion{ results = append(results, Suggestion{
Cmd: g.Cmd, Cmd: g.Cmd,
Desc: g.Desc, Desc: g.Desc,
Icon: root, Icon: rootCmdName,
}) })
} }
} }
@@ -201,7 +248,7 @@ func Lookup(input string) []Suggestion {
results = append(results, Suggestion{ results = append(results, Suggestion{
Cmd: prefix + " " + sub.Name, Cmd: prefix + " " + sub.Name,
Desc: sub.Description, Desc: sub.Description,
Icon: root, Icon: rootCmdName,
}) })
} }
} }
@@ -226,7 +273,7 @@ func Lookup(input string) []Suggestion {
results = append(results, Suggestion{ results = append(results, Suggestion{
Cmd: prefix + " " + opt.Name, Cmd: prefix + " " + opt.Name,
Desc: opt.Description, Desc: opt.Description,
Icon: root, Icon: rootCmdName,
}) })
} }
} }
@@ -236,7 +283,7 @@ func Lookup(input string) []Suggestion {
} }
func topLevelSuggestions(query string) []Suggestion { func topLevelSuggestions(query string) []Suggestion {
pathOnce.Do(scanPath) pathOnce.Do(scanExternalCommands)
results := []Suggestion{} results := []Suggestion{}
seen := make(map[string]bool) seen := make(map[string]bool)