mirror of
https://github.com/lsd-rs/lsd
synced 2024-12-14 14:12:31 +00:00
Support multiple file paths for config and theme
This commit is contained in:
parent
a1bd4d6347
commit
94538d01e0
7 changed files with 582 additions and 579 deletions
|
@ -15,6 +15,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
of characters (disabled by default).
|
||||
- Add support for `--literal` from [PanGan21](https://github.com/PanGan21)
|
||||
- Add support for tilde (`~`) expansion on Windows from [Ofer Sadan](https://github.com/ofersadan85)
|
||||
- Add support to search multiple paths for config file and theme files from [Ofer Sadan](https://github.com/ofersadan85):
|
||||
- `$XDG_CONFIG_HOME/lsd` or `$HOME/.config/lsd` (in that order) on non-Windows platforms (these are usually the same)
|
||||
- `%APPDATA%\lsd` or `%USERPROFILE%\.config\lsd` (in that order) on Windows
|
||||
- Add support for both `config.yaml` and `config.yml` for the config file name from [Ofer Sadan](https://github.com/ofersadan85)
|
||||
|
||||
## [v1.0.0] - 2023-08-25
|
||||
|
||||
|
|
1053
Cargo.lock
generated
1053
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -37,7 +37,6 @@ unicode-width = "0.1.*"
|
|||
lscolors = "0.16.0"
|
||||
wild = "2.0"
|
||||
globset = "0.4.*"
|
||||
xdg = "2.1"
|
||||
yaml-rust = "0.4.*"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_yaml = "0.9"
|
||||
|
|
19
README.md
19
README.md
|
@ -102,16 +102,21 @@ Check [Config file content](#config-file-content) for details.
|
|||
|
||||
On non-Windows systems `lsd` follows the
|
||||
[XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html)
|
||||
convention for the location of the configuration file. The configuration dir
|
||||
`lsd` uses is itself named `lsd`. In that directory it looks first for a file
|
||||
called `config.yaml`.
|
||||
For most people it should be enough to put their config file at
|
||||
`~/.config/lsd/config.yaml`.
|
||||
convention for the location of the configuration file. A `config.yaml` or `config.yml` file will be searched for in these locations, in order:
|
||||
|
||||
- `$XDG_CONFIG_HOME/lsd`
|
||||
- `$HOME/.config/lsd`
|
||||
|
||||
On most systems these are mapped to the same location, which is `~/.config/lsd/config.yaml`.
|
||||
|
||||
### Windows
|
||||
|
||||
On Windows systems `lsd` only looks for the `config.yaml` files in one location:
|
||||
`%APPDATA%\lsd\`
|
||||
On Windows systems `lsd` searches for `config.yaml` or `config.yml` in the following locations, in order:
|
||||
|
||||
- `%APPDATA%\lsd`
|
||||
- `%USERPROFILE%\.config\lsd`
|
||||
|
||||
These are usually something like `C:\Users\username\AppData\Roaming\lsd\config.yaml` and `C:\Users\username\.config\lsd\config.yaml` respectively.
|
||||
|
||||
### Custom
|
||||
|
||||
|
|
|
@ -17,9 +17,6 @@ use serde::Deserialize;
|
|||
use std::fs;
|
||||
use std::io;
|
||||
|
||||
const CONF_DIR: &str = "lsd";
|
||||
const CONF_FILE_NAME: &str = "config.yaml";
|
||||
|
||||
/// A struct to hold an optional configuration items, and provides methods
|
||||
/// around error handling in a config file.
|
||||
#[derive(Eq, PartialEq, Debug, Deserialize)]
|
||||
|
@ -144,27 +141,6 @@ impl Config {
|
|||
serde_yaml::from_str::<Self>(yaml)
|
||||
}
|
||||
|
||||
/// This provides the path for a configuration file, according to the XDG_BASE_DIRS specification.
|
||||
/// return None if error like PermissionDenied
|
||||
#[cfg(not(windows))]
|
||||
pub fn config_file_path() -> Option<PathBuf> {
|
||||
use xdg::BaseDirectories;
|
||||
match BaseDirectories::with_prefix(CONF_DIR) {
|
||||
Ok(p) => Some(p.get_config_home()),
|
||||
Err(e) => {
|
||||
print_error!("Can not open config file: {}.", e);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This provides the path for a configuration file, inside the %APPDATA% directory.
|
||||
/// return None if error like PermissionDenied
|
||||
#[cfg(windows)]
|
||||
pub fn config_file_path() -> Option<PathBuf> {
|
||||
dirs::config_dir().map(|x| x.join(CONF_DIR))
|
||||
}
|
||||
|
||||
/// This expand the `~` in path to HOME dir
|
||||
/// returns the origin one if no `~` found;
|
||||
/// returns None if error happened when getting home dir
|
||||
|
@ -189,16 +165,44 @@ impl Config {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Config paths for non-Windows platforms will be read from
|
||||
/// `$XDG_CONFIG_HOME/lsd` or `$HOME/.config/lsd`
|
||||
/// (usually, those are the same) in that order.
|
||||
/// The default paths for Windows will be read from
|
||||
/// `%APPDATA%\lsd` or `%USERPROFILE%\.config\lsd` in that order.
|
||||
/// This will apply both to the config file and the theme file.
|
||||
pub fn config_paths() -> impl Iterator<Item = PathBuf> {
|
||||
[
|
||||
dirs::config_dir(),
|
||||
dirs::home_dir().map(|h| h.join(".config")),
|
||||
]
|
||||
.iter()
|
||||
.filter_map(|p| p.as_ref().map(|p| p.join("lsd")))
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
/// Try to find either config.yaml or config.yml in the config directories
|
||||
/// and use the first one that is found. If none are found, or the parsing fails,
|
||||
/// use the default from DEFAULT_CONFIG.
|
||||
fn default() -> Self {
|
||||
if let Some(p) = Self::config_file_path() {
|
||||
if let Some(c) = Self::from_file(p.join(CONF_FILE_NAME)) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
Self::from_yaml(DEFAULT_CONFIG).unwrap()
|
||||
Config::config_paths()
|
||||
.find_map(|p| {
|
||||
let yaml = p.join("config.yaml");
|
||||
let yml = p.join("config.yml");
|
||||
if yaml.is_file() {
|
||||
Config::from_file(yaml)
|
||||
} else if yml.is_file() {
|
||||
Config::from_file(yml)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.or(Self::from_yaml(DEFAULT_CONFIG).ok())
|
||||
.expect("Failed to read both config file and default config")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ extern crate terminal_size;
|
|||
extern crate unicode_width;
|
||||
extern crate url;
|
||||
extern crate wild;
|
||||
extern crate xdg;
|
||||
extern crate yaml_rust;
|
||||
|
||||
#[cfg(unix)]
|
||||
|
|
19
src/theme.rs
19
src/theme.rs
|
@ -38,9 +38,9 @@ pub enum Error {
|
|||
}
|
||||
|
||||
impl Theme {
|
||||
/// This read theme from file,
|
||||
/// use the file path if it is absolute
|
||||
/// prefix the config_file dir to it if it is not
|
||||
/// Read theme from a file path
|
||||
/// use the file path as-is if it is absolute
|
||||
/// search the config paths folders for it if not
|
||||
pub fn from_path<D>(file: &str) -> Result<D, Error>
|
||||
where
|
||||
D: DeserializeOwned + Default,
|
||||
|
@ -54,9 +54,16 @@ impl Theme {
|
|||
let path = if Path::new(&real).is_absolute() {
|
||||
real
|
||||
} else {
|
||||
match config_file::Config::config_file_path() {
|
||||
Some(p) => p.join(real),
|
||||
None => return Err(Error::InvalidPath("config home not existed".into())),
|
||||
let path = config_file::Config::config_paths()
|
||||
.map(|p| p.join(real.clone()))
|
||||
.find(|p| p.is_file());
|
||||
match path {
|
||||
Some(p) => p,
|
||||
None => {
|
||||
return Err(Error::InvalidPath(
|
||||
"Did not find theme file in config folders".into(),
|
||||
))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue