diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2023-08-10 17:23:58 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-10 17:23:58 +1000 |
commit | c43830b0271374ab42e83771479bf757ba34839c (patch) | |
tree | b7036d76b28a624a8f573bed5c0c7f63ee366d1c /pkg | |
parent | 08624b8ef724e1c83fcaffea7d72765414065e01 (diff) | |
parent | 9c5eedf748aaf26ed2042aa20babc42fa13eca41 (diff) |
Support editing files in existing neovim instance (#2916)
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/commands/git_commands/file.go | 14 | ||||
-rw-r--r-- | pkg/commands/git_commands/file_test.go | 60 | ||||
-rw-r--r-- | pkg/config/editor_presets.go | 38 | ||||
-rw-r--r-- | pkg/config/editor_presets_test.go | 24 | ||||
-rw-r--r-- | pkg/config/user_config.go | 6 | ||||
-rw-r--r-- | pkg/gui/controllers/helpers/files_helper.go | 19 |
6 files changed, 84 insertions, 77 deletions
diff --git a/pkg/commands/git_commands/file.go b/pkg/commands/git_commands/file.go index 7efdb567a..173e342f7 100644 --- a/pkg/commands/git_commands/file.go +++ b/pkg/commands/git_commands/file.go @@ -83,14 +83,14 @@ func (self *FileCommands) GetEditCmdStr(filename string) (string, bool) { } } - template, editInTerminal := config.GetEditTemplate(&self.UserConfig.OS, self.guessDefaultEditor) + template, suspend := config.GetEditTemplate(&self.UserConfig.OS, self.guessDefaultEditor) templateValues := map[string]string{ "filename": self.cmd.Quote(filename), } cmdStr := utils.ResolvePlaceholderString(template, templateValues) - return cmdStr, editInTerminal + return cmdStr, suspend } func (self *FileCommands) GetEditAtLineCmdStr(filename string, lineNumber int) (string, bool) { @@ -101,7 +101,7 @@ func (self *FileCommands) GetEditAtLineCmdStr(filename string, lineNumber int) ( } } - template, editInTerminal := config.GetEditAtLineTemplate(&self.UserConfig.OS, self.guessDefaultEditor) + template, suspend := config.GetEditAtLineTemplate(&self.UserConfig.OS, self.guessDefaultEditor) templateValues := map[string]string{ "filename": self.cmd.Quote(filename), @@ -109,7 +109,7 @@ func (self *FileCommands) GetEditAtLineCmdStr(filename string, lineNumber int) ( } cmdStr := utils.ResolvePlaceholderString(template, templateValues) - return cmdStr, editInTerminal + return cmdStr, suspend } func (self *FileCommands) GetEditAtLineAndWaitCmdStr(filename string, lineNumber int) string { @@ -131,15 +131,15 @@ func (self *FileCommands) GetEditAtLineAndWaitCmdStr(filename string, lineNumber return cmdStr } -func (self *FileCommands) GetOpenDirInEditorCmdStr(path string) string { - template := config.GetOpenDirInEditorTemplate(&self.UserConfig.OS, self.guessDefaultEditor) +func (self *FileCommands) GetOpenDirInEditorCmdStr(path string) (string, bool) { + template, suspend := config.GetOpenDirInEditorTemplate(&self.UserConfig.OS, self.guessDefaultEditor) templateValues := map[string]string{ "dir": self.cmd.Quote(path), } cmdStr := utils.ResolvePlaceholderString(template, templateValues) - return cmdStr + return cmdStr, suspend } func (self *FileCommands) guessDefaultEditor() string { diff --git a/pkg/commands/git_commands/file_test.go b/pkg/commands/git_commands/file_test.go index 1141a3577..c87e56683 100644 --- a/pkg/commands/git_commands/file_test.go +++ b/pkg/commands/git_commands/file_test.go @@ -179,34 +179,34 @@ func TestEditFileCmdStrLegacy(t *testing.T) { func TestEditFileCmd(t *testing.T) { type scenario struct { - filename string - osConfig config.OSConfig - expectedCmdStr string - expectedEditInTerminal bool + filename string + osConfig config.OSConfig + expectedCmdStr string + suspend bool } scenarios := []scenario{ { - filename: "test", - osConfig: config.OSConfig{}, - expectedCmdStr: `vim -- "test"`, - expectedEditInTerminal: true, + filename: "test", + osConfig: config.OSConfig{}, + expectedCmdStr: `vim -- "test"`, + suspend: true, }, { filename: "test", osConfig: config.OSConfig{ Edit: "nano {{filename}}", }, - expectedCmdStr: `nano "test"`, - expectedEditInTerminal: true, + expectedCmdStr: `nano "test"`, + suspend: true, }, { filename: "file/with space", osConfig: config.OSConfig{ EditPreset: "sublime", }, - expectedCmdStr: `subl -- "file/with space"`, - expectedEditInTerminal: false, + expectedCmdStr: `subl -- "file/with space"`, + suspend: false, }, } @@ -218,28 +218,28 @@ func TestEditFileCmd(t *testing.T) { userConfig: userConfig, }) - cmdStr, editInTerminal := instance.GetEditCmdStr(s.filename) + cmdStr, suspend := instance.GetEditCmdStr(s.filename) assert.Equal(t, s.expectedCmdStr, cmdStr) - assert.Equal(t, s.expectedEditInTerminal, editInTerminal) + assert.Equal(t, s.suspend, suspend) } } func TestEditFileAtLineCmd(t *testing.T) { type scenario struct { - filename string - lineNumber int - osConfig config.OSConfig - expectedCmdStr string - expectedEditInTerminal bool + filename string + lineNumber int + osConfig config.OSConfig + expectedCmdStr string + suspend bool } scenarios := []scenario{ { - filename: "test", - lineNumber: 42, - osConfig: config.OSConfig{}, - expectedCmdStr: `vim +42 -- "test"`, - expectedEditInTerminal: true, + filename: "test", + lineNumber: 42, + osConfig: config.OSConfig{}, + expectedCmdStr: `vim +42 -- "test"`, + suspend: true, }, { filename: "test", @@ -247,8 +247,8 @@ func TestEditFileAtLineCmd(t *testing.T) { osConfig: config.OSConfig{ EditAtLine: "nano +{{line}} {{filename}}", }, - expectedCmdStr: `nano +35 "test"`, - expectedEditInTerminal: true, + expectedCmdStr: `nano +35 "test"`, + suspend: true, }, { filename: "file/with space", @@ -256,8 +256,8 @@ func TestEditFileAtLineCmd(t *testing.T) { osConfig: config.OSConfig{ EditPreset: "sublime", }, - expectedCmdStr: `subl -- "file/with space":12`, - expectedEditInTerminal: false, + expectedCmdStr: `subl -- "file/with space":12`, + suspend: false, }, } @@ -269,9 +269,9 @@ func TestEditFileAtLineCmd(t *testing.T) { userConfig: userConfig, }) - cmdStr, editInTerminal := instance.GetEditAtLineCmdStr(s.filename, s.lineNumber) + cmdStr, suspend := instance.GetEditAtLineCmdStr(s.filename, s.lineNumber) assert.Equal(t, s.expectedCmdStr, cmdStr) - assert.Equal(t, s.expectedEditInTerminal, editInTerminal) + assert.Equal(t, s.suspend, suspend) } } diff --git a/pkg/config/editor_presets.go b/pkg/config/editor_presets.go index 121401424..17850c7a5 100644 --- a/pkg/config/editor_presets.go +++ b/pkg/config/editor_presets.go @@ -28,13 +28,13 @@ func GetEditAtLineAndWaitTemplate(osConfig *OSConfig, guessDefaultEditor func() return template } -func GetOpenDirInEditorTemplate(osConfig *OSConfig, guessDefaultEditor func() string) string { +func GetOpenDirInEditorTemplate(osConfig *OSConfig, guessDefaultEditor func() string) (string, bool) { preset := getPreset(osConfig, guessDefaultEditor) template := osConfig.OpenDirInEditor if template == "" { template = preset.openDirInEditorTemplate } - return template + return template, getEditInTerminal(osConfig, preset) } type editPreset struct { @@ -42,15 +42,23 @@ type editPreset struct { editAtLineTemplate string editAtLineAndWaitTemplate string openDirInEditorTemplate string - editInTerminal bool + suspend bool } // IF YOU ADD A PRESET TO THIS FUNCTION YOU MUST UPDATE THE `Supported presets` SECTION OF docs/Config.md func getPreset(osConfig *OSConfig, guessDefaultEditor func() string) *editPreset { presets := map[string]*editPreset{ - "vi": standardTerminalEditorPreset("vi"), - "vim": standardTerminalEditorPreset("vim"), - "nvim": standardTerminalEditorPreset("nvim"), + "vi": standardTerminalEditorPreset("vi"), + "vim": standardTerminalEditorPreset("vim"), + "nvim": standardTerminalEditorPreset("nvim"), + "nvim-remote": { + editTemplate: `nvim --server "$NVIM" --remote-tab {{filename}}`, + editAtLineTemplate: `nvim --server "$NVIM" --remote-tab {{filename}}; [ -z "$NVIM" ] || nvim --server "$NVIM" --remote-send ":{{line}}<CR>"`, + // No remote-wait support yet. See https://github.com/neovim/neovim/pull/17856 + editAtLineAndWaitTemplate: `nvim +{{line}} {{filename}}`, + openDirInEditorTemplate: `nvim --server "$NVIM" --remote-tab {{dir}}`, + suspend: false, + }, "emacs": standardTerminalEditorPreset("emacs"), "nano": standardTerminalEditorPreset("nano"), "kakoune": standardTerminalEditorPreset("kak"), @@ -59,35 +67,35 @@ func getPreset(osConfig *OSConfig, guessDefaultEditor func() string) *editPreset editAtLineTemplate: "hx -- {{filename}}:{{line}}", editAtLineAndWaitTemplate: "hx -- {{filename}}:{{line}}", openDirInEditorTemplate: "hx -- {{dir}}", - editInTerminal: true, + suspend: true, }, "vscode": { editTemplate: "code --reuse-window -- {{filename}}", editAtLineTemplate: "code --reuse-window --goto -- {{filename}}:{{line}}", editAtLineAndWaitTemplate: "code --reuse-window --goto --wait -- {{filename}}:{{line}}", openDirInEditorTemplate: "code -- {{dir}}", - editInTerminal: false, + suspend: false, }, "sublime": { editTemplate: "subl -- {{filename}}", editAtLineTemplate: "subl -- {{filename}}:{{line}}", editAtLineAndWaitTemplate: "subl --wait -- {{filename}}:{{line}}", openDirInEditorTemplate: "subl -- {{dir}}", - editInTerminal: false, + suspend: false, }, "bbedit": { editTemplate: "bbedit -- {{filename}}", editAtLineTemplate: "bbedit +{{line}} -- {{filename}}", editAtLineAndWaitTemplate: "bbedit +{{line}} --wait -- {{filename}}", openDirInEditorTemplate: "bbedit -- {{dir}}", - editInTerminal: false, + suspend: false, }, "xcode": { editTemplate: "xed -- {{filename}}", editAtLineTemplate: "xed --line {{line}} -- {{filename}}", editAtLineAndWaitTemplate: "xed --line {{line}} --wait -- {{filename}}", openDirInEditorTemplate: "xed -- {{dir}}", - editInTerminal: false, + suspend: false, }, } @@ -123,13 +131,13 @@ func standardTerminalEditorPreset(editor string) *editPreset { editAtLineTemplate: editor + " +{{line}} -- {{filename}}", editAtLineAndWaitTemplate: editor + " +{{line}} -- {{filename}}", openDirInEditorTemplate: editor + " -- {{dir}}", - editInTerminal: true, + suspend: true, } } func getEditInTerminal(osConfig *OSConfig, preset *editPreset) bool { - if osConfig.EditInTerminal != nil { - return *osConfig.EditInTerminal + if osConfig.SuspendOnEdit != nil { + return *osConfig.SuspendOnEdit } - return preset.editInTerminal + return preset.suspend } diff --git a/pkg/config/editor_presets_test.go b/pkg/config/editor_presets_test.go index 1d73df8c6..1a6cb0963 100644 --- a/pkg/config/editor_presets_test.go +++ b/pkg/config/editor_presets_test.go @@ -16,7 +16,7 @@ func TestGetEditTemplate(t *testing.T) { expectedEditTemplate string expectedEditAtLineTemplate string expectedEditAtLineAndWaitTemplate string - expectedEditInTerminal bool + expectedSuspend bool }{ { "Default template is vim", @@ -52,9 +52,9 @@ func TestGetEditTemplate(t *testing.T) { { "Overriding a preset with explicit config (edit)", &OSConfig{ - EditPreset: "vscode", - Edit: "myeditor {{filename}}", - EditInTerminal: &trueVal, + EditPreset: "vscode", + Edit: "myeditor {{filename}}", + SuspendOnEdit: &trueVal, }, func() string { return "" }, "myeditor {{filename}}", @@ -65,9 +65,9 @@ func TestGetEditTemplate(t *testing.T) { { "Overriding a preset with explicit config (edit at line)", &OSConfig{ - EditPreset: "vscode", - EditAtLine: "myeditor --line={{line}} {{filename}}", - EditInTerminal: &trueVal, + EditPreset: "vscode", + EditAtLine: "myeditor --line={{line}} {{filename}}", + SuspendOnEdit: &trueVal, }, func() string { return "" }, "code --reuse-window -- {{filename}}", @@ -80,7 +80,7 @@ func TestGetEditTemplate(t *testing.T) { &OSConfig{ EditPreset: "vscode", EditAtLineAndWait: "myeditor --line={{line}} -w {{filename}}", - EditInTerminal: &trueVal, + SuspendOnEdit: &trueVal, }, func() string { return "" }, "code --reuse-window -- {{filename}}", @@ -111,13 +111,13 @@ func TestGetEditTemplate(t *testing.T) { } for _, s := range scenarios { t.Run(s.name, func(t *testing.T) { - template, editInTerminal := GetEditTemplate(s.osConfig, s.guessDefaultEditor) + template, suspend := GetEditTemplate(s.osConfig, s.guessDefaultEditor) assert.Equal(t, s.expectedEditTemplate, template) - assert.Equal(t, s.expectedEditInTerminal, editInTerminal) + assert.Equal(t, s.expectedSuspend, suspend) - template, editInTerminal = GetEditAtLineTemplate(s.osConfig, s.guessDefaultEditor) + template, suspend = GetEditAtLineTemplate(s.osConfig, s.guessDefaultEditor) assert.Equal(t, s.expectedEditAtLineTemplate, template) - assert.Equal(t, s.expectedEditInTerminal, editInTerminal) + assert.Equal(t, s.expectedSuspend, suspend) template = GetEditAtLineAndWaitTemplate(s.osConfig, s.guessDefaultEditor) assert.Equal(t, s.expectedEditAtLineAndWaitTemplate, template) diff --git a/pkg/config/user_config.go b/pkg/config/user_config.go index 050ac7099..9eb8e028a 100644 --- a/pkg/config/user_config.go +++ b/pkg/config/user_config.go @@ -316,10 +316,10 @@ type OSConfig struct { // window is closed. EditAtLineAndWait string `yaml:"editAtLineAndWait,omitempty"` - // Whether the given edit commands use the terminal. Used to decide whether - // lazygit needs to suspend to the background before calling the editor. + // Whether lazygit suspends until an edit process returns // Pointer to bool so that we can distinguish unset (nil) from false. - EditInTerminal *bool `yaml:"editInTerminal,omitempty"` + // We're naming this `editInTerminal` for backwards compatibility + SuspendOnEdit *bool `yaml:"editInTerminal,omitempty"` // For opening a directory in an editor OpenDirInEditor string `yaml:"openDirInEditor,omitempty"` diff --git a/pkg/gui/controllers/helpers/files_helper.go b/pkg/gui/controllers/helpers/files_helper.go index 8f9a816f8..140a71127 100644 --- a/pkg/gui/controllers/helpers/files_helper.go +++ b/pkg/gui/controllers/helpers/files_helper.go @@ -19,33 +19,32 @@ func NewFilesHelper(c *HelperCommon) *FilesHelper { var _ IFilesHelper = &FilesHelper{} func (self *FilesHelper) EditFile(filename string) error { - cmdStr, editInTerminal := self.c.Git().File.GetEditCmdStr(filename) - return self.callEditor(cmdStr, editInTerminal) + cmdStr, suspend := self.c.Git().File.GetEditCmdStr(filename) + return self.callEditor(cmdStr, suspend) } func (self *FilesHelper) EditFileAtLine(filename string, lineNumber int) error { - cmdStr, editInTerminal := self.c.Git().File.GetEditAtLineCmdStr(filename, lineNumber) - return self.callEditor(cmdStr, editInTerminal) + cmdStr, suspend := self.c.Git().File.GetEditAtLineCmdStr(filename, lineNumber) + return self.callEditor(cmdStr, suspend) } func (self *FilesHelper) EditFileAtLineAndWait(filename string, lineNumber int) error { cmdStr := self.c.Git().File.GetEditAtLineAndWaitCmdStr(filename, lineNumber) - // Always suspend, regardless of the value of the editInTerminal config, + // Always suspend, regardless of the value of the suspend config, // since we want to prevent interacting with the UI until the editor // returns, even if the editor doesn't use the terminal return self.callEditor(cmdStr, true) } func (self *FilesHelper) OpenDirInEditor(path string) error { - cmdStr := self.c.Git().File.GetOpenDirInEditorCmdStr(path) + cmdStr, suspend := self.c.Git().File.GetOpenDirInEditorCmdStr(path) - // Not editing in terminal because surely that's not a thing. - return self.callEditor(cmdStr, false) + return self.callEditor(cmdStr, suspend) } -func (self *FilesHelper) callEditor(cmdStr string, editInTerminal bool) error { - if editInTerminal { +func (self *FilesHelper) callEditor(cmdStr string, suspend bool) error { + if suspend { return self.c.RunSubprocessAndRefresh( self.c.OS().Cmd.NewShell(cmdStr), ) |