mirror of
https://github.com/sxyazi/yazi.git
synced 2024-11-27 05:55:43 +03:00
refactor: prefer FromStr
over Default
for configuration parsing with side effects
This commit is contained in:
parent
2a35d30f38
commit
f35712a768
72
Cargo.lock
generated
72
Cargo.lock
generated
@ -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]]
|
||||
|
@ -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"
|
||||
|
@ -37,6 +37,10 @@ impl Display for Adapter {
|
||||
|
||||
impl Adapter {
|
||||
pub async fn image_show(self, path: &Path, max: Rect) -> Result<Rect> {
|
||||
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,
|
||||
|
@ -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" ] }
|
||||
|
@ -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<Control>,
|
||||
}
|
||||
|
||||
impl Keymap {
|
||||
#[inline]
|
||||
pub fn get(&self, layer: Layer) -> &Vec<Control> {
|
||||
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<Self, Self::Err> { toml::from_str(s) }
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Keymap {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
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<Control> {
|
||||
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!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<String> = RoCell::new();
|
||||
static MERGED_KEYMAP: RoCell<String> = RoCell::new();
|
||||
static MERGED_THEME: RoCell<String> = RoCell::new();
|
||||
|
||||
pub static LAYOUT: RoCell<arc_swap::ArcSwap<Layout>> = RoCell::new();
|
||||
|
||||
pub static KEYMAP: RoCell<keymap::Keymap> = RoCell::new();
|
||||
@ -43,23 +40,23 @@ pub static WHICH: RoCell<which::Which> = 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(())
|
||||
}
|
||||
|
@ -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<Self, Self::Err> { toml::from_str(s) }
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Log {
|
||||
|
@ -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<Self, Self::Err> {
|
||||
#[derive(Deserialize)]
|
||||
struct Outer {
|
||||
manager: Manager,
|
||||
}
|
||||
|
||||
let manager = toml::from_str::<Outer>(&MERGED_YAZI).unwrap().manager;
|
||||
let manager = toml::from_str::<Outer>(s)?.manager;
|
||||
manager.validate()?;
|
||||
|
||||
check_validation(manager.validate());
|
||||
manager
|
||||
Ok(manager)
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ bitflags! {
|
||||
}
|
||||
|
||||
impl MouseEvents {
|
||||
#[inline]
|
||||
pub const fn draggable(self) -> bool { self.contains(Self::DRAG) }
|
||||
}
|
||||
|
||||
|
@ -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<String, IndexSet<Opener>>,
|
||||
}
|
||||
|
||||
impl Default for Open {
|
||||
fn default() -> Self { toml::from_str(&MERGED_YAZI).unwrap() }
|
||||
}
|
||||
|
||||
impl Open {
|
||||
pub fn openers<P, M>(&self, path: P, mime: M) -> Option<IndexSet<&Opener>>
|
||||
where
|
||||
@ -58,6 +54,12 @@ impl Open {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Open {
|
||||
type Err = toml::de::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> { toml::from_str(s) }
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Open {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
|
@ -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<Condition>,
|
||||
pub name: Option<Pattern>,
|
||||
pub mime: Option<Pattern>,
|
||||
@ -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 }
|
||||
}
|
||||
}
|
||||
|
@ -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<Previewer>,
|
||||
}
|
||||
|
||||
impl Default for Plugin {
|
||||
fn default() -> Self {
|
||||
#[derive(Deserialize)]
|
||||
struct Outer {
|
||||
plugin: Shadow,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Shadow {
|
||||
fetchers: Vec<Fetcher>,
|
||||
#[serde(default)]
|
||||
prepend_fetchers: Vec<Fetcher>,
|
||||
#[serde(default)]
|
||||
append_fetchers: Vec<Fetcher>,
|
||||
|
||||
preloaders: Vec<Preloader>,
|
||||
#[serde(default)]
|
||||
prepend_preloaders: Vec<Preloader>,
|
||||
#[serde(default)]
|
||||
append_preloaders: Vec<Preloader>,
|
||||
|
||||
previewers: Vec<Previewer>,
|
||||
#[serde(default)]
|
||||
prepend_previewers: Vec<Previewer>,
|
||||
#[serde(default)]
|
||||
append_previewers: Vec<Previewer>,
|
||||
}
|
||||
|
||||
let mut shadow = toml::from_str::<Outer>(&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<Self, Self::Err> {
|
||||
#[derive(Deserialize)]
|
||||
struct Outer {
|
||||
plugin: Shadow,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Shadow {
|
||||
fetchers: Vec<Fetcher>,
|
||||
#[serde(default)]
|
||||
prepend_fetchers: Vec<Fetcher>,
|
||||
#[serde(default)]
|
||||
append_fetchers: Vec<Fetcher>,
|
||||
|
||||
preloaders: Vec<Preloader>,
|
||||
#[serde(default)]
|
||||
prepend_preloaders: Vec<Preloader>,
|
||||
#[serde(default)]
|
||||
append_preloaders: Vec<Preloader>,
|
||||
|
||||
previewers: Vec<Previewer>,
|
||||
#[serde(default)]
|
||||
prepend_previewers: Vec<Previewer>,
|
||||
#[serde(default)]
|
||||
append_previewers: Vec<Previewer>,
|
||||
}
|
||||
|
||||
let mut shadow = toml::from_str::<Outer>(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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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<Pattern>,
|
||||
pub mime: Option<Pattern>,
|
||||
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 }
|
||||
}
|
||||
}
|
||||
|
@ -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<Self, Self::Err> {
|
||||
#[derive(Deserialize)]
|
||||
struct Outer {
|
||||
input: Input,
|
||||
}
|
||||
|
||||
toml::from_str::<Outer>(&MERGED_YAZI).unwrap().input
|
||||
Ok(toml::from_str::<Outer>(s)?.input)
|
||||
}
|
||||
}
|
||||
|
||||
impl Input {
|
||||
#[inline]
|
||||
pub const fn border(&self) -> u16 { 2 }
|
||||
}
|
||||
|
@ -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<Self, Self::Err> {
|
||||
#[derive(Deserialize)]
|
||||
struct Outer {
|
||||
select: Select,
|
||||
}
|
||||
|
||||
toml::from_str::<Outer>(&MERGED_YAZI).unwrap().select
|
||||
Ok(toml::from_str::<Outer>(s)?.select)
|
||||
}
|
||||
}
|
||||
|
||||
impl Select {
|
||||
#[inline]
|
||||
pub const fn border(&self) -> u16 { 2 }
|
||||
}
|
||||
|
@ -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<String> {
|
||||
pub(crate) fn yazi(p: &Path) -> Result<Cow<str>> {
|
||||
Self::merge_path(p.join("yazi.toml"), include_str!("../preset/yazi.toml"))
|
||||
}
|
||||
|
||||
pub(crate) fn keymap(p: &Path) -> Result<String> {
|
||||
pub(crate) fn keymap(p: &Path) -> Result<Cow<str>> {
|
||||
Self::merge_path(p.join("keymap.toml"), include_str!("../preset/keymap.toml"))
|
||||
}
|
||||
|
||||
pub(crate) fn theme(p: &Path) -> Result<String> {
|
||||
pub(crate) fn theme(p: &Path) -> Result<Cow<str>> {
|
||||
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<String> {
|
||||
pub(crate) fn merge_str(user: &str, base: &str) -> Result<Cow<'static, str>> {
|
||||
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<String> {
|
||||
fn merge_path(user: PathBuf, base: &str) -> Result<Cow<str>> {
|
||||
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:?}"))
|
||||
|
@ -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<Self, Self::Err> {
|
||||
#[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::<Outer>(&MERGED_YAZI).unwrap().preview;
|
||||
check_validation(preview.validate());
|
||||
let preview = toml::from_str::<Outer>(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))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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<Self, Self::Err> {
|
||||
#[derive(Deserialize)]
|
||||
struct Outer {
|
||||
tasks: Tasks,
|
||||
}
|
||||
|
||||
let tasks = toml::from_str::<Outer>(&MERGED_YAZI).unwrap().tasks;
|
||||
check_validation(tasks.validate());
|
||||
let tasks = toml::from_str::<Outer>(s)?.tasks;
|
||||
tasks.validate()?;
|
||||
|
||||
tasks
|
||||
Ok(tasks)
|
||||
}
|
||||
}
|
||||
|
@ -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<Self, Self::Err> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
@ -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<Self, Self::Err> {
|
||||
#[derive(Deserialize)]
|
||||
struct Outer {
|
||||
which: Which,
|
||||
}
|
||||
|
||||
toml::from_str::<Outer>(&MERGED_YAZI).unwrap().which
|
||||
Ok(toml::from_str::<Outer>(s)?.which)
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -13,7 +13,7 @@ impl<T> RoCell<T> {
|
||||
|
||||
#[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<T> RoCell<T> {
|
||||
|
||||
#[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<T> Deref for RoCell<T> {
|
||||
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() }
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user