From 1a6e79c48919c9260e51802ee8fd302d9bc58d8b Mon Sep 17 00:00:00 2001 From: cpendery Date: Tue, 12 Sep 2023 23:20:32 -0400 Subject: [PATCH] fix: add suggestion icons & refactor bad generic code in suggestions.go Signed-off-by: cpendery --- autocomplete/completion.go | 4 +- autocomplete/generators/templates.go | 3 ++ autocomplete/model/model.go | 40 +++++++++---------- autocomplete/suggestions.go | 58 ++++++++++++---------------- ui/suggestions/suggestions.go | 11 +++--- 5 files changed, 54 insertions(+), 62 deletions(-) diff --git a/autocomplete/completion.go b/autocomplete/completion.go index 0b347ae..979a579 100644 --- a/autocomplete/completion.go +++ b/autocomplete/completion.go @@ -18,6 +18,7 @@ var ( type Suggestion struct { Name string + NamePrefix string Description string } @@ -287,7 +288,8 @@ func LoadSuggestions(cmd string) ([]Suggestion, string, int) { suggestions := []Suggestion{} for _, suggestion := range termSuggestions.Suggestions { - suggestions = append(suggestions, Suggestion{Name: suggestion.Name, Description: suggestion.Description}) + icon := model.TermIcons[suggestion.Type] + suggestions = append(suggestions, Suggestion{Name: suggestion.Name, NamePrefix: icon, Description: suggestion.Description}) } lastSuggestionCmd, lastSuggestion, lastCmdRunes, lastArgDescription = cmd, suggestions, lastRunes, termSuggestions.ArgumentDescription return suggestions, termSuggestions.ArgumentDescription, lastRunes diff --git a/autocomplete/generators/templates.go b/autocomplete/generators/templates.go index f456049..d7d6af2 100644 --- a/autocomplete/generators/templates.go +++ b/autocomplete/generators/templates.go @@ -34,12 +34,15 @@ func walk(includeFiles bool) []model.TermSuggestion { continue } description := file + suggestionType := model.TermSuggestionTypeFile if dirItem.IsDir() { description = directory + suggestionType = model.TermSuggestionTypeFolder } suggestions = append(suggestions, model.TermSuggestion{ Name: dirItem.Name(), Description: description, + Type: suggestionType, }) } return suggestions diff --git a/autocomplete/model/model.go b/autocomplete/model/model.go index f87a109..76bd7dd 100644 --- a/autocomplete/model/model.go +++ b/autocomplete/model/model.go @@ -9,14 +9,6 @@ type Subcommand struct { FilterStrategy FilterStrategy } -func (s Subcommand) GetName() []string { - return s.Name -} - -func (s Subcommand) GetDescription() string { - return s.Description -} - type Option struct { Name []string //single or array string, required Args []Arg //single or array Arg, optional @@ -25,14 +17,6 @@ type Option struct { ExclusiveOn []string } -func (o Option) GetName() []string { - return o.Name -} - -func (o Option) GetDescription() string { - return o.Description -} - type Arg struct { Name string //single, optional Description string //single, optional @@ -58,15 +42,19 @@ type TermSuggestions struct { type TermSuggestion struct { Name string Description string + Type TermSuggestionType } -func (t TermSuggestion) GetName() []string { - return []string{t.Name} -} +type TermSuggestionType string -func (t TermSuggestion) GetDescription() string { - return t.Description -} +const ( + TermSuggestionTypeFolder TermSuggestionType = "folder" + TermSuggestionTypeFile TermSuggestionType = "file" + TermSuggestionTypeArg TermSuggestionType = "arg" + TermSuggestionTypeSubcommand TermSuggestionType = "subcommand" + TermSuggestionTypeOption TermSuggestionType = "option" + TermSuggestionTypeDefault TermSuggestionType = "" +) type ProcessedToken struct { Token string @@ -99,4 +87,12 @@ const ( var ( Templates = []Template{TemplateFilepaths, TemplateFolders, TemplateHistory, TemplateHelp} + TermIcons = map[TermSuggestionType]string{ + TermSuggestionTypeFolder: "📁", + TermSuggestionTypeFile: "📄", + TermSuggestionTypeSubcommand: "📦", + TermSuggestionTypeOption: "⚙️ ", + TermSuggestionTypeArg: "💪", + TermSuggestionTypeDefault: "💪", + } ) diff --git a/autocomplete/suggestions.go b/autocomplete/suggestions.go index 8cc1ddb..92d1000 100644 --- a/autocomplete/suggestions.go +++ b/autocomplete/suggestions.go @@ -10,33 +10,21 @@ import ( "github.com/lithammer/fuzzysearch/fuzzy" ) -type matchable interface { - GetName() []string - GetDescription() string +type match struct { + name string + rank int + item model.TermSuggestion } -func fuzzyMatch[M matchable](input string, targets []M, suggestions *[]model.TermSuggestion) { - type match struct { - name string - rank int - item M - } +func fuzzyMatch(input string, targets []model.TermSuggestion, suggestions *[]model.TermSuggestion) { matchers := []match{} for _, item := range targets { - bestName := "" - bestNameRank := -1 - for _, n := range item.GetName() { - rank := fuzzy.RankMatch(input, n) - if rank > bestNameRank { - bestName = n - bestNameRank = rank - } - } - if bestNameRank != -1 { + rank := fuzzy.RankMatch(input, item.Name) + if rank != -1 { matchers = append(matchers, match{ - name: bestName, + name: item.Name, item: item, - rank: bestNameRank, + rank: rank, }) } } @@ -46,34 +34,33 @@ func fuzzyMatch[M matchable](input string, targets []M, suggestions *[]model.Ter for _, m := range matchers { *suggestions = append(*suggestions, model.TermSuggestion{ Name: m.name, - Description: m.item.GetDescription(), + Description: m.item.Description, + Type: m.item.Type, }) } } func getFuzzyFilteredRecommendations(input string, suggestions *[]model.TermSuggestion) { results := []model.TermSuggestion{} - fuzzyMatch[model.TermSuggestion](input, *suggestions, &results) + fuzzyMatch(input, *suggestions, &results) *suggestions = results } -func prefixMatch[M matchable](input string, subcommands []M, suggestions *[]model.TermSuggestion) { - for _, sub := range subcommands { - for _, n := range sub.GetName() { - if strings.HasPrefix(n, input) { - *suggestions = append(*suggestions, model.TermSuggestion{ - Name: n, - Description: sub.GetDescription(), - }) - break - } +func prefixMatch(input string, targets []model.TermSuggestion, suggestions *[]model.TermSuggestion) { + for _, targ := range targets { + if strings.HasPrefix(targ.Name, input) { + *suggestions = append(*suggestions, model.TermSuggestion{ + Name: targ.Name, + Description: targ.Description, + Type: targ.Type, + }) } } } func getPrefixFilteredRecommendations(input string, suggestions *[]model.TermSuggestion) { results := []model.TermSuggestion{} - prefixMatch[model.TermSuggestion](input, *suggestions, &results) + prefixMatch(input, *suggestions, &results) *suggestions = results } @@ -100,6 +87,7 @@ func getSuggestionDrivenRecommendations(suggestionSet []model.Suggestion, sugges *suggestions = append(*suggestions, model.TermSuggestion{ Name: getLongName(suggestion.Name), Description: suggestion.Description, + Type: model.TermSuggestionTypeDefault, }) } } @@ -109,6 +97,7 @@ func getSubcommandDrivenRecommendations(spec model.Subcommand, suggestions *[]mo *suggestions = append(*suggestions, model.TermSuggestion{ Name: getLongName(sub.Name), Description: sub.Description, + Type: model.TermSuggestionTypeSubcommand, }) } } @@ -118,6 +107,7 @@ func getOptionDrivenRecommendations(options []model.Option, suggestions *[]model *suggestions = append(*suggestions, model.TermSuggestion{ Name: getShortName(op.Name), Description: op.Description, + Type: model.TermSuggestionTypeOption, }) } } diff --git a/ui/suggestions/suggestions.go b/ui/suggestions/suggestions.go index 60983cf..f6b9c34 100644 --- a/ui/suggestions/suggestions.go +++ b/ui/suggestions/suggestions.go @@ -106,12 +106,13 @@ func (m Model) Update(msg tea.Msg, command string, userInputCursorLocation int) return m } -func (m Model) renderSuggestion(suggestion string, position, cursor, width int) string { - content := wordTrunc(suggestion, width) +func (m Model) renderSuggestion(suggestion autocomplete.Suggestion, position, cursor, width int) string { + content := suggestion.NamePrefix + " " + suggestion.Name + truncatedContent := wordTrunc(content, width) if position == m.cursor%MaxSuggestions { - return lipgloss.NewStyle().Background(lipgloss.Color("#7D56F4")).Width(width).Render(content) + return lipgloss.NewStyle().Background(lipgloss.Color("#7D56F4")).Width(width).Render(truncatedContent) } - return lipgloss.NewStyle().Render(content) + return lipgloss.NewStyle().Render(truncatedContent) } func wordWrap(content string, width int) string { @@ -147,7 +148,7 @@ func (m Model) renderSuggestions(width int) string { r := make([]string, len(m.suggestions)) for idx, suggestion := range m.suggestions { - r[idx] = m.renderSuggestion(suggestion.Name, idx, m.cursor, width) + r[idx] = m.renderSuggestion(suggestion, idx, m.cursor, width) } if m.argDescription != "" {