fix: ZDOTDIR and XDG_CONFIG_HOME config detecting (#51)
From this discussion: https://www.reddit.com/r/zsh/comments/1v8rq7s/comment/p09b05o/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button --- Problem: Iris hardcodes config paths to `~/.zshrc` and `~/.config/fish/config.fish`. This ignores users' custom `ZDOTDIR` or `XDG_CONFIG_HOME` setups, polluting their `$HOME` directory during init and failing to scan their actual aliases. Also, ZDOTDIR is often set in `~/.zshenv` without export, making it invisible to Go's `os.Getenv` Solution: - Bash: default `$HOME/.bashrc` so dont mind about it - For Zsh, Iris now probes zsh directly (`zsh -c "echo $ZDOTDIR"`) with a timeout to accurately resolve custom paths even if they aint exported - For Fish, Iris now natively respects the `XDG_CONFIG_HOME` environment variable - Shared this robust resolution logic across init, uninstall, and alias scanning - Fixed alias scanning to process files in the correct zsh startup order (`.zshenv` -> `.zprofile` -> `.zshrc`) and correctly merge them
This commit is contained in:
@@ -1,11 +1,14 @@
|
|||||||
package shell
|
package shell
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"maps"
|
"maps"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Adapter defines the behavior for different shell environments
|
// 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)...)
|
return append([]byte{0x15}, []byte(selected)...)
|
||||||
}
|
}
|
||||||
func (z *ZshAdapter) ScanAliases() map[string]string {
|
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
|
// FishAdapter implementation
|
||||||
@@ -75,7 +114,15 @@ func (f *FishAdapter) PrepareSelectSequence(selected string) []byte {
|
|||||||
}
|
}
|
||||||
func (f *FishAdapter) ScanAliases() map[string]string {
|
func (f *FishAdapter) ScanAliases() map[string]string {
|
||||||
// fish uses 'alias' command in config.fish or separate function files
|
// 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 {
|
func ScanPosixAliases(files []string) map[string]string {
|
||||||
|
|||||||
+3
-2
@@ -7,6 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/versenilvis/iris/integration/shell"
|
||||||
"github.com/versenilvis/iris/internal/config"
|
"github.com/versenilvis/iris/internal/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -135,13 +136,13 @@ var setupCmd = &cobra.Command{
|
|||||||
|
|
||||||
switch shellName {
|
switch shellName {
|
||||||
case "zsh":
|
case "zsh":
|
||||||
configFile = filepath.Join(home, ".zshrc")
|
configFile = filepath.Join(shell.GetZshConfigDir(), ".zshrc")
|
||||||
evalCmd = `eval "$(iris init zsh)"`
|
evalCmd = `eval "$(iris init zsh)"`
|
||||||
case "bash":
|
case "bash":
|
||||||
configFile = filepath.Join(home, ".bashrc")
|
configFile = filepath.Join(home, ".bashrc")
|
||||||
evalCmd = `eval "$(iris init bash)"`
|
evalCmd = `eval "$(iris init bash)"`
|
||||||
case "fish":
|
case "fish":
|
||||||
configFile = filepath.Join(home, ".config", "fish", "config.fish")
|
configFile = filepath.Join(shell.GetFishConfigDir(), "config.fish")
|
||||||
evalCmd = `iris init fish | source`
|
evalCmd = `iris init fish | source`
|
||||||
default:
|
default:
|
||||||
fmt.Printf("Unsupported shell: %s. Please add iris init manually.\n", shellName)
|
fmt.Printf("Unsupported shell: %s. Please add iris init manually.\n", shellName)
|
||||||
|
|||||||
+5
-2
@@ -8,6 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/versenilvis/iris/integration/shell"
|
||||||
"github.com/versenilvis/iris/internal/config"
|
"github.com/versenilvis/iris/internal/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -26,10 +27,12 @@ var uninstallCmd = &cobra.Command{
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zshrcPath := filepath.Join(shell.GetZshConfigDir(), ".zshrc")
|
||||||
|
|
||||||
configFiles := []string{
|
configFiles := []string{
|
||||||
filepath.Join(home, ".zshrc"),
|
zshrcPath,
|
||||||
filepath.Join(home, ".bashrc"),
|
filepath.Join(home, ".bashrc"),
|
||||||
filepath.Join(home, ".config", "fish", "config.fish"),
|
filepath.Join(shell.GetFishConfigDir(), "config.fish"),
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, file := range configFiles {
|
for _, file := range configFiles {
|
||||||
|
|||||||
Reference in New Issue
Block a user