mirror of
https://github.com/lsd-rs/lsd
synced 2024-12-14 14:12:31 +00:00
🔨 simplify icon theme and updates due to review
Signed-off-by: Wei Zhang <kweizh@gmail.com>
This commit is contained in:
parent
9a7a3eaf13
commit
acae1201a8
4 changed files with 68 additions and 58 deletions
29
README.md
29
README.md
|
@ -246,7 +246,7 @@ The valid theme configurations are:
|
|||
when configured with the `theme-file-name` which is a `yaml` file,
|
||||
`lsd` will look up the theme file in the following way:
|
||||
|
||||
- relative name: check the themes under XDG Base Directory, e.g. ~/.config/lsd/themes/<theme-file-name>.yaml
|
||||
- relative name: check the XDG Base Directory, e.g. ~/.config/lsd/<theme-file-name>.yaml
|
||||
- absolute name: use the file path and name to find theme file
|
||||
|
||||
Check [Color Theme file content](#color-theme-file-content) for details.
|
||||
|
@ -301,9 +301,9 @@ Please also notice that an empty theme is **NOT** supported due to
|
|||
|
||||
### Icon Theme
|
||||
|
||||
Icon theme can be configured in a fixed location, `LSD_CONFIG_DIR/themes/icons.yaml`,
|
||||
for example, `~/.config/lsd/themes/icons.yam` on macOS,
|
||||
please check [Config file location](#config-file-location) to make sure where is `LSD_CONFIG_DIR`.
|
||||
Icon theme can be configured in a fixed location, `$XDG_CONFIG_DIR/lsd/icons.yaml`,
|
||||
for example, `~/.config/lsd/icons.yaml` on macOS,
|
||||
please check [Config file location](#config-file-location) to make sure where is `$XDG_CONFIG_DIR`.
|
||||
|
||||
As the file name indicated, the icon theme file is a `yaml` file.
|
||||
|
||||
|
@ -312,9 +312,9 @@ Check [Icon Theme file content](#icon-theme-file-content) for details.
|
|||
#### Icon Theme file content
|
||||
|
||||
lsd support 3 kinds of icon configuration:
|
||||
- icons-by-filetype
|
||||
- icons-by-name
|
||||
- icons-by-extension
|
||||
- filetype
|
||||
- name
|
||||
- extension
|
||||
|
||||
The default icon theme scheme shipped with `lsd` can be check in [icon theme source code](src/theme/icon.rs), we will load the default theme, and overwrite it with user defined parts, here is a example for icon theme.
|
||||
|
||||
|
@ -323,16 +323,16 @@ lsd icon theme support both nerd font and Unicode in the same time, you can use
|
|||
nerd font:
|
||||
|
||||
```yaml
|
||||
icons-by-name:
|
||||
name:
|
||||
.trash:
|
||||
.cargo:
|
||||
.emacs.d:
|
||||
a.out:
|
||||
icons-by-extension:
|
||||
extension:
|
||||
go:
|
||||
hs:
|
||||
rs:
|
||||
icons-by-filetype:
|
||||
filetype:
|
||||
dir:
|
||||
file:
|
||||
pipe:
|
||||
|
@ -348,11 +348,11 @@ icons-by-filetype:
|
|||
Unicode:
|
||||
|
||||
```yaml
|
||||
icons-by-name:
|
||||
name:
|
||||
.trash: 🗑
|
||||
icons-by-extension:
|
||||
extension:
|
||||
rs: 🦀
|
||||
icons-by-filetype:
|
||||
filetype:
|
||||
dir: 📂
|
||||
file: 📄
|
||||
pipe: 📩
|
||||
|
@ -361,9 +361,6 @@ icons-by-filetype:
|
|||
When creating a theme for `lsd`, you can specify any part of the default theme,
|
||||
and then change its colors, the items missed would fallback to use the default colors.
|
||||
|
||||
Please also notice that an empty theme is **NOT** supported due to
|
||||
[a bug in serde lib](https://github.com/dtolnay/serde-yaml/issues/86).
|
||||
|
||||
## External Configurations
|
||||
|
||||
### Required
|
||||
|
|
29
src/icon.rs
29
src/icon.rs
|
@ -38,34 +38,29 @@ impl Icons {
|
|||
// Check file types
|
||||
let file_type: FileType = name.file_type();
|
||||
let icon = match file_type {
|
||||
FileType::SymLink { is_dir: true } => &t.icons_by_filetype.symlink_dir,
|
||||
FileType::SymLink { is_dir: false } => &t.icons_by_filetype.symlink_file,
|
||||
FileType::Socket => &t.icons_by_filetype.socket,
|
||||
FileType::Pipe => &t.icons_by_filetype.pipe,
|
||||
FileType::CharDevice => &t.icons_by_filetype.device_char,
|
||||
FileType::BlockDevice => &t.icons_by_filetype.device_block,
|
||||
FileType::Special => &t.icons_by_filetype.special,
|
||||
FileType::SymLink { is_dir: true } => &t.filetype.symlink_dir,
|
||||
FileType::SymLink { is_dir: false } => &t.filetype.symlink_file,
|
||||
FileType::Socket => &t.filetype.socket,
|
||||
FileType::Pipe => &t.filetype.pipe,
|
||||
FileType::CharDevice => &t.filetype.device_char,
|
||||
FileType::BlockDevice => &t.filetype.device_block,
|
||||
FileType::Special => &t.filetype.special,
|
||||
_ => {
|
||||
if let Some(icon) = t
|
||||
.icons_by_name
|
||||
.get(name.file_name().to_lowercase().as_str())
|
||||
{
|
||||
if let Some(icon) = t.name.get(name.file_name().to_lowercase().as_str()) {
|
||||
icon
|
||||
} else if let Some(icon) = name
|
||||
.extension()
|
||||
.and_then(|ext| t.icons_by_extension.get(ext.to_lowercase().as_str()))
|
||||
.and_then(|ext| t.extension.get(ext.to_lowercase().as_str()))
|
||||
{
|
||||
icon
|
||||
} else {
|
||||
match file_type {
|
||||
FileType::Directory { .. } => &t.icons_by_filetype.dir,
|
||||
FileType::Directory { .. } => &t.filetype.dir,
|
||||
// If a file has no extension and is executable, show an icon.
|
||||
// Except for Windows, it marks everything as an executable.
|
||||
#[cfg(not(windows))]
|
||||
FileType::File { exec: true, .. } => {
|
||||
&t.icons_by_filetype.executable
|
||||
}
|
||||
_ => &t.icons_by_filetype.file,
|
||||
FileType::File { exec: true, .. } => &t.filetype.executable,
|
||||
_ => &t.filetype.file,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
15
src/theme.rs
15
src/theme.rs
|
@ -38,7 +38,10 @@ 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
|
||||
pub fn from_path<D: DeserializeOwned>(file: &str) -> Result<D, Error> {
|
||||
pub fn from_path<D>(file: &str) -> Result<D, Error>
|
||||
where
|
||||
D: DeserializeOwned + Default,
|
||||
{
|
||||
let real = if let Some(path) = config_file::Config::expand_home(file) {
|
||||
path
|
||||
} else {
|
||||
|
@ -49,7 +52,7 @@ impl Theme {
|
|||
real
|
||||
} else {
|
||||
match config_file::Config::config_file_path() {
|
||||
Some(p) => p.join("themes").join(real),
|
||||
Some(p) => p.join(real),
|
||||
None => return Err(Error::InvalidPath("config home not existed".into())),
|
||||
}
|
||||
};
|
||||
|
@ -72,7 +75,13 @@ impl Theme {
|
|||
}
|
||||
|
||||
/// This constructs a Theme struct with a passed [Yaml] str.
|
||||
fn with_yaml<D: DeserializeOwned>(yaml: &str) -> Result<D, serde_yaml::Error> {
|
||||
fn with_yaml<D>(yaml: &str) -> Result<D, serde_yaml::Error>
|
||||
where
|
||||
D: DeserializeOwned + Default,
|
||||
{
|
||||
if yaml.trim() == "" {
|
||||
return Ok(D::default());
|
||||
}
|
||||
serde_yaml::from_str::<D>(yaml)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,16 +6,16 @@ use std::collections::HashMap;
|
|||
#[serde(deny_unknown_fields)]
|
||||
#[serde(default)]
|
||||
pub struct IconTheme {
|
||||
pub icons_by_name: HashMap<String, String>,
|
||||
pub icons_by_extension: HashMap<String, String>,
|
||||
pub icons_by_filetype: IconByType,
|
||||
pub name: HashMap<String, String>,
|
||||
pub extension: HashMap<String, String>,
|
||||
pub filetype: ByType,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
#[serde(default)]
|
||||
pub struct IconByType {
|
||||
pub struct ByType {
|
||||
pub dir: String,
|
||||
pub file: String,
|
||||
pub pipe: String,
|
||||
|
@ -31,16 +31,16 @@ pub struct IconByType {
|
|||
impl Default for IconTheme {
|
||||
fn default() -> Self {
|
||||
IconTheme {
|
||||
icons_by_name: Self::get_default_icons_by_name(),
|
||||
icons_by_extension: Self::get_default_icons_by_extension(),
|
||||
icons_by_filetype: IconByType::default(),
|
||||
name: Self::get_default_icons_by_name(),
|
||||
extension: Self::get_default_icons_by_extension(),
|
||||
filetype: ByType::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for IconByType {
|
||||
fn default() -> IconByType {
|
||||
IconByType {
|
||||
impl Default for ByType {
|
||||
fn default() -> ByType {
|
||||
ByType {
|
||||
dir: "\u{f115}".into(), //
|
||||
file: "\u{f016}".into(), //
|
||||
pipe: "\u{f731}".into(), //
|
||||
|
@ -55,9 +55,9 @@ impl Default for IconByType {
|
|||
}
|
||||
}
|
||||
|
||||
impl IconByType {
|
||||
impl ByType {
|
||||
pub fn unicode() -> Self {
|
||||
IconByType {
|
||||
ByType {
|
||||
dir: "\u{1f4c2}".into(),
|
||||
file: "\u{1f4c4}".into(),
|
||||
pipe: "\u{1f4e9}".into(),
|
||||
|
@ -75,9 +75,9 @@ impl IconByType {
|
|||
impl IconTheme {
|
||||
pub fn unicode() -> Self {
|
||||
IconTheme {
|
||||
icons_by_name: HashMap::new(),
|
||||
icons_by_extension: HashMap::new(),
|
||||
icons_by_filetype: IconByType::unicode(),
|
||||
name: HashMap::new(),
|
||||
extension: HashMap::new(),
|
||||
filetype: ByType::unicode(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -482,16 +482,16 @@ mod tests {
|
|||
|
||||
fn partial_default_yaml() -> &'static str {
|
||||
r#"---
|
||||
icons-by-name:
|
||||
name:
|
||||
.trash:
|
||||
.cargo:
|
||||
.emacs.d:
|
||||
a.out:
|
||||
icons-by-extension:
|
||||
extension:
|
||||
go:
|
||||
hs:
|
||||
rs:
|
||||
icons-by-filetype:
|
||||
filetype:
|
||||
dir:
|
||||
file:
|
||||
pipe:
|
||||
|
@ -506,7 +506,7 @@ icons-by-filetype:
|
|||
}
|
||||
|
||||
fn check_partial_yaml(def: &IconTheme, yaml: &IconTheme) {
|
||||
assert_eq!(def.icons_by_filetype.dir, yaml.icons_by_filetype.dir,);
|
||||
assert_eq!(def.filetype.dir, yaml.filetype.dir,);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -533,7 +533,16 @@ icons-by-filetype:
|
|||
fn test_empty_theme_return_default() {
|
||||
// Must contain one field at least
|
||||
// ref https://github.com/dtolnay/serde-yaml/issues/86
|
||||
let empty: IconTheme = Theme::with_yaml("icons-by-filetype:\n dir: ").unwrap(); // is the default value
|
||||
let empty: IconTheme = Theme::with_yaml(" ").unwrap();
|
||||
let default = IconTheme::default();
|
||||
check_partial_yaml(&empty, &default);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_partial_theme_return_default() {
|
||||
// Must contain one field at least
|
||||
// ref https://github.com/dtolnay/serde-yaml/issues/86
|
||||
let empty: IconTheme = Theme::with_yaml("filetype:\n dir: ").unwrap(); // is the default value
|
||||
let default = IconTheme::default();
|
||||
check_partial_yaml(&empty, &default);
|
||||
}
|
||||
|
@ -542,7 +551,7 @@ icons-by-filetype:
|
|||
fn test_serde_dir_from_yaml() {
|
||||
// Must contain one field at least
|
||||
// ref https://github.com/dtolnay/serde-yaml/issues/86
|
||||
let empty: IconTheme = Theme::with_yaml("icons-by-filetype:\n dir: ").unwrap();
|
||||
assert_eq!(empty.icons_by_filetype.dir, "");
|
||||
let empty: IconTheme = Theme::with_yaml("filetype:\n dir: ").unwrap();
|
||||
assert_eq!(empty.filetype.dir, "");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue