mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-08-08 22:36:49 +02:00
Improve template placeholders for custom commands (#3809)
- **PR Description** Improve the template placeholders that are available for custom commands: - `SelectedCommit` replaces `SelectedLocalCommit`, `SelectedReflogCommit`, and `SelectedSubCommit` - `SelectedPath` is set to `SelectedCommitFilePath` when the CommitFiles context is active It still slightly bothers me that we don't make a similar unification for `SelectedLocalBranch` and `SelectedRemoteBranch` (and others), but it would be a bigger change to do that, and we decided in #3663 not to. Fixes #3663.
This commit is contained in:
@@ -296,9 +296,7 @@ Here's an example using a command but not specifying anything else: so each line
|
||||
Your commands can contain placeholder strings using Go's [template syntax](https://jan.newmarch.name/golang/template/chapter-template.html). The template syntax is pretty powerful, letting you do things like conditionals if you want, but for the most part you'll simply want to be accessing the fields on the following objects:
|
||||
|
||||
```
|
||||
SelectedLocalCommit
|
||||
SelectedReflogCommit
|
||||
SelectedSubCommit
|
||||
SelectedCommit
|
||||
SelectedFile
|
||||
SelectedPath
|
||||
SelectedLocalBranch
|
||||
@@ -311,6 +309,9 @@ SelectedWorktree
|
||||
CheckedOutBranch
|
||||
```
|
||||
|
||||
(For legacy reasons, `SelectedLocalCommit`, `SelectedReflogCommit`, and `SelectedSubCommit` are also available, but they are deprecated.)
|
||||
|
||||
|
||||
To see what fields are available on e.g. the `SelectedFile`, see [here](https://github.com/jesseduffield/lazygit/blob/master/pkg/gui/services/custom_commands/models.go) (all the modelling lives in the same file).
|
||||
|
||||
## Keybinding collisions
|
||||
|
@@ -300,6 +300,18 @@ func (self *ContextMgr) IsCurrent(c types.Context) bool {
|
||||
return self.Current().GetKey() == c.GetKey()
|
||||
}
|
||||
|
||||
func (self *ContextMgr) IsCurrentOrParent(c types.Context) bool {
|
||||
current := self.Current()
|
||||
for current != nil {
|
||||
if current.GetKey() == c.GetKey() {
|
||||
return true
|
||||
}
|
||||
current = current.GetParentContext()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *ContextMgr) AllFilterable() []types.IFilterableContext {
|
||||
var result []types.IFilterableContext
|
||||
|
||||
|
@@ -164,9 +164,10 @@ func worktreeShimFromModelRemote(worktree *models.Worktree) *Worktree {
|
||||
|
||||
// SessionState captures the current state of the application for use in custom commands
|
||||
type SessionState struct {
|
||||
SelectedLocalCommit *Commit
|
||||
SelectedReflogCommit *Commit
|
||||
SelectedSubCommit *Commit
|
||||
SelectedLocalCommit *Commit // deprecated, use SelectedCommit
|
||||
SelectedReflogCommit *Commit // deprecated, use SelectedCommit
|
||||
SelectedSubCommit *Commit // deprecated, use SelectedCommit
|
||||
SelectedCommit *Commit
|
||||
SelectedFile *File
|
||||
SelectedPath string
|
||||
SelectedLocalBranch *Branch
|
||||
@@ -181,19 +182,38 @@ type SessionState struct {
|
||||
}
|
||||
|
||||
func (self *SessionStateLoader) call() *SessionState {
|
||||
selectedLocalCommit := commitShimFromModelCommit(self.c.Contexts().LocalCommits.GetSelected())
|
||||
selectedReflogCommit := commitShimFromModelCommit(self.c.Contexts().ReflogCommits.GetSelected())
|
||||
selectedSubCommit := commitShimFromModelCommit(self.c.Contexts().SubCommits.GetSelected())
|
||||
|
||||
selectedCommit := selectedLocalCommit
|
||||
if self.c.Context().IsCurrentOrParent(self.c.Contexts().ReflogCommits) {
|
||||
selectedCommit = selectedReflogCommit
|
||||
} else if self.c.Context().IsCurrentOrParent(self.c.Contexts().SubCommits) {
|
||||
selectedCommit = selectedSubCommit
|
||||
}
|
||||
|
||||
selectedPath := self.c.Contexts().Files.GetSelectedPath()
|
||||
selectedCommitFilePath := self.c.Contexts().CommitFiles.GetSelectedPath()
|
||||
|
||||
if self.c.Context().IsCurrent(self.c.Contexts().CommitFiles) {
|
||||
selectedPath = selectedCommitFilePath
|
||||
}
|
||||
|
||||
return &SessionState{
|
||||
SelectedFile: fileShimFromModelFile(self.c.Contexts().Files.GetSelectedFile()),
|
||||
SelectedPath: self.c.Contexts().Files.GetSelectedPath(),
|
||||
SelectedLocalCommit: commitShimFromModelCommit(self.c.Contexts().LocalCommits.GetSelected()),
|
||||
SelectedReflogCommit: commitShimFromModelCommit(self.c.Contexts().ReflogCommits.GetSelected()),
|
||||
SelectedPath: selectedPath,
|
||||
SelectedLocalCommit: selectedLocalCommit,
|
||||
SelectedReflogCommit: selectedReflogCommit,
|
||||
SelectedSubCommit: selectedSubCommit,
|
||||
SelectedCommit: selectedCommit,
|
||||
SelectedLocalBranch: branchShimFromModelBranch(self.c.Contexts().Branches.GetSelected()),
|
||||
SelectedRemoteBranch: remoteBranchShimFromModelRemoteBranch(self.c.Contexts().RemoteBranches.GetSelected()),
|
||||
SelectedRemote: remoteShimFromModelRemote(self.c.Contexts().Remotes.GetSelected()),
|
||||
SelectedTag: tagShimFromModelRemote(self.c.Contexts().Tags.GetSelected()),
|
||||
SelectedStashEntry: stashEntryShimFromModelRemote(self.c.Contexts().Stash.GetSelected()),
|
||||
SelectedCommitFile: commitFileShimFromModelRemote(self.c.Contexts().CommitFiles.GetSelectedFile()),
|
||||
SelectedCommitFilePath: self.c.Contexts().CommitFiles.GetSelectedPath(),
|
||||
SelectedSubCommit: commitShimFromModelCommit(self.c.Contexts().SubCommits.GetSelected()),
|
||||
SelectedCommitFilePath: selectedCommitFilePath,
|
||||
SelectedWorktree: worktreeShimFromModelRemote(self.c.Contexts().Worktrees.GetSelected()),
|
||||
CheckedOutBranch: branchShimFromModelBranch(self.refsHelper.GetCheckedOutRef()),
|
||||
}
|
||||
|
@@ -284,6 +284,7 @@ type IContextMgr interface {
|
||||
CurrentSide() Context
|
||||
CurrentPopup() []Context
|
||||
IsCurrent(c Context) bool
|
||||
IsCurrentOrParent(c Context) bool
|
||||
ForEach(func(Context))
|
||||
AllList() []IListContext
|
||||
AllFilterable() []IFilterableContext
|
||||
|
67
pkg/integration/tests/custom_commands/selected_commit.go
Normal file
67
pkg/integration/tests/custom_commands/selected_commit.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package custom_commands
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var SelectedCommit = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Use the {{ .SelectedCommit }} template variable in different contexts",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.CreateNCommits(3)
|
||||
},
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.UserConfig.CustomCommands = []config.CustomCommand{
|
||||
{
|
||||
Key: "X",
|
||||
Context: "global",
|
||||
Command: "printf '%s' '{{ .SelectedCommit.Name }}' > file.txt",
|
||||
},
|
||||
}
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
// Select different commits in each of the commit views
|
||||
t.Views().Commits().Focus().
|
||||
NavigateToLine(Contains("commit 01"))
|
||||
t.Views().ReflogCommits().Focus().
|
||||
NavigateToLine(Contains("commit 02"))
|
||||
t.Views().Branches().Focus().
|
||||
Lines(Contains("master").IsSelected()).
|
||||
PressEnter()
|
||||
t.Views().SubCommits().IsFocused().
|
||||
NavigateToLine(Contains("commit 03"))
|
||||
|
||||
// SubCommits
|
||||
t.GlobalPress("X")
|
||||
t.FileSystem().FileContent("file.txt", Equals("commit 03"))
|
||||
|
||||
t.Views().SubCommits().PressEnter()
|
||||
t.GlobalPress("X")
|
||||
t.FileSystem().FileContent("file.txt", Equals("commit 03"))
|
||||
|
||||
// ReflogCommits
|
||||
t.Views().ReflogCommits().Focus()
|
||||
t.GlobalPress("X")
|
||||
t.FileSystem().FileContent("file.txt", Equals("commit: commit 02"))
|
||||
|
||||
t.Views().ReflogCommits().PressEnter()
|
||||
t.GlobalPress("X")
|
||||
t.FileSystem().FileContent("file.txt", Equals("commit: commit 02"))
|
||||
|
||||
// LocalCommits
|
||||
t.Views().Commits().Focus()
|
||||
t.GlobalPress("X")
|
||||
t.FileSystem().FileContent("file.txt", Equals("commit 01"))
|
||||
|
||||
t.Views().Commits().PressEnter()
|
||||
t.GlobalPress("X")
|
||||
t.FileSystem().FileContent("file.txt", Equals("commit 01"))
|
||||
|
||||
// None of these
|
||||
t.Views().Files().Focus()
|
||||
t.GlobalPress("X")
|
||||
t.FileSystem().FileContent("file.txt", Equals("commit 01"))
|
||||
},
|
||||
})
|
44
pkg/integration/tests/custom_commands/selected_path.go
Normal file
44
pkg/integration/tests/custom_commands/selected_path.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package custom_commands
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var SelectedPath = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Use the {{ .SelectedPath }} template variable in different contexts",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.CreateDir("folder1")
|
||||
shell.CreateFileAndAdd("folder1/file1", "")
|
||||
shell.Commit("commit")
|
||||
shell.CreateDir("folder2")
|
||||
shell.CreateFile("folder2/file2", "")
|
||||
},
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.UserConfig.CustomCommands = []config.CustomCommand{
|
||||
{
|
||||
Key: "X",
|
||||
Context: "global",
|
||||
Command: "printf '%s' '{{ .SelectedPath }}' > file.txt",
|
||||
},
|
||||
}
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Files().
|
||||
Focus().
|
||||
NavigateToLine(Contains("file2"))
|
||||
t.GlobalPress("X")
|
||||
t.FileSystem().FileContent("file.txt", Equals("folder2/file2"))
|
||||
|
||||
t.Views().Commits().
|
||||
Focus().
|
||||
PressEnter()
|
||||
t.Views().CommitFiles().
|
||||
IsFocused().
|
||||
NavigateToLine(Contains("file1"))
|
||||
t.GlobalPress("X")
|
||||
t.FileSystem().FileContent("file.txt", Equals("folder1/file1"))
|
||||
},
|
||||
})
|
@@ -124,6 +124,8 @@ var tests = []*components.IntegrationTest{
|
||||
custom_commands.MenuFromCommandsOutput,
|
||||
custom_commands.MultipleContexts,
|
||||
custom_commands.MultiplePrompts,
|
||||
custom_commands.SelectedCommit,
|
||||
custom_commands.SelectedPath,
|
||||
custom_commands.ShowOutputInPanel,
|
||||
custom_commands.SuggestionsCommand,
|
||||
custom_commands.SuggestionsPreset,
|
||||
|
Reference in New Issue
Block a user