mirror of
				https://github.com/jesseduffield/lazygit.git
				synced 2025-10-30 23:57:43 +02:00 
			
		
		
		
	WIP using runDirectCommand with xdg-open
This commit is contained in:
		| @@ -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) | ||||
|  | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -12,5 +12,6 @@ func getPlatform() *Platform { | ||||
| 		shell:        "bash", | ||||
| 		shellArg:     "-c", | ||||
| 		escapedQuote: "\"", | ||||
| 		openCommand:  "open {{filename}}", | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										15
									
								
								pkg/commands/os_linux.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								pkg/commands/os_linux.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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 &", | ||||
| 	} | ||||
| } | ||||
| @@ -6,5 +6,6 @@ func getPlatform() *Platform { | ||||
| 		shell:        "cmd", | ||||
| 		shellArg:     "/c", | ||||
| 		escapedQuote: "\\\"", | ||||
| 		openCommand:  "cygstart {{filename}}", | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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) | ||||
| } | ||||
|   | ||||
| @@ -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}, | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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 | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user