Conversation
* Show command mode suggestions and alias resolution - Display completion suggestions in command mode (fixes #72) - Show alias resolution (e.g., :sg → ec2/security-groups) (fixes #73) - Add Ctrl+C to exit command mode - Remove textInput width constraint to allow suggestions display - Update suggestions on activation * Remove command input debug leftover and SetWidth dead code * Replace magic number with commandInputWidth constant * Use ui.NoStyle() instead of inline lipgloss.NewStyle() * Fix diff command: use ID instead of Name for completion - DiffCompletionProvider: GetResourceNames→GetResourceIDs (avoid space issues) - CharLimit: 50→150 (support :diff id1 id2 with long IDs) - Tab completion: Reset() before SetValue (fix display offset bug) - handleDiffMsg: match by GetID instead of GetName * Rename DiffMsg fields: LeftName/RightName → LeftID/RightID * Improve command mode: show Enter destination, add tests - Highlight where Enter will navigate (alias resolution or prefix match) - Other suggestions shown in white (not highlighted) - Dynamic width: expand to 50 when input > 30 chars - Exclude exact match from suggestions (e.g., "sq" not shown when typing "sq") - Add Reset() comment explaining cursor offset fix - Add tests: Ctrl+C exit, alias resolution, dynamic width * Improve command mode: bash-style tab, alias prefix match, error display - Tab completion: expand to common prefix first, then cycle - Prefix match now includes aliases (cd→cdn→cloudfront) - Show error for unknown commands (3s auto-clear) - Extract resolvePrefixMatch helper for consistency
PR Review: Command mode suggestions and alias resolutionSummaryThis PR significantly improves the command mode UX by adding bash-style tab completion, alias resolution preview, error messaging, and dynamic input width. The changes are well-implemented with comprehensive test coverage. ✅ StrengthsCode Quality
UX Improvements
Architecture
🔍 Code Quality & Best Practicescommand_input.go:130-174 (Tab/Shift+Tab handlers)The bash-style completion logic is well-implemented, but has code duplication: Observation: Lines 130-151 (tab) and 153-174 (shift+tab) have nearly identical logic except for the cycling direction. Suggestion: Extract common logic to reduce duplication: func (c *CommandInput) handleTabCompletion(reverse bool) {
if len(c.suggestions) == 0 {
c.updateSuggestions()
}
if len(c.suggestions) > 0 {
current := c.textInput.Value()
prefix := commonPrefix(c.suggestions)
if len(prefix) > len(current) {
// Expand to common prefix
c.textInput.Reset()
c.textInput.SetValue(prefix)
c.suggIdx = 0
} else {
// Cycle through suggestions
if reverse {
c.suggIdx = (c.suggIdx - 1 + len(c.suggestions)) % len(c.suggestions)
} else {
// Current index is already correct for forward cycling
}
c.textInput.Reset()
c.textInput.SetValue(c.suggestions[c.suggIdx])
if !reverse {
c.suggIdx = (c.suggIdx + 1) % len(c.suggestions)
}
}
}
}
// Then in Update():
case "tab":
c.handleTabCompletion(false)
return nil, nil
case "shift+tab":
c.handleTabCompletion(true)
return nil, nil🐛 Potential Bugscommand_input.go:620-631 (Exact match exclusion)for _, svc := range c.registry.ListServices() {
// Skip if input exactly matches service (already fully typed)
if svc != input && strings.HasPrefix(svc, input) {
suggestions = append(suggestions, svc)
}
}Issue: When user types "ec2" (exact match), suggestions exclude "ec2" but might still suggest "ec2/instances", "ec2/volumes" in the resource section. This creates inconsistency - the service disappears from suggestions but resources still show. Impact: Minor UX inconsistency. Not a critical bug, but could confuse users. Suggestion: Consider whether this exclusion is necessary. Traditional bash completion still shows exact matches. If you keep it, ensure consistency across all suggestion types. command_input.go:310-315 (First match behavior)for _, svc := range c.registry.ListServices() {
if strings.HasPrefix(svc, servicePart) {
matched = svc
break // Takes first match
}
}Issue: Takes the first prefix match from an unordered list. If multiple services match the prefix (e.g., "cloud" → "cloudformation", "cloudfront", "cloudwatch"), the result is non-deterministic and depends on iteration order. Impact: Low - services are likely from a map which has undefined order in Go. Users typing "cloud" might get different results. Suggestion: Either:
// Option 1: Sort first
services := c.registry.ListServices()
slices.Sort(services)
for _, svc := range services {
if strings.HasPrefix(svc, servicePart) {
matched = svc
break
}
}⚡ Performance Considerationscommand_input.go:184-190 (Dynamic width on every input change)// Update suggestions on input change
c.updateSuggestions()
// Dynamic width: expand when input exceeds default width
inputLen := len(c.textInput.Value())
if inputLen > commandInputWidth {
c.textInput.SetWidth(commandInputWidthMax)
} else {
c.textInput.SetWidth(commandInputWidth)
}Observation: Impact: Minimal - this is a TUI with low event frequency, not a performance bottleneck. Optimization (optional): inputLen := len(c.textInput.Value())
targetWidth := commandInputWidth
if inputLen > commandInputWidth {
targetWidth = commandInputWidthMax
}
// Only update if changed
if c.textInput.Width != targetWidth {
c.textInput.SetWidth(targetWidth)
}command_input.go:746-764 (commonPrefix algorithm)The algorithm is O(n*m) where n=number of suggestions, m=length of common prefix. This is fine for small suggestion lists (typically <50 items), but could be optimized. Current implementation: Correct and readable. No action needed unless profiling shows issues. 🔒 Security ConsiderationsNo security issues identified. The code:
📝 Test CoverageExcellent test coverage with 264 added lines: Well-tested scenarios:
Potential test gaps:
Suggestion: Add test case: func TestCommandInput_PrefixMatchMultipleServices(t *testing.T) {
// Register services with common prefix: cloud*
// Verify consistent behavior across multiple runs
}📊 Changeset AnalysisFiles changed: 11 files
Code metrics:
🎯 RecommendationsPriority: High
Priority: Medium
Priority: Low
✨ Overall AssessmentRating: ⭐⭐⭐⭐½ (4.5/5) This is a high-quality PR that significantly improves UX with minimal risk:
The issues identified are minor and mostly architectural improvements rather than bugs. The prefix match non-determinism should be addressed, but overall this is ready to merge with minor fixes. Recommendation: ✅ Approve with minor revisions (fix prefix match sorting) 📚 Additional NotesVHS tapes: Great addition for visual documentation! The test-diff.tape clearly demonstrates the feature in action. API consistency: The rename from Follow-up opportunities:
Great work on this feature! 🚀 |
Summary
Test plan