diff --git a/Cargo.lock b/Cargo.lock index d508b0a9..b0376978 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -543,9 +543,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.64" +version = "1.2.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad887fd958be91b5098c0248def011f4523ab786cd411be668777e55063501f" +checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96" dependencies = [ "find-msvc-tools", "jobserver", @@ -2880,14 +2880,14 @@ checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "ratatui-core" -version = "0.1.1" -source = "git+https://github.com/yazi-rs/ratatui.git?rev=a1c4922a242861d755163ae85d7e41b85ed277d2#a1c4922a242861d755163ae85d7e41b85ed277d2" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbb175c433c8e28a809d1f5773a2ae96e68c0ce40db865cbab1020bf33ae479c" dependencies = [ "bitflags", "compact_str", "critical-section", "hashbrown 0.17.1", - "indoc", "itertools", "kasuari", "lru", @@ -2902,8 +2902,9 @@ dependencies = [ [[package]] name = "ratatui-widgets" -version = "0.3.1" -source = "git+https://github.com/yazi-rs/ratatui.git?rev=a1c4922a242861d755163ae85d7e41b85ed277d2#a1c4922a242861d755163ae85d7e41b85ed277d2" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66e3d19bcc9130ca376277d93b60767ff121ace3be06f5f95f81dd68956407d1" dependencies = [ "bitflags", "hashbrown 0.17.1", @@ -4705,10 +4706,8 @@ dependencies = [ "indexmap 2.14.0", "libc", "mlua", - "parking_lot", "paste", "ratatui-core", - "ratatui-widgets", "scopeguard", "tokio", "tokio-stream", @@ -4867,7 +4866,6 @@ dependencies = [ "regex", "serde", "serde_with", - "tokio", "toml", "tracing", "yazi-binding", @@ -5343,11 +5341,13 @@ dependencies = [ "mlua", "parking_lot", "russh", + "serde", "tokio", + "toml", "tracing", "typed-path", "yazi-binding", - "yazi-config", + "yazi-codegen", "yazi-fs", "yazi-macro", "yazi-sftp", @@ -5396,6 +5396,7 @@ dependencies = [ "tracing", "unicode-width", "yazi-binding", + "yazi-dds", "yazi-macro", "yazi-shared", "yazi-shim", diff --git a/Cargo.toml b/Cargo.toml index 8ecf9733..6985c10a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,8 +62,8 @@ parking_lot = "0.12.5" paste = "1.0.15" percent-encoding = "2.3.2" rand = { version = "0.10.1", default-features = false, features = [ "std", "sys_rng" ] } -ratatui-core = { version = "0.1.1", default-features = false, features = [ "std", "layout-cache", "serde", "underline-color" ] } -ratatui-widgets = { version = "0.3.1", default-features = false, features = [ "std", "unstable-rendered-line-info" ] } +ratatui-core = { version = "0.1.2", default-features = false, features = [ "std", "layout-cache", "serde", "underline-color" ] } +ratatui-widgets = { version = "0.3.2", default-features = false, features = [ "std", "unstable-rendered-line-info" ] } regex = "1.12.4" russh = { version = "0.61.2", default-features = false, features = [ "ring", "rsa" ] } scopeguard = "1.2.0" @@ -93,7 +93,3 @@ module_inception = "allow" option_map_unit_fn = "allow" unit_arg = "allow" use_self = "warn" - -[patch.crates-io] -ratatui-core = { git = "https://github.com/yazi-rs/ratatui.git", package = "ratatui-core", rev = "a1c4922a242861d755163ae85d7e41b85ed277d2" } -ratatui-widgets = { git = "https://github.com/yazi-rs/ratatui.git", package = "ratatui-widgets", rev = "a1c4922a242861d755163ae85d7e41b85ed277d2" } diff --git a/nix/yazi-unwrapped.nix b/nix/yazi-unwrapped.nix index 461685ec..2cae987c 100644 --- a/nix/yazi-unwrapped.nix +++ b/nix/yazi-unwrapped.nix @@ -28,10 +28,6 @@ rustPlatform.buildRustPackage (finalAttrs: { cargoLock = { lockFile = "${src}/Cargo.lock"; - outputHashes = { - "ratatui-core-0.1.1" = "sha256-wkEOgwAhW0ObtPDlJmOOoY5qf9c/P79ktN4b43jtcGw="; - "ratatui-widgets-0.3.1" = "sha256-wkEOgwAhW0ObtPDlJmOOoY5qf9c/P79ktN4b43jtcGw="; - }; }; env = { diff --git a/yazi-actor/Cargo.toml b/yazi-actor/Cargo.toml index f919778a..1015e74a 100644 --- a/yazi-actor/Cargo.toml +++ b/yazi-actor/Cargo.toml @@ -46,10 +46,8 @@ futures = { workspace = true } hashbrown = { workspace = true } indexmap = { workspace = true } mlua = { workspace = true } -parking_lot = { workspace = true } paste = { workspace = true } ratatui-core = { workspace = true } -ratatui-widgets = { workspace = true } scopeguard = { workspace = true } tokio = { workspace = true } tokio-stream = { workspace = true } diff --git a/yazi-actor/src/input/show.rs b/yazi-actor/src/input/show.rs index 29f700ad..3c3272c3 100644 --- a/yazi-actor/src/input/show.rs +++ b/yazi-actor/src/input/show.rs @@ -1,11 +1,11 @@ use std::ops::DerefMut; use anyhow::Result; -use ratatui_core::layout::Margin; use yazi_config::{THEME, YAZI}; use yazi_macro::{act, render, succ}; use yazi_parser::input::ShowForm; use yazi_shared::data::Data; +use yazi_shim::ratatui::Padable; use crate::{Actor, Ctx}; @@ -19,7 +19,7 @@ impl Actor for Show { fn act(cx: &mut Ctx, Self::Form { mut opt }: Self::Form) -> Result { act!(input:close, cx)?; - let area = cx.mgr.area(opt.position); + let area = cx.mgr.area(opt.position).padding(cx.input.padding()); let input = &mut cx.input; input.main.visible = true; input.main.title = opt.title.clone(); @@ -28,7 +28,7 @@ impl Actor for Show { opt.styles = (&THEME.input).into(); opt.blinking = YAZI.input.cursor_blink; *input.main.deref_mut() = yazi_widgets::input::Input::new(opt)?; - input.main.repos(area.inner(Margin::new(1, 1))); + input.main.repos(area); succ!(render!()); } diff --git a/yazi-binding/src/elements/area.rs b/yazi-binding/src/elements/area.rs index 2badbecb..888f06e9 100644 --- a/yazi-binding/src/elements/area.rs +++ b/yazi-binding/src/elements/area.rs @@ -71,7 +71,7 @@ impl From for Area { } impl From for Area { - fn from(value: Position) -> Self { Self::Pos(value.into()) } + fn from(value: Position) -> Self { Self::Pos(value) } } impl TryFrom<&AnyUserData> for Area { diff --git a/yazi-binding/src/position/lua.rs b/yazi-binding/src/position/lua.rs index d2ce2de2..c76ef309 100644 --- a/yazi-binding/src/position/lua.rs +++ b/yazi-binding/src/position/lua.rs @@ -19,7 +19,7 @@ impl TryFrom for Position { type Error = mlua::Error; fn try_from(t: Table) -> Result { - Ok(Self::from(Position { + Ok(Self { origin: Origin::from_str(&t.raw_get::(1)?.to_str()?).into_lua_err()?, offset: Offset { x: t.raw_get("x").unwrap_or_default(), @@ -28,7 +28,7 @@ impl TryFrom
for Position { height: t.raw_get("h").unwrap_or_default(), }, padding: Default::default(), - })) + }) } } diff --git a/yazi-config/Cargo.toml b/yazi-config/Cargo.toml index b8922323..d50defa4 100644 --- a/yazi-config/Cargo.toml +++ b/yazi-config/Cargo.toml @@ -37,6 +37,5 @@ ratatui-widgets = { workspace = true } regex = { workspace = true } serde = { workspace = true } serde_with = { workspace = true } -tokio = { workspace = true } toml = { workspace = true } tracing = { workspace = true } diff --git a/yazi-config/src/keymap/chord.rs b/yazi-config/src/keymap/chord.rs index 1c518136..44c21135 100644 --- a/yazi-config/src/keymap/chord.rs +++ b/yazi-config/src/keymap/chord.rs @@ -7,9 +7,8 @@ use serde_with::{DeserializeAs, DisplayFromStr, OneOrMany}; use yazi_binding::Iter; use yazi_codegen::DeserializeOver2; use yazi_shared::{Layer, event::{Actions, deserialize_actions}, id::Id}; -use yazi_term::event::KeyEvent; -use super::ids::chord_id; +use super::{Key, ids::chord_id}; use crate::{Mixable, Platform, keymap::{ChordArc, Chords}}; static RE: OnceLock = OnceLock::new(); @@ -19,7 +18,7 @@ pub struct Chord { #[serde(skip, default = "chord_id")] pub id: Id, #[serde(deserialize_with = "deserialize_on")] - pub on: Vec, + pub on: Vec, #[serde(deserialize_with = "deserialize_actions::")] pub run: Actions, #[serde(default)] @@ -84,11 +83,11 @@ impl Mixable for Chord { fn filter(&self) -> bool { self.r#for.matches() && !self.noop() } } -fn deserialize_on<'de, D>(deserializer: D) -> Result, D::Error> +fn deserialize_on<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { - let keys: Vec = OneOrMany::::deserialize_as(deserializer)?; + let keys: Vec = OneOrMany::::deserialize_as(deserializer)?; if keys.is_empty() { return Err(de::Error::custom("'on' cannot be empty")); } diff --git a/yazi-term/src/event/conversion.rs b/yazi-config/src/keymap/key.rs similarity index 68% rename from yazi-term/src/event/conversion.rs rename to yazi-config/src/keymap/key.rs index e5164cef..a93f318c 100644 --- a/yazi-term/src/event/conversion.rs +++ b/yazi-config/src/keymap/key.rs @@ -1,10 +1,44 @@ use std::{fmt::{Display, Write}, str::FromStr}; use anyhow::bail; +use mlua::{IntoLua, Lua, LuaSerdeExt, Value}; +use serde::{Deserialize, Serialize}; +use yazi_shim::mlua::SER_OPT; +use yazi_term::event::{KeyCode, KeyEvent, Modifiers}; -use crate::event::{KeyCode, KeyEvent, Modifiers}; +#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize)] +pub struct Key { + #[serde(flatten)] + pub code: KeyCode, + pub shift: bool, + pub ctrl: bool, + pub alt: bool, + #[serde(rename = "super")] + pub super_: bool, +} -impl FromStr for KeyEvent { +impl Key { + pub fn plain(&self) -> Option { + match self.code { + KeyCode::Char(c) if !self.ctrl && !self.alt && !self.super_ => Some(c), + _ => None, + } + } +} + +impl From for Key { + fn from(value: KeyEvent) -> Self { + Self { + code: value.code, + shift: value.modifiers.contains(Modifiers::SHIFT), + ctrl: value.modifiers.contains(Modifiers::CONTROL), + alt: value.modifiers.contains(Modifiers::ALT), + super_: value.modifiers.contains(Modifiers::SUPER), + } + } +} + +impl FromStr for Key { type Err = anyhow::Error; fn from_str(s: &str) -> Result { @@ -12,19 +46,20 @@ impl FromStr for KeyEvent { bail!("empty key") } + let mut key = Self::default(); if !s.starts_with('<') || !s.ends_with('>') { - let c = s.chars().next().unwrap(); - return Ok(Self::new(KeyCode::Char(c), Modifiers::for_char(c))); + key.code = KeyCode::Char(s.chars().next().unwrap()); + key.shift = matches!(key.code, KeyCode::Char(c) if c.is_ascii_uppercase()); + return Ok(key); } - let mut key: Self = KeyCode::Null.into(); let mut it = s[1..s.len() - 1].split_inclusive('-').peekable(); while let Some(next) = it.next() { match next.to_ascii_lowercase().as_str() { - "s-" => key.modifiers |= Modifiers::SHIFT, - "c-" => key.modifiers |= Modifiers::CONTROL, - "a-" => key.modifiers |= Modifiers::ALT, - "d-" => key.modifiers |= Modifiers::SUPER, + "s-" => key.shift = true, + "c-" => key.ctrl = true, + "a-" => key.alt = true, + "d-" => key.super_ = true, "space" => key.code = KeyCode::Char(' '), "backspace" => key.code = KeyCode::Backspace, @@ -64,12 +99,8 @@ impl FromStr for KeyEvent { _ => match next { s if it.peek().is_none() => { let c = s.chars().next().unwrap(); - key.modifiers |= Modifiers::for_char(c); - key.code = KeyCode::Char(if key.modifiers.contains(Modifiers::SHIFT) { - c.to_ascii_uppercase() - } else { - c - }); + key.shift |= c.is_ascii_uppercase(); + key.code = KeyCode::Char(if key.shift { c.to_ascii_uppercase() } else { c }); } s => bail!("unknown key: {s}"), }, @@ -83,23 +114,23 @@ impl FromStr for KeyEvent { } } -impl Display for KeyEvent { +impl Display for Key { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { if let Some(c) = self.plain() { return if c == ' ' { write!(f, "") } else { f.write_char(c) }; } write!(f, "<")?; - if self.modifiers.contains(Modifiers::SUPER) { + if self.super_ { write!(f, "D-")?; } - if self.modifiers.contains(Modifiers::CONTROL) { + if self.ctrl { write!(f, "C-")?; } - if self.modifiers.contains(Modifiers::ALT) { + if self.alt { write!(f, "A-")?; } - if self.modifiers.contains(Modifiers::SHIFT) && !matches!(self.code, KeyCode::Char(_)) { + if self.shift && !matches!(self.code, KeyCode::Char(_)) { write!(f, "S-")?; } @@ -149,3 +180,7 @@ impl Display for KeyEvent { write!(f, "{code}>") } } + +impl IntoLua for Key { + fn into_lua(self, lua: &Lua) -> mlua::Result { lua.to_value_with(&self, SER_OPT) } +} diff --git a/yazi-config/src/keymap/mod.rs b/yazi-config/src/keymap/mod.rs index de927e9d..eda8e777 100644 --- a/yazi-config/src/keymap/mod.rs +++ b/yazi-config/src/keymap/mod.rs @@ -1 +1 @@ -yazi_macro::mod_flat!(chord chord_arc chords ids keymap section); +yazi_macro::mod_flat!(chord chord_arc chords ids key keymap section); diff --git a/yazi-config/src/keymap/section.rs b/yazi-config/src/keymap/section.rs index 272b1019..583cb566 100644 --- a/yazi-config/src/keymap/section.rs +++ b/yazi-config/src/keymap/section.rs @@ -6,9 +6,8 @@ use serde::Deserialize; use yazi_codegen::DeserializeOver2; use yazi_shared::Layer; use yazi_shim::{mlua::UserDataFieldsExt, toml::DeserializeOverHook}; -use yazi_term::event::KeyEvent; -use super::{Chord, Chords, chords::layer_default}; +use super::{Key, Chord, Chords, chords::layer_default}; use crate::{keymap::ChordArc, mix}; #[derive(Default, Deserialize, DeserializeOver2)] @@ -37,7 +36,7 @@ impl KeymapSection { impl DeserializeOverHook for KeymapSection { fn deserialize_over_hook(self) -> Result { #[inline] - fn on(Chord { on, .. }: &Chord) -> [KeyEvent; 2] { + fn on(Chord { on, .. }: &Chord) -> [Key; 2] { [on.first().copied().unwrap_or_default(), on.get(1).copied().unwrap_or_default()] } diff --git a/yazi-config/src/lib.rs b/yazi-config/src/lib.rs index b79bb931..1dab24a7 100644 --- a/yazi-config/src/lib.rs +++ b/yazi-config/src/lib.rs @@ -1,6 +1,6 @@ -yazi_macro::mod_pub!(keymap mgr open opener plugin popup preview tasks theme vfs which); +yazi_macro::mod_pub!(keymap mgr open opener plugin popup preview tasks theme which); -yazi_macro::mod_flat!(icon inject layout mixing pattern platform preset priority selectable selector utils yazi); +yazi_macro::mod_flat!(icon inject layout mixing pattern platform preset priority selectable selector yazi); use std::io::{Read, Write}; diff --git a/yazi-config/src/preset.rs b/yazi-config/src/preset.rs index 2ab67ec6..06cc992f 100644 --- a/yazi-config/src/preset.rs +++ b/yazi-config/src/preset.rs @@ -1,4 +1,4 @@ -use crate::{Yazi, keymap::Keymap, theme::Theme, vfs::Vfs}; +use crate::{Yazi, keymap::Keymap, theme::Theme}; pub(crate) struct Preset; @@ -18,8 +18,4 @@ impl Preset { yazi_macro::theme_preset!("dark") }) } - - pub(super) fn vfs() -> Result { - toml::from_str(&yazi_macro::config_preset!("vfs")) - } } diff --git a/yazi-config/src/preview/preview.rs b/yazi-config/src/preview/preview.rs index 248bca84..f285dcd1 100644 --- a/yazi-config/src/preview/preview.rs +++ b/yazi-config/src/preview/preview.rs @@ -3,12 +3,11 @@ use std::path::PathBuf; use anyhow::{Context, Result}; use serde::{Deserialize, Deserializer, Serialize}; use yazi_codegen::DeserializeOver2; -use yazi_fs::{Xdg, create_owned_dir_blocking}; +use yazi_fs::{Xdg, create_owned_dir_blocking, path::sanitize_path}; use yazi_shared::timestamp_us; use yazi_shim::{SStr, toml::DeserializeOverHook}; use super::PreviewWrap; -use crate::normalize_path; #[derive(Debug, Deserialize, DeserializeOver2, Serialize)] pub struct Preview { @@ -65,7 +64,7 @@ where if path.as_os_str().is_empty() { Ok(Xdg::temp_dir().to_owned()) } else { - normalize_path(path).ok_or_else(|| { + sanitize_path(path).ok_or_else(|| { serde::de::Error::custom("cache_dir must be either empty or an absolute path.") }) } diff --git a/yazi-config/src/theme/theme.rs b/yazi-config/src/theme/theme.rs index 4d127d5a..5f507347 100644 --- a/yazi-config/src/theme/theme.rs +++ b/yazi-config/src/theme/theme.rs @@ -5,11 +5,10 @@ use arc_swap::ArcSwap; use serde::{Deserialize, Deserializer, de}; use yazi_binding::style::StyleFlat; use yazi_codegen::{DeserializeOver, DeserializeOver1, DeserializeOver2, Overlay}; -use yazi_fs::{Xdg, ok_or_not_found}; +use yazi_fs::{Xdg, ok_or_not_found, path::sanitize_path}; use yazi_shim::{arc_swap::IntoPointee, cell::SyncCell}; use super::{Custom, Filetype, Flavor, Icon}; -use crate::normalize_path; #[derive(Deserialize, DeserializeOver, DeserializeOver1, Overlay)] pub struct Theme { @@ -274,7 +273,7 @@ where { let mut path = PathBuf::deserialize(deserializer)?; if !path.as_os_str().is_empty() { - path = normalize_path(path).ok_or_else(|| { + path = sanitize_path(path).ok_or_else(|| { de::Error::custom("syntect_theme must be either empty or an absolute path.") })?; } diff --git a/yazi-core/src/core.rs b/yazi-core/src/core.rs index 3cd29787..ad6ca18c 100644 --- a/yazi-core/src/core.rs +++ b/yazi-core/src/core.rs @@ -1,5 +1,6 @@ -use ratatui_core::layout::{Margin, Position, Rect}; +use ratatui_core::layout::{Position, Rect}; use yazi_shared::Layer; +use yazi_shim::ratatui::Padable; use yazi_tty::sequence::SetCursorStyle; use crate::{cmp::Cmp, confirm::Confirm, help::Help, input::{Input, InputGuard}, mgr::Mgr, notify::Notify, pick::Pick, tab::{Folder, Tab}, tasks::Tasks, which::Which}; @@ -34,7 +35,7 @@ impl Core { pub fn cursor(&self) -> Option<(Position, SetCursorStyle)> { if let Some(guard) = self.input.lock() { let Rect { x, y, .. } = match &guard { - InputGuard::Main(_) => self.mgr.area(self.input.position()?).inner(Margin::new(1, 1)), + InputGuard::Main(_) => self.mgr.area(self.input.position()?).padding(self.input.padding()), InputGuard::Alt(_) => self.mgr.area(self.input.position()?), }; return Some((Position { x: x + guard.cursor(), y }, guard.cursor_shape())); diff --git a/yazi-core/src/input/input.rs b/yazi-core/src/input/input.rs index d7f4e628..4ee51058 100644 --- a/yazi-core/src/input/input.rs +++ b/yazi-core/src/input/input.rs @@ -1,6 +1,7 @@ use std::{ops::{Deref, DerefMut}, sync::Arc}; use parking_lot::Mutex; +use ratatui_widgets::block::Padding; use yazi_binding::{elements::Spatial, position::Position}; use crate::input::{InputGuard, InputMutGuard}; @@ -14,6 +15,8 @@ pub struct Input { impl Input { pub fn focus(&self) -> bool { self.main.visible || self.alt.is_some() } + pub fn padding(&self) -> Padding { Padding::new(1, 1, 1, 1) } + pub fn position(&self) -> Option { if self.main.visible { Some(self.main.position) diff --git a/yazi-core/src/which/option.rs b/yazi-core/src/which/option.rs index 16f80d51..1b763feb 100644 --- a/yazi-core/src/which/option.rs +++ b/yazi-core/src/which/option.rs @@ -1,9 +1,8 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Table, Value}; use tokio::sync::mpsc; -use yazi_config::{KEYMAP, keymap::ChordArc}; +use yazi_config::{KEYMAP, keymap::{ChordArc, Key}}; use yazi_macro::impl_data_any; use yazi_shared::{Layer, event::ActionCow}; -use yazi_term::event::KeyEvent; #[derive(Clone, Debug)] pub struct WhichOpt { @@ -32,8 +31,8 @@ impl TryFrom for WhichOpt { } } -impl From<(Layer, KeyEvent)> for WhichOpt { - fn from((layer, key): (Layer, KeyEvent)) -> Self { +impl From<(Layer, Key)> for WhichOpt { + fn from((layer, key): (Layer, Key)) -> Self { Self { tx: None, cands: KEYMAP diff --git a/yazi-core/src/which/which.rs b/yazi-core/src/which/which.rs index 765f70ad..a046cfcd 100644 --- a/yazi-core/src/which/which.rs +++ b/yazi-core/src/which/which.rs @@ -1,7 +1,6 @@ use tokio::sync::mpsc; -use yazi_config::keymap::ChordArc; +use yazi_config::keymap::{ChordArc, Key}; use yazi_macro::{emit, render_and}; -use yazi_term::event::KeyEvent; #[derive(Default)] pub struct Which { @@ -15,7 +14,7 @@ pub struct Which { } impl Which { - pub fn r#type(&mut self, key: KeyEvent) -> bool { + pub fn r#type(&mut self, key: Key) -> bool { self.cands.retain(|c| c.on.len() > self.times && c.on[self.times] == key); self.times += 1; diff --git a/yazi-fm/src/router.rs b/yazi-fm/src/router.rs index 556409e6..2cc863f7 100644 --- a/yazi-fm/src/router.rs +++ b/yazi-fm/src/router.rs @@ -1,6 +1,6 @@ use anyhow::Result; use yazi_actor::Ctx; -use yazi_config::{KEYMAP, keymap::Chord}; +use yazi_config::{KEYMAP, keymap::{Chord, Key}}; use yazi_macro::act; use yazi_shared::Layer; use yazi_term::event::KeyEvent; @@ -29,6 +29,7 @@ impl<'a> Router<'a> { } let layer = core.layer(); + let key = Key::from(key); Ok(match layer { L::Null | L::App | L::Notify => unreachable!(), L::Mgr | L::Tasks | L::Spot | L::Pick | L::Input | L::Confirm | L::Help => { @@ -39,7 +40,7 @@ impl<'a> Router<'a> { }) } - fn matches(&mut self, layer: Layer, key: KeyEvent) -> bool { + fn matches(&mut self, layer: Layer, key: Key) -> bool { for chord in &*KEYMAP.chords(layer) { let Chord { on, .. } = chord.as_ref(); if on.is_empty() || on[0] != key { diff --git a/yazi-fs/src/path/mod.rs b/yazi-fs/src/path/mod.rs index 66986ab4..a3b70bd8 100644 --- a/yazi-fs/src/path/mod.rs +++ b/yazi-fs/src/path/mod.rs @@ -1 +1 @@ -yazi_macro::mod_flat!(clean expand path percent relative); +yazi_macro::mod_flat!(clean expand normalize path percent relative); diff --git a/yazi-config/src/utils.rs b/yazi-fs/src/path/normalize.rs similarity index 68% rename from yazi-config/src/utils.rs rename to yazi-fs/src/path/normalize.rs index 34f18bd5..13cb152c 100644 --- a/yazi-config/src/utils.rs +++ b/yazi-fs/src/path/normalize.rs @@ -1,9 +1,10 @@ use std::path::PathBuf; -use yazi_fs::path::{clean_url, expand_url}; use yazi_shared::url::UrlBuf; -pub(crate) fn normalize_path(path: PathBuf) -> Option { +use crate::path::{clean_url, expand_url}; + +pub fn sanitize_path(path: PathBuf) -> Option { clean_url(yazi_fs::provider::local::try_absolute(expand_url(UrlBuf::from(path)))?) .into_loc() .into_os() diff --git a/yazi-macro/src/asset.rs b/yazi-macro/src/asset.rs index e3d137e6..eb75babb 100644 --- a/yazi-macro/src/asset.rs +++ b/yazi-macro/src/asset.rs @@ -6,7 +6,7 @@ macro_rules! config_preset { std::borrow::Cow::from( std::fs::read_to_string(concat!( env!("CARGO_MANIFEST_DIR"), - "/preset/", + "/../yazi-config/preset/", $name, "-default.toml" )) @@ -17,7 +17,7 @@ macro_rules! config_preset { { std::borrow::Cow::from(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/preset/", + "/../yazi-config/preset/", $name, "-default.toml" ))) diff --git a/yazi-parser/src/which/activate.rs b/yazi-parser/src/which/activate.rs index e7b45cbe..3f2acc31 100644 --- a/yazi-parser/src/which/activate.rs +++ b/yazi-parser/src/which/activate.rs @@ -1,15 +1,15 @@ use mlua::{FromLua, IntoLua, Lua, Value}; +use yazi_config::keymap::Key; use yazi_core::which::WhichOpt; use yazi_shared::{Layer, event::ActionCow}; -use yazi_term::event::KeyEvent; #[derive(Clone, Debug)] pub struct ActivateForm { pub opt: WhichOpt, } -impl From<(Layer, KeyEvent)> for ActivateForm { - fn from(value: (Layer, KeyEvent)) -> Self { Self { opt: value.into() } } +impl From<(Layer, Key)> for ActivateForm { + fn from(value: (Layer, Key)) -> Self { Self { opt: value.into() } } } impl TryFrom for ActivateForm { diff --git a/yazi-plugin/src/utils/layer.rs b/yazi-plugin/src/utils/layer.rs index f425342f..16d6c775 100644 --- a/yazi-plugin/src/utils/layer.rs +++ b/yazi-plugin/src/utils/layer.rs @@ -3,12 +3,11 @@ use std::{str::FromStr, time::Duration}; use mlua::{ExternalError, ExternalResult, Function, IntoLuaMulti, Lua, Table, Value}; use tokio_stream::wrappers::UnboundedReceiverStream; use yazi_binding::{elements::{Line, Text}, runtime}; -use yazi_config::{Platform, keymap::{Chord, ChordArc}, popup::ConfirmCfg}; +use yazi_config::{Platform, keymap::{Chord, ChordArc, Key}, popup::ConfirmCfg}; use yazi_core::notify::MessageOpt; use yazi_macro::relay; use yazi_proxy::{ConfirmProxy, InputProxy, NotifyProxy, WhichProxy}; use yazi_shared::{Debounce, Layer}; -use yazi_term::event::KeyEvent; use yazi_widgets::input::{InputOpt, InputStream}; use super::Utils; @@ -93,15 +92,15 @@ impl Utils { lua.create_function(|_, opt: MessageOpt| Ok(NotifyProxy::push(opt))) } - fn parse_keys(value: Value) -> mlua::Result> { + fn parse_keys(value: Value) -> mlua::Result> { Ok(match value { Value::String(s) => { - vec![KeyEvent::from_str(&s.to_str()?).into_lua_err()?] + vec![Key::from_str(&s.to_str()?).into_lua_err()?] } Value::Table(t) => { let mut v = Vec::with_capacity(10); for s in t.sequence_values::() { - v.push(KeyEvent::from_str(&s?.to_str()?).into_lua_err()?); + v.push(Key::from_str(&s?.to_str()?).into_lua_err()?); } v } diff --git a/yazi-term/src/event/mod.rs b/yazi-term/src/event/mod.rs index 3bec86eb..54533203 100644 --- a/yazi-term/src/event/mod.rs +++ b/yazi-term/src/event/mod.rs @@ -1 +1 @@ -yazi_macro::mod_flat!(conversion dnd event keyboard lua modifiers mouse); +yazi_macro::mod_flat!(dnd event keyboard lua modifiers mouse); diff --git a/yazi-vfs/Cargo.toml b/yazi-vfs/Cargo.toml index 01230fb6..4bbbe40c 100644 --- a/yazi-vfs/Cargo.toml +++ b/yazi-vfs/Cargo.toml @@ -14,7 +14,7 @@ workspace = true [dependencies] yazi-binding = { path = "../yazi-binding", version = "26.5.6" } -yazi-config = { path = "../yazi-config", version = "26.5.6" } +yazi-codegen = { path = "../yazi-codegen", version = "26.5.6" } yazi-fs = { path = "../yazi-fs", version = "26.5.6" } yazi-macro = { path = "../yazi-macro", version = "26.5.6" } yazi-sftp = { path = "../yazi-sftp", version = "26.5.6" } @@ -31,6 +31,8 @@ hashbrown = { workspace = true } mlua = { workspace = true } parking_lot = { workspace = true } russh = { workspace = true } +serde = { workspace = true } tokio = { workspace = true } +toml = { workspace = true } tracing = { workspace = true } typed-path = { workspace = true } diff --git a/yazi-config/src/vfs/mod.rs b/yazi-vfs/src/config/mod.rs similarity index 100% rename from yazi-config/src/vfs/mod.rs rename to yazi-vfs/src/config/mod.rs diff --git a/yazi-config/src/vfs/service.rs b/yazi-vfs/src/config/service.rs similarity index 92% rename from yazi-config/src/vfs/service.rs rename to yazi-vfs/src/config/service.rs index 627cd5d0..283f7db7 100644 --- a/yazi-config/src/vfs/service.rs +++ b/yazi-vfs/src/config/service.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -use crate::vfs::ServiceSftp; +use crate::config::ServiceSftp; #[derive(Deserialize, Serialize)] #[serde(tag = "type", rename_all = "kebab-case")] diff --git a/yazi-config/src/vfs/services.rs b/yazi-vfs/src/config/services.rs similarity index 98% rename from yazi-config/src/vfs/services.rs rename to yazi-vfs/src/config/services.rs index 7e7666e4..1264c0ff 100644 --- a/yazi-config/src/vfs/services.rs +++ b/yazi-vfs/src/config/services.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Deserializer, Serialize, de, de::{MapAccess, Visitor}}; use yazi_codegen::DeserializeOver; use yazi_shim::toml::DeserializeOverWith; -use crate::vfs::Service; +use crate::config::Service; #[derive(Serialize, Deserialize, DeserializeOver)] pub struct Services(HashMap); diff --git a/yazi-config/src/vfs/sftp.rs b/yazi-vfs/src/config/sftp.rs similarity index 94% rename from yazi-config/src/vfs/sftp.rs rename to yazi-vfs/src/config/sftp.rs index 733cd2cb..81d67e88 100644 --- a/yazi-config/src/vfs/sftp.rs +++ b/yazi-vfs/src/config/sftp.rs @@ -1,8 +1,7 @@ use std::{env, path::PathBuf}; use serde::{Deserialize, Deserializer, Serialize, de}; - -use crate::normalize_path; +use yazi_fs::path::sanitize_path; #[derive(Deserialize, Eq, Hash, PartialEq, Serialize)] pub struct ServiceSftp { @@ -27,7 +26,7 @@ where { let mut path = PathBuf::deserialize(deserializer)?; if !path.as_os_str().is_empty() { - path = normalize_path(path) + path = sanitize_path(path) .ok_or_else(|| de::Error::custom("path must be either empty or an absolute path"))?; } @@ -46,7 +45,7 @@ where if path.as_os_str().is_empty() { Ok(default_identity_agent()) } else { - normalize_path(path) + sanitize_path(path) .ok_or_else(|| de::Error::custom("identity_agent must be either empty or an absolute path")) } } diff --git a/yazi-config/src/vfs/vfs.rs b/yazi-vfs/src/config/vfs.rs similarity index 90% rename from yazi-config/src/vfs/vfs.rs rename to yazi-vfs/src/config/vfs.rs index fc2e2c3b..2b90389b 100644 --- a/yazi-config/src/vfs/vfs.rs +++ b/yazi-vfs/src/config/vfs.rs @@ -8,7 +8,7 @@ use yazi_fs::{Xdg, ok_or_not_found}; use yazi_shim::toml::DeserializeOver; use super::Service; -use crate::{Preset, vfs::Services}; +use crate::config::Services; #[derive(Deserialize, Serialize, DeserializeOver, DeserializeOver1)] pub struct Vfs { @@ -21,7 +21,8 @@ impl Vfs { async fn init() -> io::Result { tokio::task::spawn_blocking(|| -> anyhow::Result { - Ok(Preset::vfs()?.deserialize_over(&Vfs::read()?)?) + let vfs: Vfs = toml::from_str(&yazi_macro::config_preset!("vfs"))?; + Ok(vfs.deserialize_over(&Vfs::read()?)?) }) .await? .map_err(io::Error::other) diff --git a/yazi-vfs/src/lib.rs b/yazi-vfs/src/lib.rs index 8abc3e7d..498f440f 100644 --- a/yazi-vfs/src/lib.rs +++ b/yazi-vfs/src/lib.rs @@ -1,4 +1,4 @@ -yazi_macro::mod_pub!(provider); +yazi_macro::mod_pub!(config provider); yazi_macro::mod_flat!(cha file files fns op); diff --git a/yazi-vfs/src/provider/sftp/conn.rs b/yazi-vfs/src/provider/sftp/conn.rs index bfc03290..413f41db 100644 --- a/yazi-vfs/src/provider/sftp/conn.rs +++ b/yazi-vfs/src/provider/sftp/conn.rs @@ -2,9 +2,10 @@ use std::{io, sync::Arc, time::{Duration, SystemTime}}; use chrono::DateTime; use russh::keys::{PrivateKeyWithHashAlg, agent::AgentIdentity}; -use yazi_config::vfs::ServiceSftp; use yazi_fs::provider::local::Local; +use crate::config::ServiceSftp; + #[derive(Clone, Copy)] pub(super) struct Conn { pub(super) name: &'static str, diff --git a/yazi-vfs/src/provider/sftp/gate.rs b/yazi-vfs/src/provider/sftp/gate.rs index 5ad087c0..5f4a4b7d 100644 --- a/yazi-vfs/src/provider/sftp/gate.rs +++ b/yazi-vfs/src/provider/sftp/gate.rs @@ -1,11 +1,10 @@ use std::io; -use yazi_config::vfs::{ServiceSftp, Vfs}; use yazi_fs::provider::{Attrs, FileBuilder}; use yazi_sftp::fs::Flags; use yazi_shared::url::{AsUrl, Url}; -use crate::provider::sftp::Conn; +use crate::{config::{ServiceSftp, Vfs}, provider::sftp::Conn}; #[derive(Clone, Copy, Default)] pub struct Gate(crate::provider::Gate); diff --git a/yazi-vfs/src/provider/sftp/mod.rs b/yazi-vfs/src/provider/sftp/mod.rs index 9768af8d..8bf7b524 100644 --- a/yazi-vfs/src/provider/sftp/mod.rs +++ b/yazi-vfs/src/provider/sftp/mod.rs @@ -2,10 +2,7 @@ yazi_macro::mod_flat!(absolute conn gate metadata read_dir sftp); static CONN: yazi_shim::cell::RoCell< parking_lot::Mutex< - hashbrown::HashMap< - &'static yazi_config::vfs::ServiceSftp, - &'static deadpool::managed::Pool, - >, + hashbrown::HashMap<&'static crate::config::ServiceSftp, &'static deadpool::managed::Pool>, >, > = yazi_shim::cell::RoCell::new(); diff --git a/yazi-vfs/src/provider/sftp/sftp.rs b/yazi-vfs/src/provider/sftp/sftp.rs index dc7b8b65..a12690b2 100644 --- a/yazi-vfs/src/provider/sftp/sftp.rs +++ b/yazi-vfs/src/provider/sftp/sftp.rs @@ -1,13 +1,12 @@ use std::{io, sync::Arc}; use tokio::{io::{AsyncWriteExt, BufReader, BufWriter}, sync::mpsc::Receiver}; -use yazi_config::vfs::{ServiceSftp, Vfs}; use yazi_fs::{cha::ChaMode, provider::{Capabilities, DirReader, FileHolder, Provider}}; use yazi_sftp::fs::{Attrs, Flags}; use yazi_shared::{loc::LocBuf, path::{AsPath, PathBufDyn}, pool::InternStr, scheme::SchemeKind, strand::AsStrand, url::{Url, UrlBuf, UrlCow, UrlLike}}; use super::Cha; -use crate::provider::sftp::Conn; +use crate::{config::{ServiceSftp, Vfs}, provider::sftp::Conn}; #[derive(Clone)] pub struct Sftp<'a> { diff --git a/yazi-widgets/Cargo.toml b/yazi-widgets/Cargo.toml index 538983f1..0e7dee39 100644 --- a/yazi-widgets/Cargo.toml +++ b/yazi-widgets/Cargo.toml @@ -18,6 +18,7 @@ vendored-lua = [ "mlua/vendored" ] [dependencies] yazi-binding = { path = "../yazi-binding", version = "26.5.6" } +yazi-dds = { path = "../yazi-dds", version = "26.5.6" } yazi-macro = { path = "../yazi-macro", version = "26.5.6" } yazi-shared = { path = "../yazi-shared", version = "26.5.6" } yazi-shim = { path = "../yazi-shim", version = "26.5.6" } diff --git a/yazi-widgets/src/input/input_arc.rs b/yazi-widgets/src/input/input_arc.rs index b5efbb20..ae0b48ad 100644 --- a/yazi-widgets/src/input/input_arc.rs +++ b/yazi-widgets/src/input/input_arc.rs @@ -4,6 +4,9 @@ use mlua::{AnyUserData, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMetho use parking_lot::Mutex; use ratatui_core::widgets::Widget; use yazi_binding::{elements::{Area, Spatial}, impl_area_method}; +use yazi_dds::Pubsub; +use yazi_macro::err; +use yazi_shim::strum::IntoStr; use crate::input::{Input, InputOpt, InputStyles}; @@ -26,6 +29,7 @@ impl InputArc { let new = lua.create_function(move |_, (_, mut opt): (Table, InputOpt)| { opt.styles.normal = opt.styles.normal.or(styles.normal); opt.styles.selected = opt.styles.selected.or(styles.selected); + opt = opt.with_cb(|e| err!(Pubsub::pub_after_input((&e).into_str(), e.value()))); Ok(Self::from(Input::new(opt)?)) })?;