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:
commit
74fe069da9
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
61
pkg/integration/tests/custom_commands/global_context.go
Normal file
61
pkg/integration/tests/custom_commands/global_context.go
Normal 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")
|
||||
},
|
||||
})
|
58
pkg/integration/tests/custom_commands/multiple_contexts.go
Normal file
58
pkg/integration/tests/custom_commands/multiple_contexts.go
Normal 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")
|
||||
},
|
||||
})
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user