use 'suspend' instead of 'editInTerminal' internally

'suspend' is a more appropriate name, especially now that you can choose not to suspend despite
still being in a terminal
This commit is contained in:
Jesse Duffield 2023-08-09 21:34:51 +10:00
parent ca08956f77
commit 9c5eedf748
7 changed files with 75 additions and 73 deletions

View file

@ -306,7 +306,9 @@ os:
### Configuring File Editing ### Configuring File Editing
There are two commands for opening files, `o` for "open" and `e` for "edit". `o` acts as if the file was double-clicked in the Finder/Explorer, so it also works for non-text files, whereas `e` opens the file in an editor. `e` can also jump to the right line in the file if you invoke it from the staging panel, for example. To tell lazygit which editor to use for the `e` command, the easiest way to do that is to provide an editPreset config, e.g. There are two commands for opening files, `o` for "open" and `e` for "edit". `o` acts as if the file was double-clicked in the Finder/Explorer, so it also works for non-text files, whereas `e` opens the file in an editor. `e` can also jump to the right line in the file if you invoke it from the staging panel, for example.
To tell lazygit which editor to use for the `e` command, the easiest way to do that is to provide an editPreset config, e.g.
```yaml ```yaml
os: os:
@ -328,7 +330,7 @@ os:
openDirInEditor: 'myeditor {{dir}}' openDirInEditor: 'myeditor {{dir}}'
``` ```
The `editInTerminal` option is used to decide whether lazygit needs to suspend itself to the background before calling the editor. The `editInTerminal` option is used to decide whether lazygit needs to suspend itself to the background before calling the editor. It should really be named `suspend` because for some cases like when lazygit is opened from within a neovim session and you're using the `nvim-remote` preset, you're technically still in a terminal. Nonetheless we're sticking with the name `editInTerminal` for backwards compatibility.
Contributions of new editor presets are welcome; see the `getPreset` function in [`editor_presets.go`](https://github.com/jesseduffield/lazygit/blob/master/pkg/config/editor_presets.go). Contributions of new editor presets are welcome; see the `getPreset` function in [`editor_presets.go`](https://github.com/jesseduffield/lazygit/blob/master/pkg/config/editor_presets.go).

View file

@ -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{ templateValues := map[string]string{
"filename": self.cmd.Quote(filename), "filename": self.cmd.Quote(filename),
} }
cmdStr := utils.ResolvePlaceholderString(template, templateValues) cmdStr := utils.ResolvePlaceholderString(template, templateValues)
return cmdStr, editInTerminal return cmdStr, suspend
} }
func (self *FileCommands) GetEditAtLineCmdStr(filename string, lineNumber int) (string, bool) { 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{ templateValues := map[string]string{
"filename": self.cmd.Quote(filename), "filename": self.cmd.Quote(filename),
@ -109,7 +109,7 @@ func (self *FileCommands) GetEditAtLineCmdStr(filename string, lineNumber int) (
} }
cmdStr := utils.ResolvePlaceholderString(template, templateValues) cmdStr := utils.ResolvePlaceholderString(template, templateValues)
return cmdStr, editInTerminal return cmdStr, suspend
} }
func (self *FileCommands) GetEditAtLineAndWaitCmdStr(filename string, lineNumber int) string { func (self *FileCommands) GetEditAtLineAndWaitCmdStr(filename string, lineNumber int) string {
@ -132,14 +132,14 @@ func (self *FileCommands) GetEditAtLineAndWaitCmdStr(filename string, lineNumber
} }
func (self *FileCommands) GetOpenDirInEditorCmdStr(path string) (string, bool) { func (self *FileCommands) GetOpenDirInEditorCmdStr(path string) (string, bool) {
template, editInTerminal := config.GetOpenDirInEditorTemplate(&self.UserConfig.OS, self.guessDefaultEditor) template, suspend := config.GetOpenDirInEditorTemplate(&self.UserConfig.OS, self.guessDefaultEditor)
templateValues := map[string]string{ templateValues := map[string]string{
"dir": self.cmd.Quote(path), "dir": self.cmd.Quote(path),
} }
cmdStr := utils.ResolvePlaceholderString(template, templateValues) cmdStr := utils.ResolvePlaceholderString(template, templateValues)
return cmdStr, editInTerminal return cmdStr, suspend
} }
func (self *FileCommands) guessDefaultEditor() string { func (self *FileCommands) guessDefaultEditor() string {

View file

@ -179,34 +179,34 @@ func TestEditFileCmdStrLegacy(t *testing.T) {
func TestEditFileCmd(t *testing.T) { func TestEditFileCmd(t *testing.T) {
type scenario struct { type scenario struct {
filename string filename string
osConfig config.OSConfig osConfig config.OSConfig
expectedCmdStr string expectedCmdStr string
expectedEditInTerminal bool suspend bool
} }
scenarios := []scenario{ scenarios := []scenario{
{ {
filename: "test", filename: "test",
osConfig: config.OSConfig{}, osConfig: config.OSConfig{},
expectedCmdStr: `vim -- "test"`, expectedCmdStr: `vim -- "test"`,
expectedEditInTerminal: true, suspend: true,
}, },
{ {
filename: "test", filename: "test",
osConfig: config.OSConfig{ osConfig: config.OSConfig{
Edit: "nano {{filename}}", Edit: "nano {{filename}}",
}, },
expectedCmdStr: `nano "test"`, expectedCmdStr: `nano "test"`,
expectedEditInTerminal: true, suspend: true,
}, },
{ {
filename: "file/with space", filename: "file/with space",
osConfig: config.OSConfig{ osConfig: config.OSConfig{
EditPreset: "sublime", EditPreset: "sublime",
}, },
expectedCmdStr: `subl -- "file/with space"`, expectedCmdStr: `subl -- "file/with space"`,
expectedEditInTerminal: false, suspend: false,
}, },
} }
@ -218,28 +218,28 @@ func TestEditFileCmd(t *testing.T) {
userConfig: userConfig, userConfig: userConfig,
}) })
cmdStr, editInTerminal := instance.GetEditCmdStr(s.filename) cmdStr, suspend := instance.GetEditCmdStr(s.filename)
assert.Equal(t, s.expectedCmdStr, cmdStr) assert.Equal(t, s.expectedCmdStr, cmdStr)
assert.Equal(t, s.expectedEditInTerminal, editInTerminal) assert.Equal(t, s.suspend, suspend)
} }
} }
func TestEditFileAtLineCmd(t *testing.T) { func TestEditFileAtLineCmd(t *testing.T) {
type scenario struct { type scenario struct {
filename string filename string
lineNumber int lineNumber int
osConfig config.OSConfig osConfig config.OSConfig
expectedCmdStr string expectedCmdStr string
expectedEditInTerminal bool suspend bool
} }
scenarios := []scenario{ scenarios := []scenario{
{ {
filename: "test", filename: "test",
lineNumber: 42, lineNumber: 42,
osConfig: config.OSConfig{}, osConfig: config.OSConfig{},
expectedCmdStr: `vim +42 -- "test"`, expectedCmdStr: `vim +42 -- "test"`,
expectedEditInTerminal: true, suspend: true,
}, },
{ {
filename: "test", filename: "test",
@ -247,8 +247,8 @@ func TestEditFileAtLineCmd(t *testing.T) {
osConfig: config.OSConfig{ osConfig: config.OSConfig{
EditAtLine: "nano +{{line}} {{filename}}", EditAtLine: "nano +{{line}} {{filename}}",
}, },
expectedCmdStr: `nano +35 "test"`, expectedCmdStr: `nano +35 "test"`,
expectedEditInTerminal: true, suspend: true,
}, },
{ {
filename: "file/with space", filename: "file/with space",
@ -256,8 +256,8 @@ func TestEditFileAtLineCmd(t *testing.T) {
osConfig: config.OSConfig{ osConfig: config.OSConfig{
EditPreset: "sublime", EditPreset: "sublime",
}, },
expectedCmdStr: `subl -- "file/with space":12`, expectedCmdStr: `subl -- "file/with space":12`,
expectedEditInTerminal: false, suspend: false,
}, },
} }
@ -269,9 +269,9 @@ func TestEditFileAtLineCmd(t *testing.T) {
userConfig: userConfig, 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.expectedCmdStr, cmdStr)
assert.Equal(t, s.expectedEditInTerminal, editInTerminal) assert.Equal(t, s.suspend, suspend)
} }
} }

View file

@ -42,7 +42,7 @@ type editPreset struct {
editAtLineTemplate string editAtLineTemplate string
editAtLineAndWaitTemplate string editAtLineAndWaitTemplate string
openDirInEditorTemplate 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 // IF YOU ADD A PRESET TO THIS FUNCTION YOU MUST UPDATE THE `Supported presets` SECTION OF docs/Config.md
@ -57,7 +57,7 @@ func getPreset(osConfig *OSConfig, guessDefaultEditor func() string) *editPreset
// No remote-wait support yet. See https://github.com/neovim/neovim/pull/17856 // No remote-wait support yet. See https://github.com/neovim/neovim/pull/17856
editAtLineAndWaitTemplate: `nvim +{{line}} {{filename}}`, editAtLineAndWaitTemplate: `nvim +{{line}} {{filename}}`,
openDirInEditorTemplate: `nvim --server "$NVIM" --remote-tab {{dir}}`, openDirInEditorTemplate: `nvim --server "$NVIM" --remote-tab {{dir}}`,
editInTerminal: false, suspend: false,
}, },
"emacs": standardTerminalEditorPreset("emacs"), "emacs": standardTerminalEditorPreset("emacs"),
"nano": standardTerminalEditorPreset("nano"), "nano": standardTerminalEditorPreset("nano"),
@ -67,35 +67,35 @@ func getPreset(osConfig *OSConfig, guessDefaultEditor func() string) *editPreset
editAtLineTemplate: "hx -- {{filename}}:{{line}}", editAtLineTemplate: "hx -- {{filename}}:{{line}}",
editAtLineAndWaitTemplate: "hx -- {{filename}}:{{line}}", editAtLineAndWaitTemplate: "hx -- {{filename}}:{{line}}",
openDirInEditorTemplate: "hx -- {{dir}}", openDirInEditorTemplate: "hx -- {{dir}}",
editInTerminal: true, suspend: true,
}, },
"vscode": { "vscode": {
editTemplate: "code --reuse-window -- {{filename}}", editTemplate: "code --reuse-window -- {{filename}}",
editAtLineTemplate: "code --reuse-window --goto -- {{filename}}:{{line}}", editAtLineTemplate: "code --reuse-window --goto -- {{filename}}:{{line}}",
editAtLineAndWaitTemplate: "code --reuse-window --goto --wait -- {{filename}}:{{line}}", editAtLineAndWaitTemplate: "code --reuse-window --goto --wait -- {{filename}}:{{line}}",
openDirInEditorTemplate: "code -- {{dir}}", openDirInEditorTemplate: "code -- {{dir}}",
editInTerminal: false, suspend: false,
}, },
"sublime": { "sublime": {
editTemplate: "subl -- {{filename}}", editTemplate: "subl -- {{filename}}",
editAtLineTemplate: "subl -- {{filename}}:{{line}}", editAtLineTemplate: "subl -- {{filename}}:{{line}}",
editAtLineAndWaitTemplate: "subl --wait -- {{filename}}:{{line}}", editAtLineAndWaitTemplate: "subl --wait -- {{filename}}:{{line}}",
openDirInEditorTemplate: "subl -- {{dir}}", openDirInEditorTemplate: "subl -- {{dir}}",
editInTerminal: false, suspend: false,
}, },
"bbedit": { "bbedit": {
editTemplate: "bbedit -- {{filename}}", editTemplate: "bbedit -- {{filename}}",
editAtLineTemplate: "bbedit +{{line}} -- {{filename}}", editAtLineTemplate: "bbedit +{{line}} -- {{filename}}",
editAtLineAndWaitTemplate: "bbedit +{{line}} --wait -- {{filename}}", editAtLineAndWaitTemplate: "bbedit +{{line}} --wait -- {{filename}}",
openDirInEditorTemplate: "bbedit -- {{dir}}", openDirInEditorTemplate: "bbedit -- {{dir}}",
editInTerminal: false, suspend: false,
}, },
"xcode": { "xcode": {
editTemplate: "xed -- {{filename}}", editTemplate: "xed -- {{filename}}",
editAtLineTemplate: "xed --line {{line}} -- {{filename}}", editAtLineTemplate: "xed --line {{line}} -- {{filename}}",
editAtLineAndWaitTemplate: "xed --line {{line}} --wait -- {{filename}}", editAtLineAndWaitTemplate: "xed --line {{line}} --wait -- {{filename}}",
openDirInEditorTemplate: "xed -- {{dir}}", openDirInEditorTemplate: "xed -- {{dir}}",
editInTerminal: false, suspend: false,
}, },
} }
@ -131,13 +131,13 @@ func standardTerminalEditorPreset(editor string) *editPreset {
editAtLineTemplate: editor + " +{{line}} -- {{filename}}", editAtLineTemplate: editor + " +{{line}} -- {{filename}}",
editAtLineAndWaitTemplate: editor + " +{{line}} -- {{filename}}", editAtLineAndWaitTemplate: editor + " +{{line}} -- {{filename}}",
openDirInEditorTemplate: editor + " -- {{dir}}", openDirInEditorTemplate: editor + " -- {{dir}}",
editInTerminal: true, suspend: true,
} }
} }
func getEditInTerminal(osConfig *OSConfig, preset *editPreset) bool { func getEditInTerminal(osConfig *OSConfig, preset *editPreset) bool {
if osConfig.EditInTerminal != nil { if osConfig.SuspendOnEdit != nil {
return *osConfig.EditInTerminal return *osConfig.SuspendOnEdit
} }
return preset.editInTerminal return preset.suspend
} }

View file

@ -16,7 +16,7 @@ func TestGetEditTemplate(t *testing.T) {
expectedEditTemplate string expectedEditTemplate string
expectedEditAtLineTemplate string expectedEditAtLineTemplate string
expectedEditAtLineAndWaitTemplate string expectedEditAtLineAndWaitTemplate string
expectedEditInTerminal bool expectedSuspend bool
}{ }{
{ {
"Default template is vim", "Default template is vim",
@ -52,9 +52,9 @@ func TestGetEditTemplate(t *testing.T) {
{ {
"Overriding a preset with explicit config (edit)", "Overriding a preset with explicit config (edit)",
&OSConfig{ &OSConfig{
EditPreset: "vscode", EditPreset: "vscode",
Edit: "myeditor {{filename}}", Edit: "myeditor {{filename}}",
EditInTerminal: &trueVal, SuspendOnEdit: &trueVal,
}, },
func() string { return "" }, func() string { return "" },
"myeditor {{filename}}", "myeditor {{filename}}",
@ -65,9 +65,9 @@ func TestGetEditTemplate(t *testing.T) {
{ {
"Overriding a preset with explicit config (edit at line)", "Overriding a preset with explicit config (edit at line)",
&OSConfig{ &OSConfig{
EditPreset: "vscode", EditPreset: "vscode",
EditAtLine: "myeditor --line={{line}} {{filename}}", EditAtLine: "myeditor --line={{line}} {{filename}}",
EditInTerminal: &trueVal, SuspendOnEdit: &trueVal,
}, },
func() string { return "" }, func() string { return "" },
"code --reuse-window -- {{filename}}", "code --reuse-window -- {{filename}}",
@ -80,7 +80,7 @@ func TestGetEditTemplate(t *testing.T) {
&OSConfig{ &OSConfig{
EditPreset: "vscode", EditPreset: "vscode",
EditAtLineAndWait: "myeditor --line={{line}} -w {{filename}}", EditAtLineAndWait: "myeditor --line={{line}} -w {{filename}}",
EditInTerminal: &trueVal, SuspendOnEdit: &trueVal,
}, },
func() string { return "" }, func() string { return "" },
"code --reuse-window -- {{filename}}", "code --reuse-window -- {{filename}}",
@ -111,13 +111,13 @@ func TestGetEditTemplate(t *testing.T) {
} }
for _, s := range scenarios { for _, s := range scenarios {
t.Run(s.name, func(t *testing.T) { 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.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.expectedEditAtLineTemplate, template)
assert.Equal(t, s.expectedEditInTerminal, editInTerminal) assert.Equal(t, s.expectedSuspend, suspend)
template = GetEditAtLineAndWaitTemplate(s.osConfig, s.guessDefaultEditor) template = GetEditAtLineAndWaitTemplate(s.osConfig, s.guessDefaultEditor)
assert.Equal(t, s.expectedEditAtLineAndWaitTemplate, template) assert.Equal(t, s.expectedEditAtLineAndWaitTemplate, template)

View file

@ -316,10 +316,10 @@ type OSConfig struct {
// window is closed. // window is closed.
EditAtLineAndWait string `yaml:"editAtLineAndWait,omitempty"` EditAtLineAndWait string `yaml:"editAtLineAndWait,omitempty"`
// Whether the given edit commands use the terminal. Used to decide whether // Whether lazygit suspends until an edit process returns
// lazygit needs to suspend to the background before calling the editor.
// Pointer to bool so that we can distinguish unset (nil) from false. // 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 // For opening a directory in an editor
OpenDirInEditor string `yaml:"openDirInEditor,omitempty"` OpenDirInEditor string `yaml:"openDirInEditor,omitempty"`

View file

@ -19,32 +19,32 @@ func NewFilesHelper(c *HelperCommon) *FilesHelper {
var _ IFilesHelper = &FilesHelper{} var _ IFilesHelper = &FilesHelper{}
func (self *FilesHelper) EditFile(filename string) error { func (self *FilesHelper) EditFile(filename string) error {
cmdStr, editInTerminal := self.c.Git().File.GetEditCmdStr(filename) cmdStr, suspend := self.c.Git().File.GetEditCmdStr(filename)
return self.callEditor(cmdStr, editInTerminal) return self.callEditor(cmdStr, suspend)
} }
func (self *FilesHelper) EditFileAtLine(filename string, lineNumber int) error { func (self *FilesHelper) EditFileAtLine(filename string, lineNumber int) error {
cmdStr, editInTerminal := self.c.Git().File.GetEditAtLineCmdStr(filename, lineNumber) cmdStr, suspend := self.c.Git().File.GetEditAtLineCmdStr(filename, lineNumber)
return self.callEditor(cmdStr, editInTerminal) return self.callEditor(cmdStr, suspend)
} }
func (self *FilesHelper) EditFileAtLineAndWait(filename string, lineNumber int) error { func (self *FilesHelper) EditFileAtLineAndWait(filename string, lineNumber int) error {
cmdStr := self.c.Git().File.GetEditAtLineAndWaitCmdStr(filename, lineNumber) 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 // since we want to prevent interacting with the UI until the editor
// returns, even if the editor doesn't use the terminal // returns, even if the editor doesn't use the terminal
return self.callEditor(cmdStr, true) return self.callEditor(cmdStr, true)
} }
func (self *FilesHelper) OpenDirInEditor(path string) error { func (self *FilesHelper) OpenDirInEditor(path string) error {
cmdStr, editInTerminal := self.c.Git().File.GetOpenDirInEditorCmdStr(path) cmdStr, suspend := self.c.Git().File.GetOpenDirInEditorCmdStr(path)
return self.callEditor(cmdStr, editInTerminal) return self.callEditor(cmdStr, suspend)
} }
func (self *FilesHelper) callEditor(cmdStr string, editInTerminal bool) error { func (self *FilesHelper) callEditor(cmdStr string, suspend bool) error {
if editInTerminal { if suspend {
return self.c.RunSubprocessAndRefresh( return self.c.RunSubprocessAndRefresh(
self.c.OS().Cmd.NewShell(cmdStr), self.c.OS().Cmd.NewShell(cmdStr),
) )