diff --git a/integration/shell/adapter.go b/integration/shell/adapter.go index 3acf4b0..01472ee 100644 --- a/integration/shell/adapter.go +++ b/integration/shell/adapter.go @@ -1,11 +1,14 @@ package shell import ( + "context" "fmt" "maps" "os" + "os/exec" "path/filepath" "strings" + "time" ) // Adapter defines the behavior for different shell environments @@ -59,7 +62,43 @@ func (z *ZshAdapter) PrepareSelectSequence(selected string) []byte { return append([]byte{0x15}, []byte(selected)...) } func (z *ZshAdapter) ScanAliases() map[string]string { - return ScanPosixAliases([]string{".zshrc", ".zshenv", ".zprofile"}) + envSet := os.Getenv("ZDOTDIR") != "" + zdotdir := GetZshConfigDir() + home, _ := os.UserHomeDir() + + var files []string + if !envSet && zdotdir != home { + files = append(files, filepath.Join(home, ".zshenv")) + } + + files = append(files, + filepath.Join(zdotdir, ".zshenv"), + filepath.Join(zdotdir, ".zprofile"), + filepath.Join(zdotdir, ".zshrc"), + ) + + return ScanPosixAliases(files) +} + +func GetZshConfigDir() string { + if zdotdir := os.Getenv("ZDOTDIR"); zdotdir != "" { + return zdotdir + } + + // Fallback: ask zsh directly in case ZDOTDIR is set in ~/.zshenv without export + ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) + defer cancel() + cmd := exec.CommandContext(ctx, "zsh", "-c", "echo $ZDOTDIR") + out, err := cmd.Output() + if err == nil { + zdotdir := strings.TrimSpace(string(out)) + if zdotdir != "" { + return zdotdir + } + } + + home, _ := os.UserHomeDir() + return home } // FishAdapter implementation @@ -75,7 +114,15 @@ func (f *FishAdapter) PrepareSelectSequence(selected string) []byte { } func (f *FishAdapter) ScanAliases() map[string]string { // fish uses 'alias' command in config.fish or separate function files - return ScanPosixAliases([]string{filepath.Join(".config", "fish", "config.fish")}) + return ScanPosixAliases([]string{filepath.Join(GetFishConfigDir(), "config.fish")}) +} + +func GetFishConfigDir() string { + if xdg := os.Getenv("XDG_CONFIG_HOME"); xdg != "" { + return filepath.Join(xdg, "fish") + } + home, _ := os.UserHomeDir() + return filepath.Join(home, ".config", "fish") } func ScanPosixAliases(files []string) map[string]string { diff --git a/root/init.go b/root/init.go index 881ddf9..d62bafc 100644 --- a/root/init.go +++ b/root/init.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/spf13/cobra" + "github.com/versenilvis/iris/integration/shell" "github.com/versenilvis/iris/internal/config" ) @@ -135,13 +136,13 @@ var setupCmd = &cobra.Command{ switch shellName { case "zsh": - configFile = filepath.Join(home, ".zshrc") + configFile = filepath.Join(shell.GetZshConfigDir(), ".zshrc") evalCmd = `eval "$(iris init zsh)"` case "bash": configFile = filepath.Join(home, ".bashrc") evalCmd = `eval "$(iris init bash)"` case "fish": - configFile = filepath.Join(home, ".config", "fish", "config.fish") + configFile = filepath.Join(shell.GetFishConfigDir(), "config.fish") evalCmd = `iris init fish | source` default: fmt.Printf("Unsupported shell: %s. Please add iris init manually.\n", shellName) diff --git a/root/uninstall.go b/root/uninstall.go index 08bfe56..07a50a1 100644 --- a/root/uninstall.go +++ b/root/uninstall.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/spf13/cobra" + "github.com/versenilvis/iris/integration/shell" "github.com/versenilvis/iris/internal/config" ) @@ -26,10 +27,12 @@ var uninstallCmd = &cobra.Command{ return } + zshrcPath := filepath.Join(shell.GetZshConfigDir(), ".zshrc") + configFiles := []string{ - filepath.Join(home, ".zshrc"), + zshrcPath, filepath.Join(home, ".bashrc"), - filepath.Join(home, ".config", "fish", "config.fish"), + filepath.Join(shell.GetFishConfigDir(), "config.fish"), } for _, file := range configFiles {