Skip to content
Open
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
3 changes: 3 additions & 0 deletions docs-master/Config.md
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,9 @@ os:
# "{{filename}}", but doesn't support "{{line}}".
open: ""

# Whether lazygit suspends until an open process returns
openInTerminal: false

# Command for opening a link. Should contain "{{link}}".
openLink: ""

Expand Down
3 changes: 3 additions & 0 deletions docs/Config.md
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,9 @@ os:
# "{{filename}}", but doesn't support "{{line}}".
open: ""

# Whether lazygit suspends until an open process returns
openInTerminal: false

# Command for opening a link. Should contain "{{link}}".
openLink: ""

Expand Down
11 changes: 11 additions & 0 deletions pkg/commands/git_commands/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@ func (self *FileCommands) GetEditAtLineAndWaitCmdStr(filename string, lineNumber
return cmdStr
}

func (self *FileCommands) GetOpenCmdStr(filename string) (string, bool) {
template, suspend := config.GetOpenTemplate(&self.UserConfig().OS, config.GetPlatformDefaultConfig().Open)

templateValues := map[string]string{
"filename": self.cmd.Quote(filename),
}

cmdStr := utils.ResolvePlaceholderString(template, templateValues)
return cmdStr, suspend
}

func (self *FileCommands) GetOpenDirInEditorCmdStr(path string) (string, bool) {
template, suspend := config.GetOpenDirInEditorTemplate(self.os.Platform.Shell, &self.UserConfig().OS, self.guessDefaultEditor)

Expand Down
54 changes: 54 additions & 0 deletions pkg/commands/git_commands/file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/jesseduffield/lazygit/pkg/commands/git_config"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/samber/lo"
"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -152,6 +153,59 @@ func TestEditFileAtLineAndWaitCmd(t *testing.T) {
}
}

func TestOpenFileCmd(t *testing.T) {
type scenario struct {
name string
filename string
osConfig config.OSConfig
expectedCmdStr string
suspend bool
}

scenarios := []scenario{
{
name: "uses platform default open command",
filename: "test",
osConfig: config.OSConfig{},
expectedCmdStr: `open -- "test"`,
suspend: false,
},
{
name: "uses explicit open command",
filename: "file/with space",
osConfig: config.OSConfig{
Open: "custom-open {{filename}}",
},
expectedCmdStr: `custom-open "file/with space"`,
suspend: false,
},
{
name: "suspends when open is configured to run in terminal",
filename: "test",
osConfig: config.OSConfig{
SuspendOnOpen: lo.ToPtr(true),
},
expectedCmdStr: `open -- "test"`,
suspend: true,
},
}

for _, s := range scenarios {
t.Run(s.name, func(t *testing.T) {
userConfig := config.GetDefaultConfig()
userConfig.OS = s.osConfig

instance := buildFileCommands(commonDeps{
userConfig: userConfig,
})

cmdStr, suspend := instance.GetOpenCmdStr(s.filename)
assert.Equal(t, s.expectedCmdStr, cmdStr)
assert.Equal(t, s.suspend, suspend)
})
}
}

func TestGuessDefaultEditor(t *testing.T) {
type scenario struct {
gitConfigMockResponses map[string]string
Expand Down
17 changes: 17 additions & 0 deletions pkg/config/editor_presets.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ func GetEditAtLineAndWaitTemplate(shell string, osConfig *OSConfig, guessDefault
return template
}

func GetOpenTemplate(osConfig *OSConfig, defaultTemplate string) (string, bool) {
template := osConfig.Open
if template == "" {
template = defaultTemplate
}

return template, getOpenInTerminal(osConfig)
}

func GetOpenDirInEditorTemplate(shell string, osConfig *OSConfig, guessDefaultEditor func() string) (string, bool) {
preset := getPreset(shell, osConfig, guessDefaultEditor)
template := osConfig.OpenDirInEditor
Expand Down Expand Up @@ -196,3 +205,11 @@ func getEditInTerminal(osConfig *OSConfig, preset *editPreset) bool {
}
return preset.suspend()
}

func getOpenInTerminal(osConfig *OSConfig) bool {
if osConfig.SuspendOnOpen != nil {
return *osConfig.SuspendOnOpen
}

return false
}
46 changes: 46 additions & 0 deletions pkg/config/editor_presets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,49 @@ func TestGetEditTemplate(t *testing.T) {
})
}
}

func TestGetOpenTemplate(t *testing.T) {
trueVal := true

scenarios := []struct {
name string
osConfig *OSConfig
defaultTemplate string
expectedTemplate string
expectedSuspend bool
}{
{
name: "uses platform default open command",
osConfig: &OSConfig{},
defaultTemplate: "open -- {{filename}}",
expectedTemplate: "open -- {{filename}}",
expectedSuspend: false,
},
{
name: "uses explicit open command",
osConfig: &OSConfig{
Open: "myopen {{filename}}",
},
defaultTemplate: "open -- {{filename}}",
expectedTemplate: "myopen {{filename}}",
expectedSuspend: false,
},
{
name: "uses explicit open suspend setting",
osConfig: &OSConfig{
SuspendOnOpen: &trueVal,
},
defaultTemplate: "open -- {{filename}}",
expectedTemplate: "open -- {{filename}}",
expectedSuspend: true,
},
}

for _, s := range scenarios {
t.Run(s.name, func(t *testing.T) {
template, suspend := GetOpenTemplate(s.osConfig, s.defaultTemplate)
assert.Equal(t, s.expectedTemplate, template)
assert.Equal(t, s.expectedSuspend, suspend)
})
}
}
5 changes: 5 additions & 0 deletions pkg/config/user_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,11 @@ type OSConfig struct {
// Command for opening a file, as if the file is double-clicked. Should contain "{{filename}}", but doesn't support "{{line}}".
Open string `yaml:"open,omitempty"`

// Whether lazygit suspends until an open process returns
// [dev] Pointer to bool so that we can distinguish unset (nil) from false.
// [dev] We're naming this `openInTerminal` so it aligns with editInTerminal
SuspendOnOpen *bool `yaml:"openInTerminal,omitempty"`

// Command for opening a link. Should contain "{{link}}".
OpenLink string `yaml:"openLink,omitempty"`

Expand Down
7 changes: 4 additions & 3 deletions pkg/gui/controllers/helpers/files_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,9 @@ func (self *FilesHelper) OpenFile(filename string) error {
return err
}
self.c.LogAction(self.c.Tr.Actions.OpenFile)
if err := self.c.OS().OpenFile(absPath); err != nil {
return err
cmdStr, suspend := self.c.Git().File.GetOpenCmdStr(absPath)
if !suspend {
return self.c.OS().OpenFile(absPath)
}
return nil
return self.callEditor(cmdStr, suspend)
}
4 changes: 4 additions & 0 deletions schema-master/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3465,6 +3465,10 @@
"type": "string",
"description": "Command for opening a file, as if the file is double-clicked. Should contain \"{{filename}}\", but doesn't support \"{{line}}\"."
},
"openInTerminal": {
"type": "boolean",
"description": "Whether lazygit suspends until an open process returns"
},
"openLink": {
"type": "string",
"description": "Command for opening a link. Should contain \"{{link}}\"."
Expand Down