diff --git a/docs/Custom_Command_Keybindings.md b/docs/Custom_Command_Keybindings.md index 423f5ecef..b940a7bb3 100644 --- a/docs/Custom_Command_Keybindings.md +++ b/docs/Custom_Command_Keybindings.md @@ -297,6 +297,7 @@ Your commands can contain placeholder strings using Go's [template syntax](https ``` SelectedCommit +SelectedCommitRange SelectedFile SelectedPath SelectedLocalBranch @@ -314,6 +315,11 @@ CheckedOutBranch 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). +We don't support accessing all elements of a range selection yet. We might add this in the future, but as a special case you can access the range of selected commits by using `SelectedCommitRange`, which has two properties `.To` and `.From` which are the hashes of the bottom and top selected commits, respectively. This is useful for passing them to a git command that operates on a range of commits. For example, to create patches for all selected commits, you might use +```yml + command: "git format-patch {{.SelectedCommitRange.From}}^..{{.SelectedCommitRange.To}}" +``` + ## Keybinding collisions If your custom keybinding collides with an inbuilt keybinding that is defined for the same context, only the custom keybinding will be executed. This also applies to the global context. However, one caveat is that if you have a custom keybinding defined on the global context for some key, and there is an in-built keybinding defined for the same key and for a specific context (say the 'files' context), then the in-built keybinding will take precedence. See how to change in-built keybindings [here](https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#keybindings) diff --git a/pkg/gui/services/custom_commands/session_state_loader.go b/pkg/gui/services/custom_commands/session_state_loader.go index cbd04bb14..8d6ef5b48 100644 --- a/pkg/gui/services/custom_commands/session_state_loader.go +++ b/pkg/gui/services/custom_commands/session_state_loader.go @@ -162,12 +162,29 @@ func worktreeShimFromModelRemote(worktree *models.Worktree) *Worktree { } } +type CommitRange struct { + From string + To string +} + +func makeCommitRange(commits []*models.Commit, _ int, _ int) *CommitRange { + if len(commits) == 0 { + return nil + } + + return &CommitRange{ + From: commits[len(commits)-1].Hash, + To: commits[0].Hash, + } +} + // SessionState captures the current state of the application for use in custom commands type SessionState struct { SelectedLocalCommit *Commit // deprecated, use SelectedCommit SelectedReflogCommit *Commit // deprecated, use SelectedCommit SelectedSubCommit *Commit // deprecated, use SelectedCommit SelectedCommit *Commit + SelectedCommitRange *CommitRange SelectedFile *File SelectedPath string SelectedLocalBranch *Branch @@ -183,14 +200,20 @@ type SessionState struct { func (self *SessionStateLoader) call() *SessionState { selectedLocalCommit := commitShimFromModelCommit(self.c.Contexts().LocalCommits.GetSelected()) + selectedLocalCommitRange := makeCommitRange(self.c.Contexts().LocalCommits.GetSelectedItems()) selectedReflogCommit := commitShimFromModelCommit(self.c.Contexts().ReflogCommits.GetSelected()) + selectedReflogCommitRange := makeCommitRange(self.c.Contexts().ReflogCommits.GetSelectedItems()) selectedSubCommit := commitShimFromModelCommit(self.c.Contexts().SubCommits.GetSelected()) + selectedSubCommitRange := makeCommitRange(self.c.Contexts().SubCommits.GetSelectedItems()) selectedCommit := selectedLocalCommit + selectedCommitRange := selectedLocalCommitRange if self.c.Context().IsCurrentOrParent(self.c.Contexts().ReflogCommits) { selectedCommit = selectedReflogCommit + selectedCommitRange = selectedReflogCommitRange } else if self.c.Context().IsCurrentOrParent(self.c.Contexts().SubCommits) { selectedCommit = selectedSubCommit + selectedCommitRange = selectedSubCommitRange } selectedPath := self.c.Contexts().Files.GetSelectedPath() @@ -207,6 +230,7 @@ func (self *SessionStateLoader) call() *SessionState { SelectedReflogCommit: selectedReflogCommit, SelectedSubCommit: selectedSubCommit, SelectedCommit: selectedCommit, + SelectedCommitRange: selectedCommitRange, SelectedLocalBranch: branchShimFromModelBranch(self.c.Contexts().Branches.GetSelected()), SelectedRemoteBranch: remoteBranchShimFromModelRemoteBranch(self.c.Contexts().RemoteBranches.GetSelected()), SelectedRemote: remoteShimFromModelRemote(self.c.Contexts().Remotes.GetSelected()), diff --git a/pkg/integration/tests/custom_commands/selected_commit_range.go b/pkg/integration/tests/custom_commands/selected_commit_range.go new file mode 100644 index 000000000..1a4b3087c --- /dev/null +++ b/pkg/integration/tests/custom_commands/selected_commit_range.go @@ -0,0 +1,41 @@ +package custom_commands + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var SelectedCommitRange = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Use the {{ .SelectedCommitRange }} template variable", + ExtraCmdArgs: []string{}, + Skip: false, + SetupRepo: func(shell *Shell) { + shell.CreateNCommits(3) + }, + SetupConfig: func(cfg *config.AppConfig) { + cfg.GetUserConfig().CustomCommands = []config.CustomCommand{ + { + Key: "X", + Context: "global", + Command: `git log --format="%s" {{.SelectedCommitRange.From}}^..{{.SelectedCommitRange.To}} > file.txt`, + }, + } + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + t.Views().Commits().Focus(). + Lines( + Contains("commit 03").IsSelected(), + Contains("commit 02"), + Contains("commit 01"), + ) + + t.GlobalPress("X") + t.FileSystem().FileContent("file.txt", Equals("commit 03\n")) + + t.Views().Commits().Focus(). + Press(keys.Universal.RangeSelectDown) + + t.GlobalPress("X") + t.FileSystem().FileContent("file.txt", Equals("commit 03\ncommit 02\n")) + }, +}) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index a6825676a..0736677a8 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -139,6 +139,7 @@ var tests = []*components.IntegrationTest{ custom_commands.MultipleContexts, custom_commands.MultiplePrompts, custom_commands.SelectedCommit, + custom_commands.SelectedCommitRange, custom_commands.SelectedPath, custom_commands.ShowOutputInPanel, custom_commands.SuggestionsCommand,