From 22f0d9cdd37e25124a2693dc8219503657fd21b2 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Fri, 28 Jun 2024 17:13:59 +0200 Subject: [PATCH] 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). --- docs/Custom_Command_Keybindings.md | 7 +- pkg/gui/context.go | 12 ++++ .../custom_commands/session_state_loader.go | 25 +++++-- pkg/gui/types/context.go | 1 + .../tests/custom_commands/selected_commit.go | 67 +++++++++++++++++++ pkg/integration/tests/test_list.go | 1 + 6 files changed, 104 insertions(+), 9 deletions(-) create mode 100644 pkg/integration/tests/custom_commands/selected_commit.go diff --git a/docs/Custom_Command_Keybindings.md b/docs/Custom_Command_Keybindings.md index dd7c11af7..432625693 100644 --- a/docs/Custom_Command_Keybindings.md +++ b/docs/Custom_Command_Keybindings.md @@ -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 diff --git a/pkg/gui/context.go b/pkg/gui/context.go index abb7cb6ee..3ac1425fb 100644 --- a/pkg/gui/context.go +++ b/pkg/gui/context.go @@ -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 diff --git a/pkg/gui/services/custom_commands/session_state_loader.go b/pkg/gui/services/custom_commands/session_state_loader.go index 6f39c5f8c..a0e486f13 100644 --- a/pkg/gui/services/custom_commands/session_state_loader.go +++ b/pkg/gui/services/custom_commands/session_state_loader.go @@ -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,11 +182,24 @@ 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 + } + 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()), + 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()), @@ -193,7 +207,6 @@ func (self *SessionStateLoader) call() *SessionState { 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()), SelectedWorktree: worktreeShimFromModelRemote(self.c.Contexts().Worktrees.GetSelected()), CheckedOutBranch: branchShimFromModelBranch(self.refsHelper.GetCheckedOutRef()), } diff --git a/pkg/gui/types/context.go b/pkg/gui/types/context.go index 49a6e6e35..2948f2eda 100644 --- a/pkg/gui/types/context.go +++ b/pkg/gui/types/context.go @@ -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 diff --git a/pkg/integration/tests/custom_commands/selected_commit.go b/pkg/integration/tests/custom_commands/selected_commit.go new file mode 100644 index 000000000..0dda19546 --- /dev/null +++ b/pkg/integration/tests/custom_commands/selected_commit.go @@ -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")) + }, +}) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index c1038ee2a..64123ff05 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -124,6 +124,7 @@ var tests = []*components.IntegrationTest{ custom_commands.MenuFromCommandsOutput, custom_commands.MultipleContexts, custom_commands.MultiplePrompts, + custom_commands.SelectedCommit, custom_commands.ShowOutputInPanel, custom_commands.SuggestionsCommand, custom_commands.SuggestionsPreset,