From f35712a768463136a0b27d81b3d06bd1e9207876 Mon Sep 17 00:00:00 2001 From: sxyazi Date: Tue, 18 Jun 2024 16:26:29 +0800 Subject: [PATCH] refactor: prefer `FromStr` over `Default` for configuration parsing with side effects --- Cargo.lock | 72 +++++++++++----- yazi-adapter/Cargo.toml | 6 +- yazi-adapter/src/adapter.rs | 4 + yazi-config/Cargo.toml | 1 - yazi-config/src/keymap/keymap.rs | 46 ++++++----- yazi-config/src/lib.rs | 35 ++++---- yazi-config/src/log/log.rs | 10 ++- yazi-config/src/manager/manager.rs | 15 ++-- yazi-config/src/manager/mouse.rs | 1 - yazi-config/src/open/open.rs | 14 ++-- yazi-config/src/plugin/fetcher.rs | 6 +- yazi-config/src/plugin/plugin.rs | 123 ++++++++++++++-------------- yazi-config/src/plugin/preloader.rs | 5 +- yazi-config/src/popup/input.rs | 20 +++-- yazi-config/src/popup/select.rs | 20 +++-- yazi-config/src/preset.rs | 18 ++-- yazi-config/src/preview/preview.rs | 37 +++++---- yazi-config/src/tasks/tasks.rs | 16 ++-- yazi-config/src/theme/theme.rs | 16 ++-- yazi-config/src/validation.rs | 29 ------- yazi-config/src/which/which.rs | 11 ++- yazi-core/src/tasks/preload.rs | 14 ++-- yazi-plugin/Cargo.toml | 2 +- yazi-scheduler/Cargo.toml | 2 +- yazi-shared/Cargo.toml | 3 - yazi-shared/src/ro_cell.rs | 10 +-- 26 files changed, 280 insertions(+), 256 deletions(-) delete mode 100644 yazi-config/src/validation.rs diff --git a/Cargo.lock b/Cargo.lock index c3450634..1474370e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -218,6 +218,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2", +] + [[package]] name = "bstr" version = "1.9.1" @@ -970,9 +979,9 @@ dependencies = [ [[package]] name = "imagesize" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284" +checksum = "edcd27d72f2f071c64249075f42e205ff93c9a4c5f6c6da53e79ed9f9832c285" [[package]] name = "indexmap" @@ -1150,15 +1159,6 @@ dependencies = [ "which", ] -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - [[package]] name = "md-5" version = "0.10.6" @@ -1328,12 +1328,37 @@ dependencies = [ ] [[package]] -name = "objc" -version = "0.2.7" +name = "objc-sys" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" dependencies = [ - "malloc_buf", + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2-encode" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.5.0", + "block2", + "libc", + "objc2", ] [[package]] @@ -2210,17 +2235,18 @@ dependencies = [ [[package]] name = "trash" -version = "4.1.1" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c254b119cf49bdde3dfef21b1dc492dc8026b75566ca24aa77993eccd7cbc1b5" +checksum = "8d8fbfb70b1fad5c0b788f9b2e1bf4d04e5ac6efa828f1ed9ee462c50ff9cf05" dependencies = [ "chrono", "libc", "log", - "objc", + "objc2", + "objc2-foundation", "once_cell", "scopeguard", - "url", + "urlencoding", "windows", ] @@ -2284,6 +2310,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "utf8parse" version = "0.2.1" @@ -2758,7 +2790,6 @@ dependencies = [ "indexmap", "ratatui", "serde", - "shell-words", "toml", "validator", "yazi-shared", @@ -2934,7 +2965,6 @@ dependencies = [ "serde", "shell-words", "tokio", - "tracing", ] [[package]] diff --git a/yazi-adapter/Cargo.toml b/yazi-adapter/Cargo.toml index 1b0fdccf..822661c3 100644 --- a/yazi-adapter/Cargo.toml +++ b/yazi-adapter/Cargo.toml @@ -13,15 +13,15 @@ yazi-config = { path = "../yazi-config", version = "0.2.5" } yazi-shared = { path = "../yazi-shared", version = "0.2.5" } # External dependencies -ansi-to-tui = "3.1.0" +ansi-to-tui = "=3.1.0" anyhow = "1.0.86" arc-swap = "1.7.1" base64 = "0.22.1" color_quant = "1.1.0" crossterm = "0.27.0" futures = "0.3.30" -image = "0.24.9" -imagesize = "0.12.0" +image = "=0.24.9" +imagesize = "0.13.0" kamadak-exif = "0.5.5" ratatui = "0.26.3" scopeguard = "1.2.0" diff --git a/yazi-adapter/src/adapter.rs b/yazi-adapter/src/adapter.rs index 2ee59370..1a2e49bb 100644 --- a/yazi-adapter/src/adapter.rs +++ b/yazi-adapter/src/adapter.rs @@ -37,6 +37,10 @@ impl Display for Adapter { impl Adapter { pub async fn image_show(self, path: &Path, max: Rect) -> Result { + if max.is_empty() { + return Ok(Rect::default()); + } + match self { Self::Kitty => Kitty::image_show(path, max).await, Self::KittyOld => KittyOld::image_show(path, max).await, diff --git a/yazi-config/Cargo.toml b/yazi-config/Cargo.toml index 22064b68..e0e93295 100644 --- a/yazi-config/Cargo.toml +++ b/yazi-config/Cargo.toml @@ -20,6 +20,5 @@ globset = "0.4.14" indexmap = "2.2.6" ratatui = "0.26.3" serde = { version = "1.0.203", features = [ "derive" ] } -shell-words = "1.1.0" toml = { version = "0.8.14", features = [ "preserve_order" ] } validator = { version = "0.18.1", features = [ "derive" ] } diff --git a/yazi-config/src/keymap/keymap.rs b/yazi-config/src/keymap/keymap.rs index c5f755b9..f5542281 100644 --- a/yazi-config/src/keymap/keymap.rs +++ b/yazi-config/src/keymap/keymap.rs @@ -1,8 +1,10 @@ +use std::str::FromStr; + use serde::{Deserialize, Deserializer}; use yazi_shared::Layer; use super::Control; -use crate::{Preset, MERGED_KEYMAP}; +use crate::Preset; #[derive(Debug)] pub struct Keymap { @@ -14,6 +16,28 @@ pub struct Keymap { pub completion: Vec, } +impl Keymap { + #[inline] + pub fn get(&self, layer: Layer) -> &Vec { + match layer { + Layer::App => unreachable!(), + Layer::Manager => &self.manager, + Layer::Tasks => &self.tasks, + Layer::Select => &self.select, + Layer::Input => &self.input, + Layer::Help => &self.help, + Layer::Completion => &self.completion, + Layer::Which => unreachable!(), + } + } +} + +impl FromStr for Keymap { + type Err = toml::de::Error; + + fn from_str(s: &str) -> Result { toml::from_str(s) } +} + impl<'de> Deserialize<'de> for Keymap { fn deserialize(deserializer: D) -> Result where @@ -62,23 +86,3 @@ impl<'de> Deserialize<'de> for Keymap { }) } } - -impl Default for Keymap { - fn default() -> Self { toml::from_str(&MERGED_KEYMAP).unwrap() } -} - -impl Keymap { - #[inline] - pub fn get(&self, layer: Layer) -> &Vec { - match layer { - Layer::App => unreachable!(), - Layer::Manager => &self.manager, - Layer::Tasks => &self.tasks, - Layer::Select => &self.select, - Layer::Input => &self.input, - Layer::Help => &self.help, - Layer::Completion => &self.completion, - Layer::Which => unreachable!(), - } - } -} diff --git a/yazi-config/src/lib.rs b/yazi-config/src/lib.rs index 513f88fb..a715d969 100644 --- a/yazi-config/src/lib.rs +++ b/yazi-config/src/lib.rs @@ -1,5 +1,7 @@ #![allow(clippy::module_inception)] +use std::str::FromStr; + use yazi_shared::{RoCell, Xdg}; pub mod keymap; @@ -15,7 +17,6 @@ pub mod preview; mod priority; mod tasks; pub mod theme; -mod validation; pub mod which; pub use layout::*; @@ -23,10 +24,6 @@ pub(crate) use pattern::*; pub(crate) use preset::*; pub use priority::*; -static MERGED_YAZI: RoCell = RoCell::new(); -static MERGED_KEYMAP: RoCell = RoCell::new(); -static MERGED_THEME: RoCell = RoCell::new(); - pub static LAYOUT: RoCell> = RoCell::new(); pub static KEYMAP: RoCell = RoCell::new(); @@ -43,23 +40,23 @@ pub static WHICH: RoCell = RoCell::new(); pub fn init() -> anyhow::Result<()> { let config_dir = Xdg::config_dir(); - MERGED_YAZI.init(Preset::yazi(&config_dir)?); - MERGED_KEYMAP.init(Preset::keymap(&config_dir)?); - MERGED_THEME.init(Preset::theme(&config_dir)?); + let yazi_toml = &Preset::yazi(&config_dir)?; + let keymap_toml = &Preset::keymap(&config_dir)?; + let theme_toml = &Preset::theme(&config_dir)?; LAYOUT.with(Default::default); - KEYMAP.with(Default::default); - LOG.with(Default::default); - MANAGER.with(Default::default); - OPEN.with(Default::default); - PLUGIN.with(Default::default); - PREVIEW.with(Default::default); - TASKS.with(Default::default); - THEME.with(Default::default); - INPUT.with(Default::default); - SELECT.with(Default::default); - WHICH.with(Default::default); + KEYMAP.init(<_>::from_str(keymap_toml)?); + LOG.init(<_>::from_str(yazi_toml)?); + MANAGER.init(<_>::from_str(yazi_toml)?); + OPEN.init(<_>::from_str(yazi_toml)?); + PLUGIN.init(<_>::from_str(yazi_toml)?); + PREVIEW.init(<_>::from_str(yazi_toml)?); + TASKS.init(<_>::from_str(yazi_toml)?); + THEME.init(<_>::from_str(theme_toml)?); + INPUT.init(<_>::from_str(yazi_toml)?); + SELECT.init(<_>::from_str(yazi_toml)?); + WHICH.init(<_>::from_str(yazi_toml)?); Ok(()) } diff --git a/yazi-config/src/log/log.rs b/yazi-config/src/log/log.rs index 74433fdf..c92cf604 100644 --- a/yazi-config/src/log/log.rs +++ b/yazi-config/src/log/log.rs @@ -1,14 +1,16 @@ -use serde::{Deserialize, Deserializer}; +use std::str::FromStr; -use crate::MERGED_YAZI; +use serde::{Deserialize, Deserializer}; #[derive(Debug)] pub struct Log { pub enabled: bool, } -impl Default for Log { - fn default() -> Self { toml::from_str(&MERGED_YAZI).unwrap() } +impl FromStr for Log { + type Err = toml::de::Error; + + fn from_str(s: &str) -> Result { toml::from_str(s) } } impl<'de> Deserialize<'de> for Log { diff --git a/yazi-config/src/manager/manager.rs b/yazi-config/src/manager/manager.rs index e4064f01..cd980ac2 100644 --- a/yazi-config/src/manager/manager.rs +++ b/yazi-config/src/manager/manager.rs @@ -1,8 +1,9 @@ +use std::str::FromStr; + use serde::{Deserialize, Serialize}; use validator::Validate; use super::{ManagerRatio, MouseEvents, SortBy}; -use crate::{validation::check_validation, MERGED_YAZI}; #[derive(Debug, Deserialize, Serialize, Validate)] pub struct Manager { @@ -24,16 +25,18 @@ pub struct Manager { pub mouse_events: MouseEvents, } -impl Default for Manager { - fn default() -> Self { +impl FromStr for Manager { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { #[derive(Deserialize)] struct Outer { manager: Manager, } - let manager = toml::from_str::(&MERGED_YAZI).unwrap().manager; + let manager = toml::from_str::(s)?.manager; + manager.validate()?; - check_validation(manager.validate()); - manager + Ok(manager) } } diff --git a/yazi-config/src/manager/mouse.rs b/yazi-config/src/manager/mouse.rs index 812bd06b..6507db33 100644 --- a/yazi-config/src/manager/mouse.rs +++ b/yazi-config/src/manager/mouse.rs @@ -16,7 +16,6 @@ bitflags! { } impl MouseEvents { - #[inline] pub const fn draggable(self) -> bool { self.contains(Self::DRAG) } } diff --git a/yazi-config/src/open/open.rs b/yazi-config/src/open/open.rs index c83928d0..a83fbe92 100644 --- a/yazi-config/src/open/open.rs +++ b/yazi-config/src/open/open.rs @@ -1,11 +1,11 @@ -use std::{collections::HashMap, path::Path}; +use std::{collections::HashMap, path::Path, str::FromStr}; use indexmap::IndexSet; use serde::{Deserialize, Deserializer}; use yazi_shared::MIME_DIR; use super::Opener; -use crate::{open::OpenRule, Preset, MERGED_YAZI}; +use crate::{open::OpenRule, Preset}; #[derive(Debug)] pub struct Open { @@ -13,10 +13,6 @@ pub struct Open { openers: HashMap>, } -impl Default for Open { - fn default() -> Self { toml::from_str(&MERGED_YAZI).unwrap() } -} - impl Open { pub fn openers(&self, path: P, mime: M) -> Option> where @@ -58,6 +54,12 @@ impl Open { } } +impl FromStr for Open { + type Err = toml::de::Error; + + fn from_str(s: &str) -> Result { toml::from_str(s) } +} + impl<'de> Deserialize<'de> for Open { fn deserialize(deserializer: D) -> Result where diff --git a/yazi-config/src/plugin/fetcher.rs b/yazi-config/src/plugin/fetcher.rs index d9f5c00d..eece4136 100644 --- a/yazi-config/src/plugin/fetcher.rs +++ b/yazi-config/src/plugin/fetcher.rs @@ -6,7 +6,9 @@ use crate::{Pattern, Priority}; #[derive(Debug, Deserialize)] pub struct Fetcher { #[serde(skip)] - pub id: u8, + pub idx: u8, + + pub id: String, pub cond: Option, pub name: Option, pub mime: Option, @@ -24,6 +26,6 @@ pub struct FetcherProps { impl From<&Fetcher> for FetcherProps { fn from(fetcher: &Fetcher) -> Self { - Self { id: fetcher.id, name: fetcher.run.name.to_owned(), prio: fetcher.prio } + Self { id: fetcher.idx, name: fetcher.run.name.to_owned(), prio: fetcher.prio } } } diff --git a/yazi-config/src/plugin/plugin.rs b/yazi-config/src/plugin/plugin.rs index 49ccda77..902244b4 100644 --- a/yazi-config/src/plugin/plugin.rs +++ b/yazi-config/src/plugin/plugin.rs @@ -1,10 +1,10 @@ -use std::path::Path; +use std::{path::Path, str::FromStr}; use serde::Deserialize; use yazi_shared::MIME_DIR; use super::{Fetcher, Preloader, Previewer}; -use crate::{plugin::MAX_PREWORKERS, Preset, MERGED_YAZI}; +use crate::{plugin::MAX_PREWORKERS, Preset}; #[derive(Deserialize)] pub struct Plugin { @@ -13,65 +13,6 @@ pub struct Plugin { pub previewers: Vec, } -impl Default for Plugin { - fn default() -> Self { - #[derive(Deserialize)] - struct Outer { - plugin: Shadow, - } - - #[derive(Deserialize)] - struct Shadow { - fetchers: Vec, - #[serde(default)] - prepend_fetchers: Vec, - #[serde(default)] - append_fetchers: Vec, - - preloaders: Vec, - #[serde(default)] - prepend_preloaders: Vec, - #[serde(default)] - append_preloaders: Vec, - - previewers: Vec, - #[serde(default)] - prepend_previewers: Vec, - #[serde(default)] - append_previewers: Vec, - } - - let mut shadow = toml::from_str::(&MERGED_YAZI).unwrap().plugin; - if shadow.append_previewers.iter().any(|r| r.any_file()) { - shadow.previewers.retain(|r| !r.any_file()); - } - if shadow.append_previewers.iter().any(|r| r.any_dir()) { - shadow.previewers.retain(|r| !r.any_dir()); - } - - Preset::mix(&mut shadow.fetchers, shadow.prepend_fetchers, shadow.append_fetchers); - Preset::mix(&mut shadow.preloaders, shadow.prepend_preloaders, shadow.append_preloaders); - Preset::mix(&mut shadow.previewers, shadow.prepend_previewers, shadow.append_previewers); - - if shadow.fetchers.len() + shadow.preloaders.len() > MAX_PREWORKERS as usize { - panic!("Fetchers and preloaders exceed the limit of {MAX_PREWORKERS}"); - } - - for (i, p) in shadow.fetchers.iter_mut().enumerate() { - p.id = i as u8; - } - for (i, p) in shadow.preloaders.iter_mut().enumerate() { - p.id = shadow.fetchers.len() as u8 + i as u8; - } - - Self { - fetchers: shadow.fetchers, - preloaders: shadow.preloaders, - previewers: shadow.previewers, - } - } -} - impl Plugin { pub fn fetchers( &self, @@ -118,3 +59,63 @@ impl Plugin { }) } } +impl FromStr for Plugin { + type Err = toml::de::Error; + + fn from_str(s: &str) -> Result { + #[derive(Deserialize)] + struct Outer { + plugin: Shadow, + } + + #[derive(Deserialize)] + struct Shadow { + fetchers: Vec, + #[serde(default)] + prepend_fetchers: Vec, + #[serde(default)] + append_fetchers: Vec, + + preloaders: Vec, + #[serde(default)] + prepend_preloaders: Vec, + #[serde(default)] + append_preloaders: Vec, + + previewers: Vec, + #[serde(default)] + prepend_previewers: Vec, + #[serde(default)] + append_previewers: Vec, + } + + let mut shadow = toml::from_str::(s)?.plugin; + if shadow.append_previewers.iter().any(|r| r.any_file()) { + shadow.previewers.retain(|r| !r.any_file()); + } + if shadow.append_previewers.iter().any(|r| r.any_dir()) { + shadow.previewers.retain(|r| !r.any_dir()); + } + + Preset::mix(&mut shadow.fetchers, shadow.prepend_fetchers, shadow.append_fetchers); + Preset::mix(&mut shadow.preloaders, shadow.prepend_preloaders, shadow.append_preloaders); + Preset::mix(&mut shadow.previewers, shadow.prepend_previewers, shadow.append_previewers); + + if shadow.fetchers.len() + shadow.preloaders.len() > MAX_PREWORKERS as usize { + panic!("Fetchers and preloaders exceed the limit of {MAX_PREWORKERS}"); + } + + for (i, p) in shadow.fetchers.iter_mut().enumerate() { + p.idx = i as u8; + } + for (i, p) in shadow.preloaders.iter_mut().enumerate() { + p.idx = shadow.fetchers.len() as u8 + i as u8; + } + + Ok(Self { + fetchers: shadow.fetchers, + preloaders: shadow.preloaders, + previewers: shadow.previewers, + }) + } +} diff --git a/yazi-config/src/plugin/preloader.rs b/yazi-config/src/plugin/preloader.rs index 960ea276..03a4e513 100644 --- a/yazi-config/src/plugin/preloader.rs +++ b/yazi-config/src/plugin/preloader.rs @@ -6,7 +6,8 @@ use crate::{Pattern, Priority}; #[derive(Debug, Deserialize)] pub struct Preloader { #[serde(skip)] - pub id: u8, + pub idx: u8, + pub name: Option, pub mime: Option, pub run: Cmd, @@ -25,6 +26,6 @@ pub struct PreloaderProps { impl From<&Preloader> for PreloaderProps { fn from(preloader: &Preloader) -> Self { - Self { id: preloader.id, name: preloader.run.name.to_owned(), prio: preloader.prio } + Self { id: preloader.idx, name: preloader.run.name.to_owned(), prio: preloader.prio } } } diff --git a/yazi-config/src/popup/input.rs b/yazi-config/src/popup/input.rs index 5db33ef7..9ec27cdc 100644 --- a/yazi-config/src/popup/input.rs +++ b/yazi-config/src/popup/input.rs @@ -1,7 +1,8 @@ +use std::str::FromStr; + use serde::Deserialize; use super::{Offset, Origin}; -use crate::MERGED_YAZI; #[derive(Deserialize)] pub struct Input { @@ -63,18 +64,19 @@ pub struct Input { pub quit_offset: Offset, } -impl Default for Input { - fn default() -> Self { +impl Input { + pub const fn border(&self) -> u16 { 2 } +} + +impl FromStr for Input { + type Err = toml::de::Error; + + fn from_str(s: &str) -> Result { #[derive(Deserialize)] struct Outer { input: Input, } - toml::from_str::(&MERGED_YAZI).unwrap().input + Ok(toml::from_str::(s)?.input) } } - -impl Input { - #[inline] - pub const fn border(&self) -> u16 { 2 } -} diff --git a/yazi-config/src/popup/select.rs b/yazi-config/src/popup/select.rs index 05d24a19..df584df8 100644 --- a/yazi-config/src/popup/select.rs +++ b/yazi-config/src/popup/select.rs @@ -1,7 +1,8 @@ +use std::str::FromStr; + use serde::Deserialize; use super::{Offset, Origin}; -use crate::MERGED_YAZI; #[derive(Deserialize)] pub struct Select { @@ -11,18 +12,19 @@ pub struct Select { pub open_offset: Offset, } -impl Default for Select { - fn default() -> Self { +impl Select { + pub const fn border(&self) -> u16 { 2 } +} + +impl FromStr for Select { + type Err = toml::de::Error; + + fn from_str(s: &str) -> Result { #[derive(Deserialize)] struct Outer { select: Select, } - toml::from_str::(&MERGED_YAZI).unwrap().select + Ok(toml::from_str::(s)?.select) } } - -impl Select { - #[inline] - pub const fn border(&self) -> u16 { 2 } -} diff --git a/yazi-config/src/preset.rs b/yazi-config/src/preset.rs index 317c8fd4..67c59ee3 100644 --- a/yazi-config/src/preset.rs +++ b/yazi-config/src/preset.rs @@ -1,4 +1,4 @@ -use std::{mem, path::{Path, PathBuf}}; +use std::{borrow::Cow, mem, path::{Path, PathBuf}}; use anyhow::{anyhow, Context, Result}; use toml::{Table, Value}; @@ -8,17 +8,17 @@ use crate::theme::Flavor; pub(crate) struct Preset; impl Preset { - pub(crate) fn yazi(p: &Path) -> Result { + pub(crate) fn yazi(p: &Path) -> Result> { Self::merge_path(p.join("yazi.toml"), include_str!("../preset/yazi.toml")) } - pub(crate) fn keymap(p: &Path) -> Result { + pub(crate) fn keymap(p: &Path) -> Result> { Self::merge_path(p.join("keymap.toml"), include_str!("../preset/keymap.toml")) } - pub(crate) fn theme(p: &Path) -> Result { + pub(crate) fn theme(p: &Path) -> Result> { let Ok(user) = std::fs::read_to_string(p.join("theme.toml")) else { - return Ok(include_str!("../preset/theme.toml").to_owned()); + return Ok(include_str!("../preset/theme.toml").into()); }; let Some(use_) = Flavor::parse_use(&user) else { return Self::merge_str(&user, include_str!("../preset/theme.toml")); @@ -37,18 +37,18 @@ impl Preset { } #[inline] - pub(crate) fn merge_str(user: &str, base: &str) -> Result { + pub(crate) fn merge_str(user: &str, base: &str) -> Result> { let mut t = user.parse()?; Self::merge(&mut t, base.parse()?, 2); - Ok(t.to_string()) + Ok(t.to_string().into()) } #[inline] - fn merge_path(user: PathBuf, base: &str) -> Result { + fn merge_path(user: PathBuf, base: &str) -> Result> { let s = std::fs::read_to_string(&user).unwrap_or_default(); if s.is_empty() { - return Ok(base.to_string()); + return Ok(base.into()); } Self::merge_str(&s, base).with_context(|| anyhow!("Loading {user:?}")) diff --git a/yazi-config/src/preview/preview.rs b/yazi-config/src/preview/preview.rs index d58b0440..5f38a109 100644 --- a/yazi-config/src/preview/preview.rs +++ b/yazi-config/src/preview/preview.rs @@ -1,10 +1,11 @@ -use std::{path::PathBuf, time::{self, SystemTime}}; +use std::{path::PathBuf, str::FromStr, time::{self, SystemTime}}; +use anyhow::Context; use serde::{Deserialize, Serialize}; use validator::Validate; use yazi_shared::fs::expand_path; -use crate::{validation::check_validation, Xdg, MERGED_YAZI}; +use crate::Xdg; #[derive(Debug, Serialize)] pub struct Preview { @@ -22,8 +23,18 @@ pub struct Preview { pub ueberzug_offset: (f32, f32, f32, f32), } -impl Default for Preview { - fn default() -> Self { +impl Preview { + #[inline] + pub fn tmpfile(&self, prefix: &str) -> PathBuf { + let nanos = SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap().as_nanos(); + self.cache_dir.join(format!("{prefix}-{}", nanos / 1000)) + } +} + +impl FromStr for Preview { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { #[derive(Deserialize)] struct Outer { preview: Shadow, @@ -46,14 +57,14 @@ impl Default for Preview { ueberzug_offset: (f32, f32, f32, f32), } - let preview = toml::from_str::(&MERGED_YAZI).unwrap().preview; - check_validation(preview.validate()); + let preview = toml::from_str::(s)?.preview; + preview.validate()?; let cache_dir = preview.cache_dir.filter(|p| !p.is_empty()).map_or_else(Xdg::cache_dir, expand_path); - std::fs::create_dir_all(&cache_dir).expect("Failed to create cache directory"); + std::fs::create_dir_all(&cache_dir).context("Failed to create cache directory")?; - Preview { + Ok(Preview { tab_size: preview.tab_size, max_width: preview.max_width, max_height: preview.max_height, @@ -66,14 +77,6 @@ impl Default for Preview { ueberzug_scale: preview.ueberzug_scale, ueberzug_offset: preview.ueberzug_offset, - } - } -} - -impl Preview { - #[inline] - pub fn tmpfile(&self, prefix: &str) -> PathBuf { - let nanos = SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap().as_nanos(); - self.cache_dir.join(format!("{prefix}-{}", nanos / 1000)) + }) } } diff --git a/yazi-config/src/tasks/tasks.rs b/yazi-config/src/tasks/tasks.rs index 21900dfe..e922d359 100644 --- a/yazi-config/src/tasks/tasks.rs +++ b/yazi-config/src/tasks/tasks.rs @@ -1,8 +1,8 @@ +use std::str::FromStr; + use serde::Deserialize; use validator::Validate; -use crate::{validation::check_validation, MERGED_YAZI}; - #[derive(Debug, Deserialize, Validate)] pub struct Tasks { #[validate(range(min = 1, message = "Cannot be less than 1"))] @@ -18,16 +18,18 @@ pub struct Tasks { pub suppress_preload: bool, } -impl Default for Tasks { - fn default() -> Self { +impl FromStr for Tasks { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { #[derive(Deserialize)] struct Outer { tasks: Tasks, } - let tasks = toml::from_str::(&MERGED_YAZI).unwrap().tasks; - check_validation(tasks.validate()); + let tasks = toml::from_str::(s)?.tasks; + tasks.validate()?; - tasks + Ok(tasks) } } diff --git a/yazi-config/src/theme/theme.rs b/yazi-config/src/theme/theme.rs index aa79542f..da757143 100644 --- a/yazi-config/src/theme/theme.rs +++ b/yazi-config/src/theme/theme.rs @@ -1,11 +1,10 @@ -use std::path::PathBuf; +use std::{path::PathBuf, str::FromStr}; use serde::{Deserialize, Serialize}; use validator::Validate; use yazi_shared::{fs::expand_path, theme::Style, Xdg}; use super::{Filetype, Flavor, Icons}; -use crate::{validation::check_validation, MERGED_THEME}; #[derive(Deserialize, Serialize)] pub struct Theme { @@ -27,12 +26,13 @@ pub struct Theme { pub icons: Icons, } -impl Default for Theme { - fn default() -> Self { - let mut theme: Self = toml::from_str(&MERGED_THEME).unwrap(); +impl FromStr for Theme { + type Err = anyhow::Error; - check_validation(theme.manager.validate()); - check_validation(theme.which.validate()); + fn from_str(s: &str) -> Result { + let mut theme: Self = toml::from_str(s)?; + theme.manager.validate()?; + theme.which.validate()?; if theme.flavor.use_.is_empty() { theme.manager.syntect_theme = expand_path(&theme.manager.syntect_theme); @@ -41,7 +41,7 @@ impl Default for Theme { Xdg::config_dir().join(format!("flavors/{}.yazi/tmtheme.xml", theme.flavor.use_)); } - theme + Ok(theme) } } diff --git a/yazi-config/src/validation.rs b/yazi-config/src/validation.rs deleted file mode 100644 index b71e150a..00000000 --- a/yazi-config/src/validation.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::{borrow::Cow, process}; - -use validator::{ValidationErrors, ValidationErrorsKind}; - -pub fn check_validation(res: Result<(), ValidationErrors>) { - let Err(errors) = res else { return }; - - for (field, kind) in errors.into_errors() { - match kind { - ValidationErrorsKind::Struct(errors) => check_validation(Err(*errors)), - ValidationErrorsKind::List(errors) => { - for (i, errors) in errors { - eprint!("Config `{field}[{i}]` format error: "); - check_validation(Err(*errors)); - eprintln!(); - } - } - ValidationErrorsKind::Field(error) => { - for e in error { - eprintln!( - "Config `{field}` format error: {}\n", - e.message.unwrap_or(Cow::Borrowed("unknown error")) - ); - } - } - } - } - process::exit(1); -} diff --git a/yazi-config/src/which/which.rs b/yazi-config/src/which/which.rs index 7d738870..205a2bc4 100644 --- a/yazi-config/src/which/which.rs +++ b/yazi-config/src/which/which.rs @@ -1,8 +1,9 @@ +use std::str::FromStr; + use serde::{Deserialize, Serialize}; use validator::Validate; use super::SortBy; -use crate::MERGED_YAZI; #[derive(Debug, Deserialize, Serialize, Validate)] pub struct Which { @@ -13,13 +14,15 @@ pub struct Which { pub sort_translit: bool, } -impl Default for Which { - fn default() -> Self { +impl FromStr for Which { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { #[derive(Deserialize)] struct Outer { which: Which, } - toml::from_str::(&MERGED_YAZI).unwrap().which + Ok(toml::from_str::(s)?.which) } } diff --git a/yazi-core/src/tasks/preload.rs b/yazi-core/src/tasks/preload.rs index c0856341..f2ce3d5b 100644 --- a/yazi-core/src/tasks/preload.rs +++ b/yazi-core/src/tasks/preload.rs @@ -19,11 +19,11 @@ impl Tasks { for p in PLUGIN.fetchers(&f.url, mime, factors) { match loaded.get_mut(&f.url) { - Some(n) if *n & (1 << p.id) != 0 => continue, - Some(n) => *n |= 1 << p.id, - None => _ = loaded.insert(f.url.clone(), 1 << p.id), + Some(n) if *n & (1 << p.idx) != 0 => continue, + Some(n) => *n |= 1 << p.idx, + None => _ = loaded.insert(f.url.clone(), 1 << p.idx), } - tasks[p.id as usize].push(f.clone()); + tasks[p.idx as usize].push(f.clone()); } } @@ -41,9 +41,9 @@ impl Tasks { let mime = if f.is_dir() { Some(MIME_DIR) } else { mimetype.get(&f.url).map(|s| &**s) }; for p in PLUGIN.preloaders(&f.url, mime) { match loaded.get_mut(&f.url) { - Some(n) if *n & (1 << p.id) != 0 => continue, - Some(n) => *n |= 1 << p.id, - None => _ = loaded.insert(f.url.clone(), 1 << p.id), + Some(n) if *n & (1 << p.idx) != 0 => continue, + Some(n) => *n |= 1 << p.idx, + None => _ = loaded.insert(f.url.clone(), 1 << p.idx), } self.scheduler.preload_paged(p, f); } diff --git a/yazi-plugin/Cargo.toml b/yazi-plugin/Cargo.toml index 467999aa..7fe5c8c3 100644 --- a/yazi-plugin/Cargo.toml +++ b/yazi-plugin/Cargo.toml @@ -21,7 +21,7 @@ yazi-proxy = { path = "../yazi-proxy", version = "0.2.5" } yazi-shared = { path = "../yazi-shared", version = "0.2.5" } # External dependencies -ansi-to-tui = "3.1.0" +ansi-to-tui = "=3.1.0" anyhow = "1.0.86" base64 = "0.22.1" crossterm = "0.27.0" diff --git a/yazi-scheduler/Cargo.toml b/yazi-scheduler/Cargo.toml index 77e43b3b..d42b4020 100644 --- a/yazi-scheduler/Cargo.toml +++ b/yazi-scheduler/Cargo.toml @@ -30,4 +30,4 @@ tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_lev libc = "0.2.155" [target.'cfg(not(target_os = "android"))'.dependencies] -trash = "4.1.1" +trash = "5.0.0" diff --git a/yazi-shared/Cargo.toml b/yazi-shared/Cargo.toml index 2d8c7e9e..c18b36fe 100644 --- a/yazi-shared/Cargo.toml +++ b/yazi-shared/Cargo.toml @@ -24,8 +24,5 @@ serde = { version = "1.0.203", features = [ "derive" ] } shell-words = "1.1.0" tokio = { version = "1.38.0", features = [ "full" ] } -# Logging -tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] } - [target."cfg(unix)".dependencies] libc = "0.2.155" diff --git a/yazi-shared/src/ro_cell.rs b/yazi-shared/src/ro_cell.rs index 3783f618..4ed209f3 100644 --- a/yazi-shared/src/ro_cell.rs +++ b/yazi-shared/src/ro_cell.rs @@ -13,7 +13,7 @@ impl RoCell { #[inline] pub fn init(&self, value: T) { - debug_assert!(!self.is_initialized()); + debug_assert!(!self.initialized()); unsafe { *self.0.get() = Some(value); } @@ -29,25 +29,25 @@ impl RoCell { #[inline] pub fn replace(&self, value: T) -> T { - debug_assert!(self.is_initialized()); + debug_assert!(self.initialized()); unsafe { mem::replace(&mut *self.0.get(), Some(value)).unwrap_unchecked() } } #[inline] pub fn drop(&self) -> T { - debug_assert!(self.is_initialized()); + debug_assert!(self.initialized()); unsafe { mem::take(&mut *self.0.get()).unwrap_unchecked() } } #[inline] - fn is_initialized(&self) -> bool { unsafe { (*self.0.get()).is_some() } } + fn initialized(&self) -> bool { unsafe { (*self.0.get()).is_some() } } } impl Deref for RoCell { type Target = T; fn deref(&self) -> &Self::Target { - debug_assert!(self.is_initialized()); + debug_assert!(self.initialized()); unsafe { (*self.0.get()).as_ref().unwrap_unchecked() } } }