1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-04-23 12:18:51 +02:00

feat(custom command): support multiple contexts within one command (#3784)

- **PR Description**

For some custom commands, they can be used in multiple contexts. But for
now, if we want to do this, we should copy and paste the same config
times and times with just a different **context**.

Related issue: #3759 

This PR makes it possible to use multiple contexts in the `context` field of 
`customCommand`, separated by comma.
This commit is contained in:
Stefan Haller 2024-08-02 11:59:39 +02:00 committed by GitHub
commit 74fe069da9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 155 additions and 18 deletions

View File

@ -87,6 +87,11 @@ The permitted contexts are:
| stash | The 'Stash' tab |
| global | This keybinding will take affect everywhere |
> **Bonus**
>
> You can use a comma-separated string, such as `context: 'commits, subCommits'`, to make it effective in multiple contexts.
## Prompts
### Common fields

View File

@ -39,11 +39,11 @@ func (self *Client) GetCustomCommandKeybindings() ([]*types.Binding, error) {
bindings := []*types.Binding{}
for _, customCommand := range self.customCommands {
handler := self.handlerCreator.call(customCommand)
binding, err := self.keybindingCreator.call(customCommand, handler)
compoundBindings, err := self.keybindingCreator.call(customCommand, handler)
if err != nil {
return nil, err
}
bindings = append(bindings, binding)
bindings = append(bindings, compoundBindings...)
}
return bindings, nil

View File

@ -24,12 +24,12 @@ func NewKeybindingCreator(c *helpers.HelperCommon) *KeybindingCreator {
}
}
func (self *KeybindingCreator) call(customCommand config.CustomCommand, handler func() error) (*types.Binding, error) {
func (self *KeybindingCreator) call(customCommand config.CustomCommand, handler func() error) ([]*types.Binding, error) {
if customCommand.Context == "" {
return nil, formatContextNotProvidedError(customCommand)
}
viewName, err := self.getViewNameAndContexts(customCommand)
viewNames, err := self.getViewNamesAndContexts(customCommand)
if err != nil {
return nil, err
}
@ -39,27 +39,38 @@ func (self *KeybindingCreator) call(customCommand config.CustomCommand, handler
description = customCommand.Command
}
return &types.Binding{
ViewName: viewName,
Key: keybindings.GetKey(customCommand.Key),
Modifier: gocui.ModNone,
Handler: handler,
Description: description,
}, nil
return lo.Map(viewNames, func(viewName string, _ int) *types.Binding {
return &types.Binding{
ViewName: viewName,
Key: keybindings.GetKey(customCommand.Key),
Modifier: gocui.ModNone,
Handler: handler,
Description: description,
}
}), nil
}
func (self *KeybindingCreator) getViewNameAndContexts(customCommand config.CustomCommand) (string, error) {
func (self *KeybindingCreator) getViewNamesAndContexts(customCommand config.CustomCommand) ([]string, error) {
if customCommand.Context == "global" {
return "", nil
return []string{""}, nil
}
ctx, ok := self.contextForContextKey(types.ContextKey(customCommand.Context))
if !ok {
return "", formatUnknownContextError(customCommand)
contexts := strings.Split(customCommand.Context, ",")
contexts = lo.Map(contexts, func(context string, _ int) string {
return strings.TrimSpace(context)
})
viewNames := []string{}
for _, context := range contexts {
ctx, ok := self.contextForContextKey(types.ContextKey(context))
if !ok {
return []string{}, formatUnknownContextError(customCommand)
}
viewNames = append(viewNames, ctx.GetViewName())
}
viewName := ctx.GetViewName()
return viewName, nil
return viewNames, nil
}
func (self *KeybindingCreator) contextForContextKey(contextKey types.ContextKey) (types.Context, bool) {

View File

@ -0,0 +1,61 @@
package custom_commands
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var GlobalContext = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Ensure global context works",
ExtraCmdArgs: []string{},
Skip: false,
SetupRepo: func(shell *Shell) {
shell.EmptyCommit("my change")
},
SetupConfig: func(cfg *config.AppConfig) {
cfg.UserConfig.CustomCommands = []config.CustomCommand{
{
Key: "X",
Context: "global",
Command: "touch myfile",
ShowOutput: false,
},
}
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
// commits
t.Views().Commits().
Focus().
Press("X")
t.Views().Files().
Focus().
Lines(Contains("myfile"))
t.Shell().DeleteFile("myfile")
t.GlobalPress(keys.Files.RefreshFiles)
// branches
t.Views().Branches().
Focus().
Press("X")
t.Views().Files().
Focus().
Lines(Contains("myfile"))
t.Shell().DeleteFile("myfile")
t.GlobalPress(keys.Files.RefreshFiles)
// files
t.Views().Files().
Focus().
Press("X")
t.Views().Files().
Focus().
Lines(Contains("myfile"))
t.Shell().DeleteFile("myfile")
},
})

View File

@ -0,0 +1,58 @@
package custom_commands
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var MultipleContexts = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Test that multiple contexts works",
ExtraCmdArgs: []string{},
Skip: false,
SetupRepo: func(shell *Shell) {
shell.EmptyCommit("my change")
},
SetupConfig: func(cfg *config.AppConfig) {
cfg.UserConfig.CustomCommands = []config.CustomCommand{
{
Key: "X",
Context: "commits, reflogCommits",
Command: "touch myfile",
ShowOutput: false,
},
}
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
// commits
t.Views().Commits().
Focus().
Press("X")
t.Views().Files().
Focus().
Lines(Contains("myfile"))
t.Shell().DeleteFile("myfile")
t.GlobalPress(keys.Files.RefreshFiles)
// branches
t.Views().Branches().
Focus().
Press("X")
t.Views().Files().
Focus().
IsEmpty()
// files
t.Views().ReflogCommits().
Focus().
Press("X")
t.Views().Files().
Focus().
Lines(Contains("myfile"))
t.Shell().DeleteFile("myfile")
},
})

View File

@ -122,9 +122,11 @@ var tests = []*components.IntegrationTest{
custom_commands.DeleteFromHistory,
custom_commands.EditHistory,
custom_commands.FormPrompts,
custom_commands.GlobalContext,
custom_commands.History,
custom_commands.MenuFromCommand,
custom_commands.MenuFromCommandsOutput,
custom_commands.MultipleContexts,
custom_commands.MultiplePrompts,
custom_commands.OmitFromHistory,
custom_commands.ShowOutputInPanel,