mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-11 12:25:47 +02:00
Fix nvim-remote commands for fish shell (#4506)
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).
This commit is contained in:
commit
bb64e3ccb6
3 changed files with 34 additions and 20 deletions
|
@ -86,7 +86,7 @@ func (self *FileCommands) GetEditCmdStr(filenames []string) (string, bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template, suspend := config.GetEditTemplate(&self.UserConfig().OS, self.guessDefaultEditor)
|
template, suspend := config.GetEditTemplate(self.os.Platform.Shell, &self.UserConfig().OS, self.guessDefaultEditor)
|
||||||
quotedFilenames := lo.Map(filenames, func(filename string, _ int) string { return self.cmd.Quote(filename) })
|
quotedFilenames := lo.Map(filenames, func(filename string, _ int) string { return self.cmd.Quote(filename) })
|
||||||
|
|
||||||
templateValues := map[string]string{
|
templateValues := map[string]string{
|
||||||
|
@ -105,7 +105,7 @@ func (self *FileCommands) GetEditAtLineCmdStr(filename string, lineNumber int) (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template, suspend := config.GetEditAtLineTemplate(&self.UserConfig().OS, self.guessDefaultEditor)
|
template, suspend := config.GetEditAtLineTemplate(self.os.Platform.Shell, &self.UserConfig().OS, self.guessDefaultEditor)
|
||||||
|
|
||||||
templateValues := map[string]string{
|
templateValues := map[string]string{
|
||||||
"filename": self.cmd.Quote(filename),
|
"filename": self.cmd.Quote(filename),
|
||||||
|
@ -124,7 +124,7 @@ func (self *FileCommands) GetEditAtLineAndWaitCmdStr(filename string, lineNumber
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template := config.GetEditAtLineAndWaitTemplate(&self.UserConfig().OS, self.guessDefaultEditor)
|
template := config.GetEditAtLineAndWaitTemplate(self.os.Platform.Shell, &self.UserConfig().OS, self.guessDefaultEditor)
|
||||||
|
|
||||||
templateValues := map[string]string{
|
templateValues := map[string]string{
|
||||||
"filename": self.cmd.Quote(filename),
|
"filename": self.cmd.Quote(filename),
|
||||||
|
@ -136,7 +136,7 @@ func (self *FileCommands) GetEditAtLineAndWaitCmdStr(filename string, lineNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *FileCommands) GetOpenDirInEditorCmdStr(path string) (string, bool) {
|
func (self *FileCommands) GetOpenDirInEditorCmdStr(path string) (string, bool) {
|
||||||
template, suspend := config.GetOpenDirInEditorTemplate(&self.UserConfig().OS, self.guessDefaultEditor)
|
template, suspend := config.GetOpenDirInEditorTemplate(self.os.Platform.Shell, &self.UserConfig().OS, self.guessDefaultEditor)
|
||||||
|
|
||||||
templateValues := map[string]string{
|
templateValues := map[string]string{
|
||||||
"dir": self.cmd.Quote(path),
|
"dir": self.cmd.Quote(path),
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import "os"
|
import (
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
func GetEditTemplate(osConfig *OSConfig, guessDefaultEditor func() string) (string, bool) {
|
func GetEditTemplate(shell string, osConfig *OSConfig, guessDefaultEditor func() string) (string, bool) {
|
||||||
preset := getPreset(osConfig, guessDefaultEditor)
|
preset := getPreset(shell, osConfig, guessDefaultEditor)
|
||||||
template := osConfig.Edit
|
template := osConfig.Edit
|
||||||
if template == "" {
|
if template == "" {
|
||||||
template = preset.editTemplate
|
template = preset.editTemplate
|
||||||
|
@ -12,8 +15,8 @@ func GetEditTemplate(osConfig *OSConfig, guessDefaultEditor func() string) (stri
|
||||||
return template, getEditInTerminal(osConfig, preset)
|
return template, getEditInTerminal(osConfig, preset)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetEditAtLineTemplate(osConfig *OSConfig, guessDefaultEditor func() string) (string, bool) {
|
func GetEditAtLineTemplate(shell string, osConfig *OSConfig, guessDefaultEditor func() string) (string, bool) {
|
||||||
preset := getPreset(osConfig, guessDefaultEditor)
|
preset := getPreset(shell, osConfig, guessDefaultEditor)
|
||||||
template := osConfig.EditAtLine
|
template := osConfig.EditAtLine
|
||||||
if template == "" {
|
if template == "" {
|
||||||
template = preset.editAtLineTemplate
|
template = preset.editAtLineTemplate
|
||||||
|
@ -21,8 +24,8 @@ func GetEditAtLineTemplate(osConfig *OSConfig, guessDefaultEditor func() string)
|
||||||
return template, getEditInTerminal(osConfig, preset)
|
return template, getEditInTerminal(osConfig, preset)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetEditAtLineAndWaitTemplate(osConfig *OSConfig, guessDefaultEditor func() string) string {
|
func GetEditAtLineAndWaitTemplate(shell string, osConfig *OSConfig, guessDefaultEditor func() string) string {
|
||||||
preset := getPreset(osConfig, guessDefaultEditor)
|
preset := getPreset(shell, osConfig, guessDefaultEditor)
|
||||||
template := osConfig.EditAtLineAndWait
|
template := osConfig.EditAtLineAndWait
|
||||||
if template == "" {
|
if template == "" {
|
||||||
template = preset.editAtLineAndWaitTemplate
|
template = preset.editAtLineAndWaitTemplate
|
||||||
|
@ -30,8 +33,8 @@ func GetEditAtLineAndWaitTemplate(osConfig *OSConfig, guessDefaultEditor func()
|
||||||
return template
|
return template
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetOpenDirInEditorTemplate(osConfig *OSConfig, guessDefaultEditor func() string) (string, bool) {
|
func GetOpenDirInEditorTemplate(shell string, osConfig *OSConfig, guessDefaultEditor func() string) (string, bool) {
|
||||||
preset := getPreset(osConfig, guessDefaultEditor)
|
preset := getPreset(shell, osConfig, guessDefaultEditor)
|
||||||
template := osConfig.OpenDirInEditor
|
template := osConfig.OpenDirInEditor
|
||||||
if template == "" {
|
if template == "" {
|
||||||
template = preset.openDirInEditorTemplate
|
template = preset.openDirInEditorTemplate
|
||||||
|
@ -50,17 +53,28 @@ type editPreset struct {
|
||||||
func returnBool(a bool) func() bool { return (func() bool { return a }) }
|
func returnBool(a bool) func() bool { return (func() bool { return a }) }
|
||||||
|
|
||||||
// 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
|
||||||
func getPreset(osConfig *OSConfig, guessDefaultEditor func() string) *editPreset {
|
func getPreset(shell string, osConfig *OSConfig, guessDefaultEditor func() string) *editPreset {
|
||||||
|
var nvimRemoteEditTemplate, nvimRemoteEditAtLineTemplate, nvimRemoteOpenDirInEditorTemplate string
|
||||||
|
// By default fish doesn't have SHELL variable set, but it does have FISH_VERSION since Nov 2012.
|
||||||
|
if (strings.HasSuffix(shell, "fish")) || (os.Getenv("FISH_VERSION") != "") {
|
||||||
|
nvimRemoteEditTemplate = `begin; if test -z "$NVIM"; nvim -- {{filename}}; else; nvim --server "$NVIM" --remote-send "q"; nvim --server "$NVIM" --remote-tab {{filename}}; end; end`
|
||||||
|
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`
|
||||||
|
nvimRemoteOpenDirInEditorTemplate = `begin; if test -z "$NVIM"; nvim -- {{dir}}; else; nvim --server "$NVIM" --remote-send "q"; nvim --server "$NVIM" --remote-tab {{dir}}; end; end`
|
||||||
|
} else {
|
||||||
|
nvimRemoteEditTemplate = `[ -z "$NVIM" ] && (nvim -- {{filename}}) || (nvim --server "$NVIM" --remote-send "q" && nvim --server "$NVIM" --remote-tab {{filename}})`
|
||||||
|
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>")`
|
||||||
|
nvimRemoteOpenDirInEditorTemplate = `[ -z "$NVIM" ] && (nvim -- {{dir}}) || (nvim --server "$NVIM" --remote-send "q" && nvim --server "$NVIM" --remote-tab {{dir}})`
|
||||||
|
}
|
||||||
presets := map[string]*editPreset{
|
presets := map[string]*editPreset{
|
||||||
"vi": standardTerminalEditorPreset("vi"),
|
"vi": standardTerminalEditorPreset("vi"),
|
||||||
"vim": standardTerminalEditorPreset("vim"),
|
"vim": standardTerminalEditorPreset("vim"),
|
||||||
"nvim": standardTerminalEditorPreset("nvim"),
|
"nvim": standardTerminalEditorPreset("nvim"),
|
||||||
"nvim-remote": {
|
"nvim-remote": {
|
||||||
editTemplate: `[ -z "$NVIM" ] && (nvim -- {{filename}}) || (nvim --server "$NVIM" --remote-send "q" && nvim --server "$NVIM" --remote-tab {{filename}})`,
|
editTemplate: nvimRemoteEditTemplate,
|
||||||
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>")`,
|
editAtLineTemplate: nvimRemoteEditAtLineTemplate,
|
||||||
// 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: `[ -z "$NVIM" ] && (nvim -- {{dir}}) || (nvim --server "$NVIM" --remote-send "q" && nvim --server "$NVIM" --remote-tab {{dir}})`,
|
openDirInEditorTemplate: nvimRemoteOpenDirInEditorTemplate,
|
||||||
suspend: func() bool {
|
suspend: func() bool {
|
||||||
_, ok := os.LookupEnv("NVIM")
|
_, ok := os.LookupEnv("NVIM")
|
||||||
return !ok
|
return !ok
|
||||||
|
|
|
@ -111,15 +111,15 @@ 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, suspend := GetEditTemplate(s.osConfig, s.guessDefaultEditor)
|
template, suspend := GetEditTemplate("bash", s.osConfig, s.guessDefaultEditor)
|
||||||
assert.Equal(t, s.expectedEditTemplate, template)
|
assert.Equal(t, s.expectedEditTemplate, template)
|
||||||
assert.Equal(t, s.expectedSuspend, suspend)
|
assert.Equal(t, s.expectedSuspend, suspend)
|
||||||
|
|
||||||
template, suspend = GetEditAtLineTemplate(s.osConfig, s.guessDefaultEditor)
|
template, suspend = GetEditAtLineTemplate("bash", s.osConfig, s.guessDefaultEditor)
|
||||||
assert.Equal(t, s.expectedEditAtLineTemplate, template)
|
assert.Equal(t, s.expectedEditAtLineTemplate, template)
|
||||||
assert.Equal(t, s.expectedSuspend, suspend)
|
assert.Equal(t, s.expectedSuspend, suspend)
|
||||||
|
|
||||||
template = GetEditAtLineAndWaitTemplate(s.osConfig, s.guessDefaultEditor)
|
template = GetEditAtLineAndWaitTemplate("bash", s.osConfig, s.guessDefaultEditor)
|
||||||
assert.Equal(t, s.expectedEditAtLineAndWaitTemplate, template)
|
assert.Equal(t, s.expectedEditAtLineAndWaitTemplate, template)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue