Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions docs/Config.md
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,10 @@ os:
# See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-command-for-copying-to-and-pasting-from-clipboard
readFromClipboardCmd: ""

# A shell startup file containing shell aliases or shell functions. This will be sourced before running any shell commands, so that shell functions are available in the `:` command prompt or even in custom commands.
# See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#using-aliases-or-functions-in-shell-commands
shellFunctionsFile: ""

# If true, don't display introductory popups upon opening Lazygit.
disableStartupPopups: false

Expand Down Expand Up @@ -740,6 +744,21 @@ The `editInTerminal` option is used to decide whether lazygit needs to suspend i

Contributions of new editor presets are welcome; see the `getPreset` function in [`editor_presets.go`](https://github.com/jesseduffield/lazygit/blob/master/pkg/config/editor_presets.go).

## Using aliases or functions in shell commands

Lazygit has a command prompt (`:`) for quickly executing shell commands without having to quit lazygit or switch to a different terminal. Most people find it convenient to have their usual shell aliases or shell functions available at this prompt. To achieve this, put your alias definitions in a separate shell startup file (which you source from your normal startup file, i.e. from `.bashrc` or `.zshrc`), and then tell lazygit about this file like so:

```yml
os:
shellFunctionsFile: ~/.my_aliases.sh
```

For many people it might work well enough to use their entire shell config file (`~/.bashrc` or `~/.zshrc`) as the `shellFunctionsFile`, but these config files typically do a lot more than defining aliases (e.g. initialize the completion system, start an ssh-agent, etc.) and this may unnecessarily delay execution of shell commands.

When using zsh, aliases can't be used here, but functions can. It is easy to convert your existing aliases into functions, just change `alias l="ls -la"` to `l() ls -la`, for example. This way it will work as before both in the shell and in lazygit.

Note that the shell aliases file is not only used when executing shell commands, but also for [custom commands](Custom_Command_Keybindings.md), and when opening a file in the editor.

## Overriding default config file location

To override the default config directory, use `CONFIG_DIR="$HOME/.config/lazygit"`. This directory contains the config file in addition to some other files lazygit uses to keep track of state across sessions.
Expand Down
8 changes: 2 additions & 6 deletions pkg/commands/git_cmd_obj_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,8 @@ func (self *gitCmdObjBuilder) New(args []string) oscommands.ICmdObj {
return self.innerBuilder.New(args).AddEnvVars(defaultEnvVar)
}

func (self *gitCmdObjBuilder) NewShell(cmdStr string) oscommands.ICmdObj {
return self.innerBuilder.NewShell(cmdStr).AddEnvVars(defaultEnvVar)
}

func (self *gitCmdObjBuilder) NewInteractiveShell(cmdStr string) oscommands.ICmdObj {
return self.innerBuilder.NewInteractiveShell(cmdStr).AddEnvVars(defaultEnvVar)
func (self *gitCmdObjBuilder) NewShell(cmdStr string, shellFunctionsFile string) oscommands.ICmdObj {
return self.innerBuilder.NewShell(cmdStr, shellFunctionsFile).AddEnvVars(defaultEnvVar)
}

func (self *gitCmdObjBuilder) Quote(str string) string {
Expand Down
18 changes: 7 additions & 11 deletions pkg/commands/oscommands/cmd_obj_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ type ICmdObjBuilder interface {
// NewFromArgs takes a slice of strings like []string{"git", "commit"} and returns a new command object.
New(args []string) ICmdObj
// NewShell takes a string like `git commit` and returns an executable shell command for it e.g. `sh -c 'git commit'`
NewShell(commandStr string) ICmdObj
// Like NewShell, but uses the user's shell rather than "bash", and passes -i to it
NewInteractiveShell(commandStr string) ICmdObj
// shellFunctionsFile is an optional file path that will be sourced before executing the command. Callers should pass
// the value of UserConfig.OS.ShellFunctionsFile.
NewShell(commandStr string, shellFunctionsFile string) ICmdObj
// Quote wraps a string in quotes with any necessary escaping applied. The reason for bundling this up with the other methods in this interface is that we basically always need to make use of this when creating new command objects.
Quote(str string) string
}
Expand Down Expand Up @@ -44,20 +44,16 @@ func (self *CmdObjBuilder) NewWithEnviron(args []string, env []string) ICmdObj {
}
}

func (self *CmdObjBuilder) NewShell(commandStr string) ICmdObj {
func (self *CmdObjBuilder) NewShell(commandStr string, shellFunctionsFile string) ICmdObj {
if len(shellFunctionsFile) > 0 {
commandStr = fmt.Sprintf("%ssource %s\n%s", self.platform.PrefixForShellFunctionsFile, shellFunctionsFile, commandStr)
}
quotedCommand := self.quotedCommandString(commandStr)
cmdArgs := str.ToArgv(fmt.Sprintf("%s %s %s", self.platform.Shell, self.platform.ShellArg, quotedCommand))

return self.New(cmdArgs)
}

func (self *CmdObjBuilder) NewInteractiveShell(commandStr string) ICmdObj {
quotedCommand := self.quotedCommandString(commandStr + self.platform.InteractiveShellExit)
cmdArgs := str.ToArgv(fmt.Sprintf("%s %s %s %s", self.platform.InteractiveShell, self.platform.InteractiveShellArg, self.platform.ShellArg, quotedCommand))

return self.New(cmdArgs)
}

func (self *CmdObjBuilder) quotedCommandString(commandStr string) string {
// Windows does not seem to like quotes around the command
if self.platform.OS == "windows" {
Expand Down
13 changes: 5 additions & 8 deletions pkg/commands/oscommands/dummies.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,11 @@ func NewDummyCmdObjBuilder(runner ICmdObjRunner) *CmdObjBuilder {
}

var dummyPlatform = &Platform{
OS: "darwin",
Shell: "bash",
InteractiveShell: "bash",
ShellArg: "-c",
InteractiveShellArg: "-i",
InteractiveShellExit: "; exit $?",
OpenCommand: "open {{filename}}",
OpenLinkCommand: "open {{link}}",
OS: "darwin",
Shell: "bash",
ShellArg: "-c",
OpenCommand: "open {{filename}}",
OpenLinkCommand: "open {{link}}",
}

func NewDummyOSCommandWithRunner(runner *FakeCmdObjRunner) *OSCommand {
Expand Down
24 changes: 11 additions & 13 deletions pkg/commands/oscommands/os.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,12 @@ type OSCommand struct {

// Platform stores the os state
type Platform struct {
OS string
Shell string
InteractiveShell string
ShellArg string
InteractiveShellArg string
InteractiveShellExit string
OpenCommand string
OpenLinkCommand string
OS string
Shell string
ShellArg string
PrefixForShellFunctionsFile string
OpenCommand string
OpenLinkCommand string
}

// NewOSCommand os command runner
Expand Down Expand Up @@ -93,7 +91,7 @@ func (c *OSCommand) OpenFile(filename string) error {
"filename": c.Quote(filename),
}
command := utils.ResolvePlaceholderString(commandTemplate, templateValues)
return c.Cmd.NewShell(command).Run()
return c.Cmd.NewShell(command, c.UserConfig().OS.ShellFunctionsFile).Run()
}

func (c *OSCommand) OpenLink(link string) error {
Expand All @@ -110,7 +108,7 @@ func (c *OSCommand) OpenLink(link string) error {
}

command := utils.ResolvePlaceholderString(commandTemplate, templateValues)
return c.Cmd.NewShell(command).Run()
return c.Cmd.NewShell(command, c.UserConfig().OS.ShellFunctionsFile).Run()
}

// Quote wraps a message in platform-specific quotation marks
Expand Down Expand Up @@ -299,7 +297,7 @@ func (c *OSCommand) CopyToClipboard(str string) error {
cmdStr := utils.ResolvePlaceholderString(c.UserConfig().OS.CopyToClipboardCmd, map[string]string{
"text": c.Cmd.Quote(str),
})
return c.Cmd.NewShell(cmdStr).Run()
return c.Cmd.NewShell(cmdStr, c.UserConfig().OS.ShellFunctionsFile).Run()
}

return clipboard.WriteAll(str)
Expand All @@ -310,7 +308,7 @@ func (c *OSCommand) PasteFromClipboard() (string, error) {
var err error
if c.UserConfig().OS.CopyToClipboardCmd != "" {
cmdStr := c.UserConfig().OS.ReadFromClipboardCmd
s, err = c.Cmd.NewShell(cmdStr).RunWithOutput()
s, err = c.Cmd.NewShell(cmdStr, c.UserConfig().OS.ShellFunctionsFile).RunWithOutput()
} else {
s, err = clipboard.ReadAll()
}
Expand Down Expand Up @@ -360,5 +358,5 @@ func (c *OSCommand) UpdateWindowTitle() error {
return getWdErr
}
argString := fmt.Sprint("title ", filepath.Base(path), " - Lazygit")
return c.Cmd.NewShell(argString).Run()
return c.Cmd.NewShell(argString, c.UserConfig().OS.ShellFunctionsFile).Run()
}
27 changes: 9 additions & 18 deletions pkg/commands/oscommands/os_default_platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,18 @@ import (
func GetPlatform() *Platform {
shell := getUserShell()

interactiveShell := shell
interactiveShellArg := "-i"
interactiveShellExit := "; exit $?"

if strings.HasSuffix(shell, "fish") {
interactiveShellExit = "; exit $status"
} else if !(strings.HasSuffix(shell, "bash") || strings.HasSuffix(shell, "zsh")) {
interactiveShell = "bash"
interactiveShellArg = ""
interactiveShellExit = ""
prefixForShellFunctionsFile := ""
if strings.HasSuffix(shell, "bash") {
prefixForShellFunctionsFile = "shopt -s expand_aliases\n"
}

return &Platform{
OS: runtime.GOOS,
Shell: "bash",
InteractiveShell: interactiveShell,
ShellArg: "-c",
InteractiveShellArg: interactiveShellArg,
InteractiveShellExit: interactiveShellExit,
OpenCommand: "open {{filename}}",
OpenLinkCommand: "open {{link}}",
OS: runtime.GOOS,
Shell: shell,
ShellArg: "-c",
PrefixForShellFunctionsFile: prefixForShellFunctionsFile,
OpenCommand: "open {{filename}}",
OpenLinkCommand: "open {{link}}",
}
}

Expand Down
9 changes: 3 additions & 6 deletions pkg/commands/oscommands/os_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@ package oscommands

func GetPlatform() *Platform {
return &Platform{
OS: "windows",
Shell: "cmd",
InteractiveShell: "cmd",
ShellArg: "/c",
InteractiveShellArg: "",
InteractiveShellExit: "",
OS: "windows",
Shell: "cmd",
ShellArg: "/c",
}
}
20 changes: 12 additions & 8 deletions pkg/config/user_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,18 @@ type OSConfig struct {
// Command for opening a link. Should contain "{{link}}".
OpenLink string `yaml:"openLink,omitempty"`

// CopyToClipboardCmd is the command for copying to clipboard.
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-command-for-copying-to-and-pasting-from-clipboard
CopyToClipboardCmd string `yaml:"copyToClipboardCmd,omitempty"`

// ReadFromClipboardCmd is the command for reading the clipboard.
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-command-for-copying-to-and-pasting-from-clipboard
ReadFromClipboardCmd string `yaml:"readFromClipboardCmd,omitempty"`

// A shell startup file containing shell aliases or shell functions. This will be sourced before running any shell commands, so that shell functions are available in the `:` command prompt or even in custom commands.
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#using-aliases-or-functions-in-shell-commands
ShellFunctionsFile string `yaml:"shellFunctionsFile"`

// --------

// The following configs are all deprecated and kept for backward
Expand All @@ -603,14 +615,6 @@ type OSConfig struct {
// OpenLinkCommand is the command for opening a link
// Deprecated: use OpenLink instead.
OpenLinkCommand string `yaml:"openLinkCommand,omitempty" jsonschema:"deprecated"`

// CopyToClipboardCmd is the command for copying to clipboard.
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-command-for-copying-to-and-pasting-from-clipboard
CopyToClipboardCmd string `yaml:"copyToClipboardCmd,omitempty"`

// ReadFromClipboardCmd is the command for reading the clipboard.
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-command-for-copying-to-and-pasting-from-clipboard
ReadFromClipboardCmd string `yaml:"readFromClipboardCmd,omitempty"`
}

type CustomCommandAfterHook struct {
Expand Down
4 changes: 2 additions & 2 deletions pkg/gui/controllers/helpers/files_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@ func (self *FilesHelper) OpenDirInEditor(path string) error {
func (self *FilesHelper) callEditor(cmdStr string, suspend bool) error {
if suspend {
return self.c.RunSubprocessAndRefresh(
self.c.OS().Cmd.NewShell(cmdStr),
self.c.OS().Cmd.NewShell(cmdStr, self.c.UserConfig().OS.ShellFunctionsFile),
)
}

return self.c.OS().Cmd.NewShell(cmdStr).Run()
return self.c.OS().Cmd.NewShell(cmdStr, self.c.UserConfig().OS.ShellFunctionsFile).Run()
}

func (self *FilesHelper) OpenFile(filename string) error {
Expand Down
2 changes: 1 addition & 1 deletion pkg/gui/controllers/shell_command_action.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func (self *ShellCommandAction) Call() error {

self.c.LogAction(self.c.Tr.Actions.CustomCommand)
return self.c.RunSubprocessAndRefresh(
self.c.OS().Cmd.NewInteractiveShell(command),
self.c.OS().Cmd.NewShell(command, self.c.UserConfig().OS.ShellFunctionsFile),
)
},
HandleDeleteSuggestion: func(index int) error {
Expand Down
4 changes: 2 additions & 2 deletions pkg/gui/services/custom_commands/handler_creator.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func (self *HandlerCreator) generateFindSuggestionsFunc(prompt *config.CustomCom

func (self *HandlerCreator) getCommandSuggestionsFn(command string) (func(string) []*types.Suggestion, error) {
lines := []*types.Suggestion{}
err := self.c.OS().Cmd.NewShell(command).RunAndProcessLines(func(line string) (bool, error) {
err := self.c.OS().Cmd.NewShell(command, self.c.UserConfig().OS.ShellFunctionsFile).RunAndProcessLines(func(line string) (bool, error) {
lines = append(lines, &types.Suggestion{Value: line, Label: line})
return false, nil
})
Expand Down Expand Up @@ -259,7 +259,7 @@ func (self *HandlerCreator) finalHandler(customCommand config.CustomCommand, ses
return err
}

cmdObj := self.c.OS().Cmd.NewShell(cmdStr)
cmdObj := self.c.OS().Cmd.NewShell(cmdStr, self.c.UserConfig().OS.ShellFunctionsFile)

if customCommand.Subprocess != nil && *customCommand.Subprocess {
return self.c.RunSubprocessAndRefresh(cmdObj)
Expand Down
1 change: 1 addition & 0 deletions pkg/i18n/english.go
Original file line number Diff line number Diff line change
Expand Up @@ -2082,6 +2082,7 @@ gui:
`,
"0.44.0": `- The gui.branchColors config option is deprecated; it will be removed in a future version. Please use gui.branchColorPatterns instead.
- The automatic coloring of branches starting with "feature/", "bugfix/", or "hotfix/" has been removed; if you want this, it's easy to set up using the new gui.branchColorPatterns option.`,
"0.49.0": `- Executing shell commands (with the ':' prompt) no longer uses an interactive shell, which means that if you want to use your shell aliases in this prompt, you need to do a little bit of setup work. See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#using-aliases-or-functions-in-shell-commands for details.`,
},
}
}
20 changes: 12 additions & 8 deletions schema/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -1551,6 +1551,18 @@
"type": "string",
"description": "Command for opening a link. Should contain \"{{link}}\"."
},
"copyToClipboardCmd": {
"type": "string",
"description": "CopyToClipboardCmd is the command for copying to clipboard.\nSee https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-command-for-copying-to-and-pasting-from-clipboard"
},
"readFromClipboardCmd": {
"type": "string",
"description": "ReadFromClipboardCmd is the command for reading the clipboard.\nSee https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-command-for-copying-to-and-pasting-from-clipboard"
},
"shellFunctionsFile": {
"type": "string",
"description": "A shell startup file containing shell aliases or shell functions. This will be sourced before running any shell commands, so that shell functions are available in the `:` command prompt or even in custom commands.\nSee https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#using-aliases-or-functions-in-shell-commands"
},
"editCommand": {
"type": "string",
"description": "EditCommand is the command for editing a file.\nDeprecated: use Edit instead. Note that semantics are different:\nEditCommand is just the command itself, whereas Edit contains a\n\"{{filename}}\" variable."
Expand All @@ -1566,14 +1578,6 @@
"openLinkCommand": {
"type": "string",
"description": "OpenLinkCommand is the command for opening a link\nDeprecated: use OpenLink instead."
},
"copyToClipboardCmd": {
"type": "string",
"description": "CopyToClipboardCmd is the command for copying to clipboard.\nSee https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-command-for-copying-to-and-pasting-from-clipboard"
},
"readFromClipboardCmd": {
"type": "string",
"description": "ReadFromClipboardCmd is the command for reading the clipboard.\nSee https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-command-for-copying-to-and-pasting-from-clipboard"
}
},
"additionalProperties": false,
Expand Down