Skip to content

Commit fb80753

Browse files
committed
feat(custom command)!: support multiple contexts within one command
1 parent f598da0 commit fb80753

File tree

18 files changed

+75
-67
lines changed

18 files changed

+75
-67
lines changed

pkg/config/user_config.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -589,8 +589,8 @@ type CustomCommandAfterHook struct {
589589
type CustomCommand struct {
590590
// 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
591591
Key string `yaml:"key"`
592-
// The context in which to listen for the key
593-
Context string `yaml:"context" jsonschema:"enum=status,enum=files,enum=worktrees,enum=localBranches,enum=remotes,enum=remoteBranches,enum=tags,enum=commits,enum=reflogCommits,enum=subCommits,enum=commitFiles,enum=stash,enum=global"`
592+
// The contexts in which to listen for the key
593+
Contexts []string `yaml:"contexts" jsonschema:"enum=status,enum=files,enum=worktrees,enum=localBranches,enum=remotes,enum=remoteBranches,enum=tags,enum=commits,enum=reflogCommits,enum=subCommits,enum=commitFiles,enum=stash,enum=global"`
594594
// The command to run (using Go template syntax for placeholder values)
595595
Command string `yaml:"command" jsonschema:"example=git fetch {{.Form.Remote}} {{.Form.Branch}} && git checkout FETCH_HEAD"`
596596
// If true, run the command in a subprocess (e.g. if the command requires user input)

pkg/gui/services/custom_commands/client.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@ func (self *Client) GetCustomCommandKeybindings() ([]*types.Binding, error) {
3939
bindings := []*types.Binding{}
4040
for _, customCommand := range self.customCommands {
4141
handler := self.handlerCreator.call(customCommand)
42-
binding, err := self.keybindingCreator.call(customCommand, handler)
42+
compoundBindings, err := self.keybindingCreator.call(customCommand, handler)
4343
if err != nil {
4444
return nil, err
4545
}
46-
bindings = append(bindings, binding)
46+
bindings = append(bindings, compoundBindings...)
4747
}
4848

4949
return bindings, nil

pkg/gui/services/custom_commands/keybinding_creator.go

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ func NewKeybindingCreator(c *helpers.HelperCommon) *KeybindingCreator {
2424
}
2525
}
2626

27-
func (self *KeybindingCreator) call(customCommand config.CustomCommand, handler func() error) (*types.Binding, error) {
28-
if customCommand.Context == "" {
27+
func (self *KeybindingCreator) call(customCommand config.CustomCommand, handler func() error) ([]*types.Binding, error) {
28+
if customCommand.Contexts == nil || len(customCommand.Contexts) == 0 {
2929
return nil, formatContextNotProvidedError(customCommand)
3030
}
3131

32-
viewName, err := self.getViewNameAndContexts(customCommand)
32+
viewNames, err := self.getViewNamesAndContexts(customCommand)
3333
if err != nil {
3434
return nil, err
3535
}
@@ -39,27 +39,35 @@ func (self *KeybindingCreator) call(customCommand config.CustomCommand, handler
3939
description = customCommand.Command
4040
}
4141

42-
return &types.Binding{
43-
ViewName: viewName,
44-
Key: keybindings.GetKey(customCommand.Key),
45-
Modifier: gocui.ModNone,
46-
Handler: handler,
47-
Description: description,
48-
}, nil
42+
bindings := []*types.Binding{}
43+
for _, viewName := range viewNames {
44+
bindings = append(bindings, &types.Binding{
45+
ViewName: viewName,
46+
Key: keybindings.GetKey(customCommand.Key),
47+
Modifier: gocui.ModNone,
48+
Handler: handler,
49+
Description: description,
50+
})
51+
}
52+
return bindings, nil
4953
}
5054

51-
func (self *KeybindingCreator) getViewNameAndContexts(customCommand config.CustomCommand) (string, error) {
52-
if customCommand.Context == "global" {
53-
return "", nil
55+
func (self *KeybindingCreator) getViewNamesAndContexts(customCommand config.CustomCommand) ([]string, error) {
56+
if lo.Contains(customCommand.Contexts, "global") {
57+
return []string{}, nil
5458
}
5559

56-
ctx, ok := self.contextForContextKey(types.ContextKey(customCommand.Context))
57-
if !ok {
58-
return "", formatUnknownContextError(customCommand)
60+
viewNames := []string{}
61+
for _, context := range customCommand.Contexts {
62+
ctx, ok := self.contextForContextKey(types.ContextKey(context))
63+
if !ok {
64+
return []string{}, formatUnknownContextError(customCommand)
65+
}
66+
67+
viewNames = append(viewNames, ctx.GetViewName())
5968
}
6069

61-
viewName := ctx.GetViewName()
62-
return viewName, nil
70+
return viewNames, nil
6371
}
6472

6573
func (self *KeybindingCreator) contextForContextKey(contextKey types.ContextKey) (types.Context, bool) {
@@ -77,7 +85,7 @@ func formatUnknownContextError(customCommand config.CustomCommand) error {
7785
return string(key)
7886
})
7987

80-
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, ", "))
88+
return fmt.Errorf("Error when setting custom command keybindings: unknown context: %s. Key: %s, Command: %s.\nPermitted contexts: %s", strings.Join(customCommand.Contexts, ", "), customCommand.Key, customCommand.Command, strings.Join(allContextKeyStrings, ", "))
8189
}
8290

8391
func formatContextNotProvidedError(customCommand config.CustomCommand) error {

pkg/integration/tests/custom_commands/access_commit_properties.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ var AccessCommitProperties = NewIntegrationTest(NewIntegrationTestArgs{
1717
SetupConfig: func(cfg *config.AppConfig) {
1818
cfg.UserConfig.CustomCommands = []config.CustomCommand{
1919
{
20-
Key: "X",
21-
Context: "commits",
22-
Command: "printf '%s\n%s\n%s' '{{ .SelectedLocalCommit.Name }}' '{{ .SelectedLocalCommit.Hash }}' '{{ .SelectedLocalCommit.Sha }}' > file.txt",
20+
Key: "X",
21+
Contexts: []string{"commits"},
22+
Command: "printf '%s\n%s\n%s' '{{ .SelectedLocalCommit.Name }}' '{{ .SelectedLocalCommit.Hash }}' '{{ .SelectedLocalCommit.Sha }}' > file.txt",
2323
},
2424
}
2525
},

pkg/integration/tests/custom_commands/basic_cmd_from_config.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ var BasicCmdFromConfig = NewIntegrationTest(NewIntegrationTestArgs{
1515
SetupConfig: func(cfg *config.AppConfig) {
1616
cfg.UserConfig.CustomCommands = []config.CustomCommand{
1717
{
18-
Key: "a",
19-
Context: "files",
20-
Command: "touch myfile",
18+
Key: "a",
19+
Contexts: []string{"files"},
20+
Command: "touch myfile",
2121
},
2222
}
2323
},

pkg/integration/tests/custom_commands/check_for_conflicts.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ var CheckForConflicts = NewIntegrationTest(NewIntegrationTestArgs{
1616
SetupConfig: func(cfg *config.AppConfig) {
1717
cfg.UserConfig.CustomCommands = []config.CustomCommand{
1818
{
19-
Key: "m",
20-
Context: "localBranches",
21-
Command: "git merge {{ .SelectedLocalBranch.Name | quote }}",
19+
Key: "m",
20+
Contexts: []string{"localBranches"},
21+
Command: "git merge {{ .SelectedLocalBranch.Name | quote }}",
2222
After: config.CustomCommandAfterHook{
2323
CheckForConflicts: true,
2424
},

pkg/integration/tests/custom_commands/form_prompts.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ var FormPrompts = NewIntegrationTest(NewIntegrationTestArgs{
1515
SetupConfig: func(cfg *config.AppConfig) {
1616
cfg.UserConfig.CustomCommands = []config.CustomCommand{
1717
{
18-
Key: "a",
19-
Context: "files",
20-
Command: `echo {{.Form.FileContent | quote}} > {{.Form.FileName | quote}}`,
18+
Key: "a",
19+
Contexts: []string{"files"},
20+
Command: `echo {{.Form.FileContent | quote}} > {{.Form.FileName | quote}}`,
2121
Prompts: []config.CustomCommandPrompt{
2222
{
2323
Key: "FileName",

pkg/integration/tests/custom_commands/menu_from_command.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ var MenuFromCommand = NewIntegrationTest(NewIntegrationTestArgs{
2121
SetupConfig: func(cfg *config.AppConfig) {
2222
cfg.UserConfig.CustomCommands = []config.CustomCommand{
2323
{
24-
Key: "a",
25-
Context: "localBranches",
26-
Command: `echo "{{index .PromptResponses 0}} {{index .PromptResponses 1}} {{ .SelectedLocalBranch.Name }}" > output.txt`,
24+
Key: "a",
25+
Contexts: []string{"localBranches"},
26+
Command: `echo "{{index .PromptResponses 0}} {{index .PromptResponses 1}} {{ .SelectedLocalBranch.Name }}" > output.txt`,
2727
Prompts: []config.CustomCommandPrompt{
2828
{
2929
Type: "menuFromCommand",

pkg/integration/tests/custom_commands/menu_from_commands_output.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ var MenuFromCommandsOutput = NewIntegrationTest(NewIntegrationTestArgs{
2020
SetupConfig: func(cfg *config.AppConfig) {
2121
cfg.UserConfig.CustomCommands = []config.CustomCommand{
2222
{
23-
Key: "a",
24-
Context: "localBranches",
25-
Command: "git checkout {{ index .PromptResponses 1 }}",
23+
Key: "a",
24+
Contexts: []string{"localBranches"},
25+
Command: "git checkout {{ index .PromptResponses 1 }}",
2626
Prompts: []config.CustomCommandPrompt{
2727
{
2828
Type: "input",

pkg/integration/tests/custom_commands/multiple_prompts.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ var MultiplePrompts = NewIntegrationTest(NewIntegrationTestArgs{
1515
SetupConfig: func(cfg *config.AppConfig) {
1616
cfg.UserConfig.CustomCommands = []config.CustomCommand{
1717
{
18-
Key: "a",
19-
Context: "files",
20-
Command: `echo "{{index .PromptResponses 1}}" > {{index .PromptResponses 0}}`,
18+
Key: "a",
19+
Contexts: []string{"files"},
20+
Command: `echo "{{index .PromptResponses 1}}" > {{index .PromptResponses 0}}`,
2121
Prompts: []config.CustomCommandPrompt{
2222
{
2323
Type: "input",

0 commit comments

Comments
 (0)