mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-10 20:05:50 +02:00
Add runCommand
function to Go template syntax
This makes it possible to use date and time in initial values like this: ```yaml initialValue: 'ruudk/{{ runCommand "date +\"%Y/%-m\"" }}/' ``` I want to use this to configure my BranchPrefix like this: ```yaml git: branchPrefix: 'ruudk/{{ runCommand "date +\"%Y/%-m\"" }}/' ```
This commit is contained in:
parent
c7feba9bb1
commit
12820481e6
8 changed files with 140 additions and 3 deletions
|
@ -1027,6 +1027,15 @@ git:
|
|||
branchPrefix: "firstlast/"
|
||||
```
|
||||
|
||||
It's possible to use a dynamic prefix by using the `runCommand` function:
|
||||
|
||||
```yaml
|
||||
git:
|
||||
branchPrefix: "firstlast/{{ runCommand "date +\"%Y/%-m\"" }}/"
|
||||
```
|
||||
|
||||
This would produce something like: `firstlast/2025/4/`
|
||||
|
||||
## Custom git log command
|
||||
|
||||
You can override the `git log` command that's used to render the log of the selected branch like so:
|
||||
|
|
|
@ -320,6 +320,24 @@ We don't support accessing all elements of a range selection yet. We might add t
|
|||
command: "git format-patch {{.SelectedCommitRange.From}}^..{{.SelectedCommitRange.To}}"
|
||||
```
|
||||
|
||||
We support the following functions:
|
||||
|
||||
### Quoting
|
||||
|
||||
Quote wraps a string in quotes with necessary escaping for the current platform.
|
||||
|
||||
```
|
||||
git {{.SelectedFile.Name | quote}}
|
||||
```
|
||||
|
||||
### Running a command
|
||||
|
||||
Runs a command and returns the output. If the command outputs more than a single line, it will produce an error.
|
||||
|
||||
```
|
||||
initialValue: "username/{{ runCommand "date +\"%Y/%-m\"" }}/"
|
||||
```
|
||||
|
||||
## 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)
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
package git_commands
|
||||
|
||||
import "github.com/mgutz/str"
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/mgutz/str"
|
||||
)
|
||||
|
||||
type CustomCommands struct {
|
||||
*GitCommon
|
||||
|
@ -18,3 +23,18 @@ func NewCustomCommands(gitCommon *GitCommon) *CustomCommands {
|
|||
func (self *CustomCommands) RunWithOutput(cmdStr string) (string, error) {
|
||||
return self.cmd.New(str.ToArgv(cmdStr)).RunWithOutput()
|
||||
}
|
||||
|
||||
// A function that can be used as a "runCommand" entry in the template.FuncMap of templates.
|
||||
func (self *CustomCommands) TemplateFunctionRunCommand(cmdStr string) (string, error) {
|
||||
output, err := self.RunWithOutput(cmdStr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
output = strings.TrimRight(output, "\r\n")
|
||||
|
||||
if strings.Contains(output, "\r\n") {
|
||||
return "", fmt.Errorf("command output contains newlines: %s", output)
|
||||
}
|
||||
|
||||
return output, nil
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package helpers
|
|||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||
|
@ -318,7 +319,15 @@ func (self *RefsHelper) NewBranch(from string, fromFormattedName string, suggest
|
|||
)
|
||||
|
||||
if suggestedBranchName == "" {
|
||||
suggestedBranchName = self.c.UserConfig().Git.BranchPrefix
|
||||
var err error
|
||||
|
||||
suggestedBranchName, err = utils.ResolveTemplate(self.c.UserConfig().Git.BranchPrefix, nil, template.FuncMap{
|
||||
"runCommand": self.c.Git().Custom.TemplateFunctionRunCommand,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
suggestedBranchName = strings.ReplaceAll(suggestedBranchName, "\t", " ")
|
||||
}
|
||||
|
||||
refresh := func() error {
|
||||
|
|
|
@ -246,7 +246,8 @@ func (self *HandlerCreator) getResolveTemplateFn(form map[string]string, promptR
|
|||
}
|
||||
|
||||
funcs := template.FuncMap{
|
||||
"quote": self.c.OS().Quote,
|
||||
"quote": self.c.OS().Quote,
|
||||
"runCommand": self.c.Git().Custom.TemplateFunctionRunCommand,
|
||||
}
|
||||
|
||||
return func(templateStr string) (string, error) { return utils.ResolveTemplate(templateStr, objects, funcs) }
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package branch
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var NewBranchWithPrefixUsingRunCommand = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Creating a new branch with a branch prefix using a runCommand",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.GetUserConfig().Git.BranchPrefix = "myprefix/{{ runCommand \"echo dynamic\" }}/"
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.
|
||||
EmptyCommit("commit 1")
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Commits().
|
||||
Focus().
|
||||
Lines(
|
||||
Contains("commit 1").IsSelected(),
|
||||
).
|
||||
SelectNextItem().
|
||||
Press(keys.Universal.New).
|
||||
Tap(func() {
|
||||
t.ExpectPopup().Prompt().
|
||||
Title(Contains("New branch name")).
|
||||
InitialText(Equals("myprefix/dynamic/")).
|
||||
Type("my-branch").
|
||||
Confirm()
|
||||
t.Git().CurrentBranchName("myprefix/dynamic/my-branch")
|
||||
})
|
||||
},
|
||||
})
|
42
pkg/integration/tests/custom_commands/run_command.go
Normal file
42
pkg/integration/tests/custom_commands/run_command.go
Normal file
|
@ -0,0 +1,42 @@
|
|||
package custom_commands
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var RunCommand = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Using a custom command that uses runCommand template function in a prompt step",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.EmptyCommit("blah")
|
||||
},
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.GetUserConfig().CustomCommands = []config.CustomCommand{
|
||||
{
|
||||
Key: "a",
|
||||
Context: "localBranches",
|
||||
Command: `git checkout {{.Form.Branch}}`,
|
||||
Prompts: []config.CustomCommandPrompt{
|
||||
{
|
||||
Key: "Branch",
|
||||
Type: "input",
|
||||
Title: "Enter a branch name",
|
||||
InitialValue: "myprefix/{{ runCommand \"echo dynamic\" }}/",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Branches().
|
||||
Focus().
|
||||
Press("a")
|
||||
|
||||
t.ExpectPopup().Prompt().
|
||||
Title(Equals("Enter a branch name")).
|
||||
InitialText(Contains("myprefix/dynamic/")).
|
||||
Confirm()
|
||||
},
|
||||
})
|
|
@ -51,6 +51,7 @@ var tests = []*components.IntegrationTest{
|
|||
branch.NewBranchFromRemoteTrackingDifferentName,
|
||||
branch.NewBranchFromRemoteTrackingSameName,
|
||||
branch.NewBranchWithPrefix,
|
||||
branch.NewBranchWithPrefixUsingRunCommand,
|
||||
branch.OpenPullRequestInvalidTargetRemoteName,
|
||||
branch.OpenPullRequestNoUpstream,
|
||||
branch.OpenPullRequestSelectRemoteAndTargetBranch,
|
||||
|
@ -154,6 +155,7 @@ var tests = []*components.IntegrationTest{
|
|||
custom_commands.MenuFromCommandsOutput,
|
||||
custom_commands.MultipleContexts,
|
||||
custom_commands.MultiplePrompts,
|
||||
custom_commands.RunCommand,
|
||||
custom_commands.SelectedCommit,
|
||||
custom_commands.SelectedCommitRange,
|
||||
custom_commands.SelectedPath,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue