diff --git a/pkg/app/app.go b/pkg/app/app.go index ffd8807f0..fa2415fc3 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -73,7 +73,7 @@ func NewApp(config config.AppConfigurer) (*App, error) { } var err error app.Log = newLogger(config) - app.OSCommand = commands.NewOSCommand(app.Log) + app.OSCommand = commands.NewOSCommand(app.Log, config) app.Tr = i18n.NewLocalizer(app.Log) diff --git a/pkg/commands/os.go b/pkg/commands/os.go index 0fa92f724..fd27d39da 100644 --- a/pkg/commands/os.go +++ b/pkg/commands/os.go @@ -6,7 +6,8 @@ import ( "os/exec" "strings" - "github.com/davecgh/go-spew/spew" + "github.com/jesseduffield/lazygit/pkg/config" + "github.com/jesseduffield/lazygit/pkg/utils" "github.com/mgutz/str" @@ -20,22 +21,25 @@ type Platform struct { shell string shellArg string escapedQuote string + openCommand string } // OSCommand holds all the os commands type OSCommand struct { Log *logrus.Entry Platform *Platform + Config config.AppConfigurer command func(string, ...string) *exec.Cmd getGlobalGitConfig func(string) (string, error) getenv func(string) string } // NewOSCommand os command runner -func NewOSCommand(log *logrus.Entry) *OSCommand { +func NewOSCommand(log *logrus.Entry, config config.AppConfigurer) *OSCommand { return &OSCommand{ Log: log, Platform: getPlatform(), + Config: config, command: exec.Command, getGlobalGitConfig: gitconfig.Global, getenv: os.Getenv, @@ -74,12 +78,10 @@ func (c *OSCommand) FileType(path string) string { // RunDirectCommand wrapper around direct commands func (c *OSCommand) RunDirectCommand(command string) (string, error) { c.Log.WithField("command", command).Info("RunDirectCommand") - args := str.ToArgv(c.Platform.shellArg + " " + command) - c.Log.Info(spew.Sdump(args)) return sanitisedCommandOutput( exec. - Command(c.Platform.shell, args...). + Command(c.Platform.shell, c.Platform.shellArg, command). CombinedOutput(), ) } @@ -95,45 +97,23 @@ func sanitisedCommandOutput(output []byte, err error) (string, error) { } // getOpenCommand get open command -func (c *OSCommand) getOpenCommand() (string, string, error) { - //NextStep open equivalents: xdg-open (linux), cygstart (cygwin), open (OSX) - trailMap := map[string]string{ - "xdg-open": " &>/dev/null &", - "cygstart": "", - "open": "", +func (c *OSCommand) getOpenCommand() string { + if c.Config.GetUserConfig().IsSet("os.openCommand") { + return c.Config.GetUserConfig().GetString("os.openCommand") } - - for name, trail := range trailMap { - if err := c.RunCommand("which " + name); err == nil { - return name, trail, nil - } - } - return "", "", errors.New("Unsure what command to use to open this file") -} - -// VsCodeOpenFile opens the file in code, with the -r flag to open in the -// current window -// each of these open files needs to have the same function signature because -// they're being passed as arguments into another function, -// but only editFile actually returns a *exec.Cmd -func (c *OSCommand) VsCodeOpenFile(filename string) (*exec.Cmd, error) { - return nil, c.RunCommand("code -r " + filename) -} - -// SublimeOpenFile opens the filein sublime -// may be deprecated in the future -func (c *OSCommand) SublimeOpenFile(filename string) (*exec.Cmd, error) { - return nil, c.RunCommand("subl " + filename) + return c.Platform.openCommand } // OpenFile opens a file with the given func (c *OSCommand) OpenFile(filename string) error { - cmdName, cmdTrail, err := c.getOpenCommand() - if err != nil { - return err + commandTemplate := c.getOpenCommand() + templateValues := map[string]string{ + "filename": c.Quote(filename), } - return c.RunCommand(cmdName + " " + c.Quote(filename) + cmdTrail) // TODO: test on linux + command := utils.ResolvePlaceholderString(commandTemplate, templateValues) + _, err := c.RunDirectCommand(command) + return err } // EditFile opens a file in a subprocess using whatever editor is available, diff --git a/pkg/commands/os_default_platform.go b/pkg/commands/os_default_platform.go index f6ac1b515..f106bbd62 100644 --- a/pkg/commands/os_default_platform.go +++ b/pkg/commands/os_default_platform.go @@ -12,5 +12,6 @@ func getPlatform() *Platform { shell: "bash", shellArg: "-c", escapedQuote: "\"", + openCommand: "open {{filename}}", } } diff --git a/pkg/commands/os_linux.go b/pkg/commands/os_linux.go new file mode 100644 index 000000000..cbd037139 --- /dev/null +++ b/pkg/commands/os_linux.go @@ -0,0 +1,15 @@ +package commands + +import ( + "runtime" +) + +func getPlatform() *Platform { + return &Platform{ + os: runtime.GOOS, + shell: "bash", + shellArg: "-c", + escapedQuote: "\"", + openCommand: "xdg-open {{filename}} &>/dev/null &", + } +} diff --git a/pkg/commands/os_windows.go b/pkg/commands/os_windows.go index 28dd7a982..5b50d2c38 100644 --- a/pkg/commands/os_windows.go +++ b/pkg/commands/os_windows.go @@ -6,5 +6,6 @@ func getPlatform() *Platform { shell: "cmd", shellArg: "/c", escapedQuote: "\\\"", + openCommand: "cygstart {{filename}}", } } diff --git a/pkg/config/app_config.go b/pkg/config/app_config.go index c85b8e5eb..dce027c8a 100644 --- a/pkg/config/app_config.go +++ b/pkg/config/app_config.go @@ -218,9 +218,9 @@ func GetDefaultConfig() []byte { - white optionsTextColor: - blue -git: +# git: # stuff relating to git -os: +# os: # stuff relating to the OS update: method: prompt # can be: prompt | background | never diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index e7fbc5baf..a4c187c9c 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -7,7 +7,6 @@ import ( // "strings" - "os/exec" "strings" "github.com/fatih/color" @@ -250,11 +249,10 @@ func (gui *Gui) PrepareSubProcess(g *gocui.Gui, commands ...string) { }) } -func (gui *Gui) genericFileOpen(g *gocui.Gui, v *gocui.View, filename string, open func(string) (*exec.Cmd, error)) error { - - sub, err := open(filename) +func (gui *Gui) editFile(filename string) error { + sub, err := gui.OSCommand.EditFile(filename) if err != nil { - return gui.createErrorPanel(g, err.Error()) + return gui.createErrorPanel(gui.g, err.Error()) } if sub != nil { gui.SubProcess = sub @@ -268,7 +266,8 @@ func (gui *Gui) handleFileEdit(g *gocui.Gui, v *gocui.View) error { if err != nil { return err } - return gui.genericFileOpen(g, v, file.Name, gui.OSCommand.EditFile) + + return gui.editFile(file.Name) } func (gui *Gui) handleFileOpen(g *gocui.Gui, v *gocui.View) error { @@ -279,22 +278,6 @@ func (gui *Gui) handleFileOpen(g *gocui.Gui, v *gocui.View) error { return gui.openFile(file.Name) } -func (gui *Gui) handleSublimeFileOpen(g *gocui.Gui, v *gocui.View) error { - file, err := gui.getSelectedFile(g) - if err != nil { - return err - } - return gui.genericFileOpen(g, v, file.Name, gui.OSCommand.SublimeOpenFile) -} - -func (gui *Gui) handleVsCodeFileOpen(g *gocui.Gui, v *gocui.View) error { - file, err := gui.getSelectedFile(g) - if err != nil { - return err - } - return gui.genericFileOpen(g, v, file.Name, gui.OSCommand.VsCodeOpenFile) -} - func (gui *Gui) handleRefreshFiles(g *gocui.Gui, v *gocui.View) error { return gui.refreshFiles(g) } diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index 52496b918..975f5c299 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -34,8 +34,6 @@ func (gui *Gui) keybindings(g *gocui.Gui) error { {ViewName: "files", Key: 'm', Modifier: gocui.ModNone, Handler: gui.handleSwitchToMerge}, {ViewName: "files", Key: 'e', Modifier: gocui.ModNone, Handler: gui.handleFileEdit}, {ViewName: "files", Key: 'o', Modifier: gocui.ModNone, Handler: gui.handleFileOpen}, - {ViewName: "files", Key: 's', Modifier: gocui.ModNone, Handler: gui.handleSublimeFileOpen}, - {ViewName: "files", Key: 'v', Modifier: gocui.ModNone, Handler: gui.handleVsCodeFileOpen}, {ViewName: "files", Key: 'i', Modifier: gocui.ModNone, Handler: gui.handleIgnoreFile}, {ViewName: "files", Key: 'r', Modifier: gocui.ModNone, Handler: gui.handleRefreshFiles}, {ViewName: "files", Key: 'S', Modifier: gocui.ModNone, Handler: gui.handleStashSave}, diff --git a/pkg/gui/status_panel.go b/pkg/gui/status_panel.go index a9dee6a7f..583d7805a 100644 --- a/pkg/gui/status_panel.go +++ b/pkg/gui/status_panel.go @@ -76,7 +76,7 @@ func (gui *Gui) handleOpenConfig(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleEditConfig(g *gocui.Gui, v *gocui.View) error { filename := gui.Config.GetUserConfig().ConfigFileUsed() - return gui.genericFileOpen(g, v, filename, gui.OSCommand.EditFile) + return gui.editFile(filename) } func lazygitTitle() string { diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 62706559e..1d5f0f273 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -90,3 +90,11 @@ func Loader() string { index := nanos / 50000000 % int64(len(characters)) return characters[index : index+1] } + +// ResolvePlaceholderString populates a template with values +func ResolvePlaceholderString(str string, arguments map[string]string) string { + for key, value := range arguments { + str = strings.Replace(str, "{{"+key+"}}", value, -1) + } + return str +}