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-core",
|
||||
"yazi-dds",
|
||||
"yazi-fs",
|
||||
"yazi-plugin",
|
||||
"yazi-proxy",
|
||||
"yazi-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yazi-fs"
|
||||
version = "0.2.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"opendal",
|
||||
"serde",
|
||||
"tokio",
|
||||
"toml",
|
||||
"yazi-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yazi-plugin"
|
||||
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;
|
||||
pub mod preview;
|
||||
mod priority;
|
||||
pub mod schemes;
|
||||
mod tasks;
|
||||
pub mod theme;
|
||||
mod validation;
|
||||
|
|
@ -23,9 +22,6 @@ pub use layout::*;
|
|||
pub(crate) use pattern::*;
|
||||
pub(crate) use preset::*;
|
||||
pub use priority::*;
|
||||
use yazi_shared::fs::SCHEMES;
|
||||
|
||||
use crate::schemes::Schemes;
|
||||
|
||||
static MERGED_YAZI: RoCell<String> = RoCell::new();
|
||||
static MERGED_KEYMAP: RoCell<String> = RoCell::new();
|
||||
|
|
@ -65,9 +61,5 @@ pub fn init() -> anyhow::Result<()> {
|
|||
SELECT.with(Default::default);
|
||||
WHICH.with(Default::default);
|
||||
|
||||
// Load schemes.
|
||||
let schemes = Schemes::default().make()?;
|
||||
SCHEMES.init(schemes);
|
||||
|
||||
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-core = { path = "../yazi-core", 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-proxy = { path = "../yazi-proxy", 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 crate::{fs::{Cha, ChaKind, Url, SCHEMES}, theme::IconCache};
|
||||
use crate::{fs::{Cha, ChaKind, Url}, theme::IconCache};
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct File {
|
||||
|
|
@ -23,9 +23,10 @@ impl Deref for File {
|
|||
impl File {
|
||||
#[inline]
|
||||
pub async fn from(url: Url) -> Result<Self> {
|
||||
if url.is_remote().is_some() {
|
||||
return Self::from_remote(url).await;
|
||||
}
|
||||
// TODO: refactor this
|
||||
// if url.is_remote().is_some() {
|
||||
// return Self::from_remote(url).await;
|
||||
// }
|
||||
|
||||
let meta = fs::symlink_metadata(&url).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() }
|
||||
}
|
||||
|
||||
// TODO: refactor this
|
||||
/// Build a new file from remote.
|
||||
pub async fn from_remote(url: Url) -> Result<Self> {
|
||||
let scheme = url.is_remote().ok_or(anyhow!("not a remote file"))?;
|
||||
let op = SCHEMES.get(scheme)?;
|
||||
// pub async fn from_remote(url: Url) -> Result<Self> {
|
||||
// let scheme = url.is_remote().ok_or(anyhow!("not a remote file"))?;
|
||||
// let op = SCHEMES.get(scheme)?;
|
||||
|
||||
let meta = op.stat(&url.as_path().to_string_lossy()).await?;
|
||||
let mut kind = ChaKind::default();
|
||||
if meta.is_dir() {
|
||||
kind |= ChaKind::DIR;
|
||||
}
|
||||
let cha = Cha {
|
||||
kind,
|
||||
len: meta.content_length(),
|
||||
accessed: None,
|
||||
created: None,
|
||||
modified: meta
|
||||
.last_modified()
|
||||
.map(|v| SystemTime::UNIX_EPOCH.add(Duration::from_micros(v.timestamp_micros() as u64))),
|
||||
// Always return 774 for remote files.
|
||||
#[cfg(unix)]
|
||||
permissions: 0774,
|
||||
// Always return current user for remote files.
|
||||
#[cfg(unix)]
|
||||
uid: unsafe { libc::getuid().into() },
|
||||
// Always return current group for remote files.
|
||||
#[cfg(unix)]
|
||||
gid: unsafe { libc::getgid().into() },
|
||||
};
|
||||
// let meta = op.stat(&url.as_path().to_string_lossy()).await?;
|
||||
// let mut kind = ChaKind::default();
|
||||
// if meta.is_dir() {
|
||||
// kind |= ChaKind::DIR;
|
||||
// }
|
||||
// let cha = Cha {
|
||||
// kind,
|
||||
// len: meta.content_length(),
|
||||
// accessed: None,
|
||||
// created: None,
|
||||
// modified: meta
|
||||
// .last_modified()
|
||||
// .map(|v| SystemTime::UNIX_EPOCH.add(Duration::from_micros(v.timestamp_micros() as u64))),
|
||||
// // Always return 774 for remote files.
|
||||
// #[cfg(unix)]
|
||||
// permissions: 0774,
|
||||
// // Always return current user for remote files.
|
||||
// #[cfg(unix)]
|
||||
// uid: unsafe { libc::getuid().into() },
|
||||
// // Always return current group for remote files.
|
||||
// #[cfg(unix)]
|
||||
// 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]
|
||||
pub fn from_dummy(url: &Url) -> Self { Self { url: url.to_owned(), ..Default::default() } }
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ mod file;
|
|||
mod fns;
|
||||
mod op;
|
||||
mod path;
|
||||
mod schemes;
|
||||
mod url;
|
||||
|
||||
pub use cha::*;
|
||||
|
|
@ -11,5 +10,4 @@ pub use file::*;
|
|||
pub use fns::*;
|
||||
pub use op::*;
|
||||
pub use path::*;
|
||||
pub use schemes::*;
|
||||
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