Expose SelectedCommit to custom commands, deprecate Selected{Local,Reflog,Sub}Commit

SelectedCommit is context-dependent and points to SelectedLocalCommit,
SelectedReflogCommit, or SelectedSubCommit depending on which panel is active.

If none of these panels is active, it returns the selected local commit, which
is probably the most useful default (e.g. when defining custom commands for the
Files panel).
This commit is contained in:
Stefan Haller 2024-06-28 17:13:59 +02:00
parent 1cb29cea15
commit 22f0d9cdd3
6 changed files with 104 additions and 9 deletions

View file

@ -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: 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 SelectedCommit
SelectedReflogCommit
SelectedSubCommit
SelectedFile SelectedFile
SelectedPath SelectedPath
SelectedLocalBranch SelectedLocalBranch
@ -311,6 +309,9 @@ SelectedWorktree
CheckedOutBranch 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). 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 ## Keybinding collisions

View file

@ -300,6 +300,18 @@ func (self *ContextMgr) IsCurrent(c types.Context) bool {
return self.Current().GetKey() == c.GetKey() 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 { func (self *ContextMgr) AllFilterable() []types.IFilterableContext {
var result []types.IFilterableContext var result []types.IFilterableContext

View file

@ -164,9 +164,10 @@ func worktreeShimFromModelRemote(worktree *models.Worktree) *Worktree {
// SessionState captures the current state of the application for use in custom commands // SessionState captures the current state of the application for use in custom commands
type SessionState struct { type SessionState struct {
SelectedLocalCommit *Commit SelectedLocalCommit *Commit // deprecated, use SelectedCommit
SelectedReflogCommit *Commit SelectedReflogCommit *Commit // deprecated, use SelectedCommit
SelectedSubCommit *Commit SelectedSubCommit *Commit // deprecated, use SelectedCommit
SelectedCommit *Commit
SelectedFile *File SelectedFile *File
SelectedPath string SelectedPath string
SelectedLocalBranch *Branch SelectedLocalBranch *Branch
@ -181,11 +182,24 @@ type SessionState struct {
} }
func (self *SessionStateLoader) call() *SessionState { 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
}
return &SessionState{ return &SessionState{
SelectedFile: fileShimFromModelFile(self.c.Contexts().Files.GetSelectedFile()), SelectedFile: fileShimFromModelFile(self.c.Contexts().Files.GetSelectedFile()),
SelectedPath: self.c.Contexts().Files.GetSelectedPath(), SelectedPath: self.c.Contexts().Files.GetSelectedPath(),
SelectedLocalCommit: commitShimFromModelCommit(self.c.Contexts().LocalCommits.GetSelected()), SelectedLocalCommit: selectedLocalCommit,
SelectedReflogCommit: commitShimFromModelCommit(self.c.Contexts().ReflogCommits.GetSelected()), SelectedReflogCommit: selectedReflogCommit,
SelectedSubCommit: selectedSubCommit,
SelectedCommit: selectedCommit,
SelectedLocalBranch: branchShimFromModelBranch(self.c.Contexts().Branches.GetSelected()), SelectedLocalBranch: branchShimFromModelBranch(self.c.Contexts().Branches.GetSelected()),
SelectedRemoteBranch: remoteBranchShimFromModelRemoteBranch(self.c.Contexts().RemoteBranches.GetSelected()), SelectedRemoteBranch: remoteBranchShimFromModelRemoteBranch(self.c.Contexts().RemoteBranches.GetSelected()),
SelectedRemote: remoteShimFromModelRemote(self.c.Contexts().Remotes.GetSelected()), SelectedRemote: remoteShimFromModelRemote(self.c.Contexts().Remotes.GetSelected()),
@ -193,7 +207,6 @@ func (self *SessionStateLoader) call() *SessionState {
SelectedStashEntry: stashEntryShimFromModelRemote(self.c.Contexts().Stash.GetSelected()), SelectedStashEntry: stashEntryShimFromModelRemote(self.c.Contexts().Stash.GetSelected()),
SelectedCommitFile: commitFileShimFromModelRemote(self.c.Contexts().CommitFiles.GetSelectedFile()), SelectedCommitFile: commitFileShimFromModelRemote(self.c.Contexts().CommitFiles.GetSelectedFile()),
SelectedCommitFilePath: self.c.Contexts().CommitFiles.GetSelectedPath(), SelectedCommitFilePath: self.c.Contexts().CommitFiles.GetSelectedPath(),
SelectedSubCommit: commitShimFromModelCommit(self.c.Contexts().SubCommits.GetSelected()),
SelectedWorktree: worktreeShimFromModelRemote(self.c.Contexts().Worktrees.GetSelected()), SelectedWorktree: worktreeShimFromModelRemote(self.c.Contexts().Worktrees.GetSelected()),
CheckedOutBranch: branchShimFromModelBranch(self.refsHelper.GetCheckedOutRef()), CheckedOutBranch: branchShimFromModelBranch(self.refsHelper.GetCheckedOutRef()),
} }

View file

@ -284,6 +284,7 @@ type IContextMgr interface {
CurrentSide() Context CurrentSide() Context
CurrentPopup() []Context CurrentPopup() []Context
IsCurrent(c Context) bool IsCurrent(c Context) bool
IsCurrentOrParent(c Context) bool
ForEach(func(Context)) ForEach(func(Context))
AllList() []IListContext AllList() []IListContext
AllFilterable() []IFilterableContext AllFilterable() []IFilterableContext

View 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"))
},
})

View file

@ -124,6 +124,7 @@ var tests = []*components.IntegrationTest{
custom_commands.MenuFromCommandsOutput, custom_commands.MenuFromCommandsOutput,
custom_commands.MultipleContexts, custom_commands.MultipleContexts,
custom_commands.MultiplePrompts, custom_commands.MultiplePrompts,
custom_commands.SelectedCommit,
custom_commands.ShowOutputInPanel, custom_commands.ShowOutputInPanel,
custom_commands.SuggestionsCommand, custom_commands.SuggestionsCommand,
custom_commands.SuggestionsPreset, custom_commands.SuggestionsPreset,