🔨 simplify icon theme and updates due to review

Signed-off-by: Wei Zhang <kweizh@gmail.com>
This commit is contained in:
Wei Zhang 2022-09-28 01:18:51 +08:00 committed by Abin Simon
parent 9a7a3eaf13
commit acae1201a8
4 changed files with 68 additions and 58 deletions

View file

@ -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

View file

@ -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,
}
}
}

View file

@ -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)
}
}

View file

@ -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, "");
}
}