refactor: suggestion response & add argument description rendering

Signed-off-by: cpendery <cpendery@vt.edu>
This commit is contained in:
cpendery
2023-09-12 18:48:04 -04:00
parent c8faaba2c0
commit 269b95eab3
3 changed files with 54 additions and 19 deletions
+29 -17
View File
@@ -9,10 +9,11 @@ import (
)
var (
cmdDelimiter = regexp.MustCompile(`(\|\|)|(&&)|(;)`)
lastSuggestionCmd = ""
lastSuggestion = []Suggestion{}
lastCmdRunes = 0
cmdDelimiter = regexp.MustCompile(`(\|\|)|(&&)|(;)`)
lastSuggestionCmd = ""
lastSuggestion = []Suggestion{}
lastArgDescription = ""
lastCmdRunes = 0
)
type Suggestion struct {
@@ -83,7 +84,7 @@ func getPersistentTokens(tokens []model.ProcessedToken) []model.ProcessedToken {
return persistentTokens
}
func getSubcommandDrivenRecommendation(spec model.Subcommand, persistentOptions []model.Option, partialCmd *commandToken, onlyRecommendSubcommands bool, acceptedTokens []model.ProcessedToken) []model.TermSuggestion {
func getSubcommandDrivenRecommendation(spec model.Subcommand, persistentOptions []model.Option, partialCmd *commandToken, onlyRecommendSubcommands bool, acceptedTokens []model.ProcessedToken) model.TermSuggestions {
suggestions := []model.TermSuggestion{}
allOptions := append(spec.Options, persistentOptions...)
@@ -109,10 +110,12 @@ func getSubcommandDrivenRecommendation(spec model.Subcommand, persistentOptions
}
}
return suggestions
return model.TermSuggestions{
Suggestions: suggestions,
}
}
func getArgDrivenRecommendation(args []model.Arg, spec model.Subcommand, persistentOptions []model.Option, partialCmd *commandToken, acceptedTokens []model.ProcessedToken) []model.TermSuggestion {
func getArgDrivenRecommendation(args []model.Arg, spec model.Subcommand, persistentOptions []model.Option, partialCmd *commandToken, acceptedTokens []model.ProcessedToken) model.TermSuggestions {
suggestions := []model.TermSuggestion{}
activeArg := args[0]
allOptions := append(spec.Options, persistentOptions...)
@@ -135,10 +138,18 @@ func getArgDrivenRecommendation(args []model.Arg, spec model.Subcommand, persist
}
}
return suggestions
argDescriptionSuggestion := ""
if len(suggestions) == 0 {
argDescriptionSuggestion = activeArg.Name
}
return model.TermSuggestions{
ArgumentDescription: argDescriptionSuggestion,
Suggestions: suggestions,
}
}
func handleSubcommand(tokens []commandToken, spec model.Subcommand, persistentOptions []model.Option, argsDepleted bool, acceptedTokens []model.ProcessedToken) (suggestions []model.TermSuggestion) {
func handleSubcommand(tokens []commandToken, spec model.Subcommand, persistentOptions []model.Option, argsDepleted bool, acceptedTokens []model.ProcessedToken) (suggestions model.TermSuggestions) {
if len(tokens) == 0 {
return getSubcommandDrivenRecommendation(spec, persistentOptions, nil, argsDepleted, acceptedTokens)
} else if !tokens[0].complete {
@@ -163,7 +174,7 @@ func handleSubcommand(tokens []commandToken, spec model.Subcommand, persistentOp
return handleArg(tokens, spec.Args, spec, persistentOptions, acceptedTokens)
}
func handleOption(tokens []commandToken, option model.Option, spec model.Subcommand, persistentOptions []model.Option, acceptedTokens []model.ProcessedToken) (suggestions []model.TermSuggestion) {
func handleOption(tokens []commandToken, option model.Option, spec model.Subcommand, persistentOptions []model.Option, acceptedTokens []model.ProcessedToken) (suggestions model.TermSuggestions) {
if len(tokens) == 0 {
slog.Error("invalid state reached, option with no tokens")
return
@@ -186,7 +197,7 @@ persistenceDetermined:
return handleArg(tokens[1:], option.Args, spec, persistentOptions, acceptedTokens)
}
func handleArg(tokens []commandToken, args []model.Arg, spec model.Subcommand, persistentOptions []model.Option, acceptedTokens []model.ProcessedToken) (suggestions []model.TermSuggestion) {
func handleArg(tokens []commandToken, args []model.Arg, spec model.Subcommand, persistentOptions []model.Option, acceptedTokens []model.ProcessedToken) (suggestions model.TermSuggestions) {
if len(args) == 0 {
return handleSubcommand(tokens, spec, persistentOptions, true, acceptedTokens)
} else if len(tokens) == 0 {
@@ -226,7 +237,7 @@ func handleArg(tokens []commandToken, args []model.Arg, spec model.Subcommand, p
return handleArg(tokens[1:], args[1:], spec, persistentOptions, getPersistentTokens(acceptedTokens))
}
func loadSuggestions(cmd string) (suggestions []model.TermSuggestion, charsInLastCmd int) {
func loadSuggestions(cmd string) (suggestions model.TermSuggestions, charsInLastCmd int) {
activeCmd := ParseCommand(cmd)
if len(activeCmd) <= 0 {
return
@@ -246,15 +257,16 @@ func loadSuggestions(cmd string) (suggestions []model.TermSuggestion, charsInLas
return
}
func LoadSuggestions(cmd string) ([]Suggestion, int) {
func LoadSuggestions(cmd string) ([]Suggestion, string, int) {
if cmd == lastSuggestionCmd {
return lastSuggestion, lastCmdRunes
return lastSuggestion, lastArgDescription, lastCmdRunes
}
termSuggestions, lastRunes := loadSuggestions(cmd)
suggestions := []Suggestion{}
for _, suggestion := range termSuggestions {
for _, suggestion := range termSuggestions.Suggestions {
suggestions = append(suggestions, Suggestion{Name: suggestion.Name, Description: suggestion.Description})
}
lastSuggestionCmd, lastSuggestion, lastCmdRunes = cmd, suggestions, lastRunes
return suggestions, lastRunes
lastSuggestionCmd, lastSuggestion, lastCmdRunes, lastArgDescription = cmd, suggestions, lastRunes, termSuggestions.ArgumentDescription
return suggestions, termSuggestions.ArgumentDescription, lastRunes
}
+5
View File
@@ -50,6 +50,11 @@ type Suggestion struct {
Description string
}
type TermSuggestions struct {
ArgumentDescription string
Suggestions []TermSuggestion
}
type TermSuggestion struct {
Name string
Description string
+20 -2
View File
@@ -19,6 +19,7 @@ type Model struct {
cursor int
userInputCursorLocation int
suggestions []autocomplete.Suggestion
argDescription string
keyMap KeyMap
windowWidth int
windowHeight int
@@ -98,7 +99,7 @@ func (m Model) Update(msg tea.Msg, command string, userInputCursorLocation int)
m.windowWidth = msg.Width
}
m.userInputCursorLocation = userInputCursorLocation
m.suggestions, m.runesToRemove = autocomplete.LoadSuggestions(command)
m.suggestions, m.argDescription, m.runesToRemove = autocomplete.LoadSuggestions(command)
if len(m.suggestions) == 0 {
m.cursor = 0
}
@@ -157,14 +158,31 @@ func (m Model) renderDescription(width int) string {
return style.Render(wordWrap(m.suggestions[m.cursor].Description, width))
}
func (m Model) renderArgumentDescription(width int) string {
argDescriptionWidth := utils.Clamp(len(m.argDescription), 0, width)
maxLeftPaddingDescription := m.windowWidth - argDescriptionWidth - BorderOffset
var style = lipgloss.
NewStyle().
MarginLeft(utils.Clamp(m.userInputCursorLocation, 0, maxLeftPaddingDescription)).
Width(argDescriptionWidth).
BorderStyle(lipgloss.NormalBorder()).
BorderForeground(lipgloss.Color("63"))
return style.Render(wordWrap(m.argDescription, argDescriptionWidth))
}
func (m Model) View() string {
if len(m.suggestions) == 0 {
if len(m.suggestions) == 0 && m.argDescription == "" {
return ""
}
suggestionWidth := min(m.windowWidth-BorderOffset, SuggestionWidth)
descriptionWidth := min(m.windowWidth-BorderOffset, DescriptionWidth)
if len(m.suggestions) == 0 && m.argDescription != "" {
return m.renderArgumentDescription(descriptionWidth)
}
suggestionsView := m.renderSuggestions(suggestionWidth)
descriptionView := m.renderDescription(descriptionWidth)