mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
fix!: introduce a new btime term to align ctime with Unix
This commit is contained in:
parent
558d97d084
commit
8b47ebf2ce
76 changed files with 285 additions and 240 deletions
17
Cargo.lock
generated
17
Cargo.lock
generated
|
|
@ -3247,6 +3247,14 @@ dependencies = [
|
|||
"yazi-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yazi-codegen"
|
||||
version = "0.3.3"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yazi-config"
|
||||
version = "0.3.3"
|
||||
|
|
@ -3287,10 +3295,10 @@ dependencies = [
|
|||
"unicode-width",
|
||||
"yazi-adapter",
|
||||
"yazi-boot",
|
||||
"yazi-codegen",
|
||||
"yazi-config",
|
||||
"yazi-dds",
|
||||
"yazi-fs",
|
||||
"yazi-macro",
|
||||
"yazi-plugin",
|
||||
"yazi-proxy",
|
||||
"yazi-scheduler",
|
||||
|
|
@ -3339,11 +3347,11 @@ dependencies = [
|
|||
"tracing-subscriber",
|
||||
"yazi-adapter",
|
||||
"yazi-boot",
|
||||
"yazi-codegen",
|
||||
"yazi-config",
|
||||
"yazi-core",
|
||||
"yazi-dds",
|
||||
"yazi-fs",
|
||||
"yazi-macro",
|
||||
"yazi-plugin",
|
||||
"yazi-proxy",
|
||||
"yazi-shared",
|
||||
|
|
@ -3366,10 +3374,6 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "yazi-macro"
|
||||
version = "0.3.3"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yazi-plugin"
|
||||
|
|
@ -3460,6 +3464,7 @@ dependencies = [
|
|||
"tokio",
|
||||
"uzers",
|
||||
"windows-sys 0.59.0",
|
||||
"yazi-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{"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","realname","REPARSE","hardlink","hardlinking","nlink","nlink","linemodes","SIGSTOP","sevenzip","rsplitn","replacen","DECSET","DECRQM","repeek","cwds","tcsi","Hyprland","Wayfire","SWAYSOCK"],"version":"0.2","language":"en","flagWords":[]}
|
||||
{"language":"en","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","realname","REPARSE","hardlink","hardlinking","nlink","nlink","linemodes","SIGSTOP","sevenzip","rsplitn","replacen","DECSET","DECRQM","repeek","cwds","tcsi","Hyprland","Wayfire","SWAYSOCK","btime","nsec","codegen"],"version":"0.2","flagWords":[]}
|
||||
|
|
@ -113,10 +113,11 @@ impl Emulator {
|
|||
}
|
||||
|
||||
let mut term = std::env::var("TERM").unwrap_or_default();
|
||||
let program = std::env::var("TERM_PROGRAM").unwrap_or_default();
|
||||
let mut program = std::env::var("TERM_PROGRAM").unwrap_or_default();
|
||||
|
||||
if *TMUX {
|
||||
term = tmux_env("TERM").unwrap_or(term);
|
||||
program = tmux_env("TERM_PROGRAM").unwrap_or(program);
|
||||
}
|
||||
|
||||
(term, program)
|
||||
|
|
|
|||
17
yazi-codegen/Cargo.toml
Normal file
17
yazi-codegen/Cargo.toml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
[package]
|
||||
name = "yazi-codegen"
|
||||
version = "0.3.3"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = [ "sxyazi <sxyazi@gmail.com>" ]
|
||||
description = "Yazi codegen"
|
||||
homepage = "https://yazi-rs.github.io"
|
||||
repository = "https://github.com/sxyazi/yazi"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
# External dependencies
|
||||
syn = "2.0.79"
|
||||
quote = "1.0.37"
|
||||
41
yazi-codegen/src/lib.rs
Normal file
41
yazi-codegen/src/lib.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
use proc_macro::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{FnArg, ItemFn};
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn command(_: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let mut f: ItemFn = syn::parse(item).unwrap();
|
||||
let mut ins = f.sig.inputs.clone();
|
||||
|
||||
// Turn `opt: Opt` into `opt: impl Into<Opt>`
|
||||
ins[1] = {
|
||||
let FnArg::Typed(opt) = &f.sig.inputs[1] else {
|
||||
panic!("Cannot find the `opt` argument in the function signature.");
|
||||
};
|
||||
|
||||
let opt_ty = &opt.ty;
|
||||
syn::parse2(quote! { opt: impl Into<#opt_ty> }).unwrap()
|
||||
};
|
||||
|
||||
// Make the original function private and add a public wrapper
|
||||
assert!(matches!(f.vis, syn::Visibility::Public(_)));
|
||||
f.vis = syn::Visibility::Inherited;
|
||||
|
||||
// Add `__` prefix to the original function name
|
||||
let name_ori = f.sig.ident;
|
||||
f.sig.ident = format_ident!("__{}", name_ori);
|
||||
let name_new = &f.sig.ident;
|
||||
|
||||
// Collect the rest of the arguments
|
||||
let rest_args = ins.iter().skip(2).map(|arg| match arg {
|
||||
FnArg::Receiver(_) => unreachable!(),
|
||||
FnArg::Typed(t) => &t.pat,
|
||||
});
|
||||
|
||||
quote! {
|
||||
#[inline]
|
||||
pub fn #name_ori(#ins) { self.#name_new(opt.into(), #(#rest_args),*); }
|
||||
#f
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
|
@ -83,7 +83,7 @@ keymap = [
|
|||
# Linemode
|
||||
{ on = [ "m", "s" ], run = "linemode size", desc = "Linemode: size" },
|
||||
{ on = [ "m", "p" ], run = "linemode permissions", desc = "Linemode: permissions" },
|
||||
{ on = [ "m", "c" ], run = "linemode ctime", desc = "Linemode: ctime" },
|
||||
{ on = [ "m", "b" ], run = "linemode btime", desc = "Linemode: btime" },
|
||||
{ on = [ "m", "m" ], run = "linemode mtime", desc = "Linemode: mtime" },
|
||||
{ on = [ "m", "o" ], run = "linemode owner", desc = "Linemode: owner" },
|
||||
{ on = [ "m", "n" ], run = "linemode none", desc = "Linemode: none" },
|
||||
|
|
@ -104,19 +104,19 @@ keymap = [
|
|||
{ on = "N", run = "find_arrow --previous", desc = "Goto the previous found" },
|
||||
|
||||
# Sorting
|
||||
{ on = [ ",", "m" ], run = [ "sort modified --reverse=no", "linemode mtime" ], desc = "Sort by modified time" },
|
||||
{ on = [ ",", "M" ], run = [ "sort modified --reverse", "linemode mtime" ], desc = "Sort by modified time (reverse)" },
|
||||
{ on = [ ",", "c" ], run = [ "sort created --reverse=no", "linemode ctime" ], desc = "Sort by created time" },
|
||||
{ on = [ ",", "C" ], run = [ "sort created --reverse", "linemode ctime" ], desc = "Sort by created time (reverse)" },
|
||||
{ on = [ ",", "e" ], run = "sort extension --reverse=no", desc = "Sort by extension" },
|
||||
{ on = [ ",", "E" ], run = "sort extension --reverse", desc = "Sort by extension (reverse)" },
|
||||
{ on = [ ",", "a" ], run = "sort alphabetical --reverse=no", desc = "Sort alphabetically" },
|
||||
{ on = [ ",", "A" ], run = "sort alphabetical --reverse", desc = "Sort alphabetically (reverse)" },
|
||||
{ on = [ ",", "n" ], run = "sort natural --reverse=no", desc = "Sort naturally" },
|
||||
{ on = [ ",", "N" ], run = "sort natural --reverse", desc = "Sort naturally (reverse)" },
|
||||
{ on = [ ",", "s" ], run = [ "sort size --reverse=no", "linemode size" ], desc = "Sort by size" },
|
||||
{ on = [ ",", "S" ], run = [ "sort size --reverse", "linemode size" ], desc = "Sort by size (reverse)" },
|
||||
{ on = [ ",", "r" ], run = "sort random --reverse=no", desc = "Sort randomly" },
|
||||
{ on = [ ",", "m" ], run = [ "sort mtime --reverse=no", "linemode mtime" ], desc = "Sort by modified time" },
|
||||
{ on = [ ",", "M" ], run = [ "sort mtime --reverse", "linemode mtime" ], desc = "Sort by modified time (reverse)" },
|
||||
{ on = [ ",", "b" ], run = [ "sort btime --reverse=no", "linemode btime" ], desc = "Sort by birth time" },
|
||||
{ on = [ ",", "B" ], run = [ "sort btime --reverse", "linemode btime" ], desc = "Sort by birth time (reverse)" },
|
||||
{ on = [ ",", "e" ], run = "sort extension --reverse=no", desc = "Sort by extension" },
|
||||
{ on = [ ",", "E" ], run = "sort extension --reverse", desc = "Sort by extension (reverse)" },
|
||||
{ on = [ ",", "a" ], run = "sort alphabetical --reverse=no", desc = "Sort alphabetically" },
|
||||
{ on = [ ",", "A" ], run = "sort alphabetical --reverse", desc = "Sort alphabetically (reverse)" },
|
||||
{ on = [ ",", "n" ], run = "sort natural --reverse=no", desc = "Sort naturally" },
|
||||
{ on = [ ",", "N" ], run = "sort natural --reverse", desc = "Sort naturally (reverse)" },
|
||||
{ on = [ ",", "s" ], run = [ "sort size --reverse=no", "linemode size" ], desc = "Sort by size" },
|
||||
{ on = [ ",", "S" ], run = [ "sort size --reverse", "linemode size" ], desc = "Sort by size (reverse)" },
|
||||
{ on = [ ",", "r" ], run = "sort random --reverse=no", desc = "Sort randomly" },
|
||||
|
||||
# Goto
|
||||
{ on = [ "g", "h" ], run = "cd ~", desc = "Go home" },
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ use serde::{Deserialize, Serialize};
|
|||
pub enum SortBy {
|
||||
#[default]
|
||||
None,
|
||||
Modified,
|
||||
Created,
|
||||
Mtime,
|
||||
Btime,
|
||||
Extension,
|
||||
Alphabetical,
|
||||
Natural,
|
||||
|
|
@ -23,8 +23,8 @@ impl FromStr for SortBy {
|
|||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(match s {
|
||||
"none" => Self::None,
|
||||
"modified" => Self::Modified,
|
||||
"created" => Self::Created,
|
||||
"mtime" => Self::Mtime,
|
||||
"btime" => Self::Btime,
|
||||
"extension" => Self::Extension,
|
||||
"alphabetical" => Self::Alphabetical,
|
||||
"natural" => Self::Natural,
|
||||
|
|
@ -45,8 +45,8 @@ impl Display for SortBy {
|
|||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(match self {
|
||||
Self::None => "none",
|
||||
Self::Modified => "modified",
|
||||
Self::Created => "created",
|
||||
Self::Mtime => "mtime",
|
||||
Self::Btime => "btime",
|
||||
Self::Extension => "extension",
|
||||
Self::Alphabetical => "alphabetical",
|
||||
Self::Natural => "natural",
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ repository = "https://github.com/sxyazi/yazi"
|
|||
[dependencies]
|
||||
yazi-adapter = { path = "../yazi-adapter", version = "0.3.3" }
|
||||
yazi-boot = { path = "../yazi-boot", version = "0.3.3" }
|
||||
yazi-codegen = { path = "../yazi-codegen", version = "0.3.3" }
|
||||
yazi-config = { path = "../yazi-config", version = "0.3.3" }
|
||||
yazi-dds = { path = "../yazi-dds", version = "0.3.3" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "0.3.3" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "0.3.3" }
|
||||
yazi-plugin = { path = "../yazi-plugin", version = "0.3.3" }
|
||||
yazi-proxy = { path = "../yazi-proxy", version = "0.3.3" }
|
||||
yazi-scheduler = { path = "../yazi-scheduler", version = "0.3.3" }
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Completion {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn arrow(&mut self, opt: Opt) {
|
||||
if opt.step > 0 {
|
||||
self.next(opt.step as usize);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ impl From<bool> for Opt {
|
|||
}
|
||||
|
||||
impl Completion {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn close(&mut self, opt: Opt) {
|
||||
if let Some(s) = self.selected().filter(|_| opt.submit) {
|
||||
InputProxy::complete(s, self.ticket);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Completion {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn show(&mut self, opt: Opt) {
|
||||
if self.ticket != opt.ticket {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Completion {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn trigger(&mut self, opt: Opt) {
|
||||
if opt.ticket < self.ticket {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Confirm {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn arrow(&mut self, opt: Opt, manager: &Manager) {
|
||||
if opt.step > 0 {
|
||||
self.next(opt.step as usize, manager.area(self.position).width)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ impl From<bool> for Opt {
|
|||
}
|
||||
|
||||
impl Confirm {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn close(&mut self, opt: Opt) {
|
||||
if let Some(cb) = self.callback.take() {
|
||||
_ = cb.send(opt.submit);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ impl From<isize> for Opt {
|
|||
}
|
||||
|
||||
impl Help {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn arrow(&mut self, opt: Opt) {
|
||||
let max = self.bindings.len().saturating_sub(1);
|
||||
self.offset = self.offset.min(max);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ impl From<bool> for Opt {
|
|||
}
|
||||
|
||||
impl Input {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn backspace(&mut self, opt: Opt) {
|
||||
let snap = self.snaps.current_mut();
|
||||
if !opt.under && snap.cursor < 1 {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ impl From<bool> for Opt {
|
|||
}
|
||||
|
||||
impl Input {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn close(&mut self, opt: Opt) {
|
||||
if self.completion {
|
||||
CompletionProxy::close();
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Input {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn complete(&mut self, opt: Opt) {
|
||||
if self.ticket != opt.ticket {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Input {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn delete(&mut self, opt: Opt) {
|
||||
match self.snap().op {
|
||||
InputOp::None => {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ impl From<()> for Opt {
|
|||
}
|
||||
|
||||
impl Input {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn escape(&mut self, _: Opt) {
|
||||
let snap = self.snap_mut();
|
||||
match snap.mode {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Input {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn forward(&mut self, opt: Opt) {
|
||||
let snap = self.snap();
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ impl From<bool> for Opt {
|
|||
}
|
||||
|
||||
impl Input {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn insert(&mut self, opt: Opt) {
|
||||
let snap = self.snap_mut();
|
||||
if snap.mode == InputMode::Normal {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Input {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn kill(&mut self, opt: Opt) {
|
||||
let snap = self.snap_mut();
|
||||
match opt.kind.as_str() {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ impl From<isize> for Opt {
|
|||
}
|
||||
|
||||
impl Input {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn move_(&mut self, opt: Opt) {
|
||||
let snap = self.snap();
|
||||
if opt.in_operating && snap.op == InputOp::None {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Input {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn paste(&mut self, opt: Opt) {
|
||||
if let Some(start) = self.snap().op.start() {
|
||||
self.snap_mut().op = InputOp::Delete(false, false, start);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Manager {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn create(&self, opt: Opt) {
|
||||
let cwd = self.cwd().to_owned();
|
||||
tokio::spawn(async move {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Manager {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn hardlink(&mut self, opt: Opt, tasks: &Tasks) {
|
||||
if self.yanked.cut {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ impl From<Option<Url>> for Opt {
|
|||
}
|
||||
|
||||
impl Manager {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn hover(&mut self, opt: Opt) {
|
||||
if let Some(u) = opt.url {
|
||||
self.hover_do(u, opt.tab);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Manager {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn link(&mut self, opt: Opt, tasks: &Tasks) {
|
||||
if self.yanked.cut {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Manager {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn open(&mut self, opt: Opt, tasks: &Tasks) {
|
||||
if !self.active_mut().try_escape_visual() {
|
||||
return;
|
||||
|
|
@ -72,7 +72,7 @@ impl Manager {
|
|||
});
|
||||
}
|
||||
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn open_do(&mut self, opt: OpenDoOpt, tasks: &Tasks) {
|
||||
let targets: Vec<_> = opt
|
||||
.targets
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Manager {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn paste(&mut self, opt: Opt, tasks: &Tasks) {
|
||||
let (src, dest) = (self.yanked.iter().collect::<Vec<_>>(), self.cwd());
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ impl From<bool> for Opt {
|
|||
}
|
||||
|
||||
impl Manager {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn peek(&mut self, opt: Opt) {
|
||||
let Some(hovered) = self.hovered().cloned() else {
|
||||
return self.active_mut().preview.reset();
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Manager {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn quit(&self, opt: Opt, tasks: &Tasks) {
|
||||
let opt = EventQuit { no_cwd_file: opt.no_cwd_file, ..Default::default() };
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Manager {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn remove(&mut self, mut opt: Opt, tasks: &Tasks) {
|
||||
if !self.active_mut().try_escape_visual() {
|
||||
return;
|
||||
|
|
@ -55,7 +55,7 @@ impl Manager {
|
|||
});
|
||||
}
|
||||
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn remove_do(&mut self, opt: Opt, tasks: &Tasks) {
|
||||
self.tabs.iter_mut().for_each(|t| {
|
||||
t.selected.remove_many(&opt.targets, false);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Manager {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn rename(&mut self, opt: Opt) {
|
||||
if !self.active_mut().try_escape_visual() {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Manager {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn seek(&mut self, opt: Opt) {
|
||||
let Some(hovered) = self.hovered() else {
|
||||
return self.active_mut().preview.reset();
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ impl From<usize> for Opt {
|
|||
}
|
||||
|
||||
impl Tabs {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn close(&mut self, opt: Opt) {
|
||||
let len = self.items.len();
|
||||
if len < 2 || opt.idx >= len {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Tabs {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn create(&mut self, opt: Opt) {
|
||||
if self.items.len() >= MAX_TABS {
|
||||
AppProxy::notify_warn("Too many tabs", "You can only open up to 9 tabs at the same time.");
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Tabs {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn swap(&mut self, opt: Opt) {
|
||||
let idx = self.absolute(opt.step);
|
||||
if idx == self.cursor {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Tabs {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn switch(&mut self, opt: Opt) {
|
||||
let idx = if opt.relative {
|
||||
(self.cursor as isize + opt.step).rem_euclid(self.items.len() as isize) as usize
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ impl From<()> for Opt {
|
|||
}
|
||||
|
||||
impl Manager {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn unyank(&mut self, _: Opt) {
|
||||
self.yanked.clear();
|
||||
render!(self.yanked.catchup_revision(false));
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Manager {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn yank(&mut self, opt: Opt) {
|
||||
if !self.active_mut().try_escape_visual() {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Select {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn arrow(&mut self, opt: Opt) {
|
||||
if opt.step > 0 { self.next(opt.step as usize) } else { self.prev(opt.step.unsigned_abs()) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ impl From<bool> for Opt {
|
|||
}
|
||||
|
||||
impl Select {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn close(&mut self, opt: Opt) {
|
||||
if let Some(cb) = self.callback.take() {
|
||||
_ = cb.send(if opt.submit { Ok(self.cursor) } else { Err(anyhow!("canceled")) });
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ impl From<isize> for Opt {
|
|||
}
|
||||
|
||||
impl Tab {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn arrow(&mut self, opt: Opt) {
|
||||
if !self.current.arrow(opt.step) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ impl From<Url> for Opt {
|
|||
}
|
||||
|
||||
impl Tab {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn cd(&mut self, opt: Opt) {
|
||||
if !self.try_escape_visual() {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Tab {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn copy(&mut self, opt: Opt) {
|
||||
if !self.try_escape_visual() {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Tab {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn escape(&mut self, opt: Opt) {
|
||||
if opt.is_empty() {
|
||||
_ = self.escape_find()
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Tab {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn filter(&mut self, opt: Opt) {
|
||||
tokio::spawn(async move {
|
||||
let rx = InputProxy::show(InputCfg::filter());
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use super::filter::Opt;
|
|||
use crate::tab::Tab;
|
||||
|
||||
impl Tab {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn filter_do(&mut self, opt: Opt) {
|
||||
let filter = if opt.query.is_empty() {
|
||||
None
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Tab {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn find(&mut self, opt: Opt) {
|
||||
tokio::spawn(async move {
|
||||
let rx = InputProxy::show(InputCfg::find(opt.prev));
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Tab {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn find_arrow(&mut self, opt: Opt) {
|
||||
let Some(finder) = &mut self.finder else {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use super::find::Opt;
|
|||
use crate::tab::{Finder, Tab};
|
||||
|
||||
impl Tab {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn find_do(&mut self, opt: Opt) {
|
||||
let Some(query) = opt.query else {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Tab {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn leave(&mut self, _: Opt) {
|
||||
self
|
||||
.current
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ impl From<Url> for Opt {
|
|||
}
|
||||
|
||||
impl Tab {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn reveal(&mut self, opt: Opt) {
|
||||
let Some(parent) = opt.target.parent_url() else {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ impl<'a> From<Cmd> for Opt<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Tab {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn select(&mut self, opt: Opt<'a>) {
|
||||
let Some(url) = opt.url.or_else(|| self.current.hovered().map(|h| Cow::Borrowed(&h.url)))
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ impl From<Option<bool>> for Opt {
|
|||
}
|
||||
|
||||
impl Tab {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn select_all(&mut self, opt: Opt) {
|
||||
let iter = self.current.files.iter().map(|f| &f.url);
|
||||
let (removal, addition): (Vec<_>, Vec<_>) = match opt.state {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl Tab {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn visual_mode(&mut self, opt: Opt) {
|
||||
let idx = self.current.cursor;
|
||||
if opt.unset {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ impl From<isize> for Opt {
|
|||
}
|
||||
|
||||
impl Tasks {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn arrow(&mut self, opt: Opt) {
|
||||
let old = self.cursor;
|
||||
if opt.step > 0 {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ impl From<()> for Opt {
|
|||
}
|
||||
|
||||
impl Tasks {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn toggle(&mut self, _: Opt) {
|
||||
self.visible = !self.visible;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,11 +15,11 @@ vendored-lua = [ "mlua/vendored" ]
|
|||
[dependencies]
|
||||
yazi-adapter = { path = "../yazi-adapter", version = "0.3.3" }
|
||||
yazi-boot = { path = "../yazi-boot", version = "0.3.3" }
|
||||
yazi-codegen = { path = "../yazi-codegen", version = "0.3.3" }
|
||||
yazi-config = { path = "../yazi-config", version = "0.3.3" }
|
||||
yazi-core = { path = "../yazi-core", version = "0.3.3" }
|
||||
yazi-dds = { path = "../yazi-dds", version = "0.3.3" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "0.3.3" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "0.3.3" }
|
||||
yazi-plugin = { path = "../yazi-plugin", version = "0.3.3" }
|
||||
yazi-proxy = { path = "../yazi-proxy", version = "0.3.3" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "0.3.3" }
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ impl From<MouseEvent> for Opt {
|
|||
}
|
||||
|
||||
impl App {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn mouse(&mut self, opt: Opt) {
|
||||
let event = opt.event;
|
||||
let Some(size) = self.term.as_ref().and_then(|t| t.size().ok()) else { return };
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ impl From<()> for Opt {
|
|||
}
|
||||
|
||||
impl App {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn resize(&mut self, _: Opt) {
|
||||
self.cx.manager.active_mut().preview.reset();
|
||||
self.render();
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ impl From<Cmd> for Opt {
|
|||
}
|
||||
|
||||
impl App {
|
||||
#[yazi_macro::command]
|
||||
#[yazi_codegen::command]
|
||||
pub fn stop(&mut self, opt: Opt) {
|
||||
self.cx.manager.active_mut().preview.reset_image();
|
||||
|
||||
|
|
|
|||
|
|
@ -28,12 +28,12 @@ impl FilesSorter {
|
|||
|
||||
match self.by {
|
||||
SortBy::None => {}
|
||||
SortBy::Modified => items.sort_unstable_by(|a, b| {
|
||||
SortBy::Mtime => items.sort_unstable_by(|a, b| {
|
||||
let ord = self.cmp(a.mtime, b.mtime, self.promote(a, b));
|
||||
if ord == Ordering::Equal { by_alphabetical(a, b) } else { ord }
|
||||
}),
|
||||
SortBy::Created => items.sort_unstable_by(|a, b| {
|
||||
let ord = self.cmp(a.ctime, b.ctime, self.promote(a, b));
|
||||
SortBy::Btime => items.sort_unstable_by(|a, b| {
|
||||
let ord = self.cmp(a.btime, b.btime, self.promote(a, b));
|
||||
if ord == Ordering::Equal { by_alphabetical(a, b) } else { ord }
|
||||
}),
|
||||
SortBy::Extension => items.sort_unstable_by(|a, b| {
|
||||
|
|
|
|||
|
|
@ -7,11 +7,3 @@ authors = [ "sxyazi <sxyazi@gmail.com>" ]
|
|||
description = "Yazi macros"
|
||||
homepage = "https://yazi-rs.github.io"
|
||||
repository = "https://github.com/sxyazi/yazi"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
# External dependencies
|
||||
syn = "2.0.79"
|
||||
quote = "1.0.37"
|
||||
|
|
|
|||
|
|
@ -1,41 +1,2 @@
|
|||
use proc_macro::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{FnArg, ItemFn};
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn command(_: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let mut f: ItemFn = syn::parse(item).unwrap();
|
||||
let mut ins = f.sig.inputs.clone();
|
||||
|
||||
// Turn `opt: Opt` into `opt: impl Into<Opt>`
|
||||
ins[1] = {
|
||||
let FnArg::Typed(opt) = &f.sig.inputs[1] else {
|
||||
panic!("Cannot find the `opt` argument in the function signature.");
|
||||
};
|
||||
|
||||
let opt_ty = &opt.ty;
|
||||
syn::parse2(quote! { opt: impl Into<#opt_ty> }).unwrap()
|
||||
};
|
||||
|
||||
// Make the original function private and add a public wrapper
|
||||
assert!(matches!(f.vis, syn::Visibility::Public(_)));
|
||||
f.vis = syn::Visibility::Inherited;
|
||||
|
||||
// Add `__` prefix to the original function name
|
||||
let name_ori = f.sig.ident;
|
||||
f.sig.ident = format_ident!("__{}", name_ori);
|
||||
let name_new = &f.sig.ident;
|
||||
|
||||
// Collect the rest of the arguments
|
||||
let rest_args = ins.iter().skip(2).map(|arg| match arg {
|
||||
FnArg::Receiver(_) => unreachable!(),
|
||||
FnArg::Typed(t) => &t.pat,
|
||||
});
|
||||
|
||||
quote! {
|
||||
#[inline]
|
||||
pub fn #name_ori(#ins) { self.#name_new(opt.into(), #(#rest_args),*); }
|
||||
#f
|
||||
}
|
||||
.into()
|
||||
}
|
||||
mod module;
|
||||
mod platform;
|
||||
|
|
|
|||
9
yazi-macro/src/module.rs
Normal file
9
yazi-macro/src/module.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#[macro_export]
|
||||
macro_rules! mod_use {
|
||||
[ $( $name:ident $(,)? )+ ] => {
|
||||
$(
|
||||
mod $name;
|
||||
pub use $name::*;
|
||||
)+
|
||||
};
|
||||
}
|
||||
13
yazi-macro/src/platform.rs
Normal file
13
yazi-macro/src/platform.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#[macro_export]
|
||||
macro_rules! unix_either {
|
||||
($a:expr, $b:expr) => {{
|
||||
#[cfg(unix)]
|
||||
{
|
||||
$a
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
{
|
||||
$b
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
|
@ -32,8 +32,8 @@ function Linemode:size()
|
|||
end
|
||||
end
|
||||
|
||||
function Linemode:ctime()
|
||||
local time = (self._file.cha.created or 0) // 1
|
||||
function Linemode:btime()
|
||||
local time = math.floor(self._file.cha.btime or 0)
|
||||
if time == 0 then
|
||||
return ui.Line("")
|
||||
elseif os.date("%Y", time) == os.date("%Y") then
|
||||
|
|
@ -44,7 +44,7 @@ function Linemode:ctime()
|
|||
end
|
||||
|
||||
function Linemode:mtime()
|
||||
local time = (self._file.cha.modified or 0) // 1
|
||||
local time = math.floor(self._file.cha.mtime or 0)
|
||||
if time == 0 then
|
||||
return ui.Line("")
|
||||
elseif os.date("%Y", time) == os.date("%Y") then
|
||||
|
|
@ -54,7 +54,7 @@ function Linemode:mtime()
|
|||
end
|
||||
end
|
||||
|
||||
function Linemode:permissions() return ui.Line(self._file.cha:permissions() or "") end
|
||||
function Linemode:permissions() return ui.Line(self._file.cha:perm() or "") end
|
||||
|
||||
function Linemode:owner()
|
||||
local user = self._file.cha.uid and ya.user_name(self._file.cha.uid) or self._file.cha.uid
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ function Status:size()
|
|||
|
||||
local style = self:style()
|
||||
return ui.Line {
|
||||
ui.Span(" " .. ya.readable_size(h:size() or h.cha.length) .. " "):fg(style.bg):bg(THEME.status.separator_style.bg),
|
||||
ui.Span(" " .. ya.readable_size(h:size() or h.cha.len) .. " "):fg(style.bg):bg(THEME.status.separator_style.bg),
|
||||
ui.Span(THEME.status.separator_close):fg(THEME.status.separator_style.fg),
|
||||
}
|
||||
end
|
||||
|
|
@ -72,7 +72,7 @@ function Status:permissions()
|
|||
return ui.Line {}
|
||||
end
|
||||
|
||||
local perm = h.cha:permissions()
|
||||
local perm = h.cha:perm()
|
||||
if not perm then
|
||||
return ui.Line {}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ function M:preload()
|
|||
end
|
||||
|
||||
local cha = fs.cha(cache)
|
||||
if cha and cha.length > 0 then
|
||||
if cha and cha.len > 0 then
|
||||
return 1
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,22 @@ use crate::bindings::Cast;
|
|||
|
||||
pub struct Cha;
|
||||
|
||||
static WARNED: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
|
||||
|
||||
#[inline]
|
||||
fn warn_deprecated() {
|
||||
if !WARNED.swap(true, std::sync::atomic::Ordering::Relaxed) {
|
||||
yazi_proxy::AppProxy::notify(yazi_proxy::options::NotifyOpt {
|
||||
title: "Deprecated API".to_owned(),
|
||||
content: "The `created`, `modified`, `accessed`, `length`, and `permissions` properties of `Cha` have been deprecated.
|
||||
|
||||
Please use the new `btime`, `mtime`, `atime`, `len`, and `perm` instead.".to_string(),
|
||||
level: yazi_proxy::options::NotifyLevel::Warn,
|
||||
timeout: Duration::from_secs(20),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl Cha {
|
||||
pub fn register(lua: &Lua) -> mlua::Result<()> {
|
||||
lua.register_userdata_type::<yazi_shared::fs::Cha>(|reg| {
|
||||
|
|
@ -29,17 +45,21 @@ impl Cha {
|
|||
reg.add_field_method_get("nlink", |_, me| Ok((!me.is_dummy()).then_some(me.nlink)));
|
||||
}
|
||||
|
||||
reg.add_field_method_get("length", |_, me| Ok(me.len));
|
||||
reg.add_field_method_get("created", |_, me| {
|
||||
Ok(me.ctime.and_then(|t| t.duration_since(UNIX_EPOCH).map(|d| d.as_secs_f64()).ok()))
|
||||
});
|
||||
reg.add_field_method_get("modified", |_, me| {
|
||||
Ok(me.mtime.and_then(|t| t.duration_since(UNIX_EPOCH).map(|d| d.as_secs_f64()).ok()))
|
||||
});
|
||||
reg.add_field_method_get("accessed", |_, me| {
|
||||
reg.add_field_method_get("len", |_, me| Ok(me.len));
|
||||
reg.add_field_method_get("atime", |_, me| {
|
||||
Ok(me.atime.and_then(|t| t.duration_since(UNIX_EPOCH).map(|d| d.as_secs_f64()).ok()))
|
||||
});
|
||||
reg.add_method("permissions", |_, _me, ()| {
|
||||
reg.add_field_method_get("btime", |_, me| {
|
||||
Ok(me.btime.and_then(|t| t.duration_since(UNIX_EPOCH).map(|d| d.as_secs_f64()).ok()))
|
||||
});
|
||||
#[cfg(unix)]
|
||||
reg.add_field_method_get("ctime", |_, me| {
|
||||
Ok(me.ctime.and_then(|t| t.duration_since(UNIX_EPOCH).map(|d| d.as_secs_f64()).ok()))
|
||||
});
|
||||
reg.add_field_method_get("mtime", |_, me| {
|
||||
Ok(me.mtime.and_then(|t| t.duration_since(UNIX_EPOCH).map(|d| d.as_secs_f64()).ok()))
|
||||
});
|
||||
reg.add_method("perm", |_, _me, ()| {
|
||||
Ok(
|
||||
#[cfg(unix)]
|
||||
Some(yazi_shared::fs::permissions(_me.perm, _me.is_dummy())),
|
||||
|
|
@ -47,6 +67,35 @@ impl Cha {
|
|||
None::<String>,
|
||||
)
|
||||
});
|
||||
|
||||
// TODO: remove these deprecated properties in the future
|
||||
{
|
||||
reg.add_field_method_get("length", |_, me| {
|
||||
warn_deprecated();
|
||||
Ok(me.len)
|
||||
});
|
||||
reg.add_field_method_get("created", |_, me| {
|
||||
warn_deprecated();
|
||||
Ok(me.btime.and_then(|t| t.duration_since(UNIX_EPOCH).map(|d| d.as_secs_f64()).ok()))
|
||||
});
|
||||
reg.add_field_method_get("modified", |_, me| {
|
||||
warn_deprecated();
|
||||
Ok(me.mtime.and_then(|t| t.duration_since(UNIX_EPOCH).map(|d| d.as_secs_f64()).ok()))
|
||||
});
|
||||
reg.add_field_method_get("accessed", |_, me| {
|
||||
warn_deprecated();
|
||||
Ok(me.atime.and_then(|t| t.duration_since(UNIX_EPOCH).map(|d| d.as_secs_f64()).ok()))
|
||||
});
|
||||
reg.add_method("permissions", |_, _me, ()| {
|
||||
warn_deprecated();
|
||||
Ok(
|
||||
#[cfg(unix)]
|
||||
Some(yazi_shared::fs::permissions(_me.perm, _me.is_dummy())),
|
||||
#[cfg(windows)]
|
||||
None::<String>,
|
||||
)
|
||||
});
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
|
|
@ -72,6 +121,8 @@ impl Cha {
|
|||
kind,
|
||||
len: t.raw_get("len").unwrap_or_default(),
|
||||
atime: parse_time(t.raw_get("atime").ok())?,
|
||||
btime: parse_time(t.raw_get("btime").ok())?,
|
||||
#[cfg(unix)]
|
||||
ctime: parse_time(t.raw_get("ctime").ok())?,
|
||||
mtime: parse_time(t.raw_get("mtime").ok())?,
|
||||
#[cfg(unix)]
|
||||
|
|
|
|||
|
|
@ -27,27 +27,21 @@ impl AppProxy {
|
|||
|
||||
#[inline]
|
||||
pub fn notify_warn(title: &str, content: impl ToString) {
|
||||
emit!(Call(
|
||||
Cmd::new("notify").with_any("option", NotifyOpt {
|
||||
title: title.to_owned(),
|
||||
content: content.to_string(),
|
||||
level: NotifyLevel::Warn,
|
||||
timeout: Duration::from_secs(5),
|
||||
}),
|
||||
Layer::App
|
||||
));
|
||||
Self::notify(NotifyOpt {
|
||||
title: title.to_owned(),
|
||||
content: content.to_string(),
|
||||
level: NotifyLevel::Warn,
|
||||
timeout: Duration::from_secs(5),
|
||||
});
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn notify_error(title: &str, content: impl ToString) {
|
||||
emit!(Call(
|
||||
Cmd::new("notify").with_any("option", NotifyOpt {
|
||||
title: title.to_owned(),
|
||||
content: content.to_string(),
|
||||
level: NotifyLevel::Error,
|
||||
timeout: Duration::from_secs(10),
|
||||
}),
|
||||
Layer::App
|
||||
));
|
||||
Self::notify(NotifyOpt {
|
||||
title: title.to_owned(),
|
||||
content: content.to_string(),
|
||||
level: NotifyLevel::Error,
|
||||
timeout: Duration::from_secs(10),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ repository = "https://github.com/sxyazi/yazi"
|
|||
rust-version = "1.78.0"
|
||||
|
||||
[dependencies]
|
||||
yazi-macro = { path = "../yazi-macro", version = "0.3.3" }
|
||||
|
||||
# External dependencies
|
||||
anyhow = { workspace = true }
|
||||
bitflags = { workspace = true }
|
||||
crossterm = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use std::{fs::{FileType, Metadata}, time::SystemTime};
|
||||
|
||||
use bitflags::bitflags;
|
||||
use yazi_macro::unix_either;
|
||||
|
||||
bitflags! {
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
|
|
@ -20,6 +21,8 @@ pub struct Cha {
|
|||
pub kind: ChaKind,
|
||||
pub len: u64,
|
||||
pub atime: Option<SystemTime>,
|
||||
pub btime: Option<SystemTime>,
|
||||
#[cfg(unix)]
|
||||
pub ctime: Option<SystemTime>,
|
||||
pub mtime: Option<SystemTime>,
|
||||
#[cfg(unix)]
|
||||
|
|
@ -40,11 +43,16 @@ impl From<Metadata> for Cha {
|
|||
}
|
||||
|
||||
Self {
|
||||
kind: ck,
|
||||
len: m.len(),
|
||||
atime: m.accessed().ok(),
|
||||
ctime: m.created().ok(),
|
||||
mtime: m.modified().ok(),
|
||||
kind: ck,
|
||||
len: m.len(),
|
||||
atime: m.accessed().ok(),
|
||||
btime: m.created().ok(),
|
||||
#[cfg(unix)]
|
||||
ctime: {
|
||||
use std::{os::unix::fs::MetadataExt, time::{Duration, UNIX_EPOCH}};
|
||||
UNIX_EPOCH.checked_add(Duration::new(m.ctime() as u64, m.ctime_nsec() as u32))
|
||||
},
|
||||
mtime: m.modified().ok(),
|
||||
|
||||
#[cfg(unix)]
|
||||
perm: {
|
||||
|
|
@ -126,16 +134,12 @@ impl Cha {
|
|||
|
||||
#[inline]
|
||||
pub fn hits(self, c: Self) -> bool {
|
||||
self.len == c.len && self.mtime == c.mtime && self.ctime == c.ctime && self.kind == c.kind && {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
self.perm == c.perm
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
true
|
||||
}
|
||||
}
|
||||
self.len == c.len
|
||||
&& self.mtime == c.mtime
|
||||
&& unix_either!(self.ctime == c.ctime, true)
|
||||
&& self.btime == c.btime
|
||||
&& self.kind == c.kind
|
||||
&& unix_either!(self.perm == c.perm, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -157,73 +161,27 @@ impl Cha {
|
|||
|
||||
#[inline]
|
||||
pub const fn is_block(&self) -> bool {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
self.perm & libc::S_IFMT == libc::S_IFBLK
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
false
|
||||
}
|
||||
unix_either!(self.perm & libc::S_IFMT == libc::S_IFBLK, false)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn is_char(&self) -> bool {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
self.perm & libc::S_IFMT == libc::S_IFCHR
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
false
|
||||
}
|
||||
unix_either!(self.perm & libc::S_IFMT == libc::S_IFCHR, false)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn is_fifo(&self) -> bool {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
self.perm & libc::S_IFMT == libc::S_IFIFO
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
false
|
||||
}
|
||||
unix_either!(self.perm & libc::S_IFMT == libc::S_IFIFO, false)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn is_sock(&self) -> bool {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
self.perm & libc::S_IFMT == libc::S_IFSOCK
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
false
|
||||
}
|
||||
unix_either!(self.perm & libc::S_IFMT == libc::S_IFSOCK, false)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn is_exec(&self) -> bool {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
self.perm & libc::S_IXUSR != 0
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
false
|
||||
}
|
||||
}
|
||||
pub const fn is_exec(&self) -> bool { unix_either!(self.perm & libc::S_IXUSR != 0, false) }
|
||||
|
||||
#[inline]
|
||||
pub const fn is_sticky(&self) -> bool {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
self.perm & libc::S_ISVTX != 0
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
false
|
||||
}
|
||||
}
|
||||
pub const fn is_sticky(&self) -> bool { unix_either!(self.perm & libc::S_ISVTX != 0, false) }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue