feat(spec): support tool aliases (#107)
closes #57 IRIS now automatically read and suggest internal configuration aliases for Git (`.gitconfig`, `.git/config`) and Cargo (`.cargo/config.toml`) - Added the `Provider` interface and extended registry for CLI tools that define aliases - Git: parse aliases via `git config --show-scope`, supporting raw tab/space separation and scope differentiation - Cargo: traverse the directory tree upwards to root to read the `.cargo/config.toml` configuration - 0ms hot-path caching: key caching is calculated entirely via `os.Stat` mtime (no subprocess spawn) combined with a 2-second TTL window to ensure 0ms latency when typing - Lookup integration: display alias suggestions at the subcommand level and automatically expand aliases as the user enters further arguments (ignore shell pipeline commands starting with `!`)
This commit is contained in:
+75
-1
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/versenilvis/iris/integration/shell"
|
||||
"github.com/versenilvis/iris/internal/logger"
|
||||
"github.com/versenilvis/iris/spec/alias"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -51,6 +52,9 @@ func Lookup(input string) []Suggestion {
|
||||
}
|
||||
|
||||
tokens := Tokenize(input)
|
||||
originalTokens := append([]string(nil), tokens...)
|
||||
originalPrefix := ""
|
||||
expandedPrefix := ""
|
||||
|
||||
if len(tokens) == 1 && tokens[0] == "" {
|
||||
return topLevelSuggestions("", aliases)
|
||||
@@ -77,6 +81,44 @@ func Lookup(input string) []Suggestion {
|
||||
}
|
||||
}
|
||||
|
||||
// Expand tool aliases
|
||||
isAliasExpanded := false
|
||||
aliasExpansionEnd := 0
|
||||
if len(tokens) > 2 {
|
||||
rootCmdName := tokens[0]
|
||||
if provider := alias.GetProvider(rootCmdName); provider != nil {
|
||||
cwd := GetCWD()
|
||||
toolAliases := provider.GetAliases(cwd)
|
||||
subCmd := tokens[1]
|
||||
for _, a := range toolAliases {
|
||||
if a.Name == subCmd {
|
||||
if strings.HasPrefix(a.Expansion, "!") {
|
||||
return nil
|
||||
}
|
||||
aliasTokens := Tokenize(a.Expansion)
|
||||
if len(aliasTokens) > 0 && aliasTokens[len(aliasTokens)-1] == "" {
|
||||
aliasTokens = aliasTokens[:len(aliasTokens)-1]
|
||||
}
|
||||
if len(aliasTokens) > 0 && aliasTokens[0] == rootCmdName {
|
||||
aliasTokens = aliasTokens[1:]
|
||||
}
|
||||
newTokens := make([]string, 0, len(tokens)-1+len(aliasTokens))
|
||||
newTokens = append(newTokens, tokens[0])
|
||||
newTokens = append(newTokens, aliasTokens...)
|
||||
newTokens = append(newTokens, tokens[2:]...)
|
||||
tokens = newTokens
|
||||
isAliasExpanded = true
|
||||
aliasExpansionEnd = len(aliasTokens)
|
||||
expandedPrefix = strings.Join(tokens[:1+aliasExpansionEnd], " ")
|
||||
if len(originalTokens) >= 2 {
|
||||
originalPrefix = strings.Join(originalTokens[:2], " ")
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(tokens) == 1 {
|
||||
query := tokens[0]
|
||||
results := topLevelSuggestions(query, aliases)
|
||||
@@ -152,7 +194,7 @@ func Lookup(input string) []Suggestion {
|
||||
continue
|
||||
}
|
||||
// invalid subcommand word typed
|
||||
if len(currentSubs) > 0 {
|
||||
if len(currentSubs) > 0 && (!isAliasExpanded || depth > aliasExpansionEnd) {
|
||||
return nil
|
||||
}
|
||||
break
|
||||
@@ -280,6 +322,30 @@ func Lookup(input string) []Suggestion {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if depth == 1 {
|
||||
if provider := alias.GetProvider(rootCmdName); provider != nil {
|
||||
cwd := GetCWD()
|
||||
for _, a := range provider.GetAliases(cwd) {
|
||||
if partial == "" || HasPrefix(a.Name, partial) {
|
||||
priority := 70
|
||||
switch a.Scope {
|
||||
case "local", "worktree", "command":
|
||||
priority = 85
|
||||
case "system":
|
||||
priority = 65
|
||||
}
|
||||
results = append(results, Suggestion{
|
||||
Cmd: prefix + " " + a.Name,
|
||||
Desc: "Alias for: " + a.Expansion,
|
||||
Icon: rootCmdName,
|
||||
Priority: priority,
|
||||
Source: "alias",
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
usedOpts := make(map[string]bool)
|
||||
@@ -305,6 +371,14 @@ func Lookup(input string) []Suggestion {
|
||||
}
|
||||
}
|
||||
|
||||
if isAliasExpanded && expandedPrefix != "" && originalPrefix != "" {
|
||||
for i := range results {
|
||||
if strings.HasPrefix(results[i].Cmd, expandedPrefix) {
|
||||
results[i].Cmd = originalPrefix + strings.TrimPrefix(results[i].Cmd, expandedPrefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user