summaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorElwardi <elwardifadeli@gmail.com>2021-07-20 20:59:03 +0100
committerElwardi <elwardifadeli@gmail.com>2021-07-20 20:59:03 +0100
commitedfb0a26b2bebb67520061df843aa95f78a981c0 (patch)
tree6e9bb9ddb21c01a04cd7be481988652c73c18202 /pkg
parentf70435a20fb9641513aff9c94ea368973c39d252 (diff)
Refactor code around handleCustomCommandKeybinding
Diffstat (limited to 'pkg')
-rw-r--r--pkg/gui/custom_commands.go278
1 files changed, 146 insertions, 132 deletions
diff --git a/pkg/gui/custom_commands.go b/pkg/gui/custom_commands.go
index c258b600f..e9aeedb4f 100644
--- a/pkg/gui/custom_commands.go
+++ b/pkg/gui/custom_commands.go
@@ -54,6 +54,149 @@ func (gui *Gui) resolveTemplate(templateStr string, promptResponses []string) (s
return utils.ResolveTemplate(templateStr, objects)
}
+func (gui *Gui) inputPrompt(prompt config.CustomCommandPrompt, promptResponses []string, responseIdx int, wrappedF func() error) error {
+ title, err := gui.resolveTemplate(prompt.Title, promptResponses)
+ if err != nil {
+ return gui.surfaceError(err)
+ }
+
+ initialValue, err := gui.resolveTemplate(prompt.InitialValue, promptResponses)
+ if err != nil {
+ return gui.surfaceError(err)
+ }
+
+ return gui.prompt(promptOpts{
+ title: title,
+ initialContent: initialValue,
+ handleConfirm: func(str string) error {
+ promptResponses[responseIdx] = str
+ return wrappedF()
+ },
+ })
+}
+
+func (gui *Gui) menuPrompt(prompt config.CustomCommandPrompt, promptResponses []string, responseIdx int, wrappedF func() error) error {
+ // need to make a menu here some how
+ menuItems := make([]*menuItem, len(prompt.Options))
+ for i, option := range prompt.Options {
+ option := option
+
+ nameTemplate := option.Name
+ if nameTemplate == "" {
+ // this allows you to only pass values rather than bother with names/descriptions
+ nameTemplate = option.Value
+ }
+ name, err := gui.resolveTemplate(nameTemplate, promptResponses)
+ if err != nil {
+ return gui.surfaceError(err)
+ }
+
+ description, err := gui.resolveTemplate(option.Description, promptResponses)
+ if err != nil {
+ return gui.surfaceError(err)
+ }
+
+ value, err := gui.resolveTemplate(option.Value, promptResponses)
+ if err != nil {
+ return gui.surfaceError(err)
+ }
+
+ menuItems[i] = &menuItem{
+ displayStrings: []string{name, utils.ColoredString(description, color.FgYellow)},
+ onPress: func() error {
+ promptResponses[responseIdx] = value
+ return wrappedF()
+ },
+ }
+ }
+
+ title, err := gui.resolveTemplate(prompt.Title, promptResponses)
+ if err != nil {
+ return gui.surfaceError(err)
+ }
+
+ return gui.createMenu(title, menuItems, createMenuOptions{showCancel: true})
+}
+func (gui *Gui) generateMenuCandidates(commandOutput string, filter string, format string) ([]string, error) {
+ candidates := []string{}
+ reg, err := regexp.Compile(filter)
+ if err != nil {
+ return candidates, gui.surfaceError(errors.New("unable to parse filter regex, error: " + err.Error()))
+ }
+ buff := bytes.NewBuffer(nil)
+ temp, err := template.New("format").Parse(format)
+ if err != nil {
+ return candidates, gui.surfaceError(errors.New("unable to parse format, error: " + err.Error()))
+ }
+ for _, str := range strings.Split(string(commandOutput), "\n") {
+ if str == "" {
+ continue
+ }
+ tmplData := map[string]string{}
+ out := reg.FindAllStringSubmatch(str, -1)
+ if len(out) > 0 {
+ for groupIdx, group := range reg.SubexpNames() {
+ // Record matched group with group ids
+ matchName := "group_" + strconv.Itoa(groupIdx)
+ tmplData[matchName] = group
+ // Record last named group non-empty matches as group matches
+ if group != "" {
+ tmplData[group] = out[0][groupIdx]
+ }
+ }
+ }
+ err = temp.Execute(buff, tmplData)
+ if err != nil {
+ return candidates, gui.surfaceError(err)
+ }
+
+ candidates = append(candidates, strings.TrimSpace(buff.String()))
+ buff.Reset()
+ }
+ return candidates, err
+}
+
+func (gui *Gui) menuPromptFromCommand(prompt config.CustomCommandPrompt, promptResponses []string, responseIdx int, wrappedF func() error) error {
+ // Collect cmd to run from config
+ cmdStr, err := gui.resolveTemplate(prompt.Command, promptResponses)
+ if err != nil {
+ return gui.surfaceError(err)
+ }
+
+ // Collect Filter regexp
+ filter, err := gui.resolveTemplate(prompt.Filter, promptResponses)
+ if err != nil {
+ return gui.surfaceError(err)
+ }
+
+ // Run and save output
+ message, err := gui.GitCommand.RunCommandWithOutput(cmdStr)
+ if err != nil {
+ return gui.surfaceError(err)
+ }
+
+ // Need to make a menu out of what the cmd has displayed
+ candidates, err := gui.generateMenuCandidates(message, filter, prompt.Format)
+
+ menuItems := make([]*menuItem, len(candidates))
+ for i := range candidates {
+ menuItems[i] = &menuItem{
+ displayStrings: []string{candidates[i]},
+ onPress: func() error {
+ promptResponses[responseIdx] = candidates[i]
+ return wrappedF()
+ },
+ }
+ }
+
+ title, err := gui.resolveTemplate(prompt.Title, promptResponses)
+ if err != nil {
+ return gui.surfaceError(err)
+ }
+
+ return gui.createMenu(title, menuItems, createMenuOptions{showCancel: true})
+}
+
func (gui *Gui) handleCustomCommandKeybinding(customCommand config.CustomCommand) func() error {
return func() error {
promptResponses := make([]string, len(customCommand.Prompts))
@@ -94,144 +237,15 @@ func (gui *Gui) handleCustomCommandKeybinding(customCommand config.CustomCommand
switch prompt.Type {
case "input":
f = func() error {
- title, err := gui.resolveTemplate(prompt.Title, promptResponses)
- if err != nil {
- return gui.surfaceError(err)
- }
-
- initialValue, err := gui.resolveTemplate(prompt.InitialValue, promptResponses)
- if err != nil {
- return gui.surfaceError(err)
- }
-
- return gui.prompt(promptOpts{
- title: title,
- initialContent: initialValue,
- handleConfirm: func(str string) error {
- promptResponses[idx] = str
-
- return wrappedF()
- },
- })
+ return gui.inputPrompt(prompt, promptResponses, idx, wrappedF)
}
case "menu":
f = func() error {
- // need to make a menu here some how
- menuItems := make([]*menuItem, len(prompt.Options))
- for i, option := range prompt.Options {
- option := option
-
- nameTemplate := option.Name
- if nameTemplate == "" {
- // this allows you to only pass values rather than bother with names/descriptions
- nameTemplate = option.Value
- }
- name, err := gui.resolveTemplate(nameTemplate, promptResponses)
- if err != nil {
- return gui.surfaceError(err)
- }
-
- description, err := gui.resolveTemplate(option.Description, promptResponses)
- if err != nil {
- return gui.surfaceError(err)
- }
-
- value, err := gui.resolveTemplate(option.Value, promptResponses)
- if err != nil {
- return gui.surfaceError(err)
- }
-
- menuItems[i] = &menuItem{
- displayStrings: []string{name, utils.ColoredString(description, color.FgYellow)},
- onPress: func() error {
- promptResponses[idx] = value
-
- return wrappedF()
- },
- }
- }
-
- title, err := gui.resolveTemplate(prompt.Title, promptResponses)
- if err != nil {
- return gui.surfaceError(err)
- }
-
- return gui.createMenu(title, menuItems, createMenuOptions{showCancel: true})
+ return gui.menuPrompt(prompt, promptResponses, idx, wrappedF)
}
case "menuFromCommand":
f = func() error {
- // Collect cmd to run from config
- cmdStr, err := gui.resolveTemplate(prompt.Command, promptResponses)
- if err != nil {
- return gui.surfaceError(err)
- }
-
- // Collect Filter regexp
- filter, err := gui.resolveTemplate(prompt.Filter, promptResponses)
- if err != nil {
- return gui.surfaceError(err)
- }
- reg, err := regexp.Compile(filter)
- if err != nil {
- return gui.surfaceError(errors.New("unable to parse filter regex, error: " + err.Error()))
- }
-
- // Run and save output
- message, err := gui.GitCommand.RunCommandWithOutput(cmdStr)
- if err != nil {
- return gui.surfaceError(err)
- }
-
- // Need to make a menu out of what the cmd has displayed
- candidates := []string{}
- buff := bytes.NewBuffer(nil)
- temp, err := template.New("format").Parse(prompt.Format)
- if err != nil {
- return gui.surfaceError(errors.New("unable to parse format, error: " + err.Error()))
- }
- for _, str := range strings.Split(string(message), "\n") {
- if str == "" {
- continue
- }
- tmplData := map[string]string{}
- out := reg.FindAllStringSubmatch(str, -1)
- if len(out) > 0 {
- for groupIdx, group := range reg.SubexpNames() {
- // Record matched group with group ids
- matchName := "group_" + strconv.Itoa(groupIdx)
- tmplData[matchName] = group
- // Record last named group non-empty matches as group matches
- if group != "" {
- tmplData[group] = out[0][idx]
- }
- }
- }
- err = temp.Execute(buff, tmplData)
- if err != nil {
- return gui.surfaceError(err)
- }
-
- candidates = append(candidates, strings.TrimSpace(buff.String()))
- buff.Reset()
- }
-
- menuItems := make([]*menuItem, len(candidates))
- for i := range candidates {
- menuItems[i] = &menuItem{
- displayStrings: []string{candidates[i]},
- onPress: func() error {
- promptResponses[idx] = candidates[i]
- return wrappedF()
- },
- }
- }
-
- title, err := gui.resolveTemplate(prompt.Title, promptResponses)
- if err != nil {
- return gui.surfaceError(err)
- }
-
- return gui.createMenu(title, menuItems, createMenuOptions{showCancel: true})
+ return gui.menuPromptFromCommand(prompt, promptResponses, idx, wrappedF)
}
default:
return gui.createErrorPanel("custom command prompt must have a type of 'input', 'menu' or 'menuFromCommand'")