mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
refactor: derive the Into<Opt> trait with procedural macros to avoid bloat (#1742)
This commit is contained in:
parent
dcbe7873cd
commit
064517665d
61 changed files with 360 additions and 266 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
|
@ -3310,6 +3310,7 @@ dependencies = [
|
||||||
"yazi-config",
|
"yazi-config",
|
||||||
"yazi-dds",
|
"yazi-dds",
|
||||||
"yazi-fs",
|
"yazi-fs",
|
||||||
|
"yazi-macro",
|
||||||
"yazi-plugin",
|
"yazi-plugin",
|
||||||
"yazi-proxy",
|
"yazi-proxy",
|
||||||
"yazi-scheduler",
|
"yazi-scheduler",
|
||||||
|
|
@ -3362,6 +3363,7 @@ dependencies = [
|
||||||
"yazi-core",
|
"yazi-core",
|
||||||
"yazi-dds",
|
"yazi-dds",
|
||||||
"yazi-fs",
|
"yazi-fs",
|
||||||
|
"yazi-macro",
|
||||||
"yazi-plugin",
|
"yazi-plugin",
|
||||||
"yazi-proxy",
|
"yazi-proxy",
|
||||||
"yazi-shared",
|
"yazi-shared",
|
||||||
|
|
@ -3381,6 +3383,14 @@ dependencies = [
|
||||||
"yazi-shared",
|
"yazi-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yazi-macro"
|
||||||
|
version = "0.3.3"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.79",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yazi-plugin"
|
name = "yazi-plugin"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ yazi-boot = { path = "../yazi-boot", version = "0.3.3" }
|
||||||
yazi-config = { path = "../yazi-config", version = "0.3.3" }
|
yazi-config = { path = "../yazi-config", version = "0.3.3" }
|
||||||
yazi-dds = { path = "../yazi-dds", version = "0.3.3" }
|
yazi-dds = { path = "../yazi-dds", version = "0.3.3" }
|
||||||
yazi-fs = { path = "../yazi-fs", 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-plugin = { path = "../yazi-plugin", version = "0.3.3" }
|
||||||
yazi-proxy = { path = "../yazi-proxy", version = "0.3.3" }
|
yazi-proxy = { path = "../yazi-proxy", version = "0.3.3" }
|
||||||
yazi-scheduler = { path = "../yazi-scheduler", version = "0.3.3" }
|
yazi-scheduler = { path = "../yazi-scheduler", version = "0.3.3" }
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,15 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Completion {
|
impl Completion {
|
||||||
|
#[yazi_macro::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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn next(&mut self, step: usize) {
|
fn next(&mut self, step: usize) {
|
||||||
let len = self.cands.len();
|
let len = self.cands.len();
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
|
|
@ -38,13 +47,4 @@ impl Completion {
|
||||||
|
|
||||||
render!(old != self.cursor);
|
render!(old != self.cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn arrow(&mut self, opt: impl Into<Opt>) {
|
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
if opt.step > 0 {
|
|
||||||
self.next(opt.step as usize);
|
|
||||||
} else {
|
|
||||||
self.prev(opt.step.unsigned_abs());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,8 @@ impl From<bool> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Completion {
|
impl Completion {
|
||||||
pub fn close(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn close(&mut self, opt: Opt) {
|
||||||
|
|
||||||
if let Some(s) = self.selected().filter(|_| opt.submit) {
|
if let Some(s) = self.selected().filter(|_| opt.submit) {
|
||||||
InputProxy::complete(s, self.ticket);
|
InputProxy::complete(s, self.ticket);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,31 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Completion {
|
impl Completion {
|
||||||
|
#[yazi_macro::command]
|
||||||
|
pub fn show(&mut self, opt: Opt) {
|
||||||
|
if self.ticket != opt.ticket {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !opt.cache.is_empty() {
|
||||||
|
self.caches.insert(opt.cache_name.to_owned(), opt.cache);
|
||||||
|
}
|
||||||
|
let Some(cache) = self.caches.get(&opt.cache_name) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.ticket = opt.ticket;
|
||||||
|
self.cands = Self::match_candidates(&opt.word, cache);
|
||||||
|
if self.cands.is_empty() {
|
||||||
|
return render!(mem::replace(&mut self.visible, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.offset = 0;
|
||||||
|
self.cursor = 0;
|
||||||
|
self.visible = true;
|
||||||
|
render!();
|
||||||
|
}
|
||||||
|
|
||||||
fn match_candidates(word: &str, cache: &[String]) -> Vec<String> {
|
fn match_candidates(word: &str, cache: &[String]) -> Vec<String> {
|
||||||
let smart = !word.bytes().any(|c| c.is_ascii_uppercase());
|
let smart = !word.bytes().any(|c| c.is_ascii_uppercase());
|
||||||
|
|
||||||
|
|
@ -55,29 +80,4 @@ impl Completion {
|
||||||
}
|
}
|
||||||
prefixed.into_iter().map(ToOwned::to_owned).collect()
|
prefixed.into_iter().map(ToOwned::to_owned).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show(&mut self, opt: impl Into<Opt>) {
|
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
if self.ticket != opt.ticket {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !opt.cache.is_empty() {
|
|
||||||
self.caches.insert(opt.cache_name.to_owned(), opt.cache);
|
|
||||||
}
|
|
||||||
let Some(cache) = self.caches.get(&opt.cache_name) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.ticket = opt.ticket;
|
|
||||||
self.cands = Self::match_candidates(&opt.word, cache);
|
|
||||||
if self.cands.is_empty() {
|
|
||||||
return render!(mem::replace(&mut self.visible, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
self.offset = 0;
|
|
||||||
self.cursor = 0;
|
|
||||||
self.visible = true;
|
|
||||||
render!();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Completion {
|
impl Completion {
|
||||||
pub fn trigger(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn trigger(&mut self, opt: Opt) {
|
||||||
if opt.ticket < self.ticket {
|
if opt.ticket < self.ticket {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,15 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Confirm {
|
impl Confirm {
|
||||||
|
#[yazi_macro::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)
|
||||||
|
} else {
|
||||||
|
self.prev(opt.step.unsigned_abs())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn next(&mut self, step: usize, width: u16) {
|
fn next(&mut self, step: usize, width: u16) {
|
||||||
let height = self.list.line_count(width);
|
let height = self.list.line_count(width);
|
||||||
if height == 0 {
|
if height == 0 {
|
||||||
|
|
@ -29,13 +38,4 @@ impl Confirm {
|
||||||
|
|
||||||
render!(old != self.offset);
|
render!(old != self.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn arrow(&mut self, opt: impl Into<Opt>, manager: &Manager) {
|
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
if opt.step > 0 {
|
|
||||||
self.next(opt.step as usize, manager.area(self.position).width)
|
|
||||||
} else {
|
|
||||||
self.prev(opt.step.unsigned_abs())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ impl From<bool> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Confirm {
|
impl Confirm {
|
||||||
pub fn close(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn close(&mut self, opt: Opt) {
|
||||||
if let Some(cb) = self.callback.take() {
|
if let Some(cb) = self.callback.take() {
|
||||||
_ = cb.send(opt.submit);
|
_ = cb.send(opt.submit);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,12 @@ impl From<isize> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Help {
|
impl Help {
|
||||||
#[inline]
|
#[yazi_macro::command]
|
||||||
pub fn arrow(&mut self, opt: impl Into<Opt>) {
|
pub fn arrow(&mut self, opt: Opt) {
|
||||||
let max = self.bindings.len().saturating_sub(1);
|
let max = self.bindings.len().saturating_sub(1);
|
||||||
self.offset = self.offset.min(max);
|
self.offset = self.offset.min(max);
|
||||||
self.cursor = self.cursor.min(max);
|
self.cursor = self.cursor.min(max);
|
||||||
|
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
if opt.step > 0 {
|
if opt.step > 0 {
|
||||||
self.next(opt.step as usize);
|
self.next(opt.step as usize);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,9 @@ impl From<bool> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Input {
|
impl Input {
|
||||||
pub fn backspace(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
|
pub fn backspace(&mut self, opt: Opt) {
|
||||||
let snap = self.snaps.current_mut();
|
let snap = self.snaps.current_mut();
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
if !opt.under && snap.cursor < 1 {
|
if !opt.under && snap.cursor < 1 {
|
||||||
return;
|
return;
|
||||||
} else if opt.under && snap.cursor >= snap.value.len() {
|
} else if opt.under && snap.cursor >= snap.value.len() {
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,8 @@ impl From<bool> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Input {
|
impl Input {
|
||||||
pub fn close(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn close(&mut self, opt: Opt) {
|
||||||
|
|
||||||
if self.completion {
|
if self.completion {
|
||||||
CompletionProxy::close();
|
CompletionProxy::close();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Input {
|
impl Input {
|
||||||
pub fn complete(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn complete(&mut self, opt: Opt) {
|
||||||
if self.ticket != opt.ticket {
|
if self.ticket != opt.ticket {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Input {
|
impl Input {
|
||||||
pub fn delete(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn delete(&mut self, opt: Opt) {
|
||||||
match self.snap().op {
|
match self.snap().op {
|
||||||
InputOp::None => {
|
InputOp::None => {
|
||||||
self.snap_mut().op = InputOp::Delete(opt.cut, opt.insert, self.snap().cursor);
|
self.snap_mut().op = InputOp::Delete(opt.cut, opt.insert, self.snap().cursor);
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,8 @@ impl From<()> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Input {
|
impl Input {
|
||||||
pub fn escape(&mut self, _: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
|
pub fn escape(&mut self, _: Opt) {
|
||||||
let snap = self.snap_mut();
|
let snap = self.snap_mut();
|
||||||
match snap.mode {
|
match snap.mode {
|
||||||
InputMode::Normal if snap.op == InputOp::None => {
|
InputMode::Normal if snap.op == InputOp::None => {
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Input {
|
impl Input {
|
||||||
pub fn forward(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn forward(&mut self, opt: Opt) {
|
||||||
let snap = self.snap();
|
let snap = self.snap();
|
||||||
|
|
||||||
let mut it = snap.value.chars().skip(snap.cursor).enumerate();
|
let mut it = snap.value.chars().skip(snap.cursor).enumerate();
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,8 @@ impl From<bool> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Input {
|
impl Input {
|
||||||
pub fn insert(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
|
pub fn insert(&mut self, opt: Opt) {
|
||||||
let snap = self.snap_mut();
|
let snap = self.snap_mut();
|
||||||
if snap.mode == InputMode::Normal {
|
if snap.mode == InputMode::Normal {
|
||||||
snap.op = InputOp::None;
|
snap.op = InputOp::None;
|
||||||
|
|
@ -23,7 +24,6 @@ impl Input {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
if opt.append {
|
if opt.append {
|
||||||
self.move_(1);
|
self.move_(1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,33 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Input {
|
impl Input {
|
||||||
|
#[yazi_macro::command]
|
||||||
|
pub fn kill(&mut self, opt: Opt) {
|
||||||
|
let snap = self.snap_mut();
|
||||||
|
match opt.kind.as_str() {
|
||||||
|
"all" => self.kill_range(..),
|
||||||
|
"bol" => {
|
||||||
|
let end = snap.idx(snap.cursor).unwrap_or(snap.len());
|
||||||
|
self.kill_range(..end)
|
||||||
|
}
|
||||||
|
"eol" => {
|
||||||
|
let start = snap.idx(snap.cursor).unwrap_or(snap.len());
|
||||||
|
self.kill_range(start..)
|
||||||
|
}
|
||||||
|
"backward" => {
|
||||||
|
let end = snap.idx(snap.cursor).unwrap_or(snap.len());
|
||||||
|
let start = end - Self::find_word_boundary(snap.value[..end].chars().rev());
|
||||||
|
self.kill_range(start..end)
|
||||||
|
}
|
||||||
|
"forward" => {
|
||||||
|
let start = snap.idx(snap.cursor).unwrap_or(snap.len());
|
||||||
|
let end = start + Self::find_word_boundary(snap.value[start..].chars());
|
||||||
|
self.kill_range(start..end)
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn kill_range(&mut self, range: impl RangeBounds<usize>) {
|
fn kill_range(&mut self, range: impl RangeBounds<usize>) {
|
||||||
let snap = self.snap_mut();
|
let snap = self.snap_mut();
|
||||||
snap.cursor = match range.start_bound() {
|
snap.cursor = match range.start_bound() {
|
||||||
|
|
@ -64,32 +91,4 @@ impl Input {
|
||||||
let n = n + count_characters(input.clone().skip(n));
|
let n = n + count_characters(input.clone().skip(n));
|
||||||
input.take(n).fold(0, |acc, c| acc + c.len_utf8())
|
input.take(n).fold(0, |acc, c| acc + c.len_utf8())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kill(&mut self, opt: impl Into<Opt>) {
|
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
let snap = self.snap_mut();
|
|
||||||
|
|
||||||
match opt.kind.as_str() {
|
|
||||||
"all" => self.kill_range(..),
|
|
||||||
"bol" => {
|
|
||||||
let end = snap.idx(snap.cursor).unwrap_or(snap.len());
|
|
||||||
self.kill_range(..end)
|
|
||||||
}
|
|
||||||
"eol" => {
|
|
||||||
let start = snap.idx(snap.cursor).unwrap_or(snap.len());
|
|
||||||
self.kill_range(start..)
|
|
||||||
}
|
|
||||||
"backward" => {
|
|
||||||
let end = snap.idx(snap.cursor).unwrap_or(snap.len());
|
|
||||||
let start = end - Self::find_word_boundary(snap.value[..end].chars().rev());
|
|
||||||
self.kill_range(start..end)
|
|
||||||
}
|
|
||||||
"forward" => {
|
|
||||||
let start = snap.idx(snap.cursor).unwrap_or(snap.len());
|
|
||||||
let end = start + Self::find_word_boundary(snap.value[start..].chars());
|
|
||||||
self.kill_range(start..end)
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,8 @@ impl From<isize> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Input {
|
impl Input {
|
||||||
pub fn move_(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn move_(&mut self, opt: Opt) {
|
||||||
|
|
||||||
let snap = self.snap();
|
let snap = self.snap();
|
||||||
if opt.in_operating && snap.op == InputOp::None {
|
if opt.in_operating && snap.op == InputOp::None {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,8 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Input {
|
impl Input {
|
||||||
pub fn paste(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
|
pub fn paste(&mut self, opt: Opt) {
|
||||||
if let Some(start) = self.snap().op.start() {
|
if let Some(start) = self.snap().op.start() {
|
||||||
self.snap_mut().op = InputOp::Delete(false, false, start);
|
self.snap_mut().op = InputOp::Delete(false, false, start);
|
||||||
self.handle_op(self.snap().cursor, true);
|
self.handle_op(self.snap().cursor, true);
|
||||||
|
|
@ -23,7 +24,6 @@ impl Input {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
self.insert(!opt.before);
|
self.insert(!opt.before);
|
||||||
self.type_str(&s.to_string_lossy());
|
self.type_str(&s.to_string_lossy());
|
||||||
self.escape(());
|
self.escape(());
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
pub fn create(&self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn create(&self, opt: Opt) {
|
||||||
let cwd = self.cwd().to_owned();
|
let cwd = self.cwd().to_owned();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut result = InputProxy::show(InputCfg::create(opt.dir));
|
let mut result = InputProxy::show(InputCfg::create(opt.dir));
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,12 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
pub fn hardlink(&mut self, opt: impl Into<Opt>, tasks: &Tasks) {
|
#[yazi_macro::command]
|
||||||
|
pub fn hardlink(&mut self, opt: Opt, tasks: &Tasks) {
|
||||||
if self.yanked.cut {
|
if self.yanked.cut {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
tasks.file_hardlink(&self.yanked, self.cwd(), opt.force, opt.follow);
|
tasks.file_hardlink(&self.yanked, self.cwd(), opt.force, opt.follow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ impl From<Option<Url>> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
pub fn hover(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn hover(&mut self, opt: Opt) {
|
||||||
if let Some(u) = opt.url {
|
if let Some(u) = opt.url {
|
||||||
self.hover_do(u, opt.tab);
|
self.hover_do(u, opt.tab);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,12 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
pub fn link(&mut self, opt: impl Into<Opt>, tasks: &Tasks) {
|
#[yazi_macro::command]
|
||||||
|
pub fn link(&mut self, opt: Opt, tasks: &Tasks) {
|
||||||
if self.yanked.cut {
|
if self.yanked.cut {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
tasks.file_link(&self.yanked, self.cwd(), opt.relative, opt.force);
|
tasks.file_link(&self.yanked, self.cwd(), opt.relative, opt.force);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,8 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
pub fn open(&mut self, opt: impl Into<Opt>, tasks: &Tasks) {
|
#[yazi_macro::command]
|
||||||
|
pub fn open(&mut self, opt: Opt, tasks: &Tasks) {
|
||||||
if !self.active_mut().try_escape_visual() {
|
if !self.active_mut().try_escape_visual() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -31,7 +32,6 @@ impl Manager {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
let selected =
|
let selected =
|
||||||
if opt.hovered { vec![&hovered] } else { self.selected_or_hovered(true).collect() };
|
if opt.hovered { vec![&hovered] } else { self.selected_or_hovered(true).collect() };
|
||||||
|
|
||||||
|
|
@ -72,8 +72,8 @@ impl Manager {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_do(&mut self, opt: impl Into<OpenDoOpt>, tasks: &Tasks) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as OpenDoOpt;
|
pub fn open_do(&mut self, opt: OpenDoOpt, tasks: &Tasks) {
|
||||||
let targets: Vec<_> = opt
|
let targets: Vec<_> = opt
|
||||||
.targets
|
.targets
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
pub fn paste(&mut self, opt: impl Into<Opt>, tasks: &Tasks) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn paste(&mut self, opt: Opt, tasks: &Tasks) {
|
||||||
let (src, dest) = (self.yanked.iter().collect::<Vec<_>>(), self.cwd());
|
let (src, dest) = (self.yanked.iter().collect::<Vec<_>>(), self.cwd());
|
||||||
|
|
||||||
if self.yanked.cut {
|
if self.yanked.cut {
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,8 @@ impl From<bool> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
pub fn peek(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
|
pub fn peek(&mut self, opt: Opt) {
|
||||||
let Some(hovered) = self.hovered().cloned() else {
|
let Some(hovered) = self.hovered().cloned() else {
|
||||||
return self.active_mut().preview.reset();
|
return self.active_mut().preview.reset();
|
||||||
};
|
};
|
||||||
|
|
@ -40,7 +41,6 @@ impl Manager {
|
||||||
self.active_mut().preview.reset();
|
self.active_mut().preview.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
if matches!(opt.only_if, Some(u) if u != hovered.url) {
|
if matches!(opt.only_if, Some(u) if u != hovered.url) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,9 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
pub fn quit(&self, opt: impl Into<Opt>, tasks: &Tasks) {
|
#[yazi_macro::command]
|
||||||
let opt = EventQuit { no_cwd_file: opt.into().no_cwd_file, ..Default::default() };
|
pub fn quit(&self, opt: Opt, tasks: &Tasks) {
|
||||||
|
let opt = EventQuit { no_cwd_file: opt.no_cwd_file, ..Default::default() };
|
||||||
|
|
||||||
let ongoing = tasks.ongoing().clone();
|
let ongoing = tasks.ongoing().clone();
|
||||||
let (left, left_names) = {
|
let (left, left_names) = {
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,8 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
pub fn remove(&mut self, opt: impl Into<Opt>, tasks: &Tasks) {
|
#[yazi_macro::command]
|
||||||
|
pub fn remove(&mut self, mut opt: Opt, tasks: &Tasks) {
|
||||||
if !self.active_mut().try_escape_visual() {
|
if !self.active_mut().try_escape_visual() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -31,7 +32,6 @@ impl Manager {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut opt = opt.into() as Opt;
|
|
||||||
opt.targets = if opt.hovered {
|
opt.targets = if opt.hovered {
|
||||||
vec![hovered.clone()]
|
vec![hovered.clone()]
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -55,9 +55,8 @@ impl Manager {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_do(&mut self, opt: impl Into<Opt>, tasks: &Tasks) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn remove_do(&mut self, opt: Opt, tasks: &Tasks) {
|
||||||
|
|
||||||
self.tabs.iter_mut().for_each(|t| {
|
self.tabs.iter_mut().for_each(|t| {
|
||||||
t.selected.remove_many(&opt.targets, false);
|
t.selected.remove_many(&opt.targets, false);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
pub fn rename(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
|
pub fn rename(&mut self, opt: Opt) {
|
||||||
if !self.active_mut().try_escape_visual() {
|
if !self.active_mut().try_escape_visual() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -36,7 +37,6 @@ impl Manager {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
if !opt.hovered && !self.active().selected.is_empty() {
|
if !opt.hovered && !self.active().selected.is_empty() {
|
||||||
return self.bulk_rename();
|
return self.bulk_rename();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,8 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
pub fn seek(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
|
pub fn seek(&mut self, opt: Opt) {
|
||||||
let Some(hovered) = self.hovered() else {
|
let Some(hovered) = self.hovered() else {
|
||||||
return self.active_mut().preview.reset();
|
return self.active_mut().preview.reset();
|
||||||
};
|
};
|
||||||
|
|
@ -31,7 +32,6 @@ impl Manager {
|
||||||
return self.active_mut().preview.reset();
|
return self.active_mut().preview.reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
isolate::seek_sync(&previewer.run, hovered.clone(), opt.units);
|
isolate::seek_sync(&previewer.run, hovered.clone(), opt.units);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,8 @@ impl From<usize> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tabs {
|
impl Tabs {
|
||||||
pub fn close(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn close(&mut self, opt: Opt) {
|
||||||
|
|
||||||
let len = self.items.len();
|
let len = self.items.len();
|
||||||
if len < 2 || opt.idx >= len {
|
if len < 2 || opt.idx >= len {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -28,13 +28,13 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tabs {
|
impl Tabs {
|
||||||
pub fn create(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
|
pub fn create(&mut self, opt: Opt) {
|
||||||
if self.items.len() >= MAX_TABS {
|
if self.items.len() >= MAX_TABS {
|
||||||
AppProxy::notify_warn("Too many tabs", "You can only open up to 9 tabs at the same time.");
|
AppProxy::notify_warn("Too many tabs", "You can only open up to 9 tabs at the same time.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
let mut tab = Tab { idx: self.cursor + 1, ..Default::default() };
|
let mut tab = Tab { idx: self.cursor + 1, ..Default::default() };
|
||||||
|
|
||||||
if !opt.current {
|
if !opt.current {
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,9 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tabs {
|
impl Tabs {
|
||||||
pub fn swap(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let idx = self.absolute(opt.into().step);
|
pub fn swap(&mut self, opt: Opt) {
|
||||||
|
let idx = self.absolute(opt.step);
|
||||||
if idx == self.cursor {
|
if idx == self.cursor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tabs {
|
impl Tabs {
|
||||||
pub fn switch(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn switch(&mut self, opt: Opt) {
|
||||||
let idx = if opt.relative {
|
let idx = if opt.relative {
|
||||||
(self.cursor as isize + opt.step).rem_euclid(self.items.len() as isize) as usize
|
(self.cursor as isize + opt.step).rem_euclid(self.items.len() as isize) as usize
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,8 @@ impl From<()> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
pub fn unyank(&mut self, _: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
|
pub fn unyank(&mut self, _: Opt) {
|
||||||
self.yanked.clear();
|
self.yanked.clear();
|
||||||
render!(self.yanked.catchup_revision(false));
|
render!(self.yanked.catchup_revision(false));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,13 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
pub fn yank(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
|
pub fn yank(&mut self, opt: Opt) {
|
||||||
if !self.active_mut().try_escape_visual() {
|
if !self.active_mut().try_escape_visual() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.yanked = Yanked::new(opt.into().cut, self.selected_or_hovered(false).cloned().collect());
|
self.yanked = Yanked::new(opt.cut, self.selected_or_hovered(false).cloned().collect());
|
||||||
render!(self.yanked.catchup_revision(true));
|
render!(self.yanked.catchup_revision(true));
|
||||||
|
|
||||||
self.active_mut().escape_select();
|
self.active_mut().escape_select();
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,11 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Select {
|
impl Select {
|
||||||
|
#[yazi_macro::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()) }
|
||||||
|
}
|
||||||
|
|
||||||
fn next(&mut self, step: usize) {
|
fn next(&mut self, step: usize) {
|
||||||
let len = self.items.len();
|
let len = self.items.len();
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
|
|
@ -38,9 +43,4 @@ impl Select {
|
||||||
|
|
||||||
render!(old != self.cursor);
|
render!(old != self.cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn arrow(&mut self, opt: impl Into<Opt>) {
|
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
if opt.step > 0 { self.next(opt.step as usize) } else { self.prev(opt.step.unsigned_abs()) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ impl From<bool> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Select {
|
impl Select {
|
||||||
pub fn close(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn close(&mut self, opt: Opt) {
|
||||||
if let Some(cb) = self.callback.take() {
|
if let Some(cb) = self.callback.take() {
|
||||||
_ = cb.send(if opt.submit { Ok(self.cursor) } else { Err(anyhow!("canceled")) });
|
_ = cb.send(if opt.submit { Ok(self.cursor) } else { Err(anyhow!("canceled")) });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ impl From<isize> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tab {
|
impl Tab {
|
||||||
pub fn arrow(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn arrow(&mut self, opt: Opt) {
|
||||||
if !self.current.arrow(opt.step) {
|
if !self.current.arrow(opt.step) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,12 @@ impl From<Url> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tab {
|
impl Tab {
|
||||||
pub fn cd(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
|
pub fn cd(&mut self, opt: Opt) {
|
||||||
if !self.try_escape_visual() {
|
if !self.try_escape_visual() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
if opt.interactive {
|
if opt.interactive {
|
||||||
return self.cd_interactive();
|
return self.cd_interactive();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tab {
|
impl Tab {
|
||||||
pub fn copy(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn copy(&mut self, opt: Opt) {
|
||||||
if !self.try_escape_visual() {
|
if !self.try_escape_visual() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,8 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tab {
|
impl Tab {
|
||||||
pub fn escape(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn escape(&mut self, opt: Opt) {
|
||||||
if opt.is_empty() {
|
if opt.is_empty() {
|
||||||
_ = self.escape_find()
|
_ = self.escape_find()
|
||||||
|| self.escape_visual()
|
|| self.escape_visual()
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@ use std::time::Duration;
|
||||||
use tokio::pin;
|
use tokio::pin;
|
||||||
use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream};
|
use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream};
|
||||||
use yazi_config::popup::InputCfg;
|
use yazi_config::popup::InputCfg;
|
||||||
use yazi_fs::{Filter, FilterCase};
|
use yazi_fs::FilterCase;
|
||||||
use yazi_proxy::{InputProxy, ManagerProxy};
|
use yazi_proxy::InputProxy;
|
||||||
use yazi_shared::{Debounce, InputError, Layer, emit, event::Cmd, render};
|
use yazi_shared::{Debounce, InputError, Layer, emit, event::Cmd};
|
||||||
|
|
||||||
use crate::tab::Tab;
|
use crate::tab::Tab;
|
||||||
|
|
||||||
|
|
@ -27,8 +27,8 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tab {
|
impl Tab {
|
||||||
pub fn filter(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn filter(&mut self, opt: Opt) {
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let rx = InputProxy::show(InputCfg::filter());
|
let rx = InputProxy::show(InputCfg::filter());
|
||||||
|
|
||||||
|
|
@ -49,32 +49,4 @@ impl Tab {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn filter_do(&mut self, opt: impl Into<Opt>) {
|
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
|
|
||||||
let filter = if opt.query.is_empty() {
|
|
||||||
None
|
|
||||||
} else if let Ok(f) = Filter::new(&opt.query, opt.case) {
|
|
||||||
Some(f)
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
if opt.done {
|
|
||||||
ManagerProxy::update_paged(); // Update for paged files in next loop
|
|
||||||
}
|
|
||||||
|
|
||||||
let hovered = self.current.hovered().map(|f| f.urn_owned());
|
|
||||||
if !self.current.files.set_filter(filter) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.current.repos(hovered.as_ref().map(|u| u.as_urn()));
|
|
||||||
if self.current.hovered().map(|f| f.urn()) != hovered.as_ref().map(|u| u.as_urn()) {
|
|
||||||
ManagerProxy::hover(None, self.idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
render!();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
35
yazi-core/src/tab/commands/filter_do.rs
Normal file
35
yazi-core/src/tab/commands/filter_do.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
use yazi_fs::Filter;
|
||||||
|
use yazi_proxy::ManagerProxy;
|
||||||
|
use yazi_shared::render;
|
||||||
|
|
||||||
|
use super::filter::Opt;
|
||||||
|
use crate::tab::Tab;
|
||||||
|
|
||||||
|
impl Tab {
|
||||||
|
#[yazi_macro::command]
|
||||||
|
pub fn filter_do(&mut self, opt: Opt) {
|
||||||
|
let filter = if opt.query.is_empty() {
|
||||||
|
None
|
||||||
|
} else if let Ok(f) = Filter::new(&opt.query, opt.case) {
|
||||||
|
Some(f)
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if opt.done {
|
||||||
|
ManagerProxy::update_paged(); // Update for paged files in next loop
|
||||||
|
}
|
||||||
|
|
||||||
|
let hovered = self.current.hovered().map(|f| f.urn_owned());
|
||||||
|
if !self.current.files.set_filter(filter) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.current.repos(hovered.as_ref().map(|u| u.as_urn()));
|
||||||
|
if self.current.hovered().map(|f| f.urn()) != hovered.as_ref().map(|u| u.as_urn()) {
|
||||||
|
ManagerProxy::hover(None, self.idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
render!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,14 +5,14 @@ use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream};
|
||||||
use yazi_config::popup::InputCfg;
|
use yazi_config::popup::InputCfg;
|
||||||
use yazi_fs::FilterCase;
|
use yazi_fs::FilterCase;
|
||||||
use yazi_proxy::InputProxy;
|
use yazi_proxy::InputProxy;
|
||||||
use yazi_shared::{Debounce, InputError, Layer, emit, event::Cmd, render};
|
use yazi_shared::{Debounce, InputError, Layer, emit, event::Cmd};
|
||||||
|
|
||||||
use crate::tab::{Finder, Tab};
|
use crate::tab::Tab;
|
||||||
|
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
query: Option<String>,
|
pub(super) query: Option<String>,
|
||||||
prev: bool,
|
pub(super) prev: bool,
|
||||||
case: FilterCase,
|
pub(super) case: FilterCase,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Cmd> for Opt {
|
impl From<Cmd> for Opt {
|
||||||
|
|
@ -21,17 +21,9 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ArrowOpt {
|
|
||||||
prev: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Cmd> for ArrowOpt {
|
|
||||||
fn from(c: Cmd) -> Self { Self { prev: c.bool("previous") } }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Tab {
|
impl Tab {
|
||||||
pub fn find(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn find(&mut self, opt: Opt) {
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let rx = InputProxy::show(InputCfg::find(opt.prev));
|
let rx = InputProxy::show(InputCfg::find(opt.prev));
|
||||||
|
|
||||||
|
|
@ -49,48 +41,4 @@ impl Tab {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_do(&mut self, opt: impl Into<Opt>) {
|
|
||||||
let opt = opt.into() as Opt;
|
|
||||||
let Some(query) = opt.query else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if query.is_empty() {
|
|
||||||
self.escape_find();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let Ok(finder) = Finder::new(&query, opt.case) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if matches!(&self.finder, Some(f) if f.filter == finder.filter) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let step = if opt.prev {
|
|
||||||
finder.prev(&self.current.files, self.current.cursor, true)
|
|
||||||
} else {
|
|
||||||
finder.next(&self.current.files, self.current.cursor, true)
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(step) = step {
|
|
||||||
self.arrow(step);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.finder = Some(finder);
|
|
||||||
render!();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_arrow(&mut self, opt: impl Into<ArrowOpt>) {
|
|
||||||
let Some(finder) = &mut self.finder else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
render!(finder.catchup(&self.current.files));
|
|
||||||
if opt.into().prev {
|
|
||||||
finder.prev(&self.current.files, self.current.cursor, false).map(|s| self.arrow(s));
|
|
||||||
} else {
|
|
||||||
finder.next(&self.current.files, self.current.cursor, false).map(|s| self.arrow(s));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
27
yazi-core/src/tab/commands/find_arrow.rs
Normal file
27
yazi-core/src/tab/commands/find_arrow.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
use yazi_shared::{event::Cmd, render};
|
||||||
|
|
||||||
|
use crate::tab::Tab;
|
||||||
|
|
||||||
|
pub struct Opt {
|
||||||
|
prev: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Cmd> for Opt {
|
||||||
|
fn from(c: Cmd) -> Self { Self { prev: c.bool("previous") } }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tab {
|
||||||
|
#[yazi_macro::command]
|
||||||
|
pub fn find_arrow(&mut self, opt: Opt) {
|
||||||
|
let Some(finder) = &mut self.finder else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
render!(finder.catchup(&self.current.files));
|
||||||
|
if opt.prev {
|
||||||
|
finder.prev(&self.current.files, self.current.cursor, false).map(|s| self.arrow(s));
|
||||||
|
} else {
|
||||||
|
finder.next(&self.current.files, self.current.cursor, false).map(|s| self.arrow(s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
yazi-core/src/tab/commands/find_do.rs
Normal file
37
yazi-core/src/tab/commands/find_do.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
use yazi_shared::render;
|
||||||
|
|
||||||
|
use super::find::Opt;
|
||||||
|
use crate::tab::{Finder, Tab};
|
||||||
|
|
||||||
|
impl Tab {
|
||||||
|
#[yazi_macro::command]
|
||||||
|
pub fn find_do(&mut self, opt: Opt) {
|
||||||
|
let Some(query) = opt.query else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if query.is_empty() {
|
||||||
|
self.escape_find();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Ok(finder) = Finder::new(&query, opt.case) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if matches!(&self.finder, Some(f) if f.filter == finder.filter) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let step = if opt.prev {
|
||||||
|
finder.prev(&self.current.files, self.current.cursor, true)
|
||||||
|
} else {
|
||||||
|
finder.next(&self.current.files, self.current.cursor, true)
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(step) = step {
|
||||||
|
self.arrow(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.finder = Some(finder);
|
||||||
|
render!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,7 +11,8 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tab {
|
impl Tab {
|
||||||
pub fn leave(&mut self, _: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
|
pub fn leave(&mut self, _: Opt) {
|
||||||
self
|
self
|
||||||
.current
|
.current
|
||||||
.hovered()
|
.hovered()
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,10 @@ mod copy;
|
||||||
mod enter;
|
mod enter;
|
||||||
mod escape;
|
mod escape;
|
||||||
mod filter;
|
mod filter;
|
||||||
|
mod filter_do;
|
||||||
mod find;
|
mod find;
|
||||||
|
mod find_arrow;
|
||||||
|
mod find_do;
|
||||||
mod forward;
|
mod forward;
|
||||||
mod hidden;
|
mod hidden;
|
||||||
mod leave;
|
mod leave;
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,8 @@ impl From<Url> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tab {
|
impl Tab {
|
||||||
pub fn reveal(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn reveal(&mut self, opt: Opt) {
|
||||||
|
|
||||||
let Some(parent) = opt.target.parent_url() else {
|
let Some(parent) = opt.target.parent_url() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ impl<'a> From<Cmd> for Opt<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Tab {
|
impl<'a> Tab {
|
||||||
pub fn select(&mut self, opt: impl Into<Opt<'a>>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn select(&mut self, opt: Opt<'a>) {
|
||||||
let Some(url) = opt.url.or_else(|| self.current.hovered().map(|h| Cow::Borrowed(&h.url)))
|
let Some(url) = opt.url.or_else(|| self.current.hovered().map(|h| Cow::Borrowed(&h.url)))
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,10 @@ impl From<Option<bool>> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tab {
|
impl Tab {
|
||||||
pub fn select_all(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
|
pub fn select_all(&mut self, opt: Opt) {
|
||||||
let iter = self.current.files.iter().map(|f| &f.url);
|
let iter = self.current.files.iter().map(|f| &f.url);
|
||||||
let (removal, addition): (Vec<_>, Vec<_>) = match opt.into().state {
|
let (removal, addition): (Vec<_>, Vec<_>) = match opt.state {
|
||||||
Some(true) => (vec![], iter.collect()),
|
Some(true) => (vec![], iter.collect()),
|
||||||
Some(false) => (iter.collect(), vec![]),
|
Some(false) => (iter.collect(), vec![]),
|
||||||
None => iter.partition(|&u| self.selected.contains_key(u)),
|
None => iter.partition(|&u| self.selected.contains_key(u)),
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,9 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tab {
|
impl Tab {
|
||||||
pub fn visual_mode(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let opt = opt.into() as Opt;
|
pub fn visual_mode(&mut self, opt: Opt) {
|
||||||
let idx = self.current.cursor;
|
let idx = self.current.cursor;
|
||||||
|
|
||||||
if opt.unset {
|
if opt.unset {
|
||||||
self.mode = Mode::Unset(idx, BTreeSet::from([idx]));
|
self.mode = Mode::Unset(idx, BTreeSet::from([idx]));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,10 @@ impl From<isize> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tasks {
|
impl Tasks {
|
||||||
pub fn arrow(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
|
pub fn arrow(&mut self, opt: Opt) {
|
||||||
let old = self.cursor;
|
let old = self.cursor;
|
||||||
if opt.into().step > 0 {
|
if opt.step > 0 {
|
||||||
self.cursor += 1;
|
self.cursor += 1;
|
||||||
} else {
|
} else {
|
||||||
self.cursor = self.cursor.saturating_sub(1);
|
self.cursor = self.cursor.saturating_sub(1);
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,8 @@ impl From<()> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tasks {
|
impl Tasks {
|
||||||
pub fn toggle(&mut self, _: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
|
pub fn toggle(&mut self, _: Opt) {
|
||||||
self.visible = !self.visible;
|
self.visible = !self.visible;
|
||||||
|
|
||||||
if self.visible {
|
if self.visible {
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ yazi-config = { path = "../yazi-config", version = "0.3.3" }
|
||||||
yazi-core = { path = "../yazi-core", version = "0.3.3" }
|
yazi-core = { path = "../yazi-core", version = "0.3.3" }
|
||||||
yazi-dds = { path = "../yazi-dds", version = "0.3.3" }
|
yazi-dds = { path = "../yazi-dds", version = "0.3.3" }
|
||||||
yazi-fs = { path = "../yazi-fs", 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-plugin = { path = "../yazi-plugin", version = "0.3.3" }
|
||||||
yazi-proxy = { path = "../yazi-proxy", version = "0.3.3" }
|
yazi-proxy = { path = "../yazi-proxy", version = "0.3.3" }
|
||||||
yazi-shared = { path = "../yazi-shared", version = "0.3.3" }
|
yazi-shared = { path = "../yazi-shared", version = "0.3.3" }
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,9 @@ impl From<MouseEvent> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
pub(crate) fn mouse(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
let event = (opt.into() as Opt).event;
|
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 };
|
let Some(size) = self.term.as_ref().and_then(|t| t.size().ok()) else { return };
|
||||||
let Ok(evt) = yazi_plugin::bindings::MouseEvent::cast(&LUA, event) else { return };
|
let Ok(evt) = yazi_plugin::bindings::MouseEvent::cast(&LUA, event) else { return };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,8 @@ impl From<()> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
pub(crate) fn resize(&mut self, _: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
|
pub fn resize(&mut self, _: Opt) {
|
||||||
self.cx.manager.active_mut().preview.reset();
|
self.cx.manager.active_mut().preview.reset();
|
||||||
self.render();
|
self.render();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,8 @@ impl From<Cmd> for Opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
pub(crate) fn stop(&mut self, opt: impl Into<Opt>) {
|
#[yazi_macro::command]
|
||||||
|
pub fn stop(&mut self, opt: Opt) {
|
||||||
self.cx.manager.active_mut().preview.reset_image();
|
self.cx.manager.active_mut().preview.reset_image();
|
||||||
|
|
||||||
// We need to destroy the `term` first before stopping the `signals`
|
// We need to destroy the `term` first before stopping the `signals`
|
||||||
|
|
@ -20,6 +21,6 @@ impl App {
|
||||||
// while the app is being suspended.
|
// while the app is being suspended.
|
||||||
self.term = None;
|
self.term = None;
|
||||||
|
|
||||||
self.signals.stop(opt.into().tx);
|
self.signals.stop(opt.tx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
yazi-macro/Cargo.toml
Normal file
17
yazi-macro/Cargo.toml
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
[package]
|
||||||
|
name = "yazi-macro"
|
||||||
|
version = "0.3.3"
|
||||||
|
edition = "2021"
|
||||||
|
license = "MIT"
|
||||||
|
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"
|
||||||
41
yazi-macro/src/lib.rs
Normal file
41
yazi-macro/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()
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue