summaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2022-02-13 19:15:22 +1100
committerJesse Duffield <jessedduffield@gmail.com>2022-03-17 19:13:40 +1100
commit85f23198971de56195a4a1790d70e9d3b4ea1908 (patch)
tree0f5fffab65633201a864a9846ff1b3de0eccd6ce /pkg
parentc685a413c94d06f154587015a86701ec82d2ee0c (diff)
refactor custom commands panel
Diffstat (limited to 'pkg')
-rw-r--r--pkg/gui/commit_files_panel.go14
-rw-r--r--pkg/gui/custom_commands.go167
2 files changed, 101 insertions, 80 deletions
diff --git a/pkg/gui/commit_files_panel.go b/pkg/gui/commit_files_panel.go
index 610973399..df37f6b41 100644
--- a/pkg/gui/commit_files_panel.go
+++ b/pkg/gui/commit_files_panel.go
@@ -256,6 +256,13 @@ func (gui *Gui) handleToggleCommitFileDirCollapsed() error {
return nil
}
+// NOTE: this is very similar to handleToggleFileTreeView, could be DRY'd with generics
+func (gui *Gui) handleToggleCommitFileTreeView() error {
+ gui.State.Contexts.CommitFiles.CommitFileTreeViewModel.ToggleShowTree()
+
+ return gui.c.PostRefreshUpdate(gui.State.Contexts.CommitFiles)
+}
+
func (gui *Gui) SwitchToCommitFilesContext(opts controllers.SwitchToCommitFilesContextOpts) error {
// sometimes the commitFiles view is already shown in another window, so we need to ensure that window
// no longer considers the commitFiles view as its main view.
@@ -273,10 +280,3 @@ func (gui *Gui) SwitchToCommitFilesContext(opts controllers.SwitchToCommitFilesC
return gui.c.PushContext(gui.State.Contexts.CommitFiles)
}
-
-// NOTE: this is very similar to handleToggleFileTreeView, could be DRY'd with generics
-func (gui *Gui) handleToggleCommitFileTreeView() error {
- gui.State.Contexts.CommitFiles.CommitFileTreeViewModel.ToggleShowTree()
-
- return gui.c.PostRefreshUpdate(gui.State.Contexts.CommitFiles)
-}
diff --git a/pkg/gui/custom_commands.go b/pkg/gui/custom_commands.go
index 01a37adce..b4c977f3b 100644
--- a/pkg/gui/custom_commands.go
+++ b/pkg/gui/custom_commands.go
@@ -40,7 +40,7 @@ type commandMenuEntry struct {
value string
}
-func (gui *Gui) resolveTemplate(templateStr string, promptResponses []string) (string, error) {
+func (gui *Gui) getResolveTemplateFn(promptResponses []string) func(string) (string, error) {
objects := CustomCommandObjects{
SelectedFile: gui.getSelectedFile(),
SelectedPath: gui.getSelectedPath(),
@@ -58,71 +58,101 @@ func (gui *Gui) resolveTemplate(templateStr string, promptResponses []string) (s
PromptResponses: promptResponses,
}
- return utils.ResolveTemplate(templateStr, objects)
+ return func(templateStr string) (string, error) { 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)
+func resolveCustomCommandPrompt(prompt *config.CustomCommandPrompt, resolveTemplate func(string) (string, error)) (*config.CustomCommandPrompt, error) {
+ var err error
+ result := &config.CustomCommandPrompt{}
+
+ result.Title, err = resolveTemplate(prompt.Title)
if err != nil {
- return gui.c.Error(err)
+ return nil, err
}
- initialValue, err := gui.resolveTemplate(prompt.InitialValue, promptResponses)
+ result.InitialValue, err = resolveTemplate(prompt.InitialValue)
if err != nil {
- return gui.c.Error(err)
+ return nil, err
+ }
+
+ result.Command, err = resolveTemplate(prompt.Command)
+ if err != nil {
+ return nil, err
+ }
+
+ result.Filter, err = resolveTemplate(prompt.Filter)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(prompt.Options) > 0 {
+ newOptions := make([]config.CustomCommandMenuOption, len(prompt.Options))
+ for _, option := range prompt.Options {
+ option := option
+ newOption, err := resolveMenuOption(&option, resolveTemplate)
+ if err != nil {
+ return nil, err
+ }
+ newOptions = append(newOptions, *newOption)
+ }
+ prompt.Options = newOptions
+ }
+
+ return result, nil
+}
+
+func resolveMenuOption(option *config.CustomCommandMenuOption, resolveTemplate func(string) (string, error)) (*config.CustomCommandMenuOption, error) {
+ nameTemplate := option.Name
+ if nameTemplate == "" {
+ // this allows you to only pass values rather than bother with names/descriptions
+ nameTemplate = option.Value
+ }
+
+ name, err := resolveTemplate(nameTemplate)
+ if err != nil {
+ return nil, err
+ }
+
+ description, err := resolveTemplate(option.Description)
+ if err != nil {
+ return nil, err
}
+ value, err := resolveTemplate(option.Value)
+ if err != nil {
+ return nil, err
+ }
+
+ return &config.CustomCommandMenuOption{
+ Name: name,
+ Description: description,
+ Value: value,
+ }, nil
+}
+
+func (gui *Gui) inputPrompt(prompt *config.CustomCommandPrompt, wrappedF func(string) error) error {
return gui.c.Prompt(types.PromptOpts{
- Title: title,
- InitialContent: initialValue,
+ Title: prompt.Title,
+ InitialContent: prompt.InitialValue,
HandleConfirm: func(str string) error {
- promptResponses[responseIdx] = str
- return wrappedF()
+ return wrappedF(str)
},
})
}
-func (gui *Gui) menuPrompt(prompt config.CustomCommandPrompt, promptResponses []string, responseIdx int, wrappedF func() error) error {
- // need to make a menu here some how
+func (gui *Gui) menuPrompt(prompt *config.CustomCommandPrompt, wrappedF func(string) error) error {
menuItems := make([]*types.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.c.Error(err)
- }
-
- description, err := gui.resolveTemplate(option.Description, promptResponses)
- if err != nil {
- return gui.c.Error(err)
- }
-
- value, err := gui.resolveTemplate(option.Value, promptResponses)
- if err != nil {
- return gui.c.Error(err)
- }
-
menuItems[i] = &types.MenuItem{
- DisplayStrings: []string{name, style.FgYellow.Sprint(description)},
+ DisplayStrings: []string{option.Name, style.FgYellow.Sprint(option.Description)},
OnPress: func() error {
- promptResponses[responseIdx] = value
- return wrappedF()
+ return wrappedF(option.Value)
},
}
}
- title, err := gui.resolveTemplate(prompt.Title, promptResponses)
- if err != nil {
- return gui.c.Error(err)
- }
-
- return gui.c.Menu(types.CreateMenuOptions{Title: title, Items: menuItems})
+ return gui.c.Menu(types.CreateMenuOptions{Title: prompt.Title, Items: menuItems})
}
func (gui *Gui) GenerateMenuCandidates(commandOutput, filter, valueFormat, labelFormat string) ([]commandMenuEntry, error) {
@@ -191,27 +221,15 @@ func (gui *Gui) GenerateMenuCandidates(commandOutput, filter, valueFormat, label
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.c.Error(err)
- }
-
- // Collect Filter regexp
- filter, err := gui.resolveTemplate(prompt.Filter, promptResponses)
- if err != nil {
- return gui.c.Error(err)
- }
-
+func (gui *Gui) menuPromptFromCommand(prompt *config.CustomCommandPrompt, wrappedF func(string) error) error {
// Run and save output
- message, err := gui.git.Custom.RunWithOutput(cmdStr)
+ message, err := gui.git.Custom.RunWithOutput(prompt.Command)
if err != nil {
return gui.c.Error(err)
}
// Need to make a menu out of what the cmd has displayed
- candidates, err := gui.GenerateMenuCandidates(message, filter, prompt.ValueFormat, prompt.LabelFormat)
+ candidates, err := gui.GenerateMenuCandidates(message, prompt.Filter, prompt.ValueFormat, prompt.LabelFormat)
if err != nil {
return gui.c.Error(err)
}
@@ -222,18 +240,12 @@ func (gui *Gui) menuPromptFromCommand(prompt config.CustomCommandPrompt, promptR
menuItems[i] = &types.MenuItem{
DisplayStrings: []string{candidates[i].label},
OnPress: func() error {
- promptResponses[responseIdx] = candidates[i].value
- return wrappedF()
+ return wrappedF(candidates[i].value)
},
}
}
- title, err := gui.resolveTemplate(prompt.Title, promptResponses)
- if err != nil {
- return gui.c.Error(err)
- }
-
- return gui.c.Menu(types.CreateMenuOptions{Title: title, Items: menuItems})
+ return gui.c.Menu(types.CreateMenuOptions{Title: prompt.Title, Items: menuItems})
}
func (gui *Gui) handleCustomCommandKeybinding(customCommand config.CustomCommand) func() error {
@@ -241,7 +253,8 @@ func (gui *Gui) handleCustomCommandKeybinding(customCommand config.CustomCommand
promptResponses := make([]string, len(customCommand.Prompts))
f := func() error {
- cmdStr, err := gui.resolveTemplate(customCommand.Command, promptResponses)
+ resolveTemplate := gui.getResolveTemplateFn(promptResponses)
+ cmdStr, err := resolveTemplate(customCommand.Command)
if err != nil {
return gui.c.Error(err)
}
@@ -254,6 +267,7 @@ func (gui *Gui) handleCustomCommandKeybinding(customCommand config.CustomCommand
if loadingText == "" {
loadingText = gui.c.Tr.LcRunningCustomCommandStatus
}
+
return gui.c.WithWaitingStatus(loadingText, func() error {
gui.c.LogAction(gui.c.Tr.Actions.CustomCommand)
cmdObj := gui.os.Cmd.NewShell(cmdStr)
@@ -276,26 +290,33 @@ func (gui *Gui) handleCustomCommandKeybinding(customCommand config.CustomCommand
// going backwards so the outermost prompt is the first one
prompt := customCommand.Prompts[idx]
- // need to do this because f's value will change with each iteration
- wrappedF := f
+ wrappedF := func(response string) error {
+ promptResponses[idx] = response
+ return f()
+ }
+
+ resolveTemplate := gui.getResolveTemplateFn(promptResponses)
+ resolvedPrompt, err := resolveCustomCommandPrompt(&prompt, resolveTemplate)
+ if err != nil {
+ return gui.c.Error(err)
+ }
switch prompt.Type {
case "input":
f = func() error {
- return gui.inputPrompt(prompt, promptResponses, idx, wrappedF)
+ return gui.inputPrompt(resolvedPrompt, wrappedF)
}
case "menu":
f = func() error {
- return gui.menuPrompt(prompt, promptResponses, idx, wrappedF)
+ return gui.menuPrompt(resolvedPrompt, wrappedF)
}
case "menuFromCommand":
f = func() error {
- return gui.menuPromptFromCommand(prompt, promptResponses, idx, wrappedF)
+ return gui.menuPromptFromCommand(resolvedPrompt, wrappedF)
}
default:
return gui.c.ErrorMsg("custom command prompt must have a type of 'input', 'menu' or 'menuFromCommand'")
}
-
}
return f()