diff --git a/cointop/cmd/root.go b/cointop/cmd/root.go index e654348..106db28 100644 --- a/cointop/cmd/root.go +++ b/cointop/cmd/root.go @@ -101,7 +101,7 @@ See git.io/cointop for more info.`, rootCmd.Flags().StringVarP(&config, "config", "c", "", fmt.Sprintf("Config filepath. (default %s)", cointop.DefaultConfigFilepath)) rootCmd.Flags().StringVarP(&cmcAPIKey, "coinmarketcap-api-key", "", "", "Set the CoinMarketCap API key") rootCmd.Flags().StringVarP(&apiChoice, "api", "", "", "API choice. Available choices are \"coinmarketcap\" and \"coingecko\"") - rootCmd.Flags().StringVarP(&colorscheme, "colorscheme", "", "", "Colorscheme to use (default \"cointop\"). To install standard themes, do:\n\ngit clone git@github.com:cointop-sh/colors.git ~/.config/cointop/colors\n\nSee git.io/cointop#colorschemes for more info.") + rootCmd.Flags().StringVarP(&colorscheme, "colorscheme", "", "", fmt.Sprintf("Colorscheme to use (default \"cointop\").\n%s", cointop.ColorschemeHelpString)) rootCmd.Flags().StringVarP(&cacheDir, "cache-dir", "", cacheDir, "Cache directory") return rootCmd diff --git a/cointop/cointop.go b/cointop/cointop.go index 8b4c15f..67e12cb 100644 --- a/cointop/cointop.go +++ b/cointop/cointop.go @@ -149,7 +149,7 @@ var DefaultPerPage uint = 100 var DefaultColorscheme = "cointop" // DefaultConfigFilepath ... -var DefaultConfigFilepath = "~/.config/cointop/config.toml" +var DefaultConfigFilepath = pathutil.NormalizePath(":PREFERRED_CONFIG_HOME:/cointop/config.toml") // DefaultCacheDir ... var DefaultCacheDir = filecache.DefaultCacheDir @@ -499,3 +499,8 @@ func Reset(config *ResetConfig) error { return nil } + +// ColorschemeHelpString ... +func ColorschemeHelpString() string { + return fmt.Sprintf("To install standard themes, do:\n\ngit clone git@github.com:cointop-sh/colors.git %s\n\nSee git.io/cointop#colorschemes for more info.", pathutil.NormalizePath(":PREFERRED_CONFIG_HOME:/cointop/colors")) +} diff --git a/cointop/common/pathutil/pathutil.go b/cointop/common/pathutil/pathutil.go index def97a9..32e9e50 100644 --- a/cointop/common/pathutil/pathutil.go +++ b/cointop/common/pathutil/pathutil.go @@ -3,22 +3,30 @@ package pathutil import ( "os" "path/filepath" - "runtime" "strings" ) -// UserPreferredHomeDir returns the preferred home directory for the user -func UserPreferredHomeDir() string { - var home string +// UserPreferredConfigDir returns the preferred config directory for the user +func UserPreferredConfigDir() string { + defaultConfigDir := "~/.config" - if runtime.GOOS == "windows" { - home = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") - } else if runtime.GOOS == "linux" { - home = os.Getenv("XDG_CONFIG_HOME") + config, err := os.UserConfigDir() + if err != nil { + return defaultConfigDir } - if home == "" { - home, _ = os.UserHomeDir() + if config == "" { + return defaultConfigDir + } + + return config +} + +// UserPreferredHomeDir returns the preferred home directory for the user +func UserPreferredHomeDir() string { + home, err := os.UserHomeDir() + if err != nil { + return "" } return home @@ -26,11 +34,16 @@ func UserPreferredHomeDir() string { // NormalizePath normalizes and extends the path string func NormalizePath(path string) string { + userHome := UserPreferredHomeDir() + userConfigHome := UserPreferredConfigDir() + // expand tilde if strings.HasPrefix(path, "~/") { - path = filepath.Join(UserPreferredHomeDir(), path[2:]) + path = filepath.Join(userHome, path[2:]) } + path = strings.Replace(path, ":HOME:", userHome, -1) + path = strings.Replace(path, ":PREFERRED_CONFIG_HOME:", userConfigHome, -1) path = strings.Replace(path, "/", string(filepath.Separator), -1) return path diff --git a/cointop/common/pathutil/pathutil_test.go b/cointop/common/pathutil/pathutil_test.go new file mode 100644 index 0000000..0a8d070 --- /dev/null +++ b/cointop/common/pathutil/pathutil_test.go @@ -0,0 +1,29 @@ +package pathutil + +import ( + "os" + "path/filepath" + "testing" +) + +// TestNormalizePath checks that NormalizePath returns the correct directory +func TestNormalizePath(t *testing.T) { + os.Setenv("XDG_CONFIG_HOME", "/tmp/.config") + + home, _ := os.UserHomeDir() + configDir, _ := os.UserConfigDir() + + cases := []struct { + in, out string + }{ + {"~/.config/cointop/config.toml", filepath.Join(home, ".config/cointop/config.toml")}, + {":HOME:/.cointop/config.toml", filepath.Join(home, "/.cointop/config.toml")}, + {":PREFERRED_CONFIG_HOME:/cointop/config.toml", filepath.Join(configDir, "/cointop/config.toml")}, + } + for _, c := range cases { + got := NormalizePath(c.in) + if got != c.out { + t.Errorf("NormalizePath(%q) == %q, want %q", c.in, got, c.out) + } + } +} diff --git a/cointop/config.go b/cointop/config.go index 5d27b46..f0446e5 100644 --- a/cointop/config.go +++ b/cointop/config.go @@ -17,10 +17,11 @@ var fileperm = os.FileMode(0644) // NOTE: this is to support previous default config filepaths var possibleConfigPaths = []string{ - "~/.config/cointop/config.toml", - "~/.config/cointop/config", - "~/.cointop/config", - "~/.cointop/config.toml", + ":PREFERRED_CONFIG_HOME:/cointop/config.toml", + ":HOME:/.config/cointop/config.toml", + ":HOME:/.config/cointop/config", + ":HOME:/.cointop/config", + ":HOME:/.cointop/config.toml", } type config struct { @@ -334,7 +335,7 @@ func (ct *Cointop) getColorschemeColors() (map[string]interface{}, error) { return nil, err } } else { - path := pathutil.NormalizePath(fmt.Sprintf("~/.cointop/colors/%s.toml", ct.colorschemeName)) + path := fmt.Sprintf("%s/colors/%s.toml", ct.ConfigDirPath(), ct.colorschemeName) if _, err := os.Stat(path); os.IsNotExist(err) { // NOTE: case for when cointop is set as the theme but the colorscheme file doesn't exist if ct.colorschemeName == "cointop" { @@ -345,7 +346,7 @@ func (ct *Cointop) getColorschemeColors() (map[string]interface{}, error) { return colors, nil } - return nil, fmt.Errorf("The colorscheme file %q was not found.\n\nTo install standard themes, do:\n\ngit clone git@github.com:cointop-sh/colors.git ~/.config/cointop/colors\n\nFor additional instructions, visit: https://github.com/cointop-sh/colors", path) + return nil, fmt.Errorf("The colorscheme file %q was not found.\n%s", path, ColorschemeHelpString()) } if _, err := toml.DecodeFile(path, &colors); err != nil {