diff --git a/CHANGELOG.md b/CHANGELOG.md index 320b46d1..2d47df8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,8 @@ That said, these are more guidelines rather than hardset rules, though the proje ### Changes - [#1559](https://github.com/ClementTsang/bottom/pull/1559): Rename `--enable_gpu` to `--disable_gpu`, and make GPU features enabled by default. +- [#1570](https://github.com/ClementTsang/bottom/pull/1570): Consider `$XDG_CONFIG_HOME` on macOS when looking for a default config path in a + backwards-compatible fashion. ## [0.10.2] - 2024-08-05 diff --git a/docs/content/configuration/config-file/index.md b/docs/content/configuration/config-file/index.md index 433d4f3c..17fda336 100644 --- a/docs/content/configuration/config-file/index.md +++ b/docs/content/configuration/config-file/index.md @@ -6,11 +6,11 @@ For persistent configuration, and for certain configuration options, bottom supp If no config file argument is given, it will automatically look for a config file at these locations: -| OS | Default Config Location | -| ------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| macOS | `$HOME/Library/Application Support/bottom/bottom.toml`
`~/.config/bottom/bottom.toml`
`$XDG_CONFIG_HOME/bottom/bottom.toml` | -| Linux | `~/.config/bottom/bottom.toml`
`$XDG_CONFIG_HOME/bottom/bottom.toml` | -| Windows | `C:\Users\\AppData\Roaming\bottom\bottom.toml` | +| OS | Default Config Location | +| ------- | ------------------------------------------------------------------------------------------------------------------------------------------ | +| macOS | `$HOME/Library/Application Support/bottom/bottom.toml`
`$HOME/.config/bottom/bottom.toml`
`$XDG_CONFIG_HOME/bottom/bottom.toml` | +| Linux | `$HOME/.config/bottom/bottom.toml`
`$XDG_CONFIG_HOME/bottom/bottom.toml` | +| Windows | `C:\Users\\AppData\Roaming\bottom\bottom.toml` | If the config file doesn't exist at the path, bottom will automatically try to create a new config file at the location with default values. diff --git a/src/options.rs b/src/options.rs index 7e9b4cb5..72058cff 100644 --- a/src/options.rs +++ b/src/options.rs @@ -60,36 +60,67 @@ macro_rules! is_flag_enabled { }; } +/// The default config file sub-path. +const DEFAULT_CONFIG_FILE_LOCATION: &str = "bottom/bottom.toml"; + /// Returns the config path to use. If `override_config_path` is specified, then /// we will use that. If not, then return the "default" config path, which is: +/// /// - If a path already exists at `/bottom/bottom.toml`, then use that for /// legacy reasons. /// - Otherwise, use `/bottom/bottom.toml`. /// /// For more details on this, see [dirs](https://docs.rs/dirs/latest/dirs/fn.config_dir.html)' /// documentation. +/// +/// XXX: For macOS, we additionally will manually check `$XDG_CONFIG_HOME` as well first +/// before falling back to `dirs`. fn get_config_path(override_config_path: Option<&Path>) -> Option { - const DEFAULT_CONFIG_FILE_PATH: &str = "bottom/bottom.toml"; - if let Some(conf_loc) = override_config_path { return Some(conf_loc.to_path_buf()); } else if let Some(home_path) = dirs::home_dir() { let mut old_home_path = home_path; old_home_path.push(".config/"); - old_home_path.push(DEFAULT_CONFIG_FILE_PATH); - if old_home_path.exists() { - // We used to create it at `/DEFAULT_CONFIG_FILE_PATH`, but changed it - // to be more correct later. However, for legacy reasons, if it already exists, - // use the old one. - return Some(old_home_path); + old_home_path.push(DEFAULT_CONFIG_FILE_LOCATION); + if let Ok(res) = old_home_path.try_exists() { + if res { + // We used to create it at `/DEFAULT_CONFIG_FILE_PATH`, but changed it + // to be more correct later. However, for legacy reasons, if it already exists, + // use the old one. + return Some(old_home_path); + } } } - // Otherwise, return the "correct" path based on the config dir. - dirs::config_dir().map(|mut path| { - path.push(DEFAULT_CONFIG_FILE_PATH); + let config_path = dirs::config_dir().map(|mut path| { + path.push(DEFAULT_CONFIG_FILE_LOCATION); path - }) + }); + + if cfg!(target_os = "macos") { + if let Ok(xdg_config_path) = std::env::var("XDG_CONFIG_HOME") { + if !xdg_config_path.is_empty() { + // If XDG_CONFIG_HOME exists and is non-empty, _but_ we previously used the Library-based path + // for a config and it exists, then use that instead for backwards-compatibility. + if let Some(old_macos_path) = &config_path { + if let Ok(res) = old_macos_path.try_exists() { + if res { + return config_path; + } + } + } + + // Otherwise, try and use the XDG_CONFIG_HOME-based path. + let mut cfg_path = PathBuf::new(); + cfg_path.push(xdg_config_path); + cfg_path.push(DEFAULT_CONFIG_FILE_LOCATION); + + return Some(cfg_path); + } + } + } + + config_path } fn create_config_at_path(path: &Path) -> anyhow::Result { @@ -1183,4 +1214,47 @@ mod test { } } } + + /// This one has slightly more complex behaviour due to `dirs` not respecting XDG on macOS, so we manually + /// handle it. However, to ensure backwards-compatibility, we also have to do some special cases. + #[cfg(target_os = "macos")] + #[test] + fn test_get_config_path_macos() { + use super::get_config_path; + use super::DEFAULT_CONFIG_FILE_LOCATION; + use std::path::PathBuf; + + // Case three: no previous config, no XDG var. + // SAFETY: this is the only test that does this + unsafe { + std::env::remove_var("XDG_CONFIG_HOME"); + } + + let case_1 = dirs::config_dir() + .map(|mut path| { + path.push(DEFAULT_CONFIG_FILE_LOCATION); + path + }) + .unwrap(); + + // Skip this test if the file already exists. + if !case_1.exists() { + assert_eq!(get_config_path(None), Some(case_1)); + } + + // Case two: no previous config, XDG var exists. + std::env::set_var("XDG_CONFIG_HOME", "/tmp"); + let mut case_2 = PathBuf::new(); + case_2.push("/tmp"); + case_2.push(DEFAULT_CONFIG_FILE_LOCATION); + + // Skip this test if the file already exists. + if !case_2.exists() { + assert_eq!(get_config_path(None), Some(case_2)); + } + + // Case one: old non-XDG exists already, XDG var exists. + // let case_3 = case_1; + // assert_eq!(get_config_path(None), Some(case_1)); + } } diff --git a/src/options/config/style.rs b/src/options/config/style.rs index d01713f5..525f6746 100644 --- a/src/options/config/style.rs +++ b/src/options/config/style.rs @@ -231,7 +231,6 @@ mod test { #[test] fn default_selected_colour_works() { let mut colours = ColourPalette::default(); - println!("colours: {colours:?}"); let original_selected_text_colour = ColourPalette::default_palette() .selected_text_style .fg