Skip to content

Commit

Permalink
Improve template placeholders for custom commands (#3809)
Browse files Browse the repository at this point in the history
- **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.
  • Loading branch information
stefanhaller authored Aug 17, 2024
2 parents 1cb29ce + 7fb758c commit 7676572
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 11 deletions.
7 changes: 4 additions & 3 deletions docs/Custom_Command_Keybindings.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
12 changes: 12 additions & 0 deletions pkg/gui/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
36 changes: 28 additions & 8 deletions pkg/gui/services/custom_commands/session_state_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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()),
}
Expand Down
1 change: 1 addition & 0 deletions pkg/gui/types/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
67 changes: 67 additions & 0 deletions pkg/integration/tests/custom_commands/selected_commit.go
Original file line number Diff line number Diff line change
@@ -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 changes: 44 additions & 0 deletions pkg/integration/tests/custom_commands/selected_path.go
Original file line number Diff line number Diff line change
@@ -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"))
},
})
2 changes: 2 additions & 0 deletions pkg/integration/tests/test_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 7676572

Please sign in to comment.