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" }
|
||||
]
|
||||
|
||||
[icons]
|
||||
[icon]
|
||||
|
||||
"Desktop/" = ""
|
||||
"Documents/" = ""
|
||||
"Downloads/" = ""
|
||||
"Pictures/" = ""
|
||||
"Music/" = ""
|
||||
"Movies/" = ""
|
||||
"Videos/" = ""
|
||||
"Public/" = ""
|
||||
"Library/" = ""
|
||||
"Development/" = ""
|
||||
".config/" = ""
|
||||
rules = [
|
||||
# Programming
|
||||
{ name = "*.c" , text = "" },
|
||||
{ name = "*.cpp" , text = "" },
|
||||
{ name = "*.css" , text = "" },
|
||||
{ name = "*.fish" , text = "" },
|
||||
{ name = "*.go" , text = "" },
|
||||
{ name = "*.h" , text = "" },
|
||||
{ name = "*.hpp" , text = "" },
|
||||
{ name = "*.html" , text = "" },
|
||||
{ name = "*.java" , text = "" },
|
||||
{ name = "*.js" , text = "" },
|
||||
{ name = "*.jsx" , text = "" },
|
||||
{ name = "*.lua" , text = "" },
|
||||
{ name = "*.nix" , text = "" },
|
||||
{ name = "*.php" , text = "" },
|
||||
{ name = "*.py" , text = "" },
|
||||
{ name = "*.rb" , text = "" },
|
||||
{ name = "*.rs" , text = "" },
|
||||
{ name = "*.scss" , text = "" },
|
||||
{ name = "*.sh" , text = "" },
|
||||
{ name = "*.swift", text = "" },
|
||||
{ name = "*.ts" , text = "" },
|
||||
{ name = "*.tsx" , text = "" },
|
||||
{ name = "*.vim" , text = "" },
|
||||
{ name = "*.vue" , text = "" },
|
||||
|
||||
# Git
|
||||
".git/" = ""
|
||||
".gitignore" = ""
|
||||
".gitmodules" = ""
|
||||
".gitattributes" = ""
|
||||
# Text
|
||||
{ name = "*.conf", text = "" },
|
||||
{ name = "*.ini" , text = "" },
|
||||
{ name = "*.json", text = "" },
|
||||
{ name = "*.md" , text = "" },
|
||||
{ name = "*.toml", text = "" },
|
||||
{ name = "*.txt", text = "" },
|
||||
{ name = "*.yaml", text = "" },
|
||||
{ name = "*.yml" , text = "" },
|
||||
|
||||
# Dotfiles
|
||||
".DS_Store" = ""
|
||||
".bashrc" = ""
|
||||
".bashprofile" = ""
|
||||
".zshrc" = ""
|
||||
".zshenv" = ""
|
||||
".zprofile" = ""
|
||||
".vimrc" = ""
|
||||
# Archives
|
||||
{ name = "*.7z" , text = "" },
|
||||
{ name = "*.bz2", text = "" },
|
||||
{ name = "*.gz" , text = "" },
|
||||
{ name = "*.rar", text = "" },
|
||||
{ name = "*.tar", text = "" },
|
||||
{ name = "*.xz" , text = "" },
|
||||
{ name = "*.zip", text = "" },
|
||||
|
||||
# Text
|
||||
"*.txt" = ""
|
||||
"*.md" = ""
|
||||
"*.rst" = ""
|
||||
COPYING = ""
|
||||
LICENSE = ""
|
||||
# Images
|
||||
{ name = "*.HEIC", text = "" },
|
||||
{ name = "*.avif", text = "" },
|
||||
{ name = "*.bmp" , text = "" },
|
||||
{ name = "*.gif" , text = "" },
|
||||
{ name = "*.ico" , text = "" },
|
||||
{ name = "*.jpeg", text = "" },
|
||||
{ name = "*.jpg" , text = "" },
|
||||
{ name = "*.png" , text = "" },
|
||||
{ name = "*.svg" , text = "" },
|
||||
{ name = "*.webp", text = "" },
|
||||
|
||||
# Archives
|
||||
"*.zip" = ""
|
||||
"*.tar" = ""
|
||||
"*.gz" = ""
|
||||
"*.7z" = ""
|
||||
"*.bz2" = ""
|
||||
"*.xz" = ""
|
||||
# Movies
|
||||
{ name = "*.avi" , text = "" },
|
||||
{ name = "*.mkv" , text = "" },
|
||||
{ name = "*.mov" , text = "" },
|
||||
{ name = "*.mp4" , text = "" },
|
||||
{ name = "*.webm", 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
|
||||
{ name = "*.aac" , text = "" },
|
||||
{ name = "*.flac", text = "" },
|
||||
{ name = "*.m4a" , text = "" },
|
||||
{ name = "*.mp3" , text = "" },
|
||||
{ name = "*.ogg" , text = "" },
|
||||
{ name = "*.wav" , text = "" },
|
||||
|
||||
# Audio
|
||||
"*.mp3" = ""
|
||||
"*.flac" = ""
|
||||
"*.wav" = ""
|
||||
"*.aac" = ""
|
||||
"*.ogg" = ""
|
||||
"*.m4a" = ""
|
||||
"*.mp2" = ""
|
||||
# Documents
|
||||
{ name = "*.csv" , text = "" },
|
||||
{ name = "*.doc" , text = "" },
|
||||
{ name = "*.doct", text = "" },
|
||||
{ name = "*.docx", text = "" },
|
||||
{ name = "*.dot" , text = "" },
|
||||
{ name = "*.ods" , text = "" },
|
||||
{ name = "*.ots" , text = "" },
|
||||
{ name = "*.pdf" , text = "" },
|
||||
{ name = "*.pom" , text = "" },
|
||||
{ name = "*.pot" , text = "" },
|
||||
{ name = "*.potx", text = "" },
|
||||
{ name = "*.ppm" , text = "" },
|
||||
{ name = "*.ppmx", text = "" },
|
||||
{ name = "*.pps" , text = "" },
|
||||
{ name = "*.ppsx", text = "" },
|
||||
{ name = "*.ppt" , text = "" },
|
||||
{ name = "*.pptx", text = "" },
|
||||
{ name = "*.xlc" , text = "" },
|
||||
{ name = "*.xlm" , text = "" },
|
||||
{ name = "*.xls" , text = "" },
|
||||
{ name = "*.xlsm", text = "" },
|
||||
{ name = "*.xlsx", text = "" },
|
||||
{ name = "*.xlt" , text = "" },
|
||||
|
||||
# Movies
|
||||
"*.mp4" = ""
|
||||
"*.mkv" = ""
|
||||
"*.avi" = ""
|
||||
"*.mov" = ""
|
||||
"*.webm" = ""
|
||||
# Lockfiles
|
||||
{ name = "*.lock", text = "" },
|
||||
|
||||
# Images
|
||||
"*.jpg" = ""
|
||||
"*.jpeg" = ""
|
||||
"*.png" = ""
|
||||
"*.gif" = ""
|
||||
"*.webp" = ""
|
||||
"*.avif" = ""
|
||||
"*.bmp" = ""
|
||||
"*.ico" = ""
|
||||
"*.svg" = ""
|
||||
"*.xcf" = ""
|
||||
"*.HEIC" = ""
|
||||
# Misc
|
||||
{ name = "*.bin", text = "" },
|
||||
{ name = "*.exe", text = "" },
|
||||
{ name = "*.pkg", text = "" },
|
||||
|
||||
# Programming
|
||||
"*.c" = ""
|
||||
"*.cpp" = ""
|
||||
"*.h" = ""
|
||||
"*.hpp" = ""
|
||||
"*.rs" = ""
|
||||
"*.go" = ""
|
||||
"*.py" = ""
|
||||
"*.js" = ""
|
||||
"*.ts" = ""
|
||||
"*.tsx" = ""
|
||||
"*.jsx" = ""
|
||||
"*.rb" = ""
|
||||
"*.php" = ""
|
||||
"*.java" = ""
|
||||
"*.sh" = ""
|
||||
"*.fish" = ""
|
||||
"*.swift" = ""
|
||||
"*.vim" = ""
|
||||
"*.lua" = ""
|
||||
"*.html" = ""
|
||||
"*.css" = ""
|
||||
"*.scss" = ""
|
||||
"*.json" = ""
|
||||
"*.toml" = ""
|
||||
"*.yml" = ""
|
||||
"*.yaml" = ""
|
||||
"*.ini" = ""
|
||||
"*.conf" = ""
|
||||
"*.lock" = ""
|
||||
"*.nix" = ""
|
||||
Containerfile = ""
|
||||
Dockerfile = ""
|
||||
# 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 = "" },
|
||||
|
||||
# Misc
|
||||
"*.bin" = ""
|
||||
"*.exe" = ""
|
||||
"*.pkg" = ""
|
||||
# Named files
|
||||
{ name = "COPYING" , text = "" },
|
||||
{ name = "Containerfile", text = "" },
|
||||
{ name = "Dockerfile" , text = "" },
|
||||
{ name = "LICENSE" , text = "" },
|
||||
|
||||
# Default
|
||||
"*" = ""
|
||||
"*/" = ""
|
||||
# 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
|
||||
{ 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 name: Pattern,
|
||||
pub display: String,
|
||||
pub text: String,
|
||||
pub style: Style,
|
||||
}
|
||||
|
||||
impl Icon {
|
||||
@ -15,31 +14,28 @@ impl Icon {
|
||||
where
|
||||
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 {
|
||||
type Value = Vec<Icon>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a icon rule, e.g. \"*.md\" = \"\"")
|
||||
fg: Option<Color>,
|
||||
}
|
||||
|
||||
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: de::MapAccess<'de>,
|
||||
{
|
||||
let mut icons = vec![];
|
||||
while let Some((key, value)) = &map.next_entry::<String, String>()? {
|
||||
icons.push(Icon {
|
||||
name: Pattern::try_from(key.clone())
|
||||
.map_err(|e| de::Error::custom(e.to_string()))?,
|
||||
display: value.clone(),
|
||||
});
|
||||
}
|
||||
Ok(icons)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_map(IconVisitor)
|
||||
Ok(
|
||||
IconOuter::deserialize(deserializer)?
|
||||
.rules
|
||||
.into_iter()
|
||||
.map(|r| Icon {
|
||||
name: r.name,
|
||||
text: r.text,
|
||||
style: StyleShadow { fg: r.fg, ..Default::default() }.into(),
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ impl From<Style> for ratatui::style::Style {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[derive(Default, Deserialize)]
|
||||
pub(super) struct StyleShadow {
|
||||
#[serde(default)]
|
||||
pub(super) fg: Option<Color>,
|
||||
|
@ -130,7 +130,7 @@ pub struct Theme {
|
||||
// File-specific styles
|
||||
#[serde(rename = "filetype", deserialize_with = "Filetype::deserialize", skip_serializing)]
|
||||
pub filetypes: Vec<Filetype>,
|
||||
#[serde(deserialize_with = "Icon::deserialize", skip_serializing)]
|
||||
#[serde(rename = "icon", deserialize_with = "Icon::deserialize", skip_serializing)]
|
||||
pub icons: Vec<Icon>,
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use mlua::{AnyUserData, IntoLua, Lua, MetaMethod, UserDataFields, UserDataMethods, Value};
|
||||
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 super::{CtxRef, FolderRef};
|
||||
@ -69,14 +69,13 @@ impl<'a, 'b> Folder<'a, 'b> {
|
||||
p.next_back();
|
||||
Some(lua.create_string(p.as_path().as_os_str().as_encoded_bytes())).transpose()
|
||||
});
|
||||
reg.add_method("icon", |_, me, ()| {
|
||||
Ok(
|
||||
reg.add_method("icon", |lua, me, ()| {
|
||||
THEME
|
||||
.icons
|
||||
.iter()
|
||||
.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| {
|
||||
let cx = lua.named_registry_value::<CtxRef>("cx")?;
|
||||
|
@ -12,6 +12,7 @@ pub(crate) struct Lives;
|
||||
impl Lives {
|
||||
pub(crate) fn register() -> mlua::Result<()> {
|
||||
yazi_plugin::bindings::Cha::register(&LUA)?;
|
||||
yazi_plugin::bindings::Icon::register(&LUA)?;
|
||||
yazi_plugin::bindings::Url::register(&LUA)?;
|
||||
|
||||
super::Active::register(&LUA)?;
|
||||
|
@ -14,7 +14,10 @@ function Folder:by_kind(kind)
|
||||
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)
|
||||
-- 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 cha;
|
||||
mod file;
|
||||
mod icon;
|
||||
mod range;
|
||||
mod url;
|
||||
mod window;
|
||||
@ -10,6 +11,7 @@ mod window;
|
||||
pub use bindings::*;
|
||||
pub use cha::*;
|
||||
pub use file::*;
|
||||
pub use icon::*;
|
||||
pub use range::*;
|
||||
pub use url::*;
|
||||
pub use window::*;
|
||||
|
Loading…
Reference in New Issue
Block a user