Skip to content

Commit 5523680

Browse files
authored
Expose {{.SelectedCommitRange}} to custom commands (#4204)
- **PR Description** Expose `{{.SelectedCommitRange}}` to custom commands. It has fields .To and .From (the hashes of the last and the first selected commits, respectively), and it is useful for creating git commands that act on a range of commits. Fixes #4184. - **Please check if the PR fulfills these requirements** * [x] Cheatsheets are up-to-date (run `go generate ./...`) * [x] Code has been formatted (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#code-formatting)) * [x] Tests have been added/updated (see [here](https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md) for the integration test guide) * [ ] Text is internationalised (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#internationalisation)) * [ ] If a new UserConfig entry was added, make sure it can be hot-reloaded (see [here](https://github.com/jesseduffield/lazygit/blob/master/docs/dev/Codebase_Guide.md#using-userconfig)) * [x] Docs have been updated if necessary * [x] You've read through your own file changes for silly mistakes etc
2 parents d768327 + 4baf008 commit 5523680

File tree

4 files changed

+72
-0
lines changed

4 files changed

+72
-0
lines changed

docs/Custom_Command_Keybindings.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ Your commands can contain placeholder strings using Go's [template syntax](https
297297

298298
```
299299
SelectedCommit
300+
SelectedCommitRange
300301
SelectedFile
301302
SelectedPath
302303
SelectedLocalBranch
@@ -314,6 +315,11 @@ CheckedOutBranch
314315

315316
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).
316317

318+
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
319+
```yml
320+
command: "git format-patch {{.SelectedCommitRange.From}}^..{{.SelectedCommitRange.To}}"
321+
```
322+
317323
## Keybinding collisions
318324

319325
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)

pkg/gui/services/custom_commands/session_state_loader.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,29 @@ func worktreeShimFromModelRemote(worktree *models.Worktree) *Worktree {
162162
}
163163
}
164164

165+
type CommitRange struct {
166+
From string
167+
To string
168+
}
169+
170+
func makeCommitRange(commits []*models.Commit, _ int, _ int) *CommitRange {
171+
if len(commits) == 0 {
172+
return nil
173+
}
174+
175+
return &CommitRange{
176+
From: commits[len(commits)-1].Hash,
177+
To: commits[0].Hash,
178+
}
179+
}
180+
165181
// SessionState captures the current state of the application for use in custom commands
166182
type SessionState struct {
167183
SelectedLocalCommit *Commit // deprecated, use SelectedCommit
168184
SelectedReflogCommit *Commit // deprecated, use SelectedCommit
169185
SelectedSubCommit *Commit // deprecated, use SelectedCommit
170186
SelectedCommit *Commit
187+
SelectedCommitRange *CommitRange
171188
SelectedFile *File
172189
SelectedPath string
173190
SelectedLocalBranch *Branch
@@ -183,14 +200,20 @@ type SessionState struct {
183200

184201
func (self *SessionStateLoader) call() *SessionState {
185202
selectedLocalCommit := commitShimFromModelCommit(self.c.Contexts().LocalCommits.GetSelected())
203+
selectedLocalCommitRange := makeCommitRange(self.c.Contexts().LocalCommits.GetSelectedItems())
186204
selectedReflogCommit := commitShimFromModelCommit(self.c.Contexts().ReflogCommits.GetSelected())
205+
selectedReflogCommitRange := makeCommitRange(self.c.Contexts().ReflogCommits.GetSelectedItems())
187206
selectedSubCommit := commitShimFromModelCommit(self.c.Contexts().SubCommits.GetSelected())
207+
selectedSubCommitRange := makeCommitRange(self.c.Contexts().SubCommits.GetSelectedItems())
188208

189209
selectedCommit := selectedLocalCommit
210+
selectedCommitRange := selectedLocalCommitRange
190211
if self.c.Context().IsCurrentOrParent(self.c.Contexts().ReflogCommits) {
191212
selectedCommit = selectedReflogCommit
213+
selectedCommitRange = selectedReflogCommitRange
192214
} else if self.c.Context().IsCurrentOrParent(self.c.Contexts().SubCommits) {
193215
selectedCommit = selectedSubCommit
216+
selectedCommitRange = selectedSubCommitRange
194217
}
195218

196219
selectedPath := self.c.Contexts().Files.GetSelectedPath()
@@ -207,6 +230,7 @@ func (self *SessionStateLoader) call() *SessionState {
207230
SelectedReflogCommit: selectedReflogCommit,
208231
SelectedSubCommit: selectedSubCommit,
209232
SelectedCommit: selectedCommit,
233+
SelectedCommitRange: selectedCommitRange,
210234
SelectedLocalBranch: branchShimFromModelBranch(self.c.Contexts().Branches.GetSelected()),
211235
SelectedRemoteBranch: remoteBranchShimFromModelRemoteBranch(self.c.Contexts().RemoteBranches.GetSelected()),
212236
SelectedRemote: remoteShimFromModelRemote(self.c.Contexts().Remotes.GetSelected()),
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package custom_commands
2+
3+
import (
4+
"github.com/jesseduffield/lazygit/pkg/config"
5+
. "github.com/jesseduffield/lazygit/pkg/integration/components"
6+
)
7+
8+
var SelectedCommitRange = NewIntegrationTest(NewIntegrationTestArgs{
9+
Description: "Use the {{ .SelectedCommitRange }} template variable",
10+
ExtraCmdArgs: []string{},
11+
Skip: false,
12+
SetupRepo: func(shell *Shell) {
13+
shell.CreateNCommits(3)
14+
},
15+
SetupConfig: func(cfg *config.AppConfig) {
16+
cfg.GetUserConfig().CustomCommands = []config.CustomCommand{
17+
{
18+
Key: "X",
19+
Context: "global",
20+
Command: `git log --format="%s" {{.SelectedCommitRange.From}}^..{{.SelectedCommitRange.To}} > file.txt`,
21+
},
22+
}
23+
},
24+
Run: func(t *TestDriver, keys config.KeybindingConfig) {
25+
t.Views().Commits().Focus().
26+
Lines(
27+
Contains("commit 03").IsSelected(),
28+
Contains("commit 02"),
29+
Contains("commit 01"),
30+
)
31+
32+
t.GlobalPress("X")
33+
t.FileSystem().FileContent("file.txt", Equals("commit 03\n"))
34+
35+
t.Views().Commits().Focus().
36+
Press(keys.Universal.RangeSelectDown)
37+
38+
t.GlobalPress("X")
39+
t.FileSystem().FileContent("file.txt", Equals("commit 03\ncommit 02\n"))
40+
},
41+
})

pkg/integration/tests/test_list.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ var tests = []*components.IntegrationTest{
139139
custom_commands.MultipleContexts,
140140
custom_commands.MultiplePrompts,
141141
custom_commands.SelectedCommit,
142+
custom_commands.SelectedCommitRange,
142143
custom_commands.SelectedPath,
143144
custom_commands.ShowOutputInPanel,
144145
custom_commands.SuggestionsCommand,

0 commit comments

Comments
 (0)