mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
Partial refactor
This commit is contained in:
parent
d19e9d75fe
commit
4d4a260673
14 changed files with 147 additions and 137 deletions
13
Cargo.lock
generated
13
Cargo.lock
generated
|
|
@ -3281,11 +3281,24 @@ dependencies = [
|
||||||
"yazi-config",
|
"yazi-config",
|
||||||
"yazi-core",
|
"yazi-core",
|
||||||
"yazi-dds",
|
"yazi-dds",
|
||||||
|
"yazi-fs",
|
||||||
"yazi-plugin",
|
"yazi-plugin",
|
||||||
"yazi-proxy",
|
"yazi-proxy",
|
||||||
"yazi-shared",
|
"yazi-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yazi-fs"
|
||||||
|
version = "0.2.5"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"opendal",
|
||||||
|
"serde",
|
||||||
|
"tokio",
|
||||||
|
"toml",
|
||||||
|
"yazi-shared",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yazi-plugin"
|
name = "yazi-plugin"
|
||||||
version = "0.2.5"
|
version = "0.2.5"
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"language":"en","version":"0.2","flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","imagesize","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime","magick","magick","prefetcher","Prework","prefetchers","PREWORKERS","conds","translit","rxvt","Urxvt","realpath"]}
|
{"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","imagesize","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime","magick","magick","prefetcher","Prework","prefetchers","PREWORKERS","conds","translit","rxvt","Urxvt","realpath","opendal"],"language":"en","flagWords":[],"version":"0.2"}
|
||||||
|
|
@ -13,7 +13,6 @@ pub mod popup;
|
||||||
mod preset;
|
mod preset;
|
||||||
pub mod preview;
|
pub mod preview;
|
||||||
mod priority;
|
mod priority;
|
||||||
pub mod schemes;
|
|
||||||
mod tasks;
|
mod tasks;
|
||||||
pub mod theme;
|
pub mod theme;
|
||||||
mod validation;
|
mod validation;
|
||||||
|
|
@ -23,9 +22,6 @@ pub use layout::*;
|
||||||
pub(crate) use pattern::*;
|
pub(crate) use pattern::*;
|
||||||
pub(crate) use preset::*;
|
pub(crate) use preset::*;
|
||||||
pub use priority::*;
|
pub use priority::*;
|
||||||
use yazi_shared::fs::SCHEMES;
|
|
||||||
|
|
||||||
use crate::schemes::Schemes;
|
|
||||||
|
|
||||||
static MERGED_YAZI: RoCell<String> = RoCell::new();
|
static MERGED_YAZI: RoCell<String> = RoCell::new();
|
||||||
static MERGED_KEYMAP: RoCell<String> = RoCell::new();
|
static MERGED_KEYMAP: RoCell<String> = RoCell::new();
|
||||||
|
|
@ -65,9 +61,5 @@ pub fn init() -> anyhow::Result<()> {
|
||||||
SELECT.with(Default::default);
|
SELECT.with(Default::default);
|
||||||
WHICH.with(Default::default);
|
WHICH.with(Default::default);
|
||||||
|
|
||||||
// Load schemes.
|
|
||||||
let schemes = Schemes::default().make()?;
|
|
||||||
SCHEMES.init(schemes);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
mod schemes;
|
|
||||||
|
|
||||||
pub use schemes::*;
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use anyhow::Result;
|
|
||||||
use serde::{Deserialize, Deserializer};
|
|
||||||
|
|
||||||
/// Schemes in configuration file.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Schemes {
|
|
||||||
pub rules: Vec<Scheme>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Schemes {
|
|
||||||
fn default() -> Self {
|
|
||||||
let schemes_path = yazi_shared::Xdg::state_dir().join("schemes.toml");
|
|
||||||
// Ignore any errors, as it's fine to have an empty file.
|
|
||||||
let schemes_content = std::fs::read_to_string(&schemes_path).unwrap_or_default();
|
|
||||||
toml::from_str(&schemes_content).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Schemes {
|
|
||||||
/// Consume loaded config to build yazi_shared::fs::Schemes.
|
|
||||||
pub fn make(self) -> Result<yazi_shared::fs::Schemes> {
|
|
||||||
yazi_shared::fs::Schemes::from_iter(self.rules.into_iter().map(|s| (s.name, s.typ, s.config)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for Schemes {
|
|
||||||
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
#[derive(Deserialize, Default)]
|
|
||||||
#[serde(default)]
|
|
||||||
struct Outer {
|
|
||||||
schemes: Shadow,
|
|
||||||
}
|
|
||||||
#[derive(Deserialize, Default)]
|
|
||||||
struct Shadow {
|
|
||||||
rules: Vec<Scheme>,
|
|
||||||
}
|
|
||||||
|
|
||||||
let outer = Outer::deserialize(deserializer)?;
|
|
||||||
|
|
||||||
Ok(Self { rules: outer.schemes.rules })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Scheme in configuration file.
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
pub struct Scheme {
|
|
||||||
pub name: String,
|
|
||||||
#[serde(rename = "type")]
|
|
||||||
pub typ: String,
|
|
||||||
pub config: HashMap<String, String>,
|
|
||||||
}
|
|
||||||
|
|
@ -18,6 +18,7 @@ yazi-boot = { path = "../yazi-boot", version = "0.2.5" }
|
||||||
yazi-config = { path = "../yazi-config", version = "0.2.5" }
|
yazi-config = { path = "../yazi-config", version = "0.2.5" }
|
||||||
yazi-core = { path = "../yazi-core", version = "0.2.5" }
|
yazi-core = { path = "../yazi-core", version = "0.2.5" }
|
||||||
yazi-dds = { path = "../yazi-dds", version = "0.2.5" }
|
yazi-dds = { path = "../yazi-dds", version = "0.2.5" }
|
||||||
|
yazi-fs = { path = "../yazi-fs", version = "0.2.5" }
|
||||||
yazi-plugin = { path = "../yazi-plugin", version = "0.2.5" }
|
yazi-plugin = { path = "../yazi-plugin", version = "0.2.5" }
|
||||||
yazi-proxy = { path = "../yazi-proxy", version = "0.2.5" }
|
yazi-proxy = { path = "../yazi-proxy", version = "0.2.5" }
|
||||||
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
||||||
|
|
|
||||||
19
yazi-fs/Cargo.toml
Normal file
19
yazi-fs/Cargo.toml
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
[package]
|
||||||
|
name = "yazi-fs"
|
||||||
|
version = "0.2.5"
|
||||||
|
edition = "2021"
|
||||||
|
license = "MIT"
|
||||||
|
authors = [ "sxyazi <sxyazi@gmail.com>" ]
|
||||||
|
description = "Yazi file system compatibility layer"
|
||||||
|
homepage = "https://yazi-rs.github.io"
|
||||||
|
repository = "https://github.com/sxyazi/yazi"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
||||||
|
|
||||||
|
# External dependencies
|
||||||
|
anyhow = "1.0.86"
|
||||||
|
opendal = "0.47.0"
|
||||||
|
serde = { version = "1.0.203", features = [ "derive" ] }
|
||||||
|
tokio = { version = "1.38.0", features = [ "full" ] }
|
||||||
|
toml = { version = "0.8.14", features = [ "preserve_order" ] }
|
||||||
3
yazi-fs/src/lib.rs
Normal file
3
yazi-fs/src/lib.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#![allow(clippy::option_map_unit_fn)]
|
||||||
|
|
||||||
|
pub mod providers;
|
||||||
7
yazi-fs/src/providers/mod.rs
Normal file
7
yazi-fs/src/providers/mod.rs
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#![allow(clippy::module_inception)]
|
||||||
|
|
||||||
|
mod provider;
|
||||||
|
mod providers;
|
||||||
|
|
||||||
|
pub use provider::*;
|
||||||
|
pub use providers::*;
|
||||||
20
yazi-fs/src/providers/provider.rs
Normal file
20
yazi-fs/src/providers/provider.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
use std::{collections::HashMap, str::FromStr};
|
||||||
|
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct Provider {
|
||||||
|
pub name: String,
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub type_: String,
|
||||||
|
pub config: HashMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Provider> for opendal::Operator {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn try_from(value: Provider) -> Result<Self, Self::Error> {
|
||||||
|
let scheme = opendal::Scheme::from_str(&value.name)?;
|
||||||
|
Ok(opendal::Operator::via_map(scheme, value.config)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
47
yazi-fs/src/providers/providers.rs
Normal file
47
yazi-fs/src/providers/providers.rs
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
use std::{collections::HashMap, ops::Deref};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use serde::{Deserialize, Deserializer};
|
||||||
|
use yazi_shared::Xdg;
|
||||||
|
|
||||||
|
use crate::providers::Provider;
|
||||||
|
|
||||||
|
pub struct Providers(HashMap<String, opendal::Operator>);
|
||||||
|
|
||||||
|
impl Deref for Providers {
|
||||||
|
type Target = HashMap<String, opendal::Operator>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target { &self.0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Providers {
|
||||||
|
fn default() -> Self {
|
||||||
|
let s = std::fs::read_to_string(Xdg::state_dir().join(".secret.toml")).unwrap_or_default();
|
||||||
|
toml::from_str(&s).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for Providers {
|
||||||
|
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
struct Outer {
|
||||||
|
providers: Shadow,
|
||||||
|
}
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
struct Shadow {
|
||||||
|
rules: Vec<Provider>,
|
||||||
|
}
|
||||||
|
|
||||||
|
let outer = Outer::deserialize(deserializer)?;
|
||||||
|
let result: Result<_> =
|
||||||
|
outer.providers.rules.into_iter().map(|p| Ok((p.name.clone(), p.try_into()?))).collect();
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(v) => Ok(Providers(v)),
|
||||||
|
Err(e) => Err(serde::de::Error::custom(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
use std::{cell::Cell, ffi::OsStr, fs::Metadata, ops::{Add, Deref}, time::{Duration, SystemTime}};
|
use std::{cell::Cell, ffi::OsStr, fs::Metadata, ops::Deref};
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::Result;
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
|
|
||||||
use crate::{fs::{Cha, ChaKind, Url, SCHEMES}, theme::IconCache};
|
use crate::{fs::{Cha, ChaKind, Url}, theme::IconCache};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct File {
|
pub struct File {
|
||||||
|
|
@ -23,9 +23,10 @@ impl Deref for File {
|
||||||
impl File {
|
impl File {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn from(url: Url) -> Result<Self> {
|
pub async fn from(url: Url) -> Result<Self> {
|
||||||
if url.is_remote().is_some() {
|
// TODO: refactor this
|
||||||
return Self::from_remote(url).await;
|
// if url.is_remote().is_some() {
|
||||||
}
|
// return Self::from_remote(url).await;
|
||||||
|
// }
|
||||||
|
|
||||||
let meta = fs::symlink_metadata(&url).await?;
|
let meta = fs::symlink_metadata(&url).await?;
|
||||||
Ok(Self::from_meta(url, meta).await)
|
Ok(Self::from_meta(url, meta).await)
|
||||||
|
|
@ -61,37 +62,38 @@ impl File {
|
||||||
Self { url, cha: Cha::from(meta).with_kind(ck), link_to, icon: Default::default() }
|
Self { url, cha: Cha::from(meta).with_kind(ck), link_to, icon: Default::default() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: refactor this
|
||||||
/// Build a new file from remote.
|
/// Build a new file from remote.
|
||||||
pub async fn from_remote(url: Url) -> Result<Self> {
|
// pub async fn from_remote(url: Url) -> Result<Self> {
|
||||||
let scheme = url.is_remote().ok_or(anyhow!("not a remote file"))?;
|
// let scheme = url.is_remote().ok_or(anyhow!("not a remote file"))?;
|
||||||
let op = SCHEMES.get(scheme)?;
|
// let op = SCHEMES.get(scheme)?;
|
||||||
|
|
||||||
let meta = op.stat(&url.as_path().to_string_lossy()).await?;
|
// let meta = op.stat(&url.as_path().to_string_lossy()).await?;
|
||||||
let mut kind = ChaKind::default();
|
// let mut kind = ChaKind::default();
|
||||||
if meta.is_dir() {
|
// if meta.is_dir() {
|
||||||
kind |= ChaKind::DIR;
|
// kind |= ChaKind::DIR;
|
||||||
}
|
// }
|
||||||
let cha = Cha {
|
// let cha = Cha {
|
||||||
kind,
|
// kind,
|
||||||
len: meta.content_length(),
|
// len: meta.content_length(),
|
||||||
accessed: None,
|
// accessed: None,
|
||||||
created: None,
|
// created: None,
|
||||||
modified: meta
|
// modified: meta
|
||||||
.last_modified()
|
// .last_modified()
|
||||||
.map(|v| SystemTime::UNIX_EPOCH.add(Duration::from_micros(v.timestamp_micros() as u64))),
|
// .map(|v| SystemTime::UNIX_EPOCH.add(Duration::from_micros(v.timestamp_micros() as u64))),
|
||||||
// Always return 774 for remote files.
|
// // Always return 774 for remote files.
|
||||||
#[cfg(unix)]
|
// #[cfg(unix)]
|
||||||
permissions: 0774,
|
// permissions: 0774,
|
||||||
// Always return current user for remote files.
|
// // Always return current user for remote files.
|
||||||
#[cfg(unix)]
|
// #[cfg(unix)]
|
||||||
uid: unsafe { libc::getuid().into() },
|
// uid: unsafe { libc::getuid().into() },
|
||||||
// Always return current group for remote files.
|
// // Always return current group for remote files.
|
||||||
#[cfg(unix)]
|
// #[cfg(unix)]
|
||||||
gid: unsafe { libc::getgid().into() },
|
// gid: unsafe { libc::getgid().into() },
|
||||||
};
|
// };
|
||||||
|
|
||||||
Ok(Self { url, cha, link_to: None, icon: Default::default() })
|
// Ok(Self { url, cha, link_to: None, icon: Default::default() })
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_dummy(url: &Url) -> Self { Self { url: url.to_owned(), ..Default::default() } }
|
pub fn from_dummy(url: &Url) -> Self { Self { url: url.to_owned(), ..Default::default() } }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ mod file;
|
||||||
mod fns;
|
mod fns;
|
||||||
mod op;
|
mod op;
|
||||||
mod path;
|
mod path;
|
||||||
mod schemes;
|
|
||||||
mod url;
|
mod url;
|
||||||
|
|
||||||
pub use cha::*;
|
pub use cha::*;
|
||||||
|
|
@ -11,5 +10,4 @@ pub use file::*;
|
||||||
pub use fns::*;
|
pub use fns::*;
|
||||||
pub use op::*;
|
pub use op::*;
|
||||||
pub use path::*;
|
pub use path::*;
|
||||||
pub use schemes::*;
|
|
||||||
pub use url::*;
|
pub use url::*;
|
||||||
|
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
use std::{collections::HashMap, str::FromStr};
|
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
|
||||||
use opendal::Operator;
|
|
||||||
|
|
||||||
use crate::RoCell;
|
|
||||||
|
|
||||||
/// SCHEMES is the read only cell of schemes that already loaded.
|
|
||||||
pub static SCHEMES: RoCell<Schemes> = RoCell::new();
|
|
||||||
|
|
||||||
/// Schemes carries all the schemes defined in the configuration file.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Schemes(HashMap<String, Operator>);
|
|
||||||
|
|
||||||
impl Schemes {
|
|
||||||
/// Build schemes from iterator.
|
|
||||||
pub fn from_iter(
|
|
||||||
iter: impl IntoIterator<Item = (String, String, HashMap<String, String>)>,
|
|
||||||
) -> Result<Self> {
|
|
||||||
let mut schemes = HashMap::new();
|
|
||||||
for (name, typ, config) in iter {
|
|
||||||
let scheme = opendal::Scheme::from_str(&typ)?;
|
|
||||||
let operator = Operator::via_map(scheme, config)?;
|
|
||||||
schemes.insert(name, operator);
|
|
||||||
}
|
|
||||||
Ok(Self(schemes))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get operator by scheme name.
|
|
||||||
pub fn get(&self, scheme: &str) -> Result<Operator> {
|
|
||||||
self.0.get(scheme).cloned().ok_or(anyhow!("storage scheme {scheme} is not configured"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Reference in a new issue