Skip to content

Commit d79b48b

Browse files
lucaspimentelclaude
andcommitted
feat: add dynamic git alias and command completion support
Add support for dynamically loading git aliases, main commands, and extensions using git's --list-cmds feature. This provides comprehensive git completion including user-defined aliases without requiring manual configuration. Changes: - Add GetAllGitCommands() to query git for aliases, main commands, and extensions - Categorize commands with appropriate tooltips (Git alias, Git command, Git extension) - Deduplicate dynamic arguments against hardcoded SubCommands/Parameters - Update documentation to highlight dynamic git alias support Hardcoded subcommands with detailed tooltips take precedence over dynamic entries to ensure the best user experience for common commands. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent efe495a commit d79b48b

File tree

4 files changed

+61
-3
lines changed

4 files changed

+61
-3
lines changed

CLAUDE.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,12 @@ Get-PSCueModuleInfo [-AsJson] # Module diagnostics
212212
## Supported Commands
213213
git, gh, gt, az, azd, func, code, scoop, winget, wt, chezmoi, tre, lsd, dust, cd (Set-Location/sl/chdir)
214214

215+
**Git Completion Features**:
216+
- Hardcoded subcommands with detailed tooltips (add, commit, branch, etc.)
217+
- Dynamic git aliases loaded via `git --list-cmds=alias` (tooltips show "Git alias")
218+
- All git main commands via `git --list-cmds=main,nohelpers` (tooltips show "Git command")
219+
- Git extensions from PATH via `git --list-cmds=others` (tooltips show "Git extension")
220+
215221
**Plus**: Generic learning works for ANY command (kubectl, docker, cargo, npm, etc.)
216222

217223
## When Adding Features

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ This architecture enables:
4646

4747
PSCue provides detailed completions for these commands:
4848

49-
- **Git**: `git` - branches, tags, remotes, files, subcommands
49+
- **Git**: `git` - branches, tags, remotes, files, subcommands, aliases (dynamically loaded from git config)
5050
- **GitHub CLI**: `gh` - repos, PRs, issues, workflows
5151
- **Graphite CLI**: `gt` - stacked PRs, branch navigation, workflows
5252
- **Azure CLI**: `az` - resource groups, subscriptions, commands

src/PSCue.Shared/Completions/Command.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,26 @@ public List<ICompletion> GetCompletions(ReadOnlySpan<char> wordToComplete, bool
7777
}
7878

7979
// Only include dynamic arguments (git branches, scoop packages, etc.) if requested
80+
// Exclude dynamic arguments that match existing SubCommands or Parameters to avoid duplicates
81+
// (SubCommands/Parameters have better tooltips, so they should take precedence)
8082
if (includeDynamicArguments && DynamicArguments?.Invoke() is { } arguments)
8183
{
82-
Helpers.AddWhereStartsWith(arguments, results, wordToComplete);
84+
// Create a HashSet of existing completion texts for fast lookup
85+
var existingCompletions = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
86+
foreach (var item in results)
87+
{
88+
existingCompletions.Add(item.CompletionText);
89+
}
90+
91+
// Add dynamic arguments that don't duplicate existing completions
92+
foreach (var arg in arguments)
93+
{
94+
if (Helpers.StartsWith(arg.CompletionText, wordToComplete) &&
95+
!existingCompletions.Contains(arg.CompletionText))
96+
{
97+
results.Add(arg);
98+
}
99+
}
83100
}
84101

85102
return results;

src/PSCue.Shared/KnownCompletions/GitCommand.cs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,10 +344,45 @@ public static Command Create()
344344
new("--help", "Show help"),
345345
new("-C", "Run as if git was started in path"),
346346
new("-c", "Set config variable"),
347-
]
347+
],
348+
DynamicArguments = GetAllGitCommands
348349
};
349350
}
350351

352+
private static IEnumerable<DynamicArgument> GetAllGitCommands()
353+
{
354+
// Get main git commands (excluding helper commands)
355+
// These already have hardcoded entries with detailed tooltips, but this catches any new ones
356+
foreach (var line in Helpers.ExecuteCommand("git", "--list-cmds=main,nohelpers"))
357+
{
358+
var command = line.Trim();
359+
if (!string.IsNullOrWhiteSpace(command))
360+
{
361+
yield return new DynamicArgument(command, "Git command");
362+
}
363+
}
364+
365+
// Get user-defined aliases from git config
366+
foreach (var line in Helpers.ExecuteCommand("git", "--list-cmds=alias"))
367+
{
368+
var alias = line.Trim();
369+
if (!string.IsNullOrWhiteSpace(alias))
370+
{
371+
yield return new DynamicArgument(alias, "Git alias");
372+
}
373+
}
374+
375+
// Get other git commands (git-* executables in PATH)
376+
foreach (var line in Helpers.ExecuteCommand("git", "--list-cmds=others"))
377+
{
378+
var command = line.Trim();
379+
if (!string.IsNullOrWhiteSpace(command))
380+
{
381+
yield return new DynamicArgument(command, "Git extension");
382+
}
383+
}
384+
}
385+
351386
private static IEnumerable<DynamicArgument> GetBranches()
352387
{
353388
foreach (var line in Helpers.ExecuteCommand("git", "branch --format='%(refname:short)'"))

0 commit comments

Comments
 (0)