Skip to content

Commit 4d0eaea

Browse files
SavingFramestefanhaller
authored andcommitted
Fix nvim-remote commands for fish shell
Fish shell does not support "&&" and "||" operators like POSIX-compatible shells. Instead, it uses a different syntax structure based on begin/end and if/else. This caused existing lazygit nvim-remote integration templates to break when fish was the user's default shell. This commit adds explicit fish shell detection using the FISH_VERSION environment variable, and provides fish-compatible templates that correctly handle launching Neovim or sending remote commands via $NVIM. Fixes behavior where edits would not open in a new Neovim tab or line navigation would fail when $NVIM was set. Ensures smoother editing experience for users running fish shell (supported since Nov 2012 with FISH_VERSION).
1 parent 8bbfd4b commit 4d0eaea

File tree

3 files changed

+34
-20
lines changed

3 files changed

+34
-20
lines changed

pkg/commands/git_commands/file.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func (self *FileCommands) GetEditCmdStr(filenames []string) (string, bool) {
8686
}
8787
}
8888

89-
template, suspend := config.GetEditTemplate(&self.UserConfig().OS, self.guessDefaultEditor)
89+
template, suspend := config.GetEditTemplate(self.os.Platform.Shell, &self.UserConfig().OS, self.guessDefaultEditor)
9090
quotedFilenames := lo.Map(filenames, func(filename string, _ int) string { return self.cmd.Quote(filename) })
9191

9292
templateValues := map[string]string{
@@ -105,7 +105,7 @@ func (self *FileCommands) GetEditAtLineCmdStr(filename string, lineNumber int) (
105105
}
106106
}
107107

108-
template, suspend := config.GetEditAtLineTemplate(&self.UserConfig().OS, self.guessDefaultEditor)
108+
template, suspend := config.GetEditAtLineTemplate(self.os.Platform.Shell, &self.UserConfig().OS, self.guessDefaultEditor)
109109

110110
templateValues := map[string]string{
111111
"filename": self.cmd.Quote(filename),
@@ -124,7 +124,7 @@ func (self *FileCommands) GetEditAtLineAndWaitCmdStr(filename string, lineNumber
124124
}
125125
}
126126

127-
template := config.GetEditAtLineAndWaitTemplate(&self.UserConfig().OS, self.guessDefaultEditor)
127+
template := config.GetEditAtLineAndWaitTemplate(self.os.Platform.Shell, &self.UserConfig().OS, self.guessDefaultEditor)
128128

129129
templateValues := map[string]string{
130130
"filename": self.cmd.Quote(filename),
@@ -136,7 +136,7 @@ func (self *FileCommands) GetEditAtLineAndWaitCmdStr(filename string, lineNumber
136136
}
137137

138138
func (self *FileCommands) GetOpenDirInEditorCmdStr(path string) (string, bool) {
139-
template, suspend := config.GetOpenDirInEditorTemplate(&self.UserConfig().OS, self.guessDefaultEditor)
139+
template, suspend := config.GetOpenDirInEditorTemplate(self.os.Platform.Shell, &self.UserConfig().OS, self.guessDefaultEditor)
140140

141141
templateValues := map[string]string{
142142
"dir": self.cmd.Quote(path),

pkg/config/editor_presets.go

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package config
22

3-
import "os"
3+
import (
4+
"os"
5+
"strings"
6+
)
47

5-
func GetEditTemplate(osConfig *OSConfig, guessDefaultEditor func() string) (string, bool) {
6-
preset := getPreset(osConfig, guessDefaultEditor)
8+
func GetEditTemplate(shell string, osConfig *OSConfig, guessDefaultEditor func() string) (string, bool) {
9+
preset := getPreset(shell, osConfig, guessDefaultEditor)
710
template := osConfig.Edit
811
if template == "" {
912
template = preset.editTemplate
@@ -12,26 +15,26 @@ func GetEditTemplate(osConfig *OSConfig, guessDefaultEditor func() string) (stri
1215
return template, getEditInTerminal(osConfig, preset)
1316
}
1417

15-
func GetEditAtLineTemplate(osConfig *OSConfig, guessDefaultEditor func() string) (string, bool) {
16-
preset := getPreset(osConfig, guessDefaultEditor)
18+
func GetEditAtLineTemplate(shell string, osConfig *OSConfig, guessDefaultEditor func() string) (string, bool) {
19+
preset := getPreset(shell, osConfig, guessDefaultEditor)
1720
template := osConfig.EditAtLine
1821
if template == "" {
1922
template = preset.editAtLineTemplate
2023
}
2124
return template, getEditInTerminal(osConfig, preset)
2225
}
2326

24-
func GetEditAtLineAndWaitTemplate(osConfig *OSConfig, guessDefaultEditor func() string) string {
25-
preset := getPreset(osConfig, guessDefaultEditor)
27+
func GetEditAtLineAndWaitTemplate(shell string, osConfig *OSConfig, guessDefaultEditor func() string) string {
28+
preset := getPreset(shell, osConfig, guessDefaultEditor)
2629
template := osConfig.EditAtLineAndWait
2730
if template == "" {
2831
template = preset.editAtLineAndWaitTemplate
2932
}
3033
return template
3134
}
3235

33-
func GetOpenDirInEditorTemplate(osConfig *OSConfig, guessDefaultEditor func() string) (string, bool) {
34-
preset := getPreset(osConfig, guessDefaultEditor)
36+
func GetOpenDirInEditorTemplate(shell string, osConfig *OSConfig, guessDefaultEditor func() string) (string, bool) {
37+
preset := getPreset(shell, osConfig, guessDefaultEditor)
3538
template := osConfig.OpenDirInEditor
3639
if template == "" {
3740
template = preset.openDirInEditorTemplate
@@ -50,17 +53,28 @@ type editPreset struct {
5053
func returnBool(a bool) func() bool { return (func() bool { return a }) }
5154

5255
// IF YOU ADD A PRESET TO THIS FUNCTION YOU MUST UPDATE THE `Supported presets` SECTION OF docs/Config.md
53-
func getPreset(osConfig *OSConfig, guessDefaultEditor func() string) *editPreset {
56+
func getPreset(shell string, osConfig *OSConfig, guessDefaultEditor func() string) *editPreset {
57+
var nvimRemoteEditTemplate, nvimRemoteEditAtLineTemplate, nvimRemoteOpenDirInEditorTemplate string
58+
// By default fish doesn't have SHELL variable set, but it does have FISH_VERSION since Nov 2012.
59+
if (strings.HasSuffix(shell, "fish")) || (os.Getenv("FISH_VERSION") != "") {
60+
nvimRemoteEditTemplate = `begin; if test -z "$NVIM"; nvim -- {{filename}}; else; nvim --server "$NVIM" --remote-send "q"; nvim --server "$NVIM" --remote-tab {{filename}}; end; end`
61+
nvimRemoteEditAtLineTemplate = `begin; if test -z "$NVIM"; nvim +{{line}} -- {{filename}}; else; nvim --server "$NVIM" --remote-send "q"; nvim --server "$NVIM" --remote-tab {{filename}}; nvim --server "$NVIM" --remote-send ":{{line}}<CR>"; end; end`
62+
nvimRemoteOpenDirInEditorTemplate = `begin; if test -z "$NVIM"; nvim -- {{dir}}; else; nvim --server "$NVIM" --remote-send "q"; nvim --server "$NVIM" --remote-tab {{dir}}; end; end`
63+
} else {
64+
nvimRemoteEditTemplate = `[ -z "$NVIM" ] && (nvim -- {{filename}}) || (nvim --server "$NVIM" --remote-send "q" && nvim --server "$NVIM" --remote-tab {{filename}})`
65+
nvimRemoteEditAtLineTemplate = `[ -z "$NVIM" ] && (nvim +{{line}} -- {{filename}}) || (nvim --server "$NVIM" --remote-send "q" && nvim --server "$NVIM" --remote-tab {{filename}} && nvim --server "$NVIM" --remote-send ":{{line}}<CR>")`
66+
nvimRemoteOpenDirInEditorTemplate = `[ -z "$NVIM" ] && (nvim -- {{dir}}) || (nvim --server "$NVIM" --remote-send "q" && nvim --server "$NVIM" --remote-tab {{dir}})`
67+
}
5468
presets := map[string]*editPreset{
5569
"vi": standardTerminalEditorPreset("vi"),
5670
"vim": standardTerminalEditorPreset("vim"),
5771
"nvim": standardTerminalEditorPreset("nvim"),
5872
"nvim-remote": {
59-
editTemplate: `[ -z "$NVIM" ] && (nvim -- {{filename}}) || (nvim --server "$NVIM" --remote-send "q" && nvim --server "$NVIM" --remote-tab {{filename}})`,
60-
editAtLineTemplate: `[ -z "$NVIM" ] && (nvim +{{line}} -- {{filename}}) || (nvim --server "$NVIM" --remote-send "q" && nvim --server "$NVIM" --remote-tab {{filename}} && nvim --server "$NVIM" --remote-send ":{{line}}<CR>")`,
73+
editTemplate: nvimRemoteEditTemplate,
74+
editAtLineTemplate: nvimRemoteEditAtLineTemplate,
6175
// No remote-wait support yet. See https://github.com/neovim/neovim/pull/17856
6276
editAtLineAndWaitTemplate: `nvim +{{line}} {{filename}}`,
63-
openDirInEditorTemplate: `[ -z "$NVIM" ] && (nvim -- {{dir}}) || (nvim --server "$NVIM" --remote-send "q" && nvim --server "$NVIM" --remote-tab {{dir}})`,
77+
openDirInEditorTemplate: nvimRemoteOpenDirInEditorTemplate,
6478
suspend: func() bool {
6579
_, ok := os.LookupEnv("NVIM")
6680
return !ok

pkg/config/editor_presets_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,15 +111,15 @@ func TestGetEditTemplate(t *testing.T) {
111111
}
112112
for _, s := range scenarios {
113113
t.Run(s.name, func(t *testing.T) {
114-
template, suspend := GetEditTemplate(s.osConfig, s.guessDefaultEditor)
114+
template, suspend := GetEditTemplate("bash", s.osConfig, s.guessDefaultEditor)
115115
assert.Equal(t, s.expectedEditTemplate, template)
116116
assert.Equal(t, s.expectedSuspend, suspend)
117117

118-
template, suspend = GetEditAtLineTemplate(s.osConfig, s.guessDefaultEditor)
118+
template, suspend = GetEditAtLineTemplate("bash", s.osConfig, s.guessDefaultEditor)
119119
assert.Equal(t, s.expectedEditAtLineTemplate, template)
120120
assert.Equal(t, s.expectedSuspend, suspend)
121121

122-
template = GetEditAtLineAndWaitTemplate(s.osConfig, s.guessDefaultEditor)
122+
template = GetEditAtLineAndWaitTemplate("bash", s.osConfig, s.guessDefaultEditor)
123123
assert.Equal(t, s.expectedEditAtLineAndWaitTemplate, template)
124124
})
125125
}

0 commit comments

Comments
 (0)