Skip to content

Commit

Permalink
Merge pull request jesseduffield#1413 from Ryooooooga/feature/edit-line
Browse files Browse the repository at this point in the history
Make os.editCommand customizable using template
  • Loading branch information
mjarkk authored Aug 23, 2021
2 parents 508af26 + 44140ad commit 487ad19
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 22 deletions.
19 changes: 19 additions & 0 deletions docs/Config.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ git:
parseEmoji: false
os:
editCommand: '' # see 'Configuring File Editing' section
editCommandTemplate: '{{editor}} {{filename}}'
openCommand: ''
refresher:
refreshInterval: 10 # file/submodule refresh interval in seconds
Expand Down Expand Up @@ -241,6 +242,24 @@ os:
Lazygit will log an error if none of these options are set.
You can specify a line number you are currently at when in the line-by-line mode.
```yaml
os:
editCommand: 'vim'
editCommandTemplate: '{{editor}} +{{line}} {{filename}}'
```
or
```yaml
os:
editCommand: 'code'
editCommandTemplate: '{{editor}} --goto {{filename}}:{{line}}'
```
`{{editor}}` in `editCommandTemplate` is replaced with the value of `editCommand`.

### Recommended Config Values

for users of VSCode
Expand Down
12 changes: 10 additions & 2 deletions pkg/commands/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"
"path/filepath"
"strconv"
"time"

"github.com/go-errors/errors"
Expand Down Expand Up @@ -321,7 +322,7 @@ func (c *GitCommand) ResetAndClean() error {
return c.RemoveUntrackedFiles()
}

func (c *GitCommand) EditFileCmdStr(filename string) (string, error) {
func (c *GitCommand) EditFileCmdStr(filename string, lineNumber int) (string, error) {
editor := c.Config.GetUserConfig().OS.EditCommand

if editor == "" {
Expand All @@ -346,5 +347,12 @@ func (c *GitCommand) EditFileCmdStr(filename string) (string, error) {
return "", errors.New("No editor defined in config file, $GIT_EDITOR, $VISUAL, $EDITOR, or git config")
}

return fmt.Sprintf("%s %s", editor, c.OSCommand.Quote(filename)), nil
templateValues := map[string]string{
"editor": editor,
"filename": c.OSCommand.Quote(filename),
"line": strconv.Itoa(lineNumber),
}

editCmdTemplate := c.Config.GetUserConfig().OS.EditCommandTemplate
return utils.ResolvePlaceholderString(editCmdTemplate, templateValues), nil
}
42 changes: 35 additions & 7 deletions pkg/commands/files_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -741,18 +741,20 @@ func TestGitCommandRemoveUntrackedFiles(t *testing.T) {
// TestEditFileCmdStr is a function.
func TestEditFileCmdStr(t *testing.T) {
type scenario struct {
filename string
configEditCommand string
command func(string, ...string) *exec.Cmd
getenv func(string) string
getGitConfigValue func(string) (string, error)
test func(string, error)
filename string
configEditCommand string
configEditCommandTemplate string
command func(string, ...string) *exec.Cmd
getenv func(string) string
getGitConfigValue func(string) (string, error)
test func(string, error)
}

scenarios := []scenario{
{
"test",
"",
"{{editor}} {{filename}}",
func(name string, arg ...string) *exec.Cmd {
return secureexec.Command("exit", "1")
},
Expand All @@ -769,6 +771,7 @@ func TestEditFileCmdStr(t *testing.T) {
{
"test",
"nano",
"{{editor}} {{filename}}",
func(name string, args ...string) *exec.Cmd {
assert.Equal(t, "which", name)
return secureexec.Command("echo")
Expand All @@ -787,6 +790,7 @@ func TestEditFileCmdStr(t *testing.T) {
{
"test",
"",
"{{editor}} {{filename}}",
func(name string, arg ...string) *exec.Cmd {
assert.Equal(t, "which", name)
return secureexec.Command("exit", "1")
Expand All @@ -805,6 +809,7 @@ func TestEditFileCmdStr(t *testing.T) {
{
"test",
"",
"{{editor}} {{filename}}",
func(name string, arg ...string) *exec.Cmd {
assert.Equal(t, "which", name)
return secureexec.Command("exit", "1")
Expand All @@ -826,6 +831,7 @@ func TestEditFileCmdStr(t *testing.T) {
{
"test",
"",
"{{editor}} {{filename}}",
func(name string, arg ...string) *exec.Cmd {
assert.Equal(t, "which", name)
return secureexec.Command("exit", "1")
Expand All @@ -848,6 +854,7 @@ func TestEditFileCmdStr(t *testing.T) {
{
"test",
"",
"{{editor}} {{filename}}",
func(name string, arg ...string) *exec.Cmd {
assert.Equal(t, "which", name)
return secureexec.Command("echo")
Expand All @@ -866,6 +873,7 @@ func TestEditFileCmdStr(t *testing.T) {
{
"file/with space",
"",
"{{editor}} {{filename}}",
func(name string, args ...string) *exec.Cmd {
assert.Equal(t, "which", name)
return secureexec.Command("echo")
Expand All @@ -881,14 +889,34 @@ func TestEditFileCmdStr(t *testing.T) {
assert.Equal(t, "vi \"file/with space\"", cmdStr)
},
},
{
"open file/at line",
"vim",
"{{editor}} +{{line}} {{filename}}",
func(name string, args ...string) *exec.Cmd {
assert.Equal(t, "which", name)
return secureexec.Command("echo")
},
func(env string) string {
return ""
},
func(cf string) (string, error) {
return "", nil
},
func(cmdStr string, err error) {
assert.NoError(t, err)
assert.Equal(t, "vim +1 \"open file/at line\"", cmdStr)
},
},
}

for _, s := range scenarios {
gitCmd := NewDummyGitCommand()
gitCmd.Config.GetUserConfig().OS.EditCommand = s.configEditCommand
gitCmd.Config.GetUserConfig().OS.EditCommandTemplate = s.configEditCommandTemplate
gitCmd.OSCommand.Command = s.command
gitCmd.OSCommand.Getenv = s.getenv
gitCmd.getGitConfigValue = s.getGitConfigValue
s.test(gitCmd.EditFileCmdStr(s.filename))
s.test(gitCmd.EditFileCmdStr(s.filename, 1))
}
}
9 changes: 8 additions & 1 deletion pkg/commands/patch/patch_modifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,14 @@ func ModifiedPatchForLines(log *logrus.Entry, filename string, diffText string,

// I want to know, given a hunk, what line a given index is on
func (hunk *PatchHunk) LineNumberOfLine(idx int) int {
lines := hunk.bodyLines[0 : idx-hunk.FirstLineIdx-1]
n := idx - hunk.FirstLineIdx - 1
if n < 0 {
n = 0
} else if n >= len(hunk.bodyLines) {
n = len(hunk.bodyLines) - 1
}

lines := hunk.bodyLines[0:n]

offset := nLinesWithPrefix(lines, []string{"+", " "})

Expand Down
7 changes: 4 additions & 3 deletions pkg/config/config_default_platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ package config
// GetPlatformDefaultConfig gets the defaults for the platform
func GetPlatformDefaultConfig() OSConfig {
return OSConfig{
EditCommand: ``,
OpenCommand: "open {{filename}}",
OpenLinkCommand: "open {{link}}",
EditCommand: ``,
EditCommandTemplate: `{{editor}} {{filename}}`,
OpenCommand: "open {{filename}}",
OpenLinkCommand: "open {{link}}",
}
}
7 changes: 4 additions & 3 deletions pkg/config/config_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package config
// GetPlatformDefaultConfig gets the defaults for the platform
func GetPlatformDefaultConfig() OSConfig {
return OSConfig{
EditCommand: ``,
OpenCommand: `sh -c "xdg-open {{filename}} >/dev/null"`,
OpenLinkCommand: `sh -c "xdg-open {{link}} >/dev/null"`,
EditCommand: ``,
EditCommandTemplate: `{{editor}} {{filename}}`,
OpenCommand: `sh -c "xdg-open {{filename}} >/dev/null"`,
OpenLinkCommand: `sh -c "xdg-open {{link}} >/dev/null"`,
}
}
7 changes: 4 additions & 3 deletions pkg/config/config_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package config
// GetPlatformDefaultConfig gets the defaults for the platform
func GetPlatformDefaultConfig() OSConfig {
return OSConfig{
EditCommand: ``,
OpenCommand: `cmd /c "start "" {{filename}}"`,
OpenLinkCommand: `cmd /c "start "" {{link}}"`,
EditCommand: ``,
EditCommandTemplate: `{{editor}} {{filename}}`,
OpenCommand: `cmd /c "start "" {{filename}}"`,
OpenLinkCommand: `cmd /c "start "" {{link}}"`,
}
}
3 changes: 3 additions & 0 deletions pkg/config/user_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,9 @@ type OSConfig struct {
// EditCommand is the command for editing a file
EditCommand string `yaml:"editCommand,omitempty"`

// EditCommandTemplate is the command template for editing a file
EditCommandTemplate string `yaml:"editCommandTemplate,omitempty"`

// OpenCommand is the command for opening a file
OpenCommand string `yaml:"openCommand,omitempty"`

Expand Down
8 changes: 6 additions & 2 deletions pkg/gui/files_panel.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,13 +474,17 @@ func (gui *Gui) handleCommitEditorPress() error {
}

func (gui *Gui) editFile(filename string) error {
cmdStr, err := gui.GitCommand.EditFileCmdStr(filename)
return gui.editFileAtLine(filename, 1)
}

func (gui *Gui) editFileAtLine(filename string, lineNumber int) error {
cmdStr, err := gui.GitCommand.EditFileCmdStr(filename, lineNumber)
if err != nil {
return gui.surfaceError(err)
}

return gui.runSubprocessWithSuspenseAndRefresh(
gui.OSCommand.WithSpan(gui.Tr.Spans.EditFile).PrepareShellSubProcess(cmdStr),
gui.OSCommand.WithSpan(gui.Tr.Spans.EditFile).ShellCommandFromString(cmdStr),
)
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/gui/keybindings.go
Original file line number Diff line number Diff line change
Expand Up @@ -1301,7 +1301,7 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
ViewName: "main",
Contexts: []string{string(MAIN_STAGING_CONTEXT_KEY)},
Key: gui.getKey(config.Universal.Edit),
Handler: gui.handleFileEdit,
Handler: gui.handleLineByLineEdit,
Description: gui.Tr.LcEditFile,
},
{
Expand Down
10 changes: 10 additions & 0 deletions pkg/gui/line_by_line_panel.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,3 +272,13 @@ func (gui *Gui) withLBLActiveCheck(f func(*LblPanelState) error) error {

return f(state)
}

func (gui *Gui) handleLineByLineEdit() error {
file := gui.getSelectedFile()
if file == nil {
return nil
}

lineNumber := gui.State.Panels.LineByLine.CurrentLineNumber()
return gui.editFileAtLine(file.Name, lineNumber)
}

0 comments on commit 487ad19

Please sign in to comment.