diff --git a/pkg/config/user_config.go b/pkg/config/user_config.go index dfeced3c0..6461ece75 100644 --- a/pkg/config/user_config.go +++ b/pkg/config/user_config.go @@ -667,8 +667,8 @@ type CustomCommandAfterHook struct { } type CustomCommand struct { - // The key to trigger the command. Use a single letter or one of the values from https://github.com/jesseduffield/lazygit/blob/master/docs/keybindings/Custom_Keybindings.md - Key string `yaml:"key"` + // The key to trigger the command. Use a single letter or one of the values from https://github.com/jesseduffield/lazygit/blob/master/docs/keybindings/Custom_Keybindings.md. To bind several alternates to the same command, use a sequence (e.g. `[a, b]`). + Key Keybinding `yaml:"key"` // Instead of defining a single custom command, create a menu of custom commands. Useful for grouping related commands together under a single keybinding, and for keeping them out of the global keybindings menu. // When using this, all other fields except Key and Description are ignored and must be empty. CommandMenu []CustomCommand `yaml:"commandMenu"` @@ -753,8 +753,8 @@ type CustomCommandMenuOption struct { Description string `yaml:"description"` // The value that will be used in the command Value string `yaml:"value" jsonschema:"example=feature,minLength=1"` - // Keybinding to invoke this menu option without needing to navigate to it - Key string `yaml:"key"` + // Keybinding to invoke this menu option without needing to navigate to it. Accepts either a single key or a sequence of alternates. + Key Keybinding `yaml:"key"` } type CustomIconsConfig struct { diff --git a/pkg/config/user_config_validation.go b/pkg/config/user_config_validation.go index 7eeab32dd..163fc61c4 100644 --- a/pkg/config/user_config_validation.go +++ b/pkg/config/user_config_validation.go @@ -126,10 +126,12 @@ func validateKeybindings(keybindingConfig KeybindingConfig) error { return nil } -func validateCustomCommandKey(key string) error { - if !isValidKeybindingKey(key) { - return fmt.Errorf("Unrecognized key '%s' for custom command. For permitted values see %s", - key, constants.Links.Docs.CustomKeybindings) +func validateCustomCommandKey(key Keybinding) error { + for _, k := range key { + if !isValidKeybindingKey(k) { + return fmt.Errorf("Unrecognized key '%s' for custom command. For permitted values see %s", + k, constants.Links.Docs.CustomKeybindings) + } } return nil } @@ -150,7 +152,7 @@ func validateCustomCommands(customCommands []CustomCommand) error { customCommand.After != nil { commandRef := "" if len(customCommand.Key) > 0 { - commandRef = fmt.Sprintf(" with key '%s'", customCommand.Key) + commandRef = fmt.Sprintf(" with key '%s'", customCommand.Key.String()) } return fmt.Errorf("Error with custom command%s: it is not allowed to use both commandMenu and any of the other fields except key and description.", commandRef) } @@ -176,9 +178,11 @@ func validateCustomCommands(customCommands []CustomCommand) error { func validateCustomCommandPrompt(prompt CustomCommandPrompt) error { for _, option := range prompt.Options { - if !isValidKeybindingKey(option.Key) { - return fmt.Errorf("Unrecognized key '%s' for custom command prompt option. For permitted values see %s", - option.Key, constants.Links.Docs.CustomKeybindings) + for _, k := range option.Key { + if !isValidKeybindingKey(k) { + return fmt.Errorf("Unrecognized key '%s' for custom command prompt option. For permitted values see %s", + k, constants.Links.Docs.CustomKeybindings) + } } } diff --git a/pkg/config/user_config_validation_test.go b/pkg/config/user_config_validation_test.go index ec79c9c3e..bb2d2580f 100644 --- a/pkg/config/user_config_validation_test.go +++ b/pkg/config/user_config_validation_test.go @@ -146,7 +146,7 @@ func TestUserConfigValidate_enums(t *testing.T) { setup: func(config *UserConfig, value string) { config.CustomCommands = []CustomCommand{ { - Key: value, + Key: Keybinding{value}, Command: "echo 'hello'", }, } @@ -164,10 +164,10 @@ func TestUserConfigValidate_enums(t *testing.T) { setup: func(config *UserConfig, value string) { config.CustomCommands = []CustomCommand{ { - Key: "X", + Key: Keybinding{"X"}, Description: "My Custom Commands", CommandMenu: []CustomCommand{ - {Key: value, Command: "echo 'hello'", Context: "global"}, + {Key: Keybinding{value}, Command: "echo 'hello'", Context: "global"}, }, }, } @@ -185,12 +185,12 @@ func TestUserConfigValidate_enums(t *testing.T) { setup: func(config *UserConfig, value string) { config.CustomCommands = []CustomCommand{ { - Key: "X", + Key: Keybinding{"X"}, Description: "My Custom Commands", Prompts: []CustomCommandPrompt{ { Options: []CustomCommandMenuOption{ - {Key: value}, + {Key: Keybinding{value}}, }, }, }, @@ -229,10 +229,10 @@ func TestUserConfigValidate_enums(t *testing.T) { setup: func(config *UserConfig, _ string) { config.CustomCommands = []CustomCommand{ { - Key: "X", + Key: Keybinding{"X"}, Description: "My Custom Commands", CommandMenu: []CustomCommand{ - {Key: "1", Command: "echo 'hello'", Context: "global"}, + {Key: Keybinding{"1"}, Command: "echo 'hello'", Context: "global"}, }, }, } @@ -246,10 +246,10 @@ func TestUserConfigValidate_enums(t *testing.T) { setup: func(config *UserConfig, _ string) { config.CustomCommands = []CustomCommand{ { - Key: "X", + Key: Keybinding{"X"}, Context: "global", // context is not allowed for submenus CommandMenu: []CustomCommand{ - {Key: "1", Command: "echo 'hello'", Context: "global"}, + {Key: Keybinding{"1"}, Command: "echo 'hello'", Context: "global"}, }, }, } @@ -263,10 +263,10 @@ func TestUserConfigValidate_enums(t *testing.T) { setup: func(config *UserConfig, _ string) { config.CustomCommands = []CustomCommand{ { - Key: "X", + Key: Keybinding{"X"}, LoadingText: "loading", // other properties are not allowed for submenus (using loadingText as an example) CommandMenu: []CustomCommand{ - {Key: "1", Command: "echo 'hello'", Context: "global"}, + {Key: Keybinding{"1"}, Command: "echo 'hello'", Context: "global"}, }, }, } diff --git a/pkg/gui/services/custom_commands/client.go b/pkg/gui/services/custom_commands/client.go index 0884e0cce..3f16b8ba8 100644 --- a/pkg/gui/services/custom_commands/client.go +++ b/pkg/gui/services/custom_commands/client.go @@ -2,7 +2,6 @@ package custom_commands import ( "github.com/jesseduffield/lazygit/pkg/config" - "github.com/jesseduffield/lazygit/pkg/gocui" "github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/i18n" @@ -46,7 +45,7 @@ func (self *Client) GetCustomCommandKeybindings() ([]*types.Binding, error) { } bindings = append(bindings, &types.Binding{ ViewName: "", // custom commands menus are global; we filter the commands inside by context - Keys: []gocui.Key{config.GetValidatedKeyBindingKey(customCommand.Key)}, + Keys: config.GetValidatedKeyBindingKeys(customCommand.Key), Handler: handler, Description: getCustomCommandsMenuDescription(customCommand, self.c.Tr), OpensMenu: true, @@ -73,7 +72,7 @@ func (self *Client) showCustomCommandsMenu(customCommand config.CustomCommand) e } menuItems = append(menuItems, &types.MenuItem{ Label: subCommand.GetDescription(), - Keys: []gocui.Key{config.GetValidatedKeyBindingKey(subCommand.Key)}, + Keys: config.GetValidatedKeyBindingKeys(subCommand.Key), OnPress: handler, OpensMenu: true, }) @@ -93,7 +92,7 @@ func (self *Client) showCustomCommandsMenu(customCommand config.CustomCommand) e menuItems = append(menuItems, &types.MenuItem{ Label: subCommand.GetDescription(), - Keys: []gocui.Key{config.GetValidatedKeyBindingKey(subCommand.Key)}, + Keys: config.GetValidatedKeyBindingKeys(subCommand.Key), OnPress: self.handlerCreator.call(subCommand), }) } diff --git a/pkg/gui/services/custom_commands/handler_creator.go b/pkg/gui/services/custom_commands/handler_creator.go index 5f3fd27a0..19694c481 100644 --- a/pkg/gui/services/custom_commands/handler_creator.go +++ b/pkg/gui/services/custom_commands/handler_creator.go @@ -232,7 +232,7 @@ func (self *HandlerCreator) menuPrompt(prompt *config.CustomCommandPrompt, wrapp OnPress: func() error { return wrappedF(option.Value) }, - Keys: []gocui.Key{config.GetValidatedKeyBindingKey(option.Key)}, + Keys: config.GetValidatedKeyBindingKeys(option.Key), } }) diff --git a/pkg/gui/services/custom_commands/keybinding_creator.go b/pkg/gui/services/custom_commands/keybinding_creator.go index ee0e01fa4..f35fc8fd4 100644 --- a/pkg/gui/services/custom_commands/keybinding_creator.go +++ b/pkg/gui/services/custom_commands/keybinding_creator.go @@ -5,7 +5,6 @@ import ( "strings" "github.com/jesseduffield/lazygit/pkg/config" - "github.com/jesseduffield/lazygit/pkg/gocui" "github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" "github.com/jesseduffield/lazygit/pkg/gui/types" @@ -36,7 +35,7 @@ func (self *KeybindingCreator) call(customCommand config.CustomCommand, handler return lo.Map(viewNames, func(viewName string, _ int) *types.Binding { return &types.Binding{ ViewName: viewName, - Keys: []gocui.Key{config.GetValidatedKeyBindingKey(customCommand.Key)}, + Keys: config.GetValidatedKeyBindingKeys(customCommand.Key), Handler: handler, Description: customCommand.GetDescription(), } @@ -81,9 +80,9 @@ func formatUnknownContextError(customCommand config.CustomCommand) error { return string(key) }) - return fmt.Errorf("Error when setting custom command keybindings: unknown context: %s. Key: %s, Command: %s.\nPermitted contexts: %s", customCommand.Context, customCommand.Key, customCommand.Command, strings.Join(allContextKeyStrings, ", ")) + return fmt.Errorf("Error when setting custom command keybindings: unknown context: %s. Key: %s, Command: %s.\nPermitted contexts: %s", customCommand.Context, customCommand.Key.String(), customCommand.Command, strings.Join(allContextKeyStrings, ", ")) } func formatContextNotProvidedError(customCommand config.CustomCommand) error { - return fmt.Errorf("Error parsing custom command keybindings: context not provided (use context: 'global' for the global context). Key: %s, Command: %s", customCommand.Key, customCommand.Command) + return fmt.Errorf("Error parsing custom command keybindings: context not provided (use context: 'global' for the global context). Key: %s, Command: %s", customCommand.Key.String(), customCommand.Command) } diff --git a/pkg/integration/tests/config/custom_commands_in_per_repo_config.go b/pkg/integration/tests/config/custom_commands_in_per_repo_config.go index 4a66cd43c..929c7eae9 100644 --- a/pkg/integration/tests/config/custom_commands_in_per_repo_config.go +++ b/pkg/integration/tests/config/custom_commands_in_per_repo_config.go @@ -17,12 +17,12 @@ var CustomCommandsInPerRepoConfig = NewIntegrationTest(NewIntegrationTestArgs{ cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "X", + Key: config.Keybinding{"X"}, Context: "global", Command: "printf 'global X' > file.txt", }, { - Key: "Y", + Key: config.Keybinding{"Y"}, Context: "global", Command: "printf 'global Y' > file.txt", }, diff --git a/pkg/integration/tests/custom_commands/access_commit_properties.go b/pkg/integration/tests/custom_commands/access_commit_properties.go index a1ba84a27..0823b1033 100644 --- a/pkg/integration/tests/custom_commands/access_commit_properties.go +++ b/pkg/integration/tests/custom_commands/access_commit_properties.go @@ -17,7 +17,7 @@ var AccessCommitProperties = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "X", + Key: config.Keybinding{"X"}, Context: "commits", Command: "printf '%s\n%s\n%s' '{{ .SelectedLocalCommit.Name }}' '{{ .SelectedLocalCommit.Hash }}' '{{ .SelectedLocalCommit.Sha }}' > file.txt", }, diff --git a/pkg/integration/tests/custom_commands/basic_command.go b/pkg/integration/tests/custom_commands/basic_command.go index b50acc792..f5ae90a96 100644 --- a/pkg/integration/tests/custom_commands/basic_command.go +++ b/pkg/integration/tests/custom_commands/basic_command.go @@ -15,7 +15,7 @@ var BasicCommand = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "a", + Key: config.Keybinding{"a"}, Context: "files", Command: "touch myfile", }, diff --git a/pkg/integration/tests/custom_commands/check_for_conflicts.go b/pkg/integration/tests/custom_commands/check_for_conflicts.go index 70f528a6d..5d7924c90 100644 --- a/pkg/integration/tests/custom_commands/check_for_conflicts.go +++ b/pkg/integration/tests/custom_commands/check_for_conflicts.go @@ -16,7 +16,7 @@ var CheckForConflicts = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "m", + Key: config.Keybinding{"m"}, Context: "localBranches", Command: "git merge {{ .SelectedLocalBranch.Name | quote }}", After: &config.CustomCommandAfterHook{ diff --git a/pkg/integration/tests/custom_commands/conditional_prompt_false_string.go b/pkg/integration/tests/custom_commands/conditional_prompt_false_string.go index d2c6beadb..e8a64ea0d 100644 --- a/pkg/integration/tests/custom_commands/conditional_prompt_false_string.go +++ b/pkg/integration/tests/custom_commands/conditional_prompt_false_string.go @@ -15,7 +15,7 @@ var ConditionalPromptFalseString = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "a", + Key: config.Keybinding{"a"}, Context: "files", Command: `echo "{{.Form.Choice}}" > result.txt`, Prompts: []config.CustomCommandPrompt{ diff --git a/pkg/integration/tests/custom_commands/conditional_prompt_false_value.go b/pkg/integration/tests/custom_commands/conditional_prompt_false_value.go index 4a0326669..15379c7b4 100644 --- a/pkg/integration/tests/custom_commands/conditional_prompt_false_value.go +++ b/pkg/integration/tests/custom_commands/conditional_prompt_false_value.go @@ -15,7 +15,7 @@ var ConditionalPromptFalseValue = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "a", + Key: config.Keybinding{"a"}, Context: "files", Command: `echo "{{.Form.Word}} {{.Form.Extra}}" > result.txt`, Prompts: []config.CustomCommandPrompt{ diff --git a/pkg/integration/tests/custom_commands/conditional_prompts.go b/pkg/integration/tests/custom_commands/conditional_prompts.go index 4f1f97531..ef743282a 100644 --- a/pkg/integration/tests/custom_commands/conditional_prompts.go +++ b/pkg/integration/tests/custom_commands/conditional_prompts.go @@ -15,7 +15,7 @@ var ConditionalPrompts = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "a", + Key: config.Keybinding{"a"}, Context: "files", Command: `echo "{{.Form.Choice}}{{if .Form.Detail}} {{.Form.Detail}}{{end}}" > result.txt`, Prompts: []config.CustomCommandPrompt{ @@ -28,13 +28,13 @@ var ConditionalPrompts = NewIntegrationTest(NewIntegrationTestArgs{ Name: "first", Description: "First option", Value: "FIRST", - Key: "1", + Key: config.Keybinding{"1"}, }, { Name: "second", Description: "Second option", Value: "SECOND", - Key: "H", + Key: config.Keybinding{"H"}, }, }, }, diff --git a/pkg/integration/tests/custom_commands/custom_commands_submenu.go b/pkg/integration/tests/custom_commands/custom_commands_submenu.go index 93c670449..18dd51d83 100644 --- a/pkg/integration/tests/custom_commands/custom_commands_submenu.go +++ b/pkg/integration/tests/custom_commands/custom_commands_submenu.go @@ -13,21 +13,21 @@ var CustomCommandsSubmenu = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "x", + Key: config.Keybinding{"x"}, Description: "My Custom Commands", CommandMenu: []config.CustomCommand{ { - Key: "1", + Key: config.Keybinding{"1"}, Context: "global", Command: "touch myfile-global", }, { - Key: "2", + Key: config.Keybinding{"2"}, Context: "files", Command: "touch myfile-files", }, { - Key: "3", + Key: config.Keybinding{"3"}, Context: "commits", Command: "touch myfile-commits", }, diff --git a/pkg/integration/tests/custom_commands/custom_commands_submenu_with_special_keybindings.go b/pkg/integration/tests/custom_commands/custom_commands_submenu_with_special_keybindings.go index 29638ee92..e79e05991 100644 --- a/pkg/integration/tests/custom_commands/custom_commands_submenu_with_special_keybindings.go +++ b/pkg/integration/tests/custom_commands/custom_commands_submenu_with_special_keybindings.go @@ -13,29 +13,29 @@ var CustomCommandsSubmenuWithSpecialKeybindings = NewIntegrationTest(NewIntegrat SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "x", + Key: config.Keybinding{"x"}, Description: "My Custom Commands", CommandMenu: []config.CustomCommand{ { - Key: "j", + Key: config.Keybinding{"j"}, Context: "global", Command: "echo j", Output: "popup", }, { - Key: "H", + Key: config.Keybinding{"H"}, Context: "global", Command: "echo H", Output: "popup", }, { - Key: "y", + Key: config.Keybinding{"y"}, Context: "global", Command: "echo y", Output: "popup", }, { - Key: "", + Key: config.Keybinding{""}, Context: "global", Command: "echo down", Output: "popup", diff --git a/pkg/integration/tests/custom_commands/form_prompts.go b/pkg/integration/tests/custom_commands/form_prompts.go index 3e051cb8e..43246b872 100644 --- a/pkg/integration/tests/custom_commands/form_prompts.go +++ b/pkg/integration/tests/custom_commands/form_prompts.go @@ -15,7 +15,7 @@ var FormPrompts = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "a", + Key: config.Keybinding{"a"}, Context: "files", Command: `echo {{.Form.FileContent | quote}} > {{.Form.FileName | quote}}`, Prompts: []config.CustomCommandPrompt{ diff --git a/pkg/integration/tests/custom_commands/global_context.go b/pkg/integration/tests/custom_commands/global_context.go index 274d6a7ba..2c4cd464f 100644 --- a/pkg/integration/tests/custom_commands/global_context.go +++ b/pkg/integration/tests/custom_commands/global_context.go @@ -15,7 +15,7 @@ var GlobalContext = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "X", + Key: config.Keybinding{"X"}, Context: "global", Command: "touch myfile", }, diff --git a/pkg/integration/tests/custom_commands/menu_from_command.go b/pkg/integration/tests/custom_commands/menu_from_command.go index ae62c9a5c..51122aa6f 100644 --- a/pkg/integration/tests/custom_commands/menu_from_command.go +++ b/pkg/integration/tests/custom_commands/menu_from_command.go @@ -21,7 +21,7 @@ var MenuFromCommand = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "a", + Key: config.Keybinding{"a"}, Context: "localBranches", Command: `echo "{{index .PromptResponses 0}} {{index .PromptResponses 1}} {{ .SelectedLocalBranch.Name }}" > output.txt`, Prompts: []config.CustomCommandPrompt{ diff --git a/pkg/integration/tests/custom_commands/menu_from_commands_output.go b/pkg/integration/tests/custom_commands/menu_from_commands_output.go index 7820bc515..51444ad52 100644 --- a/pkg/integration/tests/custom_commands/menu_from_commands_output.go +++ b/pkg/integration/tests/custom_commands/menu_from_commands_output.go @@ -20,7 +20,7 @@ var MenuFromCommandsOutput = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "a", + Key: config.Keybinding{"a"}, Context: "localBranches", Command: "git checkout {{ index .PromptResponses 1 }}", Prompts: []config.CustomCommandPrompt{ diff --git a/pkg/integration/tests/custom_commands/menu_prompt_with_keys.go b/pkg/integration/tests/custom_commands/menu_prompt_with_keys.go index d29a049f9..4a217f924 100644 --- a/pkg/integration/tests/custom_commands/menu_prompt_with_keys.go +++ b/pkg/integration/tests/custom_commands/menu_prompt_with_keys.go @@ -15,7 +15,7 @@ var MenuPromptWithKeys = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "a", + Key: config.Keybinding{"a"}, Context: "files", Command: `echo {{.Form.Choice | quote}} > result.txt`, Prompts: []config.CustomCommandPrompt{ @@ -28,19 +28,19 @@ var MenuPromptWithKeys = NewIntegrationTest(NewIntegrationTestArgs{ Name: "first", Description: "First option", Value: "FIRST", - Key: "1", + Key: config.Keybinding{"1"}, }, { Name: "second", Description: "Second option", Value: "SECOND", - Key: "H", + Key: config.Keybinding{"H"}, }, { Name: "third", Description: "Third option", Value: "THIRD", - Key: "3", + Key: config.Keybinding{"3"}, }, }, }, diff --git a/pkg/integration/tests/custom_commands/multiple_contexts.go b/pkg/integration/tests/custom_commands/multiple_contexts.go index b53242edc..3c7e07e84 100644 --- a/pkg/integration/tests/custom_commands/multiple_contexts.go +++ b/pkg/integration/tests/custom_commands/multiple_contexts.go @@ -15,7 +15,7 @@ var MultipleContexts = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "X", + Key: config.Keybinding{"X"}, Context: "commits, reflogCommits", Command: "touch myfile", }, diff --git a/pkg/integration/tests/custom_commands/multiple_prompts.go b/pkg/integration/tests/custom_commands/multiple_prompts.go index a450f7aee..8651a330a 100644 --- a/pkg/integration/tests/custom_commands/multiple_prompts.go +++ b/pkg/integration/tests/custom_commands/multiple_prompts.go @@ -15,7 +15,7 @@ var MultiplePrompts = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "a", + Key: config.Keybinding{"a"}, Context: "files", Command: `echo "{{index .PromptResponses 1}}" > {{index .PromptResponses 0}}`, Prompts: []config.CustomCommandPrompt{ diff --git a/pkg/integration/tests/custom_commands/run_command.go b/pkg/integration/tests/custom_commands/run_command.go index ca9abb658..afff59590 100644 --- a/pkg/integration/tests/custom_commands/run_command.go +++ b/pkg/integration/tests/custom_commands/run_command.go @@ -15,7 +15,7 @@ var RunCommand = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "a", + Key: config.Keybinding{"a"}, Context: "localBranches", Command: `git checkout {{.Form.Branch}}`, Prompts: []config.CustomCommandPrompt{ diff --git a/pkg/integration/tests/custom_commands/selected_commit.go b/pkg/integration/tests/custom_commands/selected_commit.go index 49595afd0..0265759a8 100644 --- a/pkg/integration/tests/custom_commands/selected_commit.go +++ b/pkg/integration/tests/custom_commands/selected_commit.go @@ -15,7 +15,7 @@ var SelectedCommit = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "X", + Key: config.Keybinding{"X"}, Context: "global", Command: "printf '%s' '{{ .SelectedCommit.Name }}' > file.txt", }, diff --git a/pkg/integration/tests/custom_commands/selected_commit_range.go b/pkg/integration/tests/custom_commands/selected_commit_range.go index f335d91d9..6ef1305aa 100644 --- a/pkg/integration/tests/custom_commands/selected_commit_range.go +++ b/pkg/integration/tests/custom_commands/selected_commit_range.go @@ -15,7 +15,7 @@ var SelectedCommitRange = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "X", + Key: config.Keybinding{"X"}, Context: "global", Command: `git log --format="%s" {{.SelectedCommitRange.From}}^..{{.SelectedCommitRange.To}} > file.txt`, }, diff --git a/pkg/integration/tests/custom_commands/selected_path.go b/pkg/integration/tests/custom_commands/selected_path.go index c6c680335..cad479e4a 100644 --- a/pkg/integration/tests/custom_commands/selected_path.go +++ b/pkg/integration/tests/custom_commands/selected_path.go @@ -19,7 +19,7 @@ var SelectedPath = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "X", + Key: config.Keybinding{"X"}, Context: "global", Command: "printf '%s' '{{ .SelectedPath }}' > file.txt", }, diff --git a/pkg/integration/tests/custom_commands/selected_submodule.go b/pkg/integration/tests/custom_commands/selected_submodule.go index d03af03dd..0671b4b83 100644 --- a/pkg/integration/tests/custom_commands/selected_submodule.go +++ b/pkg/integration/tests/custom_commands/selected_submodule.go @@ -17,17 +17,17 @@ var SelectedSubmodule = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "X", + Key: config.Keybinding{"X"}, Context: "submodules", Command: "printf '%s' '{{ .SelectedSubmodule.Path }}' > file.txt", }, { - Key: "U", + Key: config.Keybinding{"U"}, Context: "submodules", Command: "printf '%s' '{{ .SelectedSubmodule.Url }}' > file.txt", }, { - Key: "N", + Key: config.Keybinding{"N"}, Context: "submodules", Command: "printf '%s' '{{ .SelectedSubmodule.Name }}' > file.txt", }, diff --git a/pkg/integration/tests/custom_commands/show_output_in_panel.go b/pkg/integration/tests/custom_commands/show_output_in_panel.go index 95765cb5f..4654b9b51 100644 --- a/pkg/integration/tests/custom_commands/show_output_in_panel.go +++ b/pkg/integration/tests/custom_commands/show_output_in_panel.go @@ -17,13 +17,13 @@ var ShowOutputInPanel = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "X", + Key: config.Keybinding{"X"}, Context: "commits", Command: "printf '%s' '{{ .SelectedLocalCommit.Name }}'", Output: "popup", }, { - Key: "Y", + Key: config.Keybinding{"Y"}, Context: "commits", Command: "printf '%s' '{{ .SelectedLocalCommit.Name }}'", Output: "popup", diff --git a/pkg/integration/tests/custom_commands/suggestions_command.go b/pkg/integration/tests/custom_commands/suggestions_command.go index 831ecddda..e31d6dd8b 100644 --- a/pkg/integration/tests/custom_commands/suggestions_command.go +++ b/pkg/integration/tests/custom_commands/suggestions_command.go @@ -22,7 +22,7 @@ var SuggestionsCommand = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "a", + Key: config.Keybinding{"a"}, Context: "localBranches", Command: `git checkout {{.Form.Branch}}`, Prompts: []config.CustomCommandPrompt{ diff --git a/pkg/integration/tests/custom_commands/suggestions_preset.go b/pkg/integration/tests/custom_commands/suggestions_preset.go index 285d88e01..ebd9ee5da 100644 --- a/pkg/integration/tests/custom_commands/suggestions_preset.go +++ b/pkg/integration/tests/custom_commands/suggestions_preset.go @@ -22,7 +22,7 @@ var SuggestionsPreset = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "a", + Key: config.Keybinding{"a"}, Context: "localBranches", Command: `git checkout {{.Form.Branch}}`, Prompts: []config.CustomCommandPrompt{ diff --git a/pkg/integration/tests/demo/custom_command.go b/pkg/integration/tests/demo/custom_command.go index f14a19b5f..486b3488a 100644 --- a/pkg/integration/tests/demo/custom_command.go +++ b/pkg/integration/tests/demo/custom_command.go @@ -28,7 +28,7 @@ var CustomCommand = NewIntegrationTest(NewIntegrationTestArgs{ cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "a", + Key: config.Keybinding{"a"}, Context: "localBranches", Command: `git checkout {{.Form.Branch}}`, Prompts: []config.CustomCommandPrompt{ diff --git a/pkg/integration/tests/interactive_rebase/show_exec_todos.go b/pkg/integration/tests/interactive_rebase/show_exec_todos.go index 959139154..948bfb7d8 100644 --- a/pkg/integration/tests/interactive_rebase/show_exec_todos.go +++ b/pkg/integration/tests/interactive_rebase/show_exec_todos.go @@ -12,7 +12,7 @@ var ShowExecTodos = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "X", + Key: config.Keybinding{"X"}, Context: "commits", Command: "git -c core.editor=: rebase -i -x false HEAD^^", }, diff --git a/pkg/integration/tests/submodule/enter.go b/pkg/integration/tests/submodule/enter.go index a56dd8910..b768ed40e 100644 --- a/pkg/integration/tests/submodule/enter.go +++ b/pkg/integration/tests/submodule/enter.go @@ -12,7 +12,7 @@ var Enter = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "e", + Key: config.Keybinding{"e"}, Context: "files", Command: "git commit --allow-empty -m \"empty commit\"", }, diff --git a/pkg/integration/tests/submodule/reset.go b/pkg/integration/tests/submodule/reset.go index 5e7cde7f0..d671066a1 100644 --- a/pkg/integration/tests/submodule/reset.go +++ b/pkg/integration/tests/submodule/reset.go @@ -12,7 +12,7 @@ var Reset = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "e", + Key: config.Keybinding{"e"}, Context: "files", Command: "git commit --allow-empty -m \"empty commit\" && echo \"my_file content\" > my_file", }, diff --git a/pkg/integration/tests/worktree/custom_command.go b/pkg/integration/tests/worktree/custom_command.go index a3cddd36a..e00c162c3 100644 --- a/pkg/integration/tests/worktree/custom_command.go +++ b/pkg/integration/tests/worktree/custom_command.go @@ -12,7 +12,7 @@ var CustomCommand = NewIntegrationTest(NewIntegrationTestArgs{ SetupConfig: func(cfg *config.AppConfig) { cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ { - Key: "d", + Key: config.Keybinding{"d"}, Context: "worktrees", Command: "git worktree remove {{ .SelectedWorktree.Path | quote }}", }, diff --git a/schema-master/config.json b/schema-master/config.json index 495acc1d2..1f6e9e7d8 100644 --- a/schema-master/config.json +++ b/schema-master/config.json @@ -60,8 +60,18 @@ "CustomCommand": { "properties": { "key": { - "type": "string", - "description": "The key to trigger the command. Use a single letter or one of the values from https://github.com/jesseduffield/lazygit/blob/master/docs/keybindings/Custom_Keybindings.md" + "oneOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "description": "The key to trigger the command. Use a single letter or one of the values from https://github.com/jesseduffield/lazygit/blob/master/docs/keybindings/Custom_Keybindings.md. To bind several alternates to the same command, use a sequence (e.g. `[a, b]`)." }, "commandMenu": { "items": { @@ -165,8 +175,18 @@ ] }, "key": { - "type": "string", - "description": "Keybinding to invoke this menu option without needing to navigate to it" + "oneOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "description": "Keybinding to invoke this menu option without needing to navigate to it. Accepts either a single key or a sequence of alternates." } }, "additionalProperties": false,