mirror of
https://github.com/sxyazi/yazi.git
synced 2024-12-11 09:24:55 +03:00
feat: icon color and ordered icon rules support (#503)
This commit is contained in:
parent
cd84386ead
commit
560a1bf3f9
@ -164,145 +164,149 @@ rules = [
|
|||||||
{ name = "*/", fg = "blue" }
|
{ name = "*/", fg = "blue" }
|
||||||
]
|
]
|
||||||
|
|
||||||
[icons]
|
[icon]
|
||||||
|
|
||||||
"Desktop/" = ""
|
rules = [
|
||||||
"Documents/" = ""
|
# Programming
|
||||||
"Downloads/" = ""
|
{ name = "*.c" , text = "" },
|
||||||
"Pictures/" = ""
|
{ name = "*.cpp" , text = "" },
|
||||||
"Music/" = ""
|
{ name = "*.css" , text = "" },
|
||||||
"Movies/" = ""
|
{ name = "*.fish" , text = "" },
|
||||||
"Videos/" = ""
|
{ name = "*.go" , text = "" },
|
||||||
"Public/" = ""
|
{ name = "*.h" , text = "" },
|
||||||
"Library/" = ""
|
{ name = "*.hpp" , text = "" },
|
||||||
"Development/" = ""
|
{ name = "*.html" , text = "" },
|
||||||
".config/" = ""
|
{ name = "*.java" , text = "" },
|
||||||
|
{ name = "*.js" , text = "" },
|
||||||
# Git
|
{ name = "*.jsx" , text = "" },
|
||||||
".git/" = ""
|
{ name = "*.lua" , text = "" },
|
||||||
".gitignore" = ""
|
{ name = "*.nix" , text = "" },
|
||||||
".gitmodules" = ""
|
{ name = "*.php" , text = "" },
|
||||||
".gitattributes" = ""
|
{ name = "*.py" , text = "" },
|
||||||
|
{ name = "*.rb" , text = "" },
|
||||||
# Dotfiles
|
{ name = "*.rs" , text = "" },
|
||||||
".DS_Store" = ""
|
{ name = "*.scss" , text = "" },
|
||||||
".bashrc" = ""
|
{ name = "*.sh" , text = "" },
|
||||||
".bashprofile" = ""
|
{ name = "*.swift", text = "" },
|
||||||
".zshrc" = ""
|
{ name = "*.ts" , text = "" },
|
||||||
".zshenv" = ""
|
{ name = "*.tsx" , text = "" },
|
||||||
".zprofile" = ""
|
{ name = "*.vim" , text = "" },
|
||||||
".vimrc" = ""
|
{ name = "*.vue" , text = "" },
|
||||||
|
|
||||||
# Text
|
# Text
|
||||||
"*.txt" = ""
|
{ name = "*.conf", text = "" },
|
||||||
"*.md" = ""
|
{ name = "*.ini" , text = "" },
|
||||||
"*.rst" = ""
|
{ name = "*.json", text = "" },
|
||||||
COPYING = ""
|
{ name = "*.md" , text = "" },
|
||||||
LICENSE = ""
|
{ name = "*.toml", text = "" },
|
||||||
|
{ name = "*.txt", text = "" },
|
||||||
|
{ name = "*.yaml", text = "" },
|
||||||
|
{ name = "*.yml" , text = "" },
|
||||||
|
|
||||||
# Archives
|
# Archives
|
||||||
"*.zip" = ""
|
{ name = "*.7z" , text = "" },
|
||||||
"*.tar" = ""
|
{ name = "*.bz2", text = "" },
|
||||||
"*.gz" = ""
|
{ name = "*.gz" , text = "" },
|
||||||
"*.7z" = ""
|
{ name = "*.rar", text = "" },
|
||||||
"*.bz2" = ""
|
{ name = "*.tar", text = "" },
|
||||||
"*.xz" = ""
|
{ name = "*.xz" , text = "" },
|
||||||
|
{ name = "*.zip", text = "" },
|
||||||
# Documents
|
|
||||||
"*.csv" = ""
|
|
||||||
"*.doc" = ""
|
|
||||||
"*.doct" = ""
|
|
||||||
"*.docx" = ""
|
|
||||||
"*.dot" = ""
|
|
||||||
"*.ods" = ""
|
|
||||||
"*.ots" = ""
|
|
||||||
"*.pdf" = ""
|
|
||||||
"*.pom" = ""
|
|
||||||
"*.pot" = ""
|
|
||||||
"*.ppm" = ""
|
|
||||||
"*.pps" = ""
|
|
||||||
"*.ppt" = ""
|
|
||||||
"*.potx" = ""
|
|
||||||
"*.ppmx" = ""
|
|
||||||
"*.ppsx" = ""
|
|
||||||
"*.pptx" = ""
|
|
||||||
"*.xlc" = ""
|
|
||||||
"*.xlm" = ""
|
|
||||||
"*.xls" = ""
|
|
||||||
"*.xlt" = ""
|
|
||||||
"*.xlsm" = ""
|
|
||||||
"*.xlsx" = ""
|
|
||||||
|
|
||||||
# Audio
|
|
||||||
"*.mp3" = ""
|
|
||||||
"*.flac" = ""
|
|
||||||
"*.wav" = ""
|
|
||||||
"*.aac" = ""
|
|
||||||
"*.ogg" = ""
|
|
||||||
"*.m4a" = ""
|
|
||||||
"*.mp2" = ""
|
|
||||||
|
|
||||||
# Movies
|
|
||||||
"*.mp4" = ""
|
|
||||||
"*.mkv" = ""
|
|
||||||
"*.avi" = ""
|
|
||||||
"*.mov" = ""
|
|
||||||
"*.webm" = ""
|
|
||||||
|
|
||||||
# Images
|
# Images
|
||||||
"*.jpg" = ""
|
{ name = "*.HEIC", text = "" },
|
||||||
"*.jpeg" = ""
|
{ name = "*.avif", text = "" },
|
||||||
"*.png" = ""
|
{ name = "*.bmp" , text = "" },
|
||||||
"*.gif" = ""
|
{ name = "*.gif" , text = "" },
|
||||||
"*.webp" = ""
|
{ name = "*.ico" , text = "" },
|
||||||
"*.avif" = ""
|
{ name = "*.jpeg", text = "" },
|
||||||
"*.bmp" = ""
|
{ name = "*.jpg" , text = "" },
|
||||||
"*.ico" = ""
|
{ name = "*.png" , text = "" },
|
||||||
"*.svg" = ""
|
{ name = "*.svg" , text = "" },
|
||||||
"*.xcf" = ""
|
{ name = "*.webp", text = "" },
|
||||||
"*.HEIC" = ""
|
|
||||||
|
|
||||||
# Programming
|
# Movies
|
||||||
"*.c" = ""
|
{ name = "*.avi" , text = "" },
|
||||||
"*.cpp" = ""
|
{ name = "*.mkv" , text = "" },
|
||||||
"*.h" = ""
|
{ name = "*.mov" , text = "" },
|
||||||
"*.hpp" = ""
|
{ name = "*.mp4" , text = "" },
|
||||||
"*.rs" = ""
|
{ name = "*.webm", text = "" },
|
||||||
"*.go" = ""
|
|
||||||
"*.py" = ""
|
# Audio
|
||||||
"*.js" = ""
|
{ name = "*.aac" , text = "" },
|
||||||
"*.ts" = ""
|
{ name = "*.flac", text = "" },
|
||||||
"*.tsx" = ""
|
{ name = "*.m4a" , text = "" },
|
||||||
"*.jsx" = ""
|
{ name = "*.mp3" , text = "" },
|
||||||
"*.rb" = ""
|
{ name = "*.ogg" , text = "" },
|
||||||
"*.php" = ""
|
{ name = "*.wav" , text = "" },
|
||||||
"*.java" = ""
|
|
||||||
"*.sh" = ""
|
# Documents
|
||||||
"*.fish" = ""
|
{ name = "*.csv" , text = "" },
|
||||||
"*.swift" = ""
|
{ name = "*.doc" , text = "" },
|
||||||
"*.vim" = ""
|
{ name = "*.doct", text = "" },
|
||||||
"*.lua" = ""
|
{ name = "*.docx", text = "" },
|
||||||
"*.html" = ""
|
{ name = "*.dot" , text = "" },
|
||||||
"*.css" = ""
|
{ name = "*.ods" , text = "" },
|
||||||
"*.scss" = ""
|
{ name = "*.ots" , text = "" },
|
||||||
"*.json" = ""
|
{ name = "*.pdf" , text = "" },
|
||||||
"*.toml" = ""
|
{ name = "*.pom" , text = "" },
|
||||||
"*.yml" = ""
|
{ name = "*.pot" , text = "" },
|
||||||
"*.yaml" = ""
|
{ name = "*.potx", text = "" },
|
||||||
"*.ini" = ""
|
{ name = "*.ppm" , text = "" },
|
||||||
"*.conf" = ""
|
{ name = "*.ppmx", text = "" },
|
||||||
"*.lock" = ""
|
{ name = "*.pps" , text = "" },
|
||||||
"*.nix" = ""
|
{ name = "*.ppsx", text = "" },
|
||||||
Containerfile = ""
|
{ name = "*.ppt" , text = "" },
|
||||||
Dockerfile = ""
|
{ name = "*.pptx", text = "" },
|
||||||
|
{ name = "*.xlc" , text = "" },
|
||||||
|
{ name = "*.xlm" , text = "" },
|
||||||
|
{ name = "*.xls" , text = "" },
|
||||||
|
{ name = "*.xlsm", text = "" },
|
||||||
|
{ name = "*.xlsx", text = "" },
|
||||||
|
{ name = "*.xlt" , text = "" },
|
||||||
|
|
||||||
|
# Lockfiles
|
||||||
|
{ name = "*.lock", text = "" },
|
||||||
|
|
||||||
# Misc
|
# Misc
|
||||||
"*.bin" = ""
|
{ name = "*.bin", text = "" },
|
||||||
"*.exe" = ""
|
{ name = "*.exe", text = "" },
|
||||||
"*.pkg" = ""
|
{ name = "*.pkg", text = "" },
|
||||||
|
|
||||||
|
# Dotfiles
|
||||||
|
{ name = ".DS_Store" , text = "" },
|
||||||
|
{ name = ".bashprofile" , text = "" },
|
||||||
|
{ name = ".bashrc" , text = "" },
|
||||||
|
{ name = ".gitattributes", text = "" },
|
||||||
|
{ name = ".gitignore" , text = "" },
|
||||||
|
{ name = ".gitmodules" , text = "" },
|
||||||
|
{ name = ".vimrc" , text = "" },
|
||||||
|
{ name = ".zprofile" , text = "" },
|
||||||
|
{ name = ".zshenv" , text = "" },
|
||||||
|
{ name = ".zshrc" , text = "" },
|
||||||
|
|
||||||
|
# Named files
|
||||||
|
{ name = "COPYING" , text = "" },
|
||||||
|
{ name = "Containerfile", text = "" },
|
||||||
|
{ name = "Dockerfile" , text = "" },
|
||||||
|
{ name = "LICENSE" , text = "" },
|
||||||
|
|
||||||
|
# Directories
|
||||||
|
{ name = ".config/" , text = "" },
|
||||||
|
{ name = ".git/" , text = "" },
|
||||||
|
{ name = "Desktop/" , text = "" },
|
||||||
|
{ name = "Development/", text = "" },
|
||||||
|
{ name = "Documents/" , text = "" },
|
||||||
|
{ name = "Downloads/" , text = "" },
|
||||||
|
{ name = "Library/" , text = "" },
|
||||||
|
{ name = "Movies/" , text = "" },
|
||||||
|
{ name = "Music/" , text = "" },
|
||||||
|
{ name = "Pictures/" , text = "" },
|
||||||
|
{ name = "Public/" , text = "" },
|
||||||
|
{ name = "Videos/" , text = "" },
|
||||||
|
|
||||||
# Default
|
# Default
|
||||||
"*" = ""
|
{ name = "*" , text = "" },
|
||||||
"*/" = ""
|
{ name = "*/", text = "" },
|
||||||
|
]
|
||||||
|
|
||||||
# : }}}
|
# : }}}
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
use std::fmt;
|
use serde::{Deserialize, Deserializer};
|
||||||
|
|
||||||
use serde::{de::{self, Visitor}, Deserializer};
|
use super::Style;
|
||||||
|
use crate::{theme::{Color, StyleShadow}, Pattern};
|
||||||
|
|
||||||
use crate::Pattern;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Icon {
|
pub struct Icon {
|
||||||
pub name: Pattern,
|
pub name: Pattern,
|
||||||
pub display: String,
|
pub text: String,
|
||||||
|
pub style: Style,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Icon {
|
impl Icon {
|
||||||
@ -15,31 +14,28 @@ impl Icon {
|
|||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
struct IconVisitor;
|
#[derive(Deserialize)]
|
||||||
|
struct IconOuter {
|
||||||
|
rules: Vec<IconRule>,
|
||||||
|
}
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct IconRule {
|
||||||
|
name: Pattern,
|
||||||
|
text: String,
|
||||||
|
|
||||||
impl<'de> Visitor<'de> for IconVisitor {
|
fg: Option<Color>,
|
||||||
type Value = Vec<Icon>;
|
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
formatter.write_str("a icon rule, e.g. \"*.md\" = \"\"")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
Ok(
|
||||||
where
|
IconOuter::deserialize(deserializer)?
|
||||||
A: de::MapAccess<'de>,
|
.rules
|
||||||
{
|
.into_iter()
|
||||||
let mut icons = vec![];
|
.map(|r| Icon {
|
||||||
while let Some((key, value)) = &map.next_entry::<String, String>()? {
|
name: r.name,
|
||||||
icons.push(Icon {
|
text: r.text,
|
||||||
name: Pattern::try_from(key.clone())
|
style: StyleShadow { fg: r.fg, ..Default::default() }.into(),
|
||||||
.map_err(|e| de::Error::custom(e.to_string()))?,
|
})
|
||||||
display: value.clone(),
|
.collect::<Vec<_>>(),
|
||||||
});
|
)
|
||||||
}
|
|
||||||
Ok(icons)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deserializer.deserialize_map(IconVisitor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ impl From<Style> for ratatui::style::Style {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Default, Deserialize)]
|
||||||
pub(super) struct StyleShadow {
|
pub(super) struct StyleShadow {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(super) fg: Option<Color>,
|
pub(super) fg: Option<Color>,
|
||||||
|
@ -130,7 +130,7 @@ pub struct Theme {
|
|||||||
// File-specific styles
|
// File-specific styles
|
||||||
#[serde(rename = "filetype", deserialize_with = "Filetype::deserialize", skip_serializing)]
|
#[serde(rename = "filetype", deserialize_with = "Filetype::deserialize", skip_serializing)]
|
||||||
pub filetypes: Vec<Filetype>,
|
pub filetypes: Vec<Filetype>,
|
||||||
#[serde(deserialize_with = "Icon::deserialize", skip_serializing)]
|
#[serde(rename = "icon", deserialize_with = "Icon::deserialize", skip_serializing)]
|
||||||
pub icons: Vec<Icon>,
|
pub icons: Vec<Icon>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use mlua::{AnyUserData, IntoLua, Lua, MetaMethod, UserDataFields, UserDataMethods, Value};
|
use mlua::{AnyUserData, IntoLua, Lua, MetaMethod, UserDataFields, UserDataMethods, Value};
|
||||||
use yazi_config::{LAYOUT, THEME};
|
use yazi_config::{LAYOUT, THEME};
|
||||||
use yazi_plugin::{bindings::{Cast, File, Range, Url}, elements::Style};
|
use yazi_plugin::{bindings::{Cast, File, Icon, Range, Url}, elements::Style};
|
||||||
use yazi_shared::MIME_DIR;
|
use yazi_shared::MIME_DIR;
|
||||||
|
|
||||||
use super::{CtxRef, FolderRef};
|
use super::{CtxRef, FolderRef};
|
||||||
@ -69,14 +69,13 @@ impl<'a, 'b> Folder<'a, 'b> {
|
|||||||
p.next_back();
|
p.next_back();
|
||||||
Some(lua.create_string(p.as_path().as_os_str().as_encoded_bytes())).transpose()
|
Some(lua.create_string(p.as_path().as_os_str().as_encoded_bytes())).transpose()
|
||||||
});
|
});
|
||||||
reg.add_method("icon", |_, me, ()| {
|
reg.add_method("icon", |lua, me, ()| {
|
||||||
Ok(
|
|
||||||
THEME
|
THEME
|
||||||
.icons
|
.icons
|
||||||
.iter()
|
.iter()
|
||||||
.find(|&x| x.name.match_path(&me.url, me.is_dir()))
|
.find(|&x| x.name.match_path(&me.url, me.is_dir()))
|
||||||
.map(|x| x.display.to_string()),
|
.map(|x| Icon::cast(lua, x))
|
||||||
)
|
.transpose()
|
||||||
});
|
});
|
||||||
reg.add_function("style", |lua, me: AnyUserData| {
|
reg.add_function("style", |lua, me: AnyUserData| {
|
||||||
let cx = lua.named_registry_value::<CtxRef>("cx")?;
|
let cx = lua.named_registry_value::<CtxRef>("cx")?;
|
||||||
|
@ -12,6 +12,7 @@ pub(crate) struct Lives;
|
|||||||
impl Lives {
|
impl Lives {
|
||||||
pub(crate) fn register() -> mlua::Result<()> {
|
pub(crate) fn register() -> mlua::Result<()> {
|
||||||
yazi_plugin::bindings::Cha::register(&LUA)?;
|
yazi_plugin::bindings::Cha::register(&LUA)?;
|
||||||
|
yazi_plugin::bindings::Icon::register(&LUA)?;
|
||||||
yazi_plugin::bindings::Url::register(&LUA)?;
|
yazi_plugin::bindings::Url::register(&LUA)?;
|
||||||
|
|
||||||
super::Active::register(&LUA)?;
|
super::Active::register(&LUA)?;
|
||||||
|
@ -14,7 +14,10 @@ function Folder:by_kind(kind)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Folder:icon(file) return ui.Span(" " .. file:icon() .. " ") end
|
function Folder:icon(file)
|
||||||
|
local icon = file:icon()
|
||||||
|
return icon and ui.Span(" " .. icon.text .. " "):style(icon.style) or ui.Span("")
|
||||||
|
end
|
||||||
|
|
||||||
function Folder:highlighted_name(file)
|
function Folder:highlighted_name(file)
|
||||||
-- Complete prefix when searching across directories
|
-- Complete prefix when searching across directories
|
||||||
|
26
yazi-plugin/src/bindings/icon.rs
Normal file
26
yazi-plugin/src/bindings/icon.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use mlua::{AnyUserData, Lua, UserDataFields};
|
||||||
|
|
||||||
|
use super::Cast;
|
||||||
|
use crate::elements::Style;
|
||||||
|
|
||||||
|
pub struct Icon;
|
||||||
|
|
||||||
|
impl Icon {
|
||||||
|
pub fn register(lua: &Lua) -> mlua::Result<()> {
|
||||||
|
lua.register_userdata_type::<&yazi_config::theme::Icon>(|reg| {
|
||||||
|
reg.add_field_method_get("text", |lua, me| lua.create_string(&me.text));
|
||||||
|
reg.add_field_method_get("style", |_, me| Ok(Style::from(me.style)));
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Cast<&'static yazi_config::theme::Icon> for Icon {
|
||||||
|
fn cast<'lua>(
|
||||||
|
lua: &'lua Lua,
|
||||||
|
data: &'static yazi_config::theme::Icon,
|
||||||
|
) -> mlua::Result<AnyUserData<'lua>> {
|
||||||
|
lua.create_any_userdata(data)
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
mod bindings;
|
mod bindings;
|
||||||
mod cha;
|
mod cha;
|
||||||
mod file;
|
mod file;
|
||||||
|
mod icon;
|
||||||
mod range;
|
mod range;
|
||||||
mod url;
|
mod url;
|
||||||
mod window;
|
mod window;
|
||||||
@ -10,6 +11,7 @@ mod window;
|
|||||||
pub use bindings::*;
|
pub use bindings::*;
|
||||||
pub use cha::*;
|
pub use cha::*;
|
||||||
pub use file::*;
|
pub use file::*;
|
||||||
|
pub use icon::*;
|
||||||
pub use range::*;
|
pub use range::*;
|
||||||
pub use url::*;
|
pub use url::*;
|
||||||
pub use window::*;
|
pub use window::*;
|
||||||
|
Loading…
Reference in New Issue
Block a user