mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
fix: proper invalid UTF-8 path support (#2884)
This commit is contained in:
parent
56a4e87d7e
commit
a0ab614108
50 changed files with 577 additions and 367 deletions
9
.github/workflows/draft.yml
vendored
9
.github/workflows/draft.yml
vendored
|
|
@ -109,16 +109,15 @@ jobs:
|
|||
matrix:
|
||||
include:
|
||||
- target: x86_64-unknown-linux-musl
|
||||
image: rust-musl-cross:x86_64-musl
|
||||
- target: aarch64-unknown-linux-musl
|
||||
image: rust-musl-cross:aarch64-musl
|
||||
container:
|
||||
image: docker://ghcr.io/rust-cross/${{ matrix.image }}
|
||||
image: docker://ghcr.io/cross-rs/${{ matrix.target }}:edge
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Add musl target
|
||||
run: rustup target add ${{ matrix.target }}
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
- name: Setup sccache
|
||||
uses: mozilla-actions/sccache-action@v0.0.9
|
||||
|
|
|
|||
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -3445,7 +3445,9 @@ version = "25.6.11"
|
|||
dependencies = [
|
||||
"mlua",
|
||||
"paste",
|
||||
"ratatui",
|
||||
"serde_json",
|
||||
"yazi-config",
|
||||
"yazi-fs",
|
||||
"yazi-macro",
|
||||
"yazi-shared",
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@ cp yazi-boot/completions/* "$ARTIFACT_NAME/completions"
|
|||
cp README.md LICENSE "$ARTIFACT_NAME"
|
||||
|
||||
# Zip the artifact
|
||||
if ! command -v zip &> /dev/null
|
||||
then
|
||||
sudo apt-get update && sudo apt-get install -yq zip
|
||||
if ! command -v zip &> /dev/null; then
|
||||
apt-get update && apt-get install -yq zip
|
||||
fi
|
||||
zip -r "$ARTIFACT_NAME.zip" "$ARTIFACT_NAME"
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ homepage = "https://yazi-rs.github.io"
|
|||
repository = "https://github.com/sxyazi/yazi"
|
||||
|
||||
[dependencies]
|
||||
yazi-config = { path = "../yazi-config", version = "25.6.11" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.6.11" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.6.11" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.6.11" }
|
||||
|
|
@ -16,4 +17,5 @@ yazi-shared = { path = "../yazi-shared", version = "25.6.11" }
|
|||
# External dependencies
|
||||
mlua = { workspace = true }
|
||||
paste = { workspace = true }
|
||||
ratatui = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
|
|
|||
20
yazi-binding/src/color.rs
Normal file
20
yazi-binding/src/color.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use mlua::{ExternalError, ExternalResult, UserData, Value};
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct Color(pub ratatui::style::Color);
|
||||
|
||||
impl TryFrom<Value> for Color {
|
||||
type Error = mlua::Error;
|
||||
|
||||
fn try_from(value: Value) -> Result<Self, Self::Error> {
|
||||
Ok(Self(match value {
|
||||
Value::String(s) => ratatui::style::Color::from_str(&s.to_str()?).into_lua_err()?,
|
||||
Value::UserData(ud) => ud.borrow::<Self>()?.0,
|
||||
_ => Err("expected a Color".into_lua_err())?,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Color {}
|
||||
|
|
@ -1,25 +1,24 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{UserData, UserDataFields, Value};
|
||||
use yazi_binding::cached_field;
|
||||
|
||||
use crate::elements::Style;
|
||||
use crate::{Style, cached_field};
|
||||
|
||||
pub struct Icon {
|
||||
inner: &'static yazi_shared::theme::Icon,
|
||||
inner: &'static yazi_config::Icon,
|
||||
|
||||
v_text: Option<Value>,
|
||||
v_style: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for Icon {
|
||||
type Target = yazi_shared::theme::Icon;
|
||||
type Target = yazi_config::Icon;
|
||||
|
||||
fn deref(&self) -> &Self::Target { self.inner }
|
||||
}
|
||||
|
||||
impl From<&'static yazi_shared::theme::Icon> for Icon {
|
||||
fn from(icon: &'static yazi_shared::theme::Icon) -> Self {
|
||||
impl From<&'static yazi_config::Icon> for Icon {
|
||||
fn from(icon: &'static yazi_config::Icon) -> Self {
|
||||
Self { inner: icon, v_text: None, v_style: None }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
mod macros;
|
||||
|
||||
yazi_macro::mod_flat!(error id stage url urn);
|
||||
yazi_macro::mod_flat!(color error icon id stage style url urn);
|
||||
|
|
|
|||
|
|
@ -17,3 +17,71 @@ macro_rules! cached_field {
|
|||
});
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_style_shorthands {
|
||||
($methods:ident, $($field:tt).+) => {
|
||||
$methods.add_function_mut("fg", |lua, (ud, value): (mlua::AnyUserData, mlua::Value)| {
|
||||
match value {
|
||||
mlua::Value::Nil => {
|
||||
ud.borrow::<Self>()?.$($field).+.fg.map($crate::Color).into_lua(lua)
|
||||
},
|
||||
_ => {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.fg = Some($crate::Color::try_from(value)?.0);
|
||||
ud.into_lua(lua)
|
||||
}
|
||||
}
|
||||
});
|
||||
$methods.add_function_mut("bg", |lua, (ud, value): (mlua::AnyUserData, mlua::Value)| {
|
||||
match value {
|
||||
mlua::Value::Nil => {
|
||||
ud.borrow::<Self>()?.$($field).+.bg.map($crate::Color).into_lua(lua)
|
||||
}
|
||||
_ => {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.bg = Some($crate::Color::try_from(value)?.0);
|
||||
ud.into_lua(lua)
|
||||
}
|
||||
}
|
||||
});
|
||||
$methods.add_function_mut("bold", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::BOLD;
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("dim", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::DIM;
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("italic", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::ITALIC;
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("underline", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::UNDERLINED;
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("blink", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::SLOW_BLINK;
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("blink_rapid", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::RAPID_BLINK;
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("reverse", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::REVERSED;
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("hidden", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::HIDDEN;
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("crossed", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::CROSSED_OUT;
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("reset", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier = ratatui::style::Modifier::empty();
|
||||
Ok(ud)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
|||
45
yazi-binding/src/style.rs
Normal file
45
yazi-binding/src/style.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
use mlua::{AnyUserData, ExternalError, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value};
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct Style(pub ratatui::style::Style);
|
||||
|
||||
impl Style {
|
||||
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||
let new = lua.create_function(|_, (_, value): (Table, Value)| Self::try_from(value))?;
|
||||
|
||||
let style = lua.create_table()?;
|
||||
style.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
||||
|
||||
style.into_lua(lua)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Value> for Style {
|
||||
type Error = mlua::Error;
|
||||
|
||||
fn try_from(value: Value) -> Result<Self, Self::Error> {
|
||||
Ok(Self(match value {
|
||||
Value::Nil => Default::default(),
|
||||
Value::UserData(ud) => ud.borrow::<Self>()?.0,
|
||||
_ => Err("expected a Style or nil".into_lua_err())?,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<yazi_config::Style> for Style {
|
||||
fn from(value: yazi_config::Style) -> Self { Self(value.into()) }
|
||||
}
|
||||
|
||||
impl UserData for Style {
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
crate::impl_style_shorthands!(methods, 0);
|
||||
|
||||
methods.add_function_mut("patch", |_, (ud, value): (AnyUserData, Value)| {
|
||||
{
|
||||
let mut me = ud.borrow_mut::<Self>()?;
|
||||
me.0 = me.0.patch(Self::try_from(value)?.0);
|
||||
}
|
||||
Ok(ud)
|
||||
})
|
||||
}
|
||||
}
|
||||
21
yazi-config/src/color.rs
Normal file
21
yazi-config/src/color.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct Color(ratatui::style::Color);
|
||||
|
||||
impl<'de> Deserialize<'de> for Color {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
ratatui::style::Color::from_str(&String::deserialize(deserializer)?)
|
||||
.map_err(serde::de::Error::custom)
|
||||
.map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Color> for ratatui::style::Color {
|
||||
fn from(value: Color) -> Self { value.0 }
|
||||
}
|
||||
7
yazi-config/src/icon.rs
Normal file
7
yazi-config/src/icon.rs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
use crate::Style;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Icon {
|
||||
pub text: String,
|
||||
pub style: Style,
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
yazi_macro::mod_pub!(keymap mgr open opener plugin popup preview tasks theme which);
|
||||
|
||||
yazi_macro::mod_flat!(layout pattern platform preset priority yazi);
|
||||
yazi_macro::mod_flat!(color icon layout pattern platform preset priority style yazi);
|
||||
|
||||
use std::io::{Read, Write};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use anyhow::{Result, bail};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::Deserialize;
|
||||
use yazi_codegen::DeserializeOver2;
|
||||
use yazi_fs::{CWD, SortBy};
|
||||
|
||||
use super::{MgrRatio, MouseEvents};
|
||||
|
||||
#[derive(Debug, Deserialize, DeserializeOver2, Serialize)]
|
||||
#[derive(Debug, Deserialize, DeserializeOver2)]
|
||||
pub struct Mgr {
|
||||
pub ratio: MgrRatio,
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use ratatui::style::Modifier;
|
||||
use serde::{Deserialize, Serialize, Serializer, ser::SerializeMap};
|
||||
use serde::Deserialize;
|
||||
|
||||
use super::Color;
|
||||
use crate::Color;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize)]
|
||||
pub struct Style {
|
||||
|
|
@ -29,19 +29,6 @@ pub struct Style {
|
|||
pub crossed: bool,
|
||||
}
|
||||
|
||||
impl Serialize for Style {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut map = serializer.serialize_map(Some(3))?;
|
||||
map.serialize_entry("fg", &self.fg)?;
|
||||
map.serialize_entry("bg", &self.bg)?;
|
||||
map.serialize_entry("modifier", &Modifier::from(*self).bits())?;
|
||||
map.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Style> for ratatui::style::Style {
|
||||
fn from(value: Style) -> Self {
|
||||
ratatui::style::Style {
|
||||
|
|
@ -3,10 +3,9 @@ use std::ops::Deref;
|
|||
use serde::Deserialize;
|
||||
use yazi_codegen::DeserializeOver2;
|
||||
use yazi_fs::File;
|
||||
use yazi_shared::theme::Style;
|
||||
|
||||
use super::Is;
|
||||
use crate::Pattern;
|
||||
use crate::{Pattern, Style};
|
||||
|
||||
#[derive(Deserialize, DeserializeOver2)]
|
||||
pub struct Filetype {
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ use anyhow::Result;
|
|||
use serde::{Deserialize, Deserializer};
|
||||
use yazi_codegen::DeserializeOver2;
|
||||
use yazi_fs::File;
|
||||
use yazi_shared::{Condition, theme::{Color, Icon as I, Style}};
|
||||
use yazi_shared::Condition;
|
||||
|
||||
use crate::Pattern;
|
||||
use crate::{Color, Icon as I, Pattern, Style};
|
||||
|
||||
#[derive(Default, Deserialize, DeserializeOver2)]
|
||||
pub struct Icon {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::{Result, bail};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::Deserialize;
|
||||
use yazi_codegen::{DeserializeOver1, DeserializeOver2};
|
||||
use yazi_fs::expand_path;
|
||||
use yazi_shared::theme::Style;
|
||||
|
||||
use super::{Filetype, Flavor, Icon};
|
||||
use crate::Style;
|
||||
|
||||
#[derive(Deserialize, DeserializeOver1, Serialize)]
|
||||
#[derive(Deserialize, DeserializeOver1)]
|
||||
pub struct Theme {
|
||||
pub flavor: Flavor,
|
||||
pub mgr: Mgr,
|
||||
|
|
@ -32,31 +32,31 @@ pub struct Theme {
|
|||
pub icon: Icon,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, DeserializeOver2, Serialize)]
|
||||
#[derive(Deserialize, DeserializeOver2)]
|
||||
pub struct Mgr {
|
||||
cwd: Style,
|
||||
pub cwd: Style,
|
||||
|
||||
// Hovered
|
||||
hovered: Style,
|
||||
preview_hovered: Style,
|
||||
pub hovered: Style,
|
||||
pub preview_hovered: Style,
|
||||
|
||||
// Find
|
||||
find_keyword: Style,
|
||||
find_position: Style,
|
||||
pub find_keyword: Style,
|
||||
pub find_position: Style,
|
||||
|
||||
// Symlink
|
||||
symlink_target: Style,
|
||||
pub symlink_target: Style,
|
||||
|
||||
// Marker
|
||||
marker_copied: Style,
|
||||
marker_cut: Style,
|
||||
marker_marked: Style,
|
||||
marker_selected: Style,
|
||||
pub marker_copied: Style,
|
||||
pub marker_cut: Style,
|
||||
pub marker_marked: Style,
|
||||
pub marker_selected: Style,
|
||||
|
||||
// Count
|
||||
count_copied: Style,
|
||||
count_cut: Style,
|
||||
count_selected: Style,
|
||||
pub count_copied: Style,
|
||||
pub count_cut: Style,
|
||||
pub count_selected: Style,
|
||||
|
||||
// Border
|
||||
pub border_symbol: String,
|
||||
|
|
@ -66,7 +66,7 @@ pub struct Mgr {
|
|||
pub syntect_theme: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, DeserializeOver2, Serialize)]
|
||||
#[derive(Deserialize, DeserializeOver2)]
|
||||
pub struct Tabs {
|
||||
pub active: Style,
|
||||
pub inactive: Style,
|
||||
|
|
@ -75,13 +75,13 @@ pub struct Tabs {
|
|||
pub sep_outer: TabsSep,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, DeserializeOver2, Serialize)]
|
||||
#[derive(Deserialize, DeserializeOver2)]
|
||||
pub struct TabsSep {
|
||||
pub open: String,
|
||||
pub close: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, DeserializeOver2, Serialize)]
|
||||
#[derive(Deserialize, DeserializeOver2)]
|
||||
pub struct Mode {
|
||||
pub normal_main: Style,
|
||||
pub normal_alt: Style,
|
||||
|
|
@ -93,7 +93,7 @@ pub struct Mode {
|
|||
pub unset_alt: Style,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, DeserializeOver2, Serialize)]
|
||||
#[derive(Deserialize, DeserializeOver2)]
|
||||
pub struct Status {
|
||||
pub overall: Style,
|
||||
pub sep_left: StatusSep,
|
||||
|
|
@ -112,13 +112,13 @@ pub struct Status {
|
|||
pub progress_error: Style,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, DeserializeOver2, Serialize)]
|
||||
#[derive(Deserialize, DeserializeOver2)]
|
||||
pub struct StatusSep {
|
||||
pub open: String,
|
||||
pub close: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, DeserializeOver2, Serialize)]
|
||||
#[derive(Deserialize, DeserializeOver2)]
|
||||
pub struct Which {
|
||||
pub cols: u8,
|
||||
pub mask: Style,
|
||||
|
|
@ -130,7 +130,7 @@ pub struct Which {
|
|||
pub separator_style: Style,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, DeserializeOver2, Serialize)]
|
||||
#[derive(Deserialize, DeserializeOver2)]
|
||||
pub struct Confirm {
|
||||
pub border: Style,
|
||||
pub title: Style,
|
||||
|
|
@ -142,7 +142,7 @@ pub struct Confirm {
|
|||
pub btn_labels: [String; 2],
|
||||
}
|
||||
|
||||
#[derive(Deserialize, DeserializeOver2, Serialize)]
|
||||
#[derive(Deserialize, DeserializeOver2)]
|
||||
pub struct Spot {
|
||||
pub border: Style,
|
||||
pub title: Style,
|
||||
|
|
@ -151,7 +151,7 @@ pub struct Spot {
|
|||
pub tbl_cell: Style,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, DeserializeOver2, Serialize)]
|
||||
#[derive(Deserialize, DeserializeOver2)]
|
||||
pub struct Notify {
|
||||
pub title_info: Style,
|
||||
pub title_warn: Style,
|
||||
|
|
@ -162,14 +162,14 @@ pub struct Notify {
|
|||
pub icon_error: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, DeserializeOver2, Serialize)]
|
||||
#[derive(Deserialize, DeserializeOver2)]
|
||||
pub struct Pick {
|
||||
pub border: Style,
|
||||
pub active: Style,
|
||||
pub inactive: Style,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, DeserializeOver2, Serialize)]
|
||||
#[derive(Deserialize, DeserializeOver2)]
|
||||
pub struct Input {
|
||||
pub border: Style,
|
||||
pub title: Style,
|
||||
|
|
@ -177,7 +177,7 @@ pub struct Input {
|
|||
pub selected: Style,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, DeserializeOver2, Serialize)]
|
||||
#[derive(Deserialize, DeserializeOver2)]
|
||||
pub struct Cmp {
|
||||
pub border: Style,
|
||||
pub active: Style,
|
||||
|
|
@ -188,14 +188,14 @@ pub struct Cmp {
|
|||
pub icon_command: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, DeserializeOver2, Serialize)]
|
||||
#[derive(Deserialize, DeserializeOver2)]
|
||||
pub struct Tasks {
|
||||
pub border: Style,
|
||||
pub title: Style,
|
||||
pub hovered: Style,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, DeserializeOver2, Serialize)]
|
||||
#[derive(Deserialize, DeserializeOver2)]
|
||||
pub struct Help {
|
||||
pub on: Style,
|
||||
pub run: Style,
|
||||
|
|
|
|||
|
|
@ -100,36 +100,36 @@ mod tests {
|
|||
|
||||
use super::*;
|
||||
|
||||
fn compare(s: &str, parent: &str, child: &str) -> bool {
|
||||
fn compare(s: &str, parent: &str, child: &str) {
|
||||
let (p, c) = Cmp::split_path(s).unwrap();
|
||||
let p = p.strip_prefix(yazi_fs::CWD.load().as_ref()).unwrap_or(&p);
|
||||
p == Path::new(parent) && c == child
|
||||
assert_eq!((p, c.as_str()), (Path::new(parent), child));
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn test_split() {
|
||||
yazi_fs::init();
|
||||
assert!(compare("", "", ""));
|
||||
assert!(compare(" ", "", " "));
|
||||
assert!(compare("/", "/", ""));
|
||||
assert!(compare("//", "//", ""));
|
||||
assert!(compare("/foo", "/", "foo"));
|
||||
assert!(compare("/foo/", "/foo/", ""));
|
||||
assert!(compare("/foo/bar", "/foo/", "bar"));
|
||||
compare("", "", "");
|
||||
compare(" ", "", " ");
|
||||
compare("/", "/", "");
|
||||
compare("//", "//", "");
|
||||
compare("/foo", "/", "foo");
|
||||
compare("/foo/", "/foo/", "");
|
||||
compare("/foo/bar", "/foo/", "bar");
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn test_split() {
|
||||
yazi_fs::init();
|
||||
assert!(compare("foo", "", "foo"));
|
||||
assert!(compare("foo\\", "foo\\", ""));
|
||||
assert!(compare("foo\\bar", "foo\\", "bar"));
|
||||
assert!(compare("foo\\bar\\", "foo\\bar\\", ""));
|
||||
assert!(compare("C:\\", "C:\\", ""));
|
||||
assert!(compare("C:\\foo", "C:\\", "foo"));
|
||||
assert!(compare("C:\\foo\\", "C:\\foo\\", ""));
|
||||
assert!(compare("C:\\foo\\bar", "C:\\foo\\", "bar"));
|
||||
compare("foo", "", "foo");
|
||||
compare("foo\\", "foo\\", "");
|
||||
compare("foo\\bar", "foo\\", "bar");
|
||||
compare("foo\\bar\\", "foo\\bar\\", "");
|
||||
compare("C:\\", "C:\\", "");
|
||||
compare("C:\\foo", "C:\\", "foo");
|
||||
compare("C:\\foo\\", "C:\\foo\\", "");
|
||||
compare("C:\\foo\\bar", "C:\\foo\\", "bar");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use yazi_boot::BOOT;
|
||||
use yazi_fs::expand_path;
|
||||
use yazi_macro::render;
|
||||
use yazi_proxy::AppProxy;
|
||||
use yazi_shared::{event::CmdCow, url::Url};
|
||||
|
|
@ -8,20 +9,21 @@ use crate::{mgr::Tabs, tab::{Tab, commands::CdSource}};
|
|||
const MAX_TABS: usize = 9;
|
||||
|
||||
struct Opt {
|
||||
url: Url,
|
||||
current: bool,
|
||||
wd: Option<Url>,
|
||||
}
|
||||
|
||||
impl From<CmdCow> for Opt {
|
||||
fn from(mut c: CmdCow) -> Self {
|
||||
if c.bool("current") {
|
||||
Self { url: Default::default(), current: true }
|
||||
} else {
|
||||
Self {
|
||||
url: c.take_first_url().unwrap_or_else(|| Url::from(&BOOT.cwds[0])),
|
||||
current: false,
|
||||
}
|
||||
return Self { wd: None };
|
||||
}
|
||||
let Some(mut wd) = c.take_first_url() else {
|
||||
return Self { wd: Some(Url::from(&BOOT.cwds[0])) };
|
||||
};
|
||||
if wd.is_regular() && !c.bool("raw") {
|
||||
wd = Url::from(expand_path(wd));
|
||||
}
|
||||
Self { wd: Some(wd) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -34,8 +36,8 @@ impl Tabs {
|
|||
}
|
||||
|
||||
let mut tab = Tab::default();
|
||||
if !opt.current {
|
||||
tab.cd((opt.url, CdSource::Tab));
|
||||
if let Some(wd) = opt.wd {
|
||||
tab.cd((wd, CdSource::Tab));
|
||||
} else if let Some(h) = self.active().hovered() {
|
||||
tab.pref = self.active().pref.clone();
|
||||
tab.apply_files_attrs();
|
||||
|
|
|
|||
|
|
@ -13,31 +13,22 @@ use crate::tab::Tab;
|
|||
|
||||
struct Opt {
|
||||
target: Url,
|
||||
source: CdSource,
|
||||
interactive: bool,
|
||||
source: CdSource,
|
||||
}
|
||||
|
||||
impl From<CmdCow> for Opt {
|
||||
fn from(mut c: CmdCow) -> Self {
|
||||
Self {
|
||||
source: CdSource::Cd,
|
||||
interactive: c.bool("interactive"),
|
||||
..Self::from(c.take_first_url().unwrap_or_default())
|
||||
let mut target = c.take_first_url().unwrap_or_default();
|
||||
if target.is_regular() && !c.bool("raw") {
|
||||
target = Url::from(expand_path(target));
|
||||
}
|
||||
Self { target, interactive: c.bool("interactive"), source: CdSource::Cd }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Url> for Opt {
|
||||
fn from(target: Url) -> Self { Self::from((target, CdSource::Cd)) }
|
||||
}
|
||||
|
||||
impl From<(Url, CdSource)> for Opt {
|
||||
fn from((mut target, source): (Url, CdSource)) -> Self {
|
||||
if target.is_regular() {
|
||||
target = Url::from(expand_path(&target));
|
||||
}
|
||||
Self { target, source, interactive: false }
|
||||
}
|
||||
fn from((target, source): (Url, CdSource)) -> Self { Self { target, interactive: false, source } }
|
||||
}
|
||||
|
||||
impl Tab {
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ struct Opt {
|
|||
impl From<CmdCow> for Opt {
|
||||
fn from(mut c: CmdCow) -> Self {
|
||||
let mut target = c.take_first_url().unwrap_or_default();
|
||||
if target.is_regular() {
|
||||
target = Url::from(expand_path(&target));
|
||||
if target.is_regular() && !c.bool("raw") {
|
||||
target = Url::from(expand_path(target));
|
||||
}
|
||||
|
||||
Self { target, source: CdSource::Reveal, no_dummy: c.bool("no-dummy") }
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{AnyUserData, IntoLua, UserData, UserDataFields, UserDataMethods, Value};
|
||||
use yazi_binding::Style;
|
||||
use yazi_config::THEME;
|
||||
use yazi_plugin::{bindings::Range, elements::Style};
|
||||
use yazi_plugin::bindings::Range;
|
||||
|
||||
use super::Lives;
|
||||
use crate::{Ctx, lives::PtrCell};
|
||||
|
|
|
|||
|
|
@ -61,8 +61,8 @@ impl Widget for Notify<'_> {
|
|||
Block::bordered()
|
||||
.border_type(BorderType::Rounded)
|
||||
.title(format!("{} {}", m.level.icon(), m.title))
|
||||
.title_style(*m.level.style())
|
||||
.border_style(*m.level.style()),
|
||||
.title_style(m.level.style())
|
||||
.border_style(m.level.style()),
|
||||
)
|
||||
.render(rect, buf);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::{ffi::OsStr, fs::{FileType, Metadata}, hash::{BuildHasher, Hash, Hasher
|
|||
|
||||
use anyhow::Result;
|
||||
use tokio::fs;
|
||||
use yazi_shared::{SyncCell, theme::IconCache, url::{Url, Urn, UrnBuf}};
|
||||
use yazi_shared::url::{Url, Urn, UrnBuf};
|
||||
|
||||
use crate::cha::Cha;
|
||||
|
||||
|
|
@ -11,7 +11,6 @@ pub struct File {
|
|||
pub url: Url,
|
||||
pub cha: Cha,
|
||||
pub link_to: Option<Url>,
|
||||
pub icon: SyncCell<IconCache>,
|
||||
}
|
||||
|
||||
impl Deref for File {
|
||||
|
|
@ -35,13 +34,13 @@ impl File {
|
|||
|
||||
let cha = Cha::from_follow(&url, meta).await;
|
||||
|
||||
Self { url, cha, link_to, icon: Default::default() }
|
||||
Self { url, cha, link_to }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_dummy(url: Url, ft: Option<FileType>) -> Self {
|
||||
let cha = Cha::from_dummy(&url, ft);
|
||||
Self { url, cha, link_to: None, icon: Default::default() }
|
||||
Self { url, cha, link_to: None }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -59,12 +58,7 @@ impl File {
|
|||
|
||||
#[inline]
|
||||
pub fn rebase(&self, parent: &Url) -> Self {
|
||||
Self {
|
||||
url: self.url.rebase(parent),
|
||||
cha: self.cha,
|
||||
link_to: self.link_to.clone(),
|
||||
icon: Default::default(),
|
||||
}
|
||||
Self { url: self.url.rebase(parent), cha: self.cha, link_to: self.link_to.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ impl Partitions {
|
|||
|
||||
// Unmangle '\t', '\n', ' ', '#', and r'\'
|
||||
// https://elixir.bootlin.com/linux/v6.13-rc3/source/fs/proc_namespace.c#L89
|
||||
fn unmangle_octal(s: &str) -> Cow<str> {
|
||||
fn unmangle_octal(s: &str) -> Cow<'_, str> {
|
||||
let mut s = Cow::Borrowed(s);
|
||||
for (a, b) in
|
||||
[(r"\011", "\t"), (r"\012", "\n"), (r"\040", " "), (r"\043", "#"), (r"\134", r"\")]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::{borrow::Cow, env, ffi::OsString, future::Future, io, path::{Component, Path, PathBuf}};
|
||||
use std::{borrow::Cow, env, ffi::{OsStr, OsString}, future::Future, io, path::{Component, Path, PathBuf}};
|
||||
|
||||
use tokio::fs;
|
||||
use yazi_shared::url::{Loc, Url};
|
||||
|
|
@ -37,28 +37,29 @@ pub fn expand_path(p: impl AsRef<Path>) -> PathBuf { _expand_path(p.as_ref()) }
|
|||
fn _expand_path(p: &Path) -> PathBuf {
|
||||
// ${HOME} or $HOME
|
||||
#[cfg(unix)]
|
||||
let re = regex::Regex::new(r"\$(?:\{([^}]+)\}|([a-zA-Z\d_]+))").unwrap();
|
||||
let re = regex::bytes::Regex::new(r"\$(?:\{([^}]+)\}|([a-zA-Z\d_]+))").unwrap();
|
||||
|
||||
// %USERPROFILE%
|
||||
#[cfg(windows)]
|
||||
let re = regex::Regex::new(r"%([^%]+)%").unwrap();
|
||||
let re = regex::bytes::Regex::new(r"%([^%]+)%").unwrap();
|
||||
|
||||
let s = p.to_string_lossy();
|
||||
let s = re.replace_all(&s, |caps: ®ex::Captures| {
|
||||
let b = re.replace_all(p.as_os_str().as_encoded_bytes(), |caps: ®ex::bytes::Captures| {
|
||||
let name = caps.get(2).or_else(|| caps.get(1)).unwrap();
|
||||
env::var(name.as_str()).unwrap_or_else(|_| caps.get(0).unwrap().as_str().to_owned())
|
||||
str::from_utf8(name.as_bytes())
|
||||
.ok()
|
||||
.and_then(env::var_os)
|
||||
.map_or_else(|| caps.get(0).unwrap().as_bytes().to_owned(), |s| s.into_encoded_bytes())
|
||||
});
|
||||
|
||||
// Windows paths that only have a drive letter but no root, e.g. "D:"
|
||||
#[cfg(windows)]
|
||||
if s.len() == 2 {
|
||||
let b = s.as_bytes();
|
||||
if b.len() == 2 {
|
||||
if b[1] == b':' && b[0].is_ascii_alphabetic() {
|
||||
return PathBuf::from(s.to_uppercase() + "\\");
|
||||
return PathBuf::from(format!("{}:\\", b[0].to_ascii_uppercase() as char));
|
||||
}
|
||||
}
|
||||
|
||||
let p = Path::new(s.as_ref());
|
||||
let p = unsafe { Path::new(OsStr::from_encoded_bytes_unchecked(b.as_ref())) };
|
||||
if let Ok(rest) = p.strip_prefix("~") {
|
||||
clean_path(dirs::home_dir().unwrap_or_default().join(rest))
|
||||
} else if p.is_absolute() {
|
||||
|
|
@ -175,7 +176,7 @@ pub fn path_relative_to<'a>(path: &'a Path, root: &Path) -> Cow<'a, Path> {
|
|||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn backslash_to_slash(p: &Path) -> Cow<Path> {
|
||||
pub fn backslash_to_slash(p: &Path) -> Cow<'_, Path> {
|
||||
let bytes = p.as_os_str().as_encoded_bytes();
|
||||
|
||||
// Fast path to skip if there are no backslashes
|
||||
|
|
|
|||
|
|
@ -41,9 +41,9 @@ function Status:mode()
|
|||
|
||||
local style = self:style()
|
||||
return ui.Line {
|
||||
ui.Span(th.status.sep_left.open):fg(style.main.bg):bg("reset"),
|
||||
ui.Span(th.status.sep_left.open):fg(style.main:bg()):bg("reset"),
|
||||
ui.Span(" " .. mode .. " "):style(style.main),
|
||||
ui.Span(th.status.sep_left.close):fg(style.main.bg):bg(style.alt.bg),
|
||||
ui.Span(th.status.sep_left.close):fg(style.main:bg()):bg(style.alt:bg()),
|
||||
}
|
||||
end
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ function Status:size()
|
|||
local style = self:style()
|
||||
return ui.Line {
|
||||
ui.Span(" " .. ya.readable_size(size) .. " "):style(style.alt),
|
||||
ui.Span(th.status.sep_left.close):fg(style.alt.bg),
|
||||
ui.Span(th.status.sep_left.close):fg(style.alt:bg()),
|
||||
}
|
||||
end
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ function Status:percent()
|
|||
|
||||
local style = self:style()
|
||||
return ui.Line {
|
||||
ui.Span(" " .. th.status.sep_right.open):fg(style.alt.bg),
|
||||
ui.Span(" " .. th.status.sep_right.open):fg(style.alt:bg()),
|
||||
ui.Span(percent):style(style.alt),
|
||||
}
|
||||
end
|
||||
|
|
@ -125,9 +125,9 @@ function Status:position()
|
|||
|
||||
local style = self:style()
|
||||
return ui.Line {
|
||||
ui.Span(th.status.sep_right.open):fg(style.main.bg):bg(style.alt.bg),
|
||||
ui.Span(th.status.sep_right.open):fg(style.main:bg()):bg(style.alt:bg()),
|
||||
ui.Span(string.format(" %2d/%-2d ", math.min(cursor + 1, length), length)):style(style.main),
|
||||
ui.Span(th.status.sep_right.close):fg(style.main.bg):bg("reset"),
|
||||
ui.Span(th.status.sep_right.close):fg(style.main:bg()):bg("reset"),
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ function Tabs:redraw()
|
|||
end
|
||||
|
||||
local lines = {
|
||||
ui.Line(th.tabs.sep_outer.open):fg(th.tabs.inactive.bg),
|
||||
ui.Line(th.tabs.sep_outer.open):fg(th.tabs.inactive:bg()),
|
||||
}
|
||||
|
||||
local pos = lines[1]:width()
|
||||
|
|
@ -36,7 +36,7 @@ function Tabs:redraw()
|
|||
self._offsets[i], pos = pos, pos + lines[#lines]:width()
|
||||
end
|
||||
|
||||
lines[#lines + 1] = ui.Line(th.tabs.sep_outer.close):fg(th.tabs.inactive.bg)
|
||||
lines[#lines + 1] = ui.Line(th.tabs.sep_outer.close):fg(th.tabs.inactive:bg())
|
||||
return ui.Line(lines):area(self._area)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ function M:entry()
|
|||
local urls = M.split_urls(cwd, output)
|
||||
if #urls == 1 then
|
||||
local cha = #selected == 0 and fs.cha(urls[1])
|
||||
ya.emit(cha and cha.is_dir and "cd" or "reveal", { urls[1] })
|
||||
ya.emit(cha and cha.is_dir and "cd" or "reveal", { urls[1], raw = true })
|
||||
elseif #urls > 1 then
|
||||
urls.state = #selected > 0 and "off" or "on"
|
||||
ya.emit("toggle_all", urls)
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ local function entry()
|
|||
|
||||
local target = output.stdout:gsub("\n$", "")
|
||||
if target ~= "" then
|
||||
ya.emit("cd", { target })
|
||||
ya.emit("cd", { target, raw = true })
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
yazi_macro::mod_flat!(calculator cha chan icon image input layer mouse permit range);
|
||||
yazi_macro::mod_flat!(calculator cha chan image input layer mouse permit range);
|
||||
|
|
|
|||
|
|
@ -1,31 +1,282 @@
|
|||
use mlua::{IntoLua, Lua, LuaSerdeExt, Value};
|
||||
use mlua::{IntoLua, Lua, Value};
|
||||
use yazi_binding::{Style, Url};
|
||||
use yazi_config::THEME;
|
||||
|
||||
use super::OPTS;
|
||||
use crate::Composer;
|
||||
|
||||
pub struct Theme;
|
||||
|
||||
impl Theme {
|
||||
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||
Composer::make(lua, |lua, key| match key {
|
||||
b"mgr" => Self::mgr(lua),
|
||||
b"tabs" => Self::tabs(lua),
|
||||
b"mode" => Self::mode(lua),
|
||||
b"status" => Self::status(lua),
|
||||
b"which" => Self::which(lua),
|
||||
b"confirm" => Self::confirm(lua),
|
||||
b"spot" => Self::spot(lua),
|
||||
b"notify" => Self::notify(lua),
|
||||
b"pick" => Self::pick(lua),
|
||||
b"input" => Self::input(lua),
|
||||
b"cmp" => Self::cmp(lua),
|
||||
b"tasks" => Self::tasks(lua),
|
||||
b"help" => Self::help(lua),
|
||||
_ => Ok(Value::Nil),
|
||||
})
|
||||
}
|
||||
|
||||
fn mgr(lua: &Lua) -> mlua::Result<Value> {
|
||||
Composer::make(lua, |lua, key| {
|
||||
let m = &THEME.mgr;
|
||||
match key {
|
||||
b"mgr" => lua.to_value_with(&THEME.mgr, OPTS)?,
|
||||
b"tabs" => lua.to_value_with(&THEME.tabs, OPTS)?,
|
||||
b"mode" => lua.to_value_with(&THEME.mode, OPTS)?,
|
||||
b"status" => lua.to_value_with(&THEME.status, OPTS)?,
|
||||
b"which" => lua.to_value_with(&THEME.which, OPTS)?,
|
||||
b"confirm" => lua.to_value_with(&THEME.confirm, OPTS)?,
|
||||
b"spot" => lua.to_value_with(&THEME.spot, OPTS)?,
|
||||
b"notify" => lua.to_value_with(&THEME.notify, OPTS)?,
|
||||
b"pick" => lua.to_value_with(&THEME.pick, OPTS)?,
|
||||
b"input" => lua.to_value_with(&THEME.input, OPTS)?,
|
||||
b"cmp" => lua.to_value_with(&THEME.cmp, OPTS)?,
|
||||
b"tasks" => lua.to_value_with(&THEME.tasks, OPTS)?,
|
||||
b"help" => lua.to_value_with(&THEME.help, OPTS)?,
|
||||
_ => return Ok(Value::Nil),
|
||||
b"cwd" => Style::from(m.cwd).into_lua(lua),
|
||||
|
||||
b"hovered" => Style::from(m.hovered).into_lua(lua),
|
||||
b"preview_hovered" => Style::from(m.preview_hovered).into_lua(lua),
|
||||
|
||||
b"find_keyword" => Style::from(m.find_keyword).into_lua(lua),
|
||||
b"find_position" => Style::from(m.find_position).into_lua(lua),
|
||||
|
||||
b"symlink_target" => Style::from(m.symlink_target).into_lua(lua),
|
||||
|
||||
b"marker_copied" => Style::from(m.marker_copied).into_lua(lua),
|
||||
b"marker_cut" => Style::from(m.marker_cut).into_lua(lua),
|
||||
b"marker_marked" => Style::from(m.marker_marked).into_lua(lua),
|
||||
b"marker_selected" => Style::from(m.marker_selected).into_lua(lua),
|
||||
|
||||
b"count_copied" => Style::from(m.count_copied).into_lua(lua),
|
||||
b"count_cut" => Style::from(m.count_cut).into_lua(lua),
|
||||
b"count_selected" => Style::from(m.count_selected).into_lua(lua),
|
||||
|
||||
b"border_symbol" => lua.create_string(&m.border_symbol)?.into_lua(lua),
|
||||
b"border_style" => Style::from(m.border_style).into_lua(lua),
|
||||
|
||||
b"syntect_theme" => Url::new(&m.syntect_theme).into_lua(lua),
|
||||
_ => Ok(Value::Nil),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn tabs(lua: &Lua) -> mlua::Result<Value> {
|
||||
Composer::make(lua, |lua, key| {
|
||||
let t = &THEME.tabs;
|
||||
match key {
|
||||
b"active" => Style::from(t.active).into_lua(lua),
|
||||
b"inactive" => Style::from(t.inactive).into_lua(lua),
|
||||
|
||||
b"sep_inner" => lua
|
||||
.create_table_from([
|
||||
("open", lua.create_string(&t.sep_inner.open)?),
|
||||
("close", lua.create_string(&t.sep_inner.close)?),
|
||||
])?
|
||||
.into_lua(lua),
|
||||
b"sep_outer" => lua
|
||||
.create_table_from([
|
||||
("open", lua.create_string(&t.sep_outer.open)?),
|
||||
("close", lua.create_string(&t.sep_outer.close)?),
|
||||
])?
|
||||
.into_lua(lua),
|
||||
|
||||
_ => Ok(Value::Nil),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn mode(lua: &Lua) -> mlua::Result<Value> {
|
||||
Composer::make(lua, |lua, key| {
|
||||
let t = &THEME.mode;
|
||||
match key {
|
||||
b"normal_main" => Style::from(t.normal_main).into_lua(lua),
|
||||
b"normal_alt" => Style::from(t.normal_alt).into_lua(lua),
|
||||
|
||||
b"select_main" => Style::from(t.select_main).into_lua(lua),
|
||||
b"select_alt" => Style::from(t.select_alt).into_lua(lua),
|
||||
|
||||
b"unset_main" => Style::from(t.unset_main).into_lua(lua),
|
||||
b"unset_alt" => Style::from(t.unset_alt).into_lua(lua),
|
||||
|
||||
_ => Ok(Value::Nil),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn status(lua: &Lua) -> mlua::Result<Value> {
|
||||
Composer::make(lua, |lua, key| {
|
||||
let t = &THEME.status;
|
||||
match key {
|
||||
b"overall" => Style::from(t.overall).into_lua(lua),
|
||||
b"sep_left" => lua
|
||||
.create_table_from([
|
||||
("open", lua.create_string(&t.sep_left.open)?),
|
||||
("close", lua.create_string(&t.sep_left.close)?),
|
||||
])?
|
||||
.into_lua(lua),
|
||||
b"sep_right" => lua
|
||||
.create_table_from([
|
||||
("open", lua.create_string(&t.sep_right.open)?),
|
||||
("close", lua.create_string(&t.sep_right.close)?),
|
||||
])?
|
||||
.into_lua(lua),
|
||||
|
||||
b"perm_sep" => Style::from(t.perm_sep).into_lua(lua),
|
||||
b"perm_type" => Style::from(t.perm_type).into_lua(lua),
|
||||
b"perm_read" => Style::from(t.perm_read).into_lua(lua),
|
||||
b"perm_write" => Style::from(t.perm_write).into_lua(lua),
|
||||
b"perm_exec" => Style::from(t.perm_exec).into_lua(lua),
|
||||
|
||||
b"progress_label" => Style::from(t.progress_label).into_lua(lua),
|
||||
b"progress_normal" => Style::from(t.progress_normal).into_lua(lua),
|
||||
b"progress_error" => Style::from(t.progress_error).into_lua(lua),
|
||||
|
||||
_ => Ok(Value::Nil),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn which(lua: &Lua) -> mlua::Result<Value> {
|
||||
Composer::make(lua, |lua, key| {
|
||||
let t = &THEME.which;
|
||||
match key {
|
||||
b"cols" => t.cols.into_lua(lua),
|
||||
b"mask" => Style::from(t.mask).into_lua(lua),
|
||||
b"cand" => Style::from(t.cand).into_lua(lua),
|
||||
b"rest" => Style::from(t.rest).into_lua(lua),
|
||||
b"desc" => Style::from(t.desc).into_lua(lua),
|
||||
|
||||
b"separator" => lua.create_string(&t.separator)?.into_lua(lua),
|
||||
b"separator_style" => Style::from(t.separator_style).into_lua(lua),
|
||||
|
||||
_ => Ok(Value::Nil),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn confirm(lua: &Lua) -> mlua::Result<Value> {
|
||||
Composer::make(lua, |lua, key| {
|
||||
let t = &THEME.confirm;
|
||||
match key {
|
||||
b"border" => Style::from(t.border).into_lua(lua),
|
||||
b"title" => Style::from(t.title).into_lua(lua),
|
||||
b"content" => Style::from(t.content).into_lua(lua),
|
||||
b"list" => Style::from(t.list).into_lua(lua),
|
||||
|
||||
b"btn_yes" => Style::from(t.btn_yes).into_lua(lua),
|
||||
b"btn_no" => Style::from(t.btn_no).into_lua(lua),
|
||||
b"btn_labels" => lua
|
||||
.create_sequence_from([
|
||||
lua.create_string(&t.btn_labels[0])?,
|
||||
lua.create_string(&t.btn_labels[1])?,
|
||||
])?
|
||||
.into_lua(lua),
|
||||
|
||||
_ => Ok(Value::Nil),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn spot(lua: &Lua) -> mlua::Result<Value> {
|
||||
Composer::make(lua, |lua, key| {
|
||||
let t = &THEME.spot;
|
||||
match key {
|
||||
b"border" => Style::from(t.border).into_lua(lua),
|
||||
b"title" => Style::from(t.title).into_lua(lua),
|
||||
|
||||
b"tbl_col" => Style::from(t.tbl_col).into_lua(lua),
|
||||
b"tbl_cell" => Style::from(t.tbl_cell).into_lua(lua),
|
||||
|
||||
_ => Ok(Value::Nil),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn notify(lua: &Lua) -> mlua::Result<Value> {
|
||||
Composer::make(lua, |lua, key| {
|
||||
let t = &THEME.notify;
|
||||
match key {
|
||||
b"title_info" => Style::from(t.title_info).into_lua(lua),
|
||||
b"title_warn" => Style::from(t.title_warn).into_lua(lua),
|
||||
b"title_error" => Style::from(t.title_error).into_lua(lua),
|
||||
|
||||
b"icon_info" => lua.create_string(&t.icon_info)?.into_lua(lua),
|
||||
b"icon_warn" => lua.create_string(&t.icon_warn)?.into_lua(lua),
|
||||
b"icon_error" => lua.create_string(&t.icon_error)?.into_lua(lua),
|
||||
|
||||
_ => Ok(Value::Nil),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn pick(lua: &Lua) -> mlua::Result<Value> {
|
||||
Composer::make(lua, |lua, key| {
|
||||
let t = &THEME.pick;
|
||||
match key {
|
||||
b"border" => Style::from(t.border).into_lua(lua),
|
||||
b"active" => Style::from(t.active).into_lua(lua),
|
||||
b"inactive" => Style::from(t.inactive).into_lua(lua),
|
||||
|
||||
_ => Ok(Value::Nil),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn input(lua: &Lua) -> mlua::Result<Value> {
|
||||
Composer::make(lua, |lua, key| {
|
||||
let t = &THEME.input;
|
||||
match key {
|
||||
b"border" => Style::from(t.border).into_lua(lua),
|
||||
b"title" => Style::from(t.title).into_lua(lua),
|
||||
b"value" => Style::from(t.value).into_lua(lua),
|
||||
b"selected" => Style::from(t.selected).into_lua(lua),
|
||||
|
||||
_ => Ok(Value::Nil),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn cmp(lua: &Lua) -> mlua::Result<Value> {
|
||||
Composer::make(lua, |lua, key| {
|
||||
let t = &THEME.cmp;
|
||||
match key {
|
||||
b"border" => Style::from(t.border).into_lua(lua),
|
||||
b"active" => Style::from(t.active).into_lua(lua),
|
||||
b"inactive" => Style::from(t.inactive).into_lua(lua),
|
||||
|
||||
b"icon_file" => lua.create_string(&t.icon_file)?.into_lua(lua),
|
||||
b"icon_folder" => lua.create_string(&t.icon_folder)?.into_lua(lua),
|
||||
b"icon_command" => lua.create_string(&t.icon_command)?.into_lua(lua),
|
||||
|
||||
_ => Ok(Value::Nil),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn tasks(lua: &Lua) -> mlua::Result<Value> {
|
||||
Composer::make(lua, |lua, key| {
|
||||
let t = &THEME.tasks;
|
||||
match key {
|
||||
b"border" => Style::from(t.border).into_lua(lua),
|
||||
b"title" => Style::from(t.title).into_lua(lua),
|
||||
b"hovered" => Style::from(t.hovered).into_lua(lua),
|
||||
|
||||
_ => Ok(Value::Nil),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn help(lua: &Lua) -> mlua::Result<Value> {
|
||||
Composer::make(lua, |lua, key| {
|
||||
let t = &THEME.help;
|
||||
match key {
|
||||
b"on" => Style::from(t.on).into_lua(lua),
|
||||
b"run" => Style::from(t.run).into_lua(lua),
|
||||
b"desc" => Style::from(t.desc).into_lua(lua),
|
||||
|
||||
b"hovered" => Style::from(t.hovered).into_lua(lua),
|
||||
b"footer" => Style::from(t.footer).into_lua(lua),
|
||||
|
||||
_ => Ok(Value::Nil),
|
||||
}
|
||||
.into_lua(lua)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
|||
b"Rect" => super::Rect::compose(lua)?,
|
||||
b"Row" => super::Row::compose(lua)?,
|
||||
b"Span" => super::Span::compose(lua)?,
|
||||
b"Style" => super::Style::compose(lua)?,
|
||||
b"Style" => yazi_binding::Style::compose(lua)?,
|
||||
b"Table" => super::Table::compose(lua)?,
|
||||
b"Text" => super::Text::compose(lua)?,
|
||||
b"Wrap" => super::Wrap::compose(lua)?,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use mlua::{AnyUserData, ExternalError, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value};
|
||||
use ratatui::widgets::Widget;
|
||||
use yazi_binding::Style;
|
||||
|
||||
use super::{Area, Span};
|
||||
use crate::elements::Style;
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Gauge {
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ impl UserData for Line {
|
|||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
crate::impl_area_method!(methods);
|
||||
crate::impl_style_method!(methods, inner.style);
|
||||
crate::impl_style_shorthands!(methods, inner.style);
|
||||
yazi_binding::impl_style_shorthands!(methods, inner.style);
|
||||
|
||||
methods.add_method("width", |_, me, ()| Ok(me.inner.width()));
|
||||
methods.add_function_mut("align", |_, (ud, align): (AnyUserData, Align)| {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
yazi_macro::mod_flat!(align area bar border cell clear constraint edge elements gauge layout line list pad pos rect renderable row span style table text utils wrap);
|
||||
yazi_macro::mod_flat!(align area bar border cell clear constraint edge elements gauge layout line list pad pos rect renderable row span table text utils wrap);
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ impl TryFrom<Value> for Span {
|
|||
impl UserData for Span {
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
crate::impl_style_method!(methods, 0.style);
|
||||
crate::impl_style_shorthands!(methods, 0.style);
|
||||
yazi_binding::impl_style_shorthands!(methods, 0.style);
|
||||
|
||||
methods.add_method("visible", |_, Span(me), ()| {
|
||||
Ok(me.content.chars().any(|c| c.width().unwrap_or(0) > 0))
|
||||
|
|
|
|||
|
|
@ -1,66 +0,0 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use mlua::{AnyUserData, ExternalError, ExternalResult, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value};
|
||||
use yazi_shared::theme::Color;
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct Style(pub(super) ratatui::style::Style);
|
||||
|
||||
impl Style {
|
||||
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||
let new = lua.create_function(|_, (_, value): (Table, Value)| Self::try_from(value))?;
|
||||
|
||||
let style = lua.create_table()?;
|
||||
style.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
|
||||
|
||||
style.into_lua(lua)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Table> for Style {
|
||||
type Error = mlua::Error;
|
||||
|
||||
fn try_from(value: Table) -> Result<Self, Self::Error> {
|
||||
let mut style = ratatui::style::Style::default();
|
||||
if let Ok(fg) = value.raw_get::<mlua::String>("fg") {
|
||||
style.fg = Some(Color::from_str(&fg.to_str()?).into_lua_err()?.into());
|
||||
}
|
||||
if let Ok(bg) = value.raw_get::<mlua::String>("bg") {
|
||||
style.bg = Some(Color::from_str(&bg.to_str()?).into_lua_err()?.into());
|
||||
}
|
||||
style.add_modifier =
|
||||
ratatui::style::Modifier::from_bits_truncate(value.raw_get("modifier").unwrap_or_default());
|
||||
Ok(Self(style))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Value> for Style {
|
||||
type Error = mlua::Error;
|
||||
|
||||
fn try_from(value: Value) -> Result<Self, Self::Error> {
|
||||
Ok(Self(match value {
|
||||
Value::Nil => Default::default(),
|
||||
Value::Table(tb) => Self::try_from(tb)?.0,
|
||||
Value::UserData(ud) => ud.borrow::<Self>()?.0,
|
||||
_ => Err("expected a Style or Table or nil".into_lua_err())?,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<yazi_shared::theme::Style> for Style {
|
||||
fn from(value: yazi_shared::theme::Style) -> Self { Self(value.into()) }
|
||||
}
|
||||
|
||||
impl UserData for Style {
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
crate::impl_style_shorthands!(methods, 0);
|
||||
|
||||
methods.add_function_mut("patch", |_, (ud, value): (AnyUserData, Value)| {
|
||||
{
|
||||
let mut me = ud.borrow_mut::<Self>()?;
|
||||
me.0 = me.0.patch(Self::try_from(value)?.0);
|
||||
}
|
||||
Ok(ud)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
use mlua::{AnyUserData, ExternalError, IntoLua, Lua, MetaMethod, UserData, Value};
|
||||
use ratatui::widgets::StatefulWidget;
|
||||
use yazi_binding::Style;
|
||||
|
||||
use super::{Area, Row};
|
||||
use crate::elements::{Constraint, Style};
|
||||
use crate::elements::Constraint;
|
||||
|
||||
const EXPECTED: &str = "expected a table of Rows";
|
||||
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ impl UserData for Text {
|
|||
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
|
||||
crate::impl_area_method!(methods);
|
||||
crate::impl_style_method!(methods, inner.style);
|
||||
crate::impl_style_shorthands!(methods, inner.style);
|
||||
yazi_binding::impl_style_shorthands!(methods, inner.style);
|
||||
|
||||
methods.add_function_mut("align", |_, (ud, align): (AnyUserData, Align)| {
|
||||
ud.borrow_mut::<Self>()?.inner.alignment = Some(align.0);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
macro_rules! impl_style_method {
|
||||
($methods:ident, $($field:tt).+) => {
|
||||
$methods.add_function_mut("style", |_, (ud, value): (mlua::AnyUserData, mlua::Value)| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+ = $crate::elements::Style::try_from(value)?.0;
|
||||
ud.borrow_mut::<Self>()?.$($field).+ = yazi_binding::Style::try_from(value)?.0;
|
||||
Ok(ud)
|
||||
});
|
||||
};
|
||||
|
|
@ -26,60 +26,6 @@ macro_rules! impl_area_method {
|
|||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_style_shorthands {
|
||||
($methods:ident, $($field:tt).+) => {
|
||||
$methods.add_function_mut("fg", |_, (ud, color): (mlua::AnyUserData, String)| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.fg = yazi_shared::theme::Color::try_from(color).ok().map(Into::into);
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("bg", |_, (ud, color): (mlua::AnyUserData, String)| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.bg = yazi_shared::theme::Color::try_from(color).ok().map(Into::into);
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("bold", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::BOLD;
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("dim", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::DIM;
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("italic", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::ITALIC;
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("underline", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::UNDERLINED;
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("blink", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::SLOW_BLINK;
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("blink_rapid", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::RAPID_BLINK;
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("reverse", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::REVERSED;
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("hidden", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::HIDDEN;
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("crossed", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier |= ratatui::style::Modifier::CROSSED_OUT;
|
||||
Ok(ud)
|
||||
});
|
||||
$methods.add_function_mut("reset", |_, ud: mlua::AnyUserData| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+.add_modifier = ratatui::style::Modifier::empty();
|
||||
Ok(ud)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_file_fields {
|
||||
($fields:ident) => {
|
||||
|
|
@ -104,18 +50,9 @@ macro_rules! impl_file_methods {
|
|||
$methods.add_method("hash", |_, me, ()| Ok(me.hash_u64()));
|
||||
|
||||
$methods.add_method("icon", |_, me, ()| {
|
||||
use yazi_shared::theme::IconCache;
|
||||
use $crate::bindings::Icon;
|
||||
|
||||
Ok(match me.icon.get() {
|
||||
IconCache::Missing => {
|
||||
let matched = yazi_config::THEME.icon.matches(me);
|
||||
me.icon.set(matched.map_or(IconCache::Undefined, IconCache::Icon));
|
||||
matched.map(Icon::from)
|
||||
}
|
||||
IconCache::Undefined => None,
|
||||
IconCache::Icon(cached) => Some(Icon::from(cached)),
|
||||
})
|
||||
use yazi_binding::Icon;
|
||||
// TODO: use a cache
|
||||
Ok(yazi_config::THEME.icon.matches(me).map(Icon::from))
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ use std::{str::FromStr, time::Duration};
|
|||
|
||||
use mlua::{ExternalError, ExternalResult};
|
||||
use serde::Deserialize;
|
||||
use yazi_config::THEME;
|
||||
use yazi_shared::{event::CmdCow, theme::Style};
|
||||
use yazi_config::{Style, THEME};
|
||||
use yazi_shared::event::CmdCow;
|
||||
|
||||
pub struct NotifyOpt {
|
||||
pub title: String,
|
||||
|
|
@ -60,11 +60,11 @@ impl NotifyLevel {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn style(self) -> &'static Style {
|
||||
pub fn style(self) -> Style {
|
||||
match self {
|
||||
Self::Info => &THEME.notify.title_info,
|
||||
Self::Warn => &THEME.notify.title_warn,
|
||||
Self::Error => &THEME.notify.title_error,
|
||||
Self::Info => THEME.notify.title_info,
|
||||
Self::Warn => THEME.notify.title_warn,
|
||||
Self::Error => THEME.notify.title_error,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ pub struct TabProxy;
|
|||
|
||||
impl TabProxy {
|
||||
pub fn cd(target: &Url) {
|
||||
emit!(Call(Cmd::args("mgr:cd", [target])));
|
||||
emit!(Call(Cmd::args("mgr:cd", [target]).with("raw", true)));
|
||||
}
|
||||
|
||||
pub fn reveal(target: &Url) {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ authors = [ "sxyazi <sxyazi@gmail.com>" ]
|
|||
description = "Yazi shared library"
|
||||
homepage = "https://yazi-rs.github.io"
|
||||
repository = "https://github.com/sxyazi/yazi"
|
||||
rust-version = "1.86.0"
|
||||
rust-version = "1.87.0"
|
||||
|
||||
[dependencies]
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.6.11" }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#![allow(clippy::option_map_unit_fn)]
|
||||
|
||||
yazi_macro::mod_pub!(errors event shell theme translit url);
|
||||
yazi_macro::mod_pub!(errors event shell translit url);
|
||||
|
||||
yazi_macro::mod_flat!(chars condition debounce either env id layer natsort number os rand ro_cell sync_cell terminal throttle time utf8);
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ pub fn escape_str(s: &str) -> Cow<'_, str> {
|
|||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn escape_os_str(s: &std::ffi::OsStr) -> Cow<std::ffi::OsStr> {
|
||||
pub fn escape_os_str(s: &std::ffi::OsStr) -> Cow<'_, std::ffi::OsStr> {
|
||||
use std::os::windows::ffi::{OsStrExt, OsStringExt};
|
||||
|
||||
let wide = s.encode_wide();
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use anyhow::{Result, anyhow};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize)]
|
||||
#[serde(try_from = "String")]
|
||||
pub struct Color(ratatui::style::Color);
|
||||
|
||||
impl FromStr for Color {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
ratatui::style::Color::from_str(s).map(Self).map_err(|_| anyhow!("invalid color: {s}"))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for Color {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> { Self::from_str(&s) }
|
||||
}
|
||||
|
||||
impl From<Color> for ratatui::style::Color {
|
||||
fn from(value: Color) -> Self { value.0 }
|
||||
}
|
||||
|
||||
impl Serialize for Color {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
self.0.to_string().serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
use super::Style;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Icon {
|
||||
pub text: String,
|
||||
pub style: Style,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub enum IconCache {
|
||||
#[default]
|
||||
Missing,
|
||||
Undefined,
|
||||
Icon(&'static Icon),
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
yazi_macro::mod_flat!(color icon style);
|
||||
|
|
@ -21,7 +21,8 @@ impl Urn {
|
|||
#[cfg(unix)]
|
||||
#[inline]
|
||||
pub fn is_hidden(&self) -> bool {
|
||||
self.name().is_some_and(|s| s.as_encoded_bytes().starts_with(b"."))
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
self.name().is_some_and(|s| s.as_bytes().starts_with(b"."))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue