Partial refactor

This commit is contained in:
sxyazi 2024-06-14 23:53:20 +08:00
parent d19e9d75fe
commit 4d4a260673
No known key found for this signature in database
14 changed files with 147 additions and 137 deletions

13
Cargo.lock generated
View file

@ -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"

View file

@ -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"}

View file

@ -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(())
}

View file

@ -1,3 +0,0 @@
mod schemes;
pub use schemes::*;

View file

@ -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>,
}

View file

@ -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
View 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
View file

@ -0,0 +1,3 @@
#![allow(clippy::option_map_unit_fn)]
pub mod providers;

View file

@ -0,0 +1,7 @@
#![allow(clippy::module_inception)]
mod provider;
mod providers;
pub use provider::*;
pub use providers::*;

View 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)?)
}
}

View 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)),
}
}
}

View file

@ -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() } }

View file

@ -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::*;

View file

@ -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"))
}
}