Repository: jesseduffield/lazygit (language: go)

Issue:
Edit file jumps current cursor line
**Is your feature request related to a problem? Please describe.**
When partially adding a file, I would sometimes like to edit the current line before adding it, pressing `e` opens the file in `$EDITOR` which is for me `vim`, but the cursor is at the start of the file.

**Describe the solution you'd like**
`vim` can take an argument in the form of `+135` which puts the cursor on the 135th line.

**Describe alternatives you've considered**
I tried pressing `o` to _open_ the file, but then `lazygit` crashes because it tries to run `xdg-open filename:135`, which fails, and the error isn't handled well, I guess.

**Additional context**
Should I open a separate issue for `xdg-open filename:135` causing a crash?



Discussion / hints:
There is a section in the docs for configuring this to your editor: https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#configuring-file-editing

However it sounds like we should have some sensible built-in defaults for the common editors like vim, vscode, sublime, emacs, etc. I'll chuck a good-first-issue label on this for that purpose.

For anybody who wants to tackle this issue, the relevant method is `GetEditCmdStr` in `pkg/commands/git_commands/file.go`. We can check to see if `editCmdTemplate` is set to the default (i.e. `{{editor}} {{filename}}`) and if so, refer to a list of editor-specific templates.

Fix patch:
diff --git a/pkg/commands/git_commands/file.go b/pkg/commands/git_commands/file.go
index 026d79cb0f1..1837ee4a437 100644
--- a/pkg/commands/git_commands/file.go
+++ b/pkg/commands/git_commands/file.go
@@ -5,6 +5,7 @@ import (
 	"strconv"
 
 	"github.com/go-errors/errors"
+	"github.com/jesseduffield/lazygit/pkg/config"
 	"github.com/jesseduffield/lazygit/pkg/utils"
 )
 
@@ -58,5 +59,15 @@ func (self *FileCommands) GetEditCmdStr(filename string, lineNumber int) (string
 	}
 
 	editCmdTemplate := self.UserConfig.OS.EditCommandTemplate
+	if editCmdTemplate == config.DefaultEditCommandTemplate {
+		switch editor {
+		case "emacs", "nano", "vi", "vim":
+			editCmdTemplate = "{{editor}} +{{line}} {{filename}}"
+		case "subl":
+			editCmdTemplate = "{{editor}} {{filename}}:{{line}}"
+		case "code":
+			editCmdTemplate = "{{editor}} -r --goto {{filename}}:{{line}}"
+		}
+	}
 	return utils.ResolvePlaceholderString(editCmdTemplate, templateValues), nil
 }
diff --git a/pkg/config/config_default_platform.go b/pkg/config/config_default_platform.go
index 32b1df473f1..32b76cbf08f 100644
--- a/pkg/config/config_default_platform.go
+++ b/pkg/config/config_default_platform.go
@@ -3,11 +3,13 @@
 
 package config
 
+const DefaultEditCommandTemplate = `{{editor}} {{filename}}`
+
 // GetPlatformDefaultConfig gets the defaults for the platform
 func GetPlatformDefaultConfig() OSConfig {
 	return OSConfig{
 		EditCommand:         ``,
-		EditCommandTemplate: `{{editor}} {{filename}}`,
+		EditCommandTemplate: DefaultEditCommandTemplate,
 		OpenCommand:         "open {{filename}}",
 		OpenLinkCommand:     "open {{link}}",
 	}
diff --git a/pkg/config/config_linux.go b/pkg/config/config_linux.go
index dd5708a536e..93baa133509 100644
--- a/pkg/config/config_linux.go
+++ b/pkg/config/config_linux.go
@@ -1,10 +1,12 @@
 package config
 
+const DefaultEditCommandTemplate = `{{editor}} {{filename}}`
+
 // GetPlatformDefaultConfig gets the defaults for the platform
 func GetPlatformDefaultConfig() OSConfig {
 	return OSConfig{
 		EditCommand:         ``,
-		EditCommandTemplate: `{{editor}} {{filename}}`,
+		EditCommandTemplate: DefaultEditCommandTemplate,
 		OpenCommand:         `xdg-open {{filename}} >/dev/null`,
 		OpenLinkCommand:     `xdg-open {{link}} >/dev/null`,
 	}
diff --git a/pkg/config/config_windows.go b/pkg/config/config_windows.go
index 301eecec192..eb0b00728fd 100644
--- a/pkg/config/config_windows.go
+++ b/pkg/config/config_windows.go
@@ -1,10 +1,12 @@
 package config
 
+const DefaultEditCommandTemplate = `{{editor}} {{filename}}`
+
 // GetPlatformDefaultConfig gets the defaults for the platform
 func GetPlatformDefaultConfig() OSConfig {
 	return OSConfig{
 		EditCommand:         ``,
-		EditCommandTemplate: `{{editor}} {{filename}}`,
+		EditCommandTemplate: DefaultEditCommandTemplate,
 		OpenCommand:         `start "" {{filename}}`,
 		OpenLinkCommand:     `start "" {{link}}`,
 	}


Test patch:
diff --git a/pkg/commands/git_commands/file_test.go b/pkg/commands/git_commands/file_test.go
index a26699b3ee9..61482054b46 100644
--- a/pkg/commands/git_commands/file_test.go
+++ b/pkg/commands/git_commands/file_test.go
@@ -47,7 +47,7 @@ func TestEditFileCmdStr(t *testing.T) {
 			gitConfigMockResponses: nil,
 			test: func(cmdStr string, err error) {
 				assert.NoError(t, err)
-				assert.Equal(t, `nano "test"`, cmdStr)
+				assert.Equal(t, `nano +1 "test"`, cmdStr)
 			},
 		},
 		{
@@ -61,7 +61,7 @@ func TestEditFileCmdStr(t *testing.T) {
 			gitConfigMockResponses: map[string]string{"core.editor": "nano"},
 			test: func(cmdStr string, err error) {
 				assert.NoError(t, err)
-				assert.Equal(t, `nano "test"`, cmdStr)
+				assert.Equal(t, `nano +1 "test"`, cmdStr)
 			},
 		},
 		{
@@ -79,6 +79,7 @@ func TestEditFileCmdStr(t *testing.T) {
 			gitConfigMockResponses: nil,
 			test: func(cmdStr string, err error) {
 				assert.NoError(t, err)
+				assert.Equal(t, `nano +1 "test"`, cmdStr)
 			},
 		},
 		{
@@ -96,7 +97,7 @@ func TestEditFileCmdStr(t *testing.T) {
 			gitConfigMockResponses: nil,
 			test: func(cmdStr string, err error) {
 				assert.NoError(t, err)
-				assert.Equal(t, `emacs "test"`, cmdStr)
+				assert.Equal(t, `emacs +1 "test"`, cmdStr)
 			},
 		},
 		{
@@ -111,7 +112,7 @@ func TestEditFileCmdStr(t *testing.T) {
 			gitConfigMockResponses: nil,
 			test: func(cmdStr string, err error) {
 				assert.NoError(t, err)
-				assert.Equal(t, `vi "test"`, cmdStr)
+				assert.Equal(t, `vi +1 "test"`, cmdStr)
 			},
 		},
 		{
@@ -126,7 +127,7 @@ func TestEditFileCmdStr(t *testing.T) {
 			gitConfigMockResponses: nil,
 			test: func(cmdStr string, err error) {
 				assert.NoError(t, err)
-				assert.Equal(t, `vi "file/with space"`, cmdStr)
+				assert.Equal(t, `vi +1 "file/with space"`, cmdStr)
 			},
 		},
 		{