mirror of
https://github.com/lsd-rs/lsd
synced 2024-12-14 22:22:26 +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).
|
of characters (disabled by default).
|
||||||
- Add support for `--literal` from [PanGan21](https://github.com/PanGan21)
|
- 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 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
|
## [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"
|
lscolors = "0.16.0"
|
||||||
wild = "2.0"
|
wild = "2.0"
|
||||||
globset = "0.4.*"
|
globset = "0.4.*"
|
||||||
xdg = "2.1"
|
|
||||||
yaml-rust = "0.4.*"
|
yaml-rust = "0.4.*"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_yaml = "0.9"
|
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
|
On non-Windows systems `lsd` follows the
|
||||||
[XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html)
|
[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
|
convention for the location of the configuration file. A `config.yaml` or `config.yml` file will be searched for in these locations, in order:
|
||||||
`lsd` uses is itself named `lsd`. In that directory it looks first for a file
|
|
||||||
called `config.yaml`.
|
- `$XDG_CONFIG_HOME/lsd`
|
||||||
For most people it should be enough to put their config file at
|
- `$HOME/.config/lsd`
|
||||||
`~/.config/lsd/config.yaml`.
|
|
||||||
|
On most systems these are mapped to the same location, which is `~/.config/lsd/config.yaml`.
|
||||||
|
|
||||||
### Windows
|
### Windows
|
||||||
|
|
||||||
On Windows systems `lsd` only looks for the `config.yaml` files in one location:
|
On Windows systems `lsd` searches for `config.yaml` or `config.yml` in the following locations, in order:
|
||||||
`%APPDATA%\lsd\`
|
|
||||||
|
- `%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
|
### Custom
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,6 @@ use serde::Deserialize;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io;
|
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
|
/// A struct to hold an optional configuration items, and provides methods
|
||||||
/// around error handling in a config file.
|
/// around error handling in a config file.
|
||||||
#[derive(Eq, PartialEq, Debug, Deserialize)]
|
#[derive(Eq, PartialEq, Debug, Deserialize)]
|
||||||
|
@ -144,27 +141,6 @@ impl Config {
|
||||||
serde_yaml::from_str::<Self>(yaml)
|
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
|
/// This expand the `~` in path to HOME dir
|
||||||
/// returns the origin one if no `~` found;
|
/// returns the origin one if no `~` found;
|
||||||
/// returns None if error happened when getting home dir
|
/// 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 {
|
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 {
|
fn default() -> Self {
|
||||||
if let Some(p) = Self::config_file_path() {
|
Config::config_paths()
|
||||||
if let Some(c) = Self::from_file(p.join(CONF_FILE_NAME)) {
|
.find_map(|p| {
|
||||||
return c;
|
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
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
Self::from_yaml(DEFAULT_CONFIG).unwrap()
|
.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 unicode_width;
|
||||||
extern crate url;
|
extern crate url;
|
||||||
extern crate wild;
|
extern crate wild;
|
||||||
extern crate xdg;
|
|
||||||
extern crate yaml_rust;
|
extern crate yaml_rust;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
|
19
src/theme.rs
19
src/theme.rs
|
@ -38,9 +38,9 @@ pub enum Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Theme {
|
impl Theme {
|
||||||
/// This read theme from file,
|
/// Read theme from a file path
|
||||||
/// use the file path if it is absolute
|
/// use the file path as-is if it is absolute
|
||||||
/// prefix the config_file dir to it if it is not
|
/// search the config paths folders for it if not
|
||||||
pub fn from_path<D>(file: &str) -> Result<D, Error>
|
pub fn from_path<D>(file: &str) -> Result<D, Error>
|
||||||
where
|
where
|
||||||
D: DeserializeOwned + Default,
|
D: DeserializeOwned + Default,
|
||||||
|
@ -54,9 +54,16 @@ impl Theme {
|
||||||
let path = if Path::new(&real).is_absolute() {
|
let path = if Path::new(&real).is_absolute() {
|
||||||
real
|
real
|
||||||
} else {
|
} else {
|
||||||
match config_file::Config::config_file_path() {
|
let path = config_file::Config::config_paths()
|
||||||
Some(p) => p.join(real),
|
.map(|p| p.join(real.clone()))
|
||||||
None => return Err(Error::InvalidPath("config home not existed".into())),
|
.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