mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-21 16:38:23 +01:00
support fish shell with wsh (#874)
This commit is contained in:
parent
3ebdd9c01e
commit
29b80bc028
2
frontend/types/gotypes.d.ts
vendored
2
frontend/types/gotypes.d.ts
vendored
@ -301,6 +301,7 @@ declare global {
|
|||||||
"term:fontfamily"?: string;
|
"term:fontfamily"?: string;
|
||||||
"term:mode"?: string;
|
"term:mode"?: string;
|
||||||
"term:theme"?: string;
|
"term:theme"?: string;
|
||||||
|
"term:localshellpath"?: string;
|
||||||
count?: number;
|
count?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -417,6 +418,7 @@ declare global {
|
|||||||
"term:fontsize"?: number;
|
"term:fontsize"?: number;
|
||||||
"term:fontfamily"?: string;
|
"term:fontfamily"?: string;
|
||||||
"term:disablewebgl"?: boolean;
|
"term:disablewebgl"?: boolean;
|
||||||
|
"term:localshellpath"?: string;
|
||||||
"editor:minimapenabled"?: boolean;
|
"editor:minimapenabled"?: boolean;
|
||||||
"editor:stickyscrollenabled"?: boolean;
|
"editor:stickyscrollenabled"?: boolean;
|
||||||
"web:*"?: boolean;
|
"web:*"?: boolean;
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"github.com/wavetermdev/waveterm/pkg/shellexec"
|
"github.com/wavetermdev/waveterm/pkg/shellexec"
|
||||||
"github.com/wavetermdev/waveterm/pkg/wavebase"
|
"github.com/wavetermdev/waveterm/pkg/wavebase"
|
||||||
"github.com/wavetermdev/waveterm/pkg/waveobj"
|
"github.com/wavetermdev/waveterm/pkg/waveobj"
|
||||||
|
"github.com/wavetermdev/waveterm/pkg/wconfig"
|
||||||
"github.com/wavetermdev/waveterm/pkg/wps"
|
"github.com/wavetermdev/waveterm/pkg/wps"
|
||||||
"github.com/wavetermdev/waveterm/pkg/wshrpc"
|
"github.com/wavetermdev/waveterm/pkg/wshrpc"
|
||||||
"github.com/wavetermdev/waveterm/pkg/wshutil"
|
"github.com/wavetermdev/waveterm/pkg/wshutil"
|
||||||
@ -286,6 +287,7 @@ func (bc *BlockController) DoRunShellCommand(rc *RunShellOpts, blockMeta waveobj
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// local terminal
|
||||||
if !blockMeta.GetBool(waveobj.MetaKey_CmdNoWsh, false) {
|
if !blockMeta.GetBool(waveobj.MetaKey_CmdNoWsh, false) {
|
||||||
jwtStr, err := wshutil.MakeClientJWTToken(wshrpc.RpcContext{TabId: bc.TabId, BlockId: bc.BlockId}, wavebase.GetDomainSocketName())
|
jwtStr, err := wshutil.MakeClientJWTToken(wshrpc.RpcContext{TabId: bc.TabId, BlockId: bc.BlockId}, wavebase.GetDomainSocketName())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -293,6 +295,13 @@ func (bc *BlockController) DoRunShellCommand(rc *RunShellOpts, blockMeta waveobj
|
|||||||
}
|
}
|
||||||
cmdOpts.Env[wshutil.WaveJwtTokenVarName] = jwtStr
|
cmdOpts.Env[wshutil.WaveJwtTokenVarName] = jwtStr
|
||||||
}
|
}
|
||||||
|
settings := wconfig.GetWatcher().GetFullConfig().Settings
|
||||||
|
if settings.TermLocalShellPath != "" {
|
||||||
|
cmdOpts.ShellPath = settings.TermLocalShellPath
|
||||||
|
}
|
||||||
|
if blockMeta.GetString(waveobj.MetaKey_TermLocalShellPath, "") != "" {
|
||||||
|
cmdOpts.ShellPath = blockMeta.GetString(waveobj.MetaKey_TermLocalShellPath, "")
|
||||||
|
}
|
||||||
shellProc, err = shellexec.StartShellProc(rc.TermSize, cmdStr, cmdOpts)
|
shellProc, err = shellexec.StartShellProc(rc.TermSize, cmdStr, cmdOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"github.com/wavetermdev/waveterm/pkg/remote"
|
"github.com/wavetermdev/waveterm/pkg/remote"
|
||||||
"github.com/wavetermdev/waveterm/pkg/remote/conncontroller"
|
"github.com/wavetermdev/waveterm/pkg/remote/conncontroller"
|
||||||
"github.com/wavetermdev/waveterm/pkg/util/shellutil"
|
"github.com/wavetermdev/waveterm/pkg/util/shellutil"
|
||||||
|
"github.com/wavetermdev/waveterm/pkg/util/utilfn"
|
||||||
"github.com/wavetermdev/waveterm/pkg/wavebase"
|
"github.com/wavetermdev/waveterm/pkg/wavebase"
|
||||||
"github.com/wavetermdev/waveterm/pkg/waveobj"
|
"github.com/wavetermdev/waveterm/pkg/waveobj"
|
||||||
"github.com/wavetermdev/waveterm/pkg/wshutil"
|
"github.com/wavetermdev/waveterm/pkg/wshutil"
|
||||||
@ -33,6 +34,7 @@ type CommandOptsType struct {
|
|||||||
Login bool `json:"login,omitempty"`
|
Login bool `json:"login,omitempty"`
|
||||||
Cwd string `json:"cwd,omitempty"`
|
Cwd string `json:"cwd,omitempty"`
|
||||||
Env map[string]string `json:"env,omitempty"`
|
Env map[string]string `json:"env,omitempty"`
|
||||||
|
ShellPath string `json:"shellPath,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ShellProc struct {
|
type ShellProc struct {
|
||||||
@ -140,15 +142,19 @@ func (pp *PipePty) WriteString(s string) (n int, err error) {
|
|||||||
|
|
||||||
func StartRemoteShellProc(termSize waveobj.TermSize, cmdStr string, cmdOpts CommandOptsType, conn *conncontroller.SSHConn) (*ShellProc, error) {
|
func StartRemoteShellProc(termSize waveobj.TermSize, cmdStr string, cmdOpts CommandOptsType, conn *conncontroller.SSHConn) (*ShellProc, error) {
|
||||||
client := conn.GetClient()
|
client := conn.GetClient()
|
||||||
shellPath, err := remote.DetectShell(client)
|
shellPath := cmdOpts.ShellPath
|
||||||
if err != nil {
|
if shellPath == "" {
|
||||||
return nil, err
|
remoteShellPath, err := remote.DetectShell(client)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
shellPath = remoteShellPath
|
||||||
}
|
}
|
||||||
var shellOpts []string
|
var shellOpts []string
|
||||||
var cmdCombined string
|
var cmdCombined string
|
||||||
log.Printf("detected shell: %s", shellPath)
|
log.Printf("detected shell: %s", shellPath)
|
||||||
|
|
||||||
err = remote.InstallClientRcFiles(client)
|
err := remote.InstallClientRcFiles(client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error installing rc files: %v", err)
|
log.Printf("error installing rc files: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -163,6 +169,9 @@ func StartRemoteShellProc(termSize waveobj.TermSize, cmdStr string, cmdOpts Comm
|
|||||||
// add --rcfile
|
// add --rcfile
|
||||||
// cant set -l or -i with --rcfile
|
// cant set -l or -i with --rcfile
|
||||||
shellOpts = append(shellOpts, "--rcfile", fmt.Sprintf(`"%s"/.waveterm/%s/.bashrc`, homeDir, shellutil.BashIntegrationDir))
|
shellOpts = append(shellOpts, "--rcfile", fmt.Sprintf(`"%s"/.waveterm/%s/.bashrc`, homeDir, shellutil.BashIntegrationDir))
|
||||||
|
} else if isFishShell(shellPath) {
|
||||||
|
carg := fmt.Sprintf(`"set -x PATH \"%s\"/.waveterm/%s $PATH"`, homeDir, shellutil.WaveHomeBinDir)
|
||||||
|
shellOpts = append(shellOpts, "-C", carg)
|
||||||
} else if remote.IsPowershell(shellPath) {
|
} else if remote.IsPowershell(shellPath) {
|
||||||
// powershell is weird about quoted path executables and requires an ampersand first
|
// powershell is weird about quoted path executables and requires an ampersand first
|
||||||
shellPath = "& " + shellPath
|
shellPath = "& " + shellPath
|
||||||
@ -264,17 +273,29 @@ func isBashShell(shellPath string) bool {
|
|||||||
return strings.Contains(shellBase, "bash")
|
return strings.Contains(shellBase, "bash")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isFishShell(shellPath string) bool {
|
||||||
|
// get the base path, and then check contains
|
||||||
|
shellBase := filepath.Base(shellPath)
|
||||||
|
return strings.Contains(shellBase, "fish")
|
||||||
|
}
|
||||||
|
|
||||||
func StartShellProc(termSize waveobj.TermSize, cmdStr string, cmdOpts CommandOptsType) (*ShellProc, error) {
|
func StartShellProc(termSize waveobj.TermSize, cmdStr string, cmdOpts CommandOptsType) (*ShellProc, error) {
|
||||||
shellutil.InitCustomShellStartupFiles()
|
shellutil.InitCustomShellStartupFiles()
|
||||||
var ecmd *exec.Cmd
|
var ecmd *exec.Cmd
|
||||||
var shellOpts []string
|
var shellOpts []string
|
||||||
|
shellPath := cmdOpts.ShellPath
|
||||||
shellPath := shellutil.DetectLocalShellPath()
|
if shellPath == "" {
|
||||||
|
shellPath = shellutil.DetectLocalShellPath()
|
||||||
|
}
|
||||||
if cmdStr == "" {
|
if cmdStr == "" {
|
||||||
if isBashShell(shellPath) {
|
if isBashShell(shellPath) {
|
||||||
// add --rcfile
|
// add --rcfile
|
||||||
// cant set -l or -i with --rcfile
|
// cant set -l or -i with --rcfile
|
||||||
shellOpts = append(shellOpts, "--rcfile", shellutil.GetBashRcFileOverride())
|
shellOpts = append(shellOpts, "--rcfile", shellutil.GetBashRcFileOverride())
|
||||||
|
} else if isFishShell(shellPath) {
|
||||||
|
wshBinDir := filepath.Join(wavebase.GetWaveHomeDir(), shellutil.WaveHomeBinDir)
|
||||||
|
quotedWshBinDir := utilfn.ShellQuote(wshBinDir, false, 300)
|
||||||
|
shellOpts = append(shellOpts, "-C", fmt.Sprintf("set -x PATH %s $PATH", quotedWshBinDir))
|
||||||
} else if remote.IsPowershell(shellPath) {
|
} else if remote.IsPowershell(shellPath) {
|
||||||
shellOpts = append(shellOpts, "-ExecutionPolicy", "Bypass", "-NoExit", "-File", shellutil.GetWavePowershellEnv())
|
shellOpts = append(shellOpts, "-ExecutionPolicy", "Bypass", "-NoExit", "-File", shellutil.GetWavePowershellEnv())
|
||||||
} else {
|
} else {
|
||||||
@ -322,7 +343,6 @@ func StartShellProc(termSize waveobj.TermSize, cmdStr string, cmdOpts CommandOpt
|
|||||||
}
|
}
|
||||||
cmdPty, err := pty.StartWithSize(ecmd, &pty.Winsize{Rows: uint16(termSize.Rows), Cols: uint16(termSize.Cols)})
|
cmdPty, err := pty.StartWithSize(ecmd, &pty.Winsize{Rows: uint16(termSize.Rows), Cols: uint16(termSize.Cols)})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmdPty.Close()
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &ShellProc{Cmd: CmdWrap{ecmd, cmdPty}, CloseOnce: &sync.Once{}, DoneCh: make(chan any)}, nil
|
return &ShellProc{Cmd: CmdWrap{ecmd, cmdPty}, CloseOnce: &sync.Once{}, DoneCh: make(chan any)}, nil
|
||||||
|
@ -59,6 +59,7 @@ const (
|
|||||||
MetaKey_TermFontFamily = "term:fontfamily"
|
MetaKey_TermFontFamily = "term:fontfamily"
|
||||||
MetaKey_TermMode = "term:mode"
|
MetaKey_TermMode = "term:mode"
|
||||||
MetaKey_TermTheme = "term:theme"
|
MetaKey_TermTheme = "term:theme"
|
||||||
|
MetaKey_TermLocalShellPath = "term:localshellpath"
|
||||||
|
|
||||||
MetaKey_Count = "count"
|
MetaKey_Count = "count"
|
||||||
)
|
)
|
||||||
|
@ -54,12 +54,14 @@ type MetaTSType struct {
|
|||||||
BgOpacity float64 `json:"bg:opacity,omitempty"`
|
BgOpacity float64 `json:"bg:opacity,omitempty"`
|
||||||
BgBlendMode string `json:"bg:blendmode,omitempty"`
|
BgBlendMode string `json:"bg:blendmode,omitempty"`
|
||||||
|
|
||||||
TermClear bool `json:"term:*,omitempty"`
|
TermClear bool `json:"term:*,omitempty"`
|
||||||
TermFontSize int `json:"term:fontsize,omitempty"`
|
TermFontSize int `json:"term:fontsize,omitempty"`
|
||||||
TermFontFamily string `json:"term:fontfamily,omitempty"`
|
TermFontFamily string `json:"term:fontfamily,omitempty"`
|
||||||
TermMode string `json:"term:mode,omitempty"`
|
TermMode string `json:"term:mode,omitempty"`
|
||||||
TermTheme string `json:"term:theme,omitempty"`
|
TermTheme string `json:"term:theme,omitempty"`
|
||||||
Count int `json:"count,omitempty"` // temp for cpu plot. will remove later
|
TermLocalShellPath string `json:"term:localshellpath,omitempty"` // matches settings
|
||||||
|
|
||||||
|
Count int `json:"count,omitempty"` // temp for cpu plot. will remove later
|
||||||
}
|
}
|
||||||
|
|
||||||
type MetaDataDecl struct {
|
type MetaDataDecl struct {
|
||||||
|
@ -18,6 +18,7 @@ const (
|
|||||||
ConfigKey_TermFontSize = "term:fontsize"
|
ConfigKey_TermFontSize = "term:fontsize"
|
||||||
ConfigKey_TermFontFamily = "term:fontfamily"
|
ConfigKey_TermFontFamily = "term:fontfamily"
|
||||||
ConfigKey_TermDisableWebGl = "term:disablewebgl"
|
ConfigKey_TermDisableWebGl = "term:disablewebgl"
|
||||||
|
ConfigKey_TermLocalShellPath = "term:localshellpath"
|
||||||
|
|
||||||
ConfigKey_EditorMinimapEnabled = "editor:minimapenabled"
|
ConfigKey_EditorMinimapEnabled = "editor:minimapenabled"
|
||||||
ConfigKey_EditorStickyScrollEnabled = "editor:stickyscrollenabled"
|
ConfigKey_EditorStickyScrollEnabled = "editor:stickyscrollenabled"
|
||||||
|
@ -48,10 +48,11 @@ type SettingsType struct {
|
|||||||
AiMaxTokens float64 `json:"ai:maxtokens,omitempty"`
|
AiMaxTokens float64 `json:"ai:maxtokens,omitempty"`
|
||||||
AiTimeoutMs float64 `json:"ai:timeoutms,omitempty"`
|
AiTimeoutMs float64 `json:"ai:timeoutms,omitempty"`
|
||||||
|
|
||||||
TermClear bool `json:"term:*,omitempty"`
|
TermClear bool `json:"term:*,omitempty"`
|
||||||
TermFontSize float64 `json:"term:fontsize,omitempty"`
|
TermFontSize float64 `json:"term:fontsize,omitempty"`
|
||||||
TermFontFamily string `json:"term:fontfamily,omitempty"`
|
TermFontFamily string `json:"term:fontfamily,omitempty"`
|
||||||
TermDisableWebGl bool `json:"term:disablewebgl,omitempty"`
|
TermDisableWebGl bool `json:"term:disablewebgl,omitempty"`
|
||||||
|
TermLocalShellPath string `json:"term:localshellpath,omitempty"`
|
||||||
|
|
||||||
EditorMinimapEnabled bool `json:"editor:minimapenabled,omitempty"`
|
EditorMinimapEnabled bool `json:"editor:minimapenabled,omitempty"`
|
||||||
EditorStickyScrollEnabled bool `json:"editor:stickyscrollenabled,omitempty"`
|
EditorStickyScrollEnabled bool `json:"editor:stickyscrollenabled,omitempty"`
|
||||||
|
Loading…
Reference in New Issue
Block a user