From ce09ef80023fa36dffbe18d6d9975ca9937e022e Mon Sep 17 00:00:00 2001 From: sxyazi Date: Mon, 7 Oct 2024 22:00:26 +0800 Subject: [PATCH] refactor: derive the `Into` trait with procedural macros to avoid bloat --- Cargo.lock | 10 +++ yazi-core/Cargo.toml | 1 + yazi-core/src/completion/commands/arrow.rs | 18 +++--- yazi-core/src/completion/commands/close.rs | 5 +- yazi-core/src/completion/commands/show.rs | 50 +++++++-------- yazi-core/src/completion/commands/trigger.rs | 4 +- yazi-core/src/confirm/commands/arrow.rs | 18 +++--- yazi-core/src/confirm/commands/close.rs | 4 +- yazi-core/src/help/commands/arrow.rs | 5 +- yazi-core/src/input/commands/backspace.rs | 4 +- yazi-core/src/input/commands/close.rs | 5 +- yazi-core/src/input/commands/complete.rs | 4 +- yazi-core/src/input/commands/delete.rs | 4 +- yazi-core/src/input/commands/escape.rs | 3 +- yazi-core/src/input/commands/forward.rs | 4 +- yazi-core/src/input/commands/insert.rs | 4 +- yazi-core/src/input/commands/kill.rs | 55 ++++++++-------- yazi-core/src/input/commands/move_.rs | 5 +- yazi-core/src/input/commands/paste.rs | 4 +- yazi-core/src/manager/commands/create.rs | 4 +- yazi-core/src/manager/commands/hardlink.rs | 4 +- yazi-core/src/manager/commands/hover.rs | 4 +- yazi-core/src/manager/commands/link.rs | 4 +- yazi-core/src/manager/commands/open.rs | 8 +-- yazi-core/src/manager/commands/paste.rs | 4 +- yazi-core/src/manager/commands/peek.rs | 4 +- yazi-core/src/manager/commands/quit.rs | 5 +- yazi-core/src/manager/commands/remove.rs | 9 ++- yazi-core/src/manager/commands/rename.rs | 4 +- yazi-core/src/manager/commands/seek.rs | 4 +- yazi-core/src/manager/commands/tab_close.rs | 5 +- yazi-core/src/manager/commands/tab_create.rs | 4 +- yazi-core/src/manager/commands/tab_swap.rs | 5 +- yazi-core/src/manager/commands/tab_switch.rs | 4 +- yazi-core/src/manager/commands/unyank.rs | 3 +- yazi-core/src/manager/commands/yank.rs | 5 +- yazi-core/src/select/commands/arrow.rs | 10 +-- yazi-core/src/select/commands/close.rs | 4 +- yazi-core/src/tab/commands/arrow.rs | 4 +- yazi-core/src/tab/commands/cd.rs | 4 +- yazi-core/src/tab/commands/copy.rs | 4 +- yazi-core/src/tab/commands/escape.rs | 4 +- yazi-core/src/tab/commands/filter.rs | 38 ++--------- yazi-core/src/tab/commands/filter_do.rs | 35 +++++++++++ yazi-core/src/tab/commands/find.rs | 66 +++----------------- yazi-core/src/tab/commands/find_arrow.rs | 27 ++++++++ yazi-core/src/tab/commands/find_do.rs | 37 +++++++++++ yazi-core/src/tab/commands/leave.rs | 3 +- yazi-core/src/tab/commands/mod.rs | 3 + yazi-core/src/tab/commands/reveal.rs | 5 +- yazi-core/src/tab/commands/select.rs | 4 +- yazi-core/src/tab/commands/select_all.rs | 5 +- yazi-core/src/tab/commands/visual_mode.rs | 5 +- yazi-core/src/tasks/commands/arrow.rs | 5 +- yazi-core/src/tasks/commands/toggle.rs | 3 +- yazi-fm/Cargo.toml | 1 + yazi-fm/src/app/commands/mouse.rs | 6 +- yazi-fm/src/app/commands/resize.rs | 3 +- yazi-fm/src/app/commands/stop.rs | 5 +- yazi-macro/Cargo.toml | 17 +++++ yazi-macro/src/lib.rs | 41 ++++++++++++ 61 files changed, 360 insertions(+), 266 deletions(-) create mode 100644 yazi-core/src/tab/commands/filter_do.rs create mode 100644 yazi-core/src/tab/commands/find_arrow.rs create mode 100644 yazi-core/src/tab/commands/find_do.rs create mode 100644 yazi-macro/Cargo.toml create mode 100644 yazi-macro/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index a078b2370..7176ad5d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3310,6 +3310,7 @@ dependencies = [ "yazi-config", "yazi-dds", "yazi-fs", + "yazi-macro", "yazi-plugin", "yazi-proxy", "yazi-scheduler", @@ -3362,6 +3363,7 @@ dependencies = [ "yazi-core", "yazi-dds", "yazi-fs", + "yazi-macro", "yazi-plugin", "yazi-proxy", "yazi-shared", @@ -3381,6 +3383,14 @@ dependencies = [ "yazi-shared", ] +[[package]] +name = "yazi-macro" +version = "0.3.3" +dependencies = [ + "quote", + "syn 2.0.79", +] + [[package]] name = "yazi-plugin" version = "0.3.3" diff --git a/yazi-core/Cargo.toml b/yazi-core/Cargo.toml index 335fe3a1b..f0331b6ce 100644 --- a/yazi-core/Cargo.toml +++ b/yazi-core/Cargo.toml @@ -14,6 +14,7 @@ yazi-boot = { path = "../yazi-boot", 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" } diff --git a/yazi-core/src/completion/commands/arrow.rs b/yazi-core/src/completion/commands/arrow.rs index ed11a79d0..78e9894e3 100644 --- a/yazi-core/src/completion/commands/arrow.rs +++ b/yazi-core/src/completion/commands/arrow.rs @@ -11,6 +11,15 @@ impl From for Opt { } 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) { let len = self.cands.len(); if len == 0 { @@ -38,13 +47,4 @@ impl Completion { render!(old != self.cursor); } - - pub fn arrow(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; - if opt.step > 0 { - self.next(opt.step as usize); - } else { - self.prev(opt.step.unsigned_abs()); - } - } } diff --git a/yazi-core/src/completion/commands/close.rs b/yazi-core/src/completion/commands/close.rs index 447e9ef77..476c9125f 100644 --- a/yazi-core/src/completion/commands/close.rs +++ b/yazi-core/src/completion/commands/close.rs @@ -15,9 +15,8 @@ impl From for Opt { } impl Completion { - pub fn close(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; - + #[yazi_macro::command] + pub fn close(&mut self, opt: Opt) { if let Some(s) = self.selected().filter(|_| opt.submit) { InputProxy::complete(s, self.ticket); } diff --git a/yazi-core/src/completion/commands/show.rs b/yazi-core/src/completion/commands/show.rs index 6b0bdd822..e25e8407b 100644 --- a/yazi-core/src/completion/commands/show.rs +++ b/yazi-core/src/completion/commands/show.rs @@ -25,6 +25,31 @@ impl From for Opt { } 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 { let smart = !word.bytes().any(|c| c.is_ascii_uppercase()); @@ -55,29 +80,4 @@ impl Completion { } prefixed.into_iter().map(ToOwned::to_owned).collect() } - - pub fn show(&mut self, opt: impl Into) { - 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!(); - } } diff --git a/yazi-core/src/completion/commands/trigger.rs b/yazi-core/src/completion/commands/trigger.rs index d4976f57f..868211444 100644 --- a/yazi-core/src/completion/commands/trigger.rs +++ b/yazi-core/src/completion/commands/trigger.rs @@ -26,8 +26,8 @@ impl From for Opt { } impl Completion { - pub fn trigger(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; + #[yazi_macro::command] + pub fn trigger(&mut self, opt: Opt) { if opt.ticket < self.ticket { return; } diff --git a/yazi-core/src/confirm/commands/arrow.rs b/yazi-core/src/confirm/commands/arrow.rs index fe5ae8998..1fe6ce968 100644 --- a/yazi-core/src/confirm/commands/arrow.rs +++ b/yazi-core/src/confirm/commands/arrow.rs @@ -11,6 +11,15 @@ impl From for Opt { } 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) { let height = self.list.line_count(width); if height == 0 { @@ -29,13 +38,4 @@ impl Confirm { render!(old != self.offset); } - - pub fn arrow(&mut self, opt: impl Into, 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()) - } - } } diff --git a/yazi-core/src/confirm/commands/close.rs b/yazi-core/src/confirm/commands/close.rs index 665b08ac3..9c6862cd0 100644 --- a/yazi-core/src/confirm/commands/close.rs +++ b/yazi-core/src/confirm/commands/close.rs @@ -14,8 +14,8 @@ impl From for Opt { } impl Confirm { - pub fn close(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; + #[yazi_macro::command] + pub fn close(&mut self, opt: Opt) { if let Some(cb) = self.callback.take() { _ = cb.send(opt.submit); } diff --git a/yazi-core/src/help/commands/arrow.rs b/yazi-core/src/help/commands/arrow.rs index b84f8e302..b8766e3c3 100644 --- a/yazi-core/src/help/commands/arrow.rs +++ b/yazi-core/src/help/commands/arrow.rs @@ -14,13 +14,12 @@ impl From for Opt { } impl Help { - #[inline] - pub fn arrow(&mut self, opt: impl Into) { + #[yazi_macro::command] + pub fn arrow(&mut self, opt: Opt) { let max = self.bindings.len().saturating_sub(1); self.offset = self.offset.min(max); self.cursor = self.cursor.min(max); - let opt = opt.into() as Opt; if opt.step > 0 { self.next(opt.step as usize); } else { diff --git a/yazi-core/src/input/commands/backspace.rs b/yazi-core/src/input/commands/backspace.rs index 2b88ceb7f..e2d2310d0 100644 --- a/yazi-core/src/input/commands/backspace.rs +++ b/yazi-core/src/input/commands/backspace.rs @@ -14,9 +14,9 @@ impl From for Opt { } impl Input { - pub fn backspace(&mut self, opt: impl Into) { + #[yazi_macro::command] + pub fn backspace(&mut self, opt: Opt) { let snap = self.snaps.current_mut(); - let opt = opt.into() as Opt; if !opt.under && snap.cursor < 1 { return; } else if opt.under && snap.cursor >= snap.value.len() { diff --git a/yazi-core/src/input/commands/close.rs b/yazi-core/src/input/commands/close.rs index 52096f97e..eab0e5196 100644 --- a/yazi-core/src/input/commands/close.rs +++ b/yazi-core/src/input/commands/close.rs @@ -15,9 +15,8 @@ impl From for Opt { } impl Input { - pub fn close(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; - + #[yazi_macro::command] + pub fn close(&mut self, opt: Opt) { if self.completion { CompletionProxy::close(); } diff --git a/yazi-core/src/input/commands/complete.rs b/yazi-core/src/input/commands/complete.rs index 8c3704c1d..0b26808bb 100644 --- a/yazi-core/src/input/commands/complete.rs +++ b/yazi-core/src/input/commands/complete.rs @@ -25,8 +25,8 @@ impl From for Opt { } impl Input { - pub fn complete(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; + #[yazi_macro::command] + pub fn complete(&mut self, opt: Opt) { if self.ticket != opt.ticket { return; } diff --git a/yazi-core/src/input/commands/delete.rs b/yazi-core/src/input/commands/delete.rs index a9cae2b2b..a704fae7e 100644 --- a/yazi-core/src/input/commands/delete.rs +++ b/yazi-core/src/input/commands/delete.rs @@ -12,8 +12,8 @@ impl From for Opt { } impl Input { - pub fn delete(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; + #[yazi_macro::command] + pub fn delete(&mut self, opt: Opt) { match self.snap().op { InputOp::None => { self.snap_mut().op = InputOp::Delete(opt.cut, opt.insert, self.snap().cursor); diff --git a/yazi-core/src/input/commands/escape.rs b/yazi-core/src/input/commands/escape.rs index cfd6e91ea..fc60696d6 100644 --- a/yazi-core/src/input/commands/escape.rs +++ b/yazi-core/src/input/commands/escape.rs @@ -13,7 +13,8 @@ impl From<()> for Opt { } impl Input { - pub fn escape(&mut self, _: impl Into) { + #[yazi_macro::command] + pub fn escape(&mut self, _: Opt) { let snap = self.snap_mut(); match snap.mode { InputMode::Normal if snap.op == InputOp::None => { diff --git a/yazi-core/src/input/commands/forward.rs b/yazi-core/src/input/commands/forward.rs index 290b456ef..5a058d902 100644 --- a/yazi-core/src/input/commands/forward.rs +++ b/yazi-core/src/input/commands/forward.rs @@ -11,8 +11,8 @@ impl From for Opt { } impl Input { - pub fn forward(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; + #[yazi_macro::command] + pub fn forward(&mut self, opt: Opt) { let snap = self.snap(); let mut it = snap.value.chars().skip(snap.cursor).enumerate(); diff --git a/yazi-core/src/input/commands/insert.rs b/yazi-core/src/input/commands/insert.rs index 14dd53738..525ed7005 100644 --- a/yazi-core/src/input/commands/insert.rs +++ b/yazi-core/src/input/commands/insert.rs @@ -14,7 +14,8 @@ impl From for Opt { } impl Input { - pub fn insert(&mut self, opt: impl Into) { + #[yazi_macro::command] + pub fn insert(&mut self, opt: Opt) { let snap = self.snap_mut(); if snap.mode == InputMode::Normal { snap.op = InputOp::None; @@ -23,7 +24,6 @@ impl Input { return; } - let opt = opt.into() as Opt; if opt.append { self.move_(1); } diff --git a/yazi-core/src/input/commands/kill.rs b/yazi-core/src/input/commands/kill.rs index 97ac4455f..a4f7fdd1d 100644 --- a/yazi-core/src/input/commands/kill.rs +++ b/yazi-core/src/input/commands/kill.rs @@ -13,6 +13,33 @@ impl From for Opt { } 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) { let snap = self.snap_mut(); snap.cursor = match range.start_bound() { @@ -64,32 +91,4 @@ impl Input { let n = n + count_characters(input.clone().skip(n)); input.take(n).fold(0, |acc, c| acc + c.len_utf8()) } - - pub fn kill(&mut self, opt: impl Into) { - 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) - } - _ => {} - } - } } diff --git a/yazi-core/src/input/commands/move_.rs b/yazi-core/src/input/commands/move_.rs index 092f47c53..9b30a18d8 100644 --- a/yazi-core/src/input/commands/move_.rs +++ b/yazi-core/src/input/commands/move_.rs @@ -21,9 +21,8 @@ impl From for Opt { } impl Input { - pub fn move_(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; - + #[yazi_macro::command] + pub fn move_(&mut self, opt: Opt) { let snap = self.snap(); if opt.in_operating && snap.op == InputOp::None { return; diff --git a/yazi-core/src/input/commands/paste.rs b/yazi-core/src/input/commands/paste.rs index b339b2b27..fb4296b09 100644 --- a/yazi-core/src/input/commands/paste.rs +++ b/yazi-core/src/input/commands/paste.rs @@ -12,7 +12,8 @@ impl From for Opt { } impl Input { - pub fn paste(&mut self, opt: impl Into) { + #[yazi_macro::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); self.handle_op(self.snap().cursor, true); @@ -23,7 +24,6 @@ impl Input { return; } - let opt = opt.into() as Opt; self.insert(!opt.before); self.type_str(&s.to_string_lossy()); self.escape(()); diff --git a/yazi-core/src/manager/commands/create.rs b/yazi-core/src/manager/commands/create.rs index 60f2cc8d3..ac2963b01 100644 --- a/yazi-core/src/manager/commands/create.rs +++ b/yazi-core/src/manager/commands/create.rs @@ -18,8 +18,8 @@ impl From for Opt { } impl Manager { - pub fn create(&self, opt: impl Into) { - let opt = opt.into() as Opt; + #[yazi_macro::command] + pub fn create(&self, opt: Opt) { let cwd = self.cwd().to_owned(); tokio::spawn(async move { let mut result = InputProxy::show(InputCfg::create(opt.dir)); diff --git a/yazi-core/src/manager/commands/hardlink.rs b/yazi-core/src/manager/commands/hardlink.rs index c215deeb2..f2068ee49 100644 --- a/yazi-core/src/manager/commands/hardlink.rs +++ b/yazi-core/src/manager/commands/hardlink.rs @@ -12,12 +12,12 @@ impl From for Opt { } impl Manager { - pub fn hardlink(&mut self, opt: impl Into, tasks: &Tasks) { + #[yazi_macro::command] + pub fn hardlink(&mut self, opt: Opt, tasks: &Tasks) { if self.yanked.cut { return; } - let opt = opt.into() as Opt; tasks.file_hardlink(&self.yanked, self.cwd(), opt.force, opt.follow); } } diff --git a/yazi-core/src/manager/commands/hover.rs b/yazi-core/src/manager/commands/hover.rs index f5cdefcab..a2b1fcdc5 100644 --- a/yazi-core/src/manager/commands/hover.rs +++ b/yazi-core/src/manager/commands/hover.rs @@ -23,8 +23,8 @@ impl From> for Opt { } impl Manager { - pub fn hover(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; + #[yazi_macro::command] + pub fn hover(&mut self, opt: Opt) { if let Some(u) = opt.url { self.hover_do(u, opt.tab); } else { diff --git a/yazi-core/src/manager/commands/link.rs b/yazi-core/src/manager/commands/link.rs index 4a3857b79..6956dbc9b 100644 --- a/yazi-core/src/manager/commands/link.rs +++ b/yazi-core/src/manager/commands/link.rs @@ -12,12 +12,12 @@ impl From for Opt { } impl Manager { - pub fn link(&mut self, opt: impl Into, tasks: &Tasks) { + #[yazi_macro::command] + pub fn link(&mut self, opt: Opt, tasks: &Tasks) { if self.yanked.cut { return; } - let opt = opt.into() as Opt; tasks.file_link(&self.yanked, self.cwd(), opt.relative, opt.force); } } diff --git a/yazi-core/src/manager/commands/open.rs b/yazi-core/src/manager/commands/open.rs index 2d4f78309..fe4c13b6d 100644 --- a/yazi-core/src/manager/commands/open.rs +++ b/yazi-core/src/manager/commands/open.rs @@ -23,7 +23,8 @@ impl From for Opt { } impl Manager { - pub fn open(&mut self, opt: impl Into, tasks: &Tasks) { + #[yazi_macro::command] + pub fn open(&mut self, opt: Opt, tasks: &Tasks) { if !self.active_mut().try_escape_visual() { return; } @@ -31,7 +32,6 @@ impl Manager { return; }; - let opt = opt.into() as Opt; let selected = 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, tasks: &Tasks) { - let opt = opt.into() as OpenDoOpt; + #[yazi_macro::command] + pub fn open_do(&mut self, opt: OpenDoOpt, tasks: &Tasks) { let targets: Vec<_> = opt .targets .into_iter() diff --git a/yazi-core/src/manager/commands/paste.rs b/yazi-core/src/manager/commands/paste.rs index 61a7c6abc..d1c754d88 100644 --- a/yazi-core/src/manager/commands/paste.rs +++ b/yazi-core/src/manager/commands/paste.rs @@ -12,8 +12,8 @@ impl From for Opt { } impl Manager { - pub fn paste(&mut self, opt: impl Into, tasks: &Tasks) { - let opt = opt.into() as Opt; + #[yazi_macro::command] + pub fn paste(&mut self, opt: Opt, tasks: &Tasks) { let (src, dest) = (self.yanked.iter().collect::>(), self.cwd()); if self.yanked.cut { diff --git a/yazi-core/src/manager/commands/peek.rs b/yazi-core/src/manager/commands/peek.rs index 58f50b952..16726e51f 100644 --- a/yazi-core/src/manager/commands/peek.rs +++ b/yazi-core/src/manager/commands/peek.rs @@ -25,7 +25,8 @@ impl From for Opt { } impl Manager { - pub fn peek(&mut self, opt: impl Into) { + #[yazi_macro::command] + pub fn peek(&mut self, opt: Opt) { let Some(hovered) = self.hovered().cloned() else { return self.active_mut().preview.reset(); }; @@ -40,7 +41,6 @@ impl Manager { self.active_mut().preview.reset(); } - let opt = opt.into() as Opt; if matches!(opt.only_if, Some(u) if u != hovered.url) { return; } diff --git a/yazi-core/src/manager/commands/quit.rs b/yazi-core/src/manager/commands/quit.rs index 0442ffbdb..f1280c53a 100644 --- a/yazi-core/src/manager/commands/quit.rs +++ b/yazi-core/src/manager/commands/quit.rs @@ -19,8 +19,9 @@ impl From for Opt { } impl Manager { - pub fn quit(&self, opt: impl Into, tasks: &Tasks) { - let opt = EventQuit { no_cwd_file: opt.into().no_cwd_file, ..Default::default() }; + #[yazi_macro::command] + 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 (left, left_names) = { diff --git a/yazi-core/src/manager/commands/remove.rs b/yazi-core/src/manager/commands/remove.rs index af3837227..c05d74da5 100644 --- a/yazi-core/src/manager/commands/remove.rs +++ b/yazi-core/src/manager/commands/remove.rs @@ -23,7 +23,8 @@ impl From for Opt { } impl Manager { - pub fn remove(&mut self, opt: impl Into, tasks: &Tasks) { + #[yazi_macro::command] + pub fn remove(&mut self, mut opt: Opt, tasks: &Tasks) { if !self.active_mut().try_escape_visual() { return; } @@ -31,7 +32,6 @@ impl Manager { return; }; - let mut opt = opt.into() as Opt; opt.targets = if opt.hovered { vec![hovered.clone()] } else { @@ -55,9 +55,8 @@ impl Manager { }); } - pub fn remove_do(&mut self, opt: impl Into, tasks: &Tasks) { - let opt = opt.into() as Opt; - + #[yazi_macro::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); }); diff --git a/yazi-core/src/manager/commands/rename.rs b/yazi-core/src/manager/commands/rename.rs index 46082b24d..154affc5b 100644 --- a/yazi-core/src/manager/commands/rename.rs +++ b/yazi-core/src/manager/commands/rename.rs @@ -28,7 +28,8 @@ impl From for Opt { } impl Manager { - pub fn rename(&mut self, opt: impl Into) { + #[yazi_macro::command] + pub fn rename(&mut self, opt: Opt) { if !self.active_mut().try_escape_visual() { return; } @@ -36,7 +37,6 @@ impl Manager { return; }; - let opt = opt.into() as Opt; if !opt.hovered && !self.active().selected.is_empty() { return self.bulk_rename(); } diff --git a/yazi-core/src/manager/commands/seek.rs b/yazi-core/src/manager/commands/seek.rs index 13dfe1c81..402f5bc91 100644 --- a/yazi-core/src/manager/commands/seek.rs +++ b/yazi-core/src/manager/commands/seek.rs @@ -14,7 +14,8 @@ impl From for Opt { } impl Manager { - pub fn seek(&mut self, opt: impl Into) { + #[yazi_macro::command] + pub fn seek(&mut self, opt: Opt) { let Some(hovered) = self.hovered() else { return self.active_mut().preview.reset(); }; @@ -31,7 +32,6 @@ impl Manager { return self.active_mut().preview.reset(); }; - let opt = opt.into() as Opt; isolate::seek_sync(&previewer.run, hovered.clone(), opt.units); } } diff --git a/yazi-core/src/manager/commands/tab_close.rs b/yazi-core/src/manager/commands/tab_close.rs index bc0424db3..d05b951a7 100644 --- a/yazi-core/src/manager/commands/tab_close.rs +++ b/yazi-core/src/manager/commands/tab_close.rs @@ -15,9 +15,8 @@ impl From for Opt { } impl Tabs { - pub fn close(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; - + #[yazi_macro::command] + pub fn close(&mut self, opt: Opt) { let len = self.items.len(); if len < 2 || opt.idx >= len { return; diff --git a/yazi-core/src/manager/commands/tab_create.rs b/yazi-core/src/manager/commands/tab_create.rs index 56efc4995..5d2738abf 100644 --- a/yazi-core/src/manager/commands/tab_create.rs +++ b/yazi-core/src/manager/commands/tab_create.rs @@ -28,13 +28,13 @@ impl From for Opt { } impl Tabs { - pub fn create(&mut self, opt: impl Into) { + #[yazi_macro::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."); return; } - let opt = opt.into() as Opt; let mut tab = Tab { idx: self.cursor + 1, ..Default::default() }; if !opt.current { diff --git a/yazi-core/src/manager/commands/tab_swap.rs b/yazi-core/src/manager/commands/tab_swap.rs index 5068980ef..a87144970 100644 --- a/yazi-core/src/manager/commands/tab_swap.rs +++ b/yazi-core/src/manager/commands/tab_swap.rs @@ -11,8 +11,9 @@ impl From for Opt { } impl Tabs { - pub fn swap(&mut self, opt: impl Into) { - let idx = self.absolute(opt.into().step); + #[yazi_macro::command] + pub fn swap(&mut self, opt: Opt) { + let idx = self.absolute(opt.step); if idx == self.cursor { return; } diff --git a/yazi-core/src/manager/commands/tab_switch.rs b/yazi-core/src/manager/commands/tab_switch.rs index b07ee6bd6..a506e3bc0 100644 --- a/yazi-core/src/manager/commands/tab_switch.rs +++ b/yazi-core/src/manager/commands/tab_switch.rs @@ -14,8 +14,8 @@ impl From for Opt { } impl Tabs { - pub fn switch(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; + #[yazi_macro::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 } else { diff --git a/yazi-core/src/manager/commands/unyank.rs b/yazi-core/src/manager/commands/unyank.rs index cc6e2932f..0619ea666 100644 --- a/yazi-core/src/manager/commands/unyank.rs +++ b/yazi-core/src/manager/commands/unyank.rs @@ -12,7 +12,8 @@ impl From<()> for Opt { } impl Manager { - pub fn unyank(&mut self, _: impl Into) { + #[yazi_macro::command] + pub fn unyank(&mut self, _: Opt) { self.yanked.clear(); render!(self.yanked.catchup_revision(false)); } diff --git a/yazi-core/src/manager/commands/yank.rs b/yazi-core/src/manager/commands/yank.rs index acbbbde63..262b915ba 100644 --- a/yazi-core/src/manager/commands/yank.rs +++ b/yazi-core/src/manager/commands/yank.rs @@ -11,12 +11,13 @@ impl From for Opt { } impl Manager { - pub fn yank(&mut self, opt: impl Into) { + #[yazi_macro::command] + pub fn yank(&mut self, opt: Opt) { if !self.active_mut().try_escape_visual() { 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)); self.active_mut().escape_select(); diff --git a/yazi-core/src/select/commands/arrow.rs b/yazi-core/src/select/commands/arrow.rs index 17b1c310d..29570b8ce 100644 --- a/yazi-core/src/select/commands/arrow.rs +++ b/yazi-core/src/select/commands/arrow.rs @@ -11,6 +11,11 @@ impl From for Opt { } 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) { let len = self.items.len(); if len == 0 { @@ -38,9 +43,4 @@ impl Select { render!(old != self.cursor); } - - pub fn arrow(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; - if opt.step > 0 { self.next(opt.step as usize) } else { self.prev(opt.step.unsigned_abs()) } - } } diff --git a/yazi-core/src/select/commands/close.rs b/yazi-core/src/select/commands/close.rs index 69209e141..bb7c43ecc 100644 --- a/yazi-core/src/select/commands/close.rs +++ b/yazi-core/src/select/commands/close.rs @@ -15,8 +15,8 @@ impl From for Opt { } impl Select { - pub fn close(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; + #[yazi_macro::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")) }); } diff --git a/yazi-core/src/tab/commands/arrow.rs b/yazi-core/src/tab/commands/arrow.rs index cd6d3522f..0d76d9bd4 100644 --- a/yazi-core/src/tab/commands/arrow.rs +++ b/yazi-core/src/tab/commands/arrow.rs @@ -25,8 +25,8 @@ impl From for Opt { } impl Tab { - pub fn arrow(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; + #[yazi_macro::command] + pub fn arrow(&mut self, opt: Opt) { if !self.current.arrow(opt.step) { return; } diff --git a/yazi-core/src/tab/commands/cd.rs b/yazi-core/src/tab/commands/cd.rs index bbf8a1a92..667a74847 100644 --- a/yazi-core/src/tab/commands/cd.rs +++ b/yazi-core/src/tab/commands/cd.rs @@ -29,12 +29,12 @@ impl From for Opt { } impl Tab { - pub fn cd(&mut self, opt: impl Into) { + #[yazi_macro::command] + pub fn cd(&mut self, opt: Opt) { if !self.try_escape_visual() { return; } - let opt = opt.into() as Opt; if opt.interactive { return self.cd_interactive(); } diff --git a/yazi-core/src/tab/commands/copy.rs b/yazi-core/src/tab/commands/copy.rs index 9bd4926aa..3effedb00 100644 --- a/yazi-core/src/tab/commands/copy.rs +++ b/yazi-core/src/tab/commands/copy.rs @@ -14,8 +14,8 @@ impl From for Opt { } impl Tab { - pub fn copy(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; + #[yazi_macro::command] + pub fn copy(&mut self, opt: Opt) { if !self.try_escape_visual() { return; } diff --git a/yazi-core/src/tab/commands/escape.rs b/yazi-core/src/tab/commands/escape.rs index bcb30877c..b70358208 100644 --- a/yazi-core/src/tab/commands/escape.rs +++ b/yazi-core/src/tab/commands/escape.rs @@ -31,8 +31,8 @@ impl From for Opt { } impl Tab { - pub fn escape(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; + #[yazi_macro::command] + pub fn escape(&mut self, opt: Opt) { if opt.is_empty() { _ = self.escape_find() || self.escape_visual() diff --git a/yazi-core/src/tab/commands/filter.rs b/yazi-core/src/tab/commands/filter.rs index 5be874bdb..786ecbc84 100644 --- a/yazi-core/src/tab/commands/filter.rs +++ b/yazi-core/src/tab/commands/filter.rs @@ -3,9 +3,9 @@ use std::time::Duration; use tokio::pin; use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream}; use yazi_config::popup::InputCfg; -use yazi_fs::{Filter, FilterCase}; -use yazi_proxy::{InputProxy, ManagerProxy}; -use yazi_shared::{Debounce, InputError, Layer, emit, event::Cmd, render}; +use yazi_fs::FilterCase; +use yazi_proxy::InputProxy; +use yazi_shared::{Debounce, InputError, Layer, emit, event::Cmd}; use crate::tab::Tab; @@ -27,8 +27,8 @@ impl From for Opt { } impl Tab { - pub fn filter(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; + #[yazi_macro::command] + pub fn filter(&mut self, opt: Opt) { tokio::spawn(async move { let rx = InputProxy::show(InputCfg::filter()); @@ -49,32 +49,4 @@ impl Tab { } }); } - - pub fn filter_do(&mut self, opt: impl Into) { - 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!(); - } } diff --git a/yazi-core/src/tab/commands/filter_do.rs b/yazi-core/src/tab/commands/filter_do.rs new file mode 100644 index 000000000..30f7d6097 --- /dev/null +++ b/yazi-core/src/tab/commands/filter_do.rs @@ -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!(); + } +} diff --git a/yazi-core/src/tab/commands/find.rs b/yazi-core/src/tab/commands/find.rs index eab50738c..ded0ed07f 100644 --- a/yazi-core/src/tab/commands/find.rs +++ b/yazi-core/src/tab/commands/find.rs @@ -5,14 +5,14 @@ use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream}; use yazi_config::popup::InputCfg; use yazi_fs::FilterCase; 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 { - query: Option, - prev: bool, - case: FilterCase, + pub(super) query: Option, + pub(super) prev: bool, + pub(super) case: FilterCase, } impl From for Opt { @@ -21,17 +21,9 @@ impl From for Opt { } } -pub struct ArrowOpt { - prev: bool, -} - -impl From for ArrowOpt { - fn from(c: Cmd) -> Self { Self { prev: c.bool("previous") } } -} - impl Tab { - pub fn find(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; + #[yazi_macro::command] + pub fn find(&mut self, opt: Opt) { tokio::spawn(async move { let rx = InputProxy::show(InputCfg::find(opt.prev)); @@ -49,48 +41,4 @@ impl Tab { } }); } - - pub fn find_do(&mut self, opt: impl Into) { - 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) { - 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)); - } - } } diff --git a/yazi-core/src/tab/commands/find_arrow.rs b/yazi-core/src/tab/commands/find_arrow.rs new file mode 100644 index 000000000..51d4f02f0 --- /dev/null +++ b/yazi-core/src/tab/commands/find_arrow.rs @@ -0,0 +1,27 @@ +use yazi_shared::{event::Cmd, render}; + +use crate::tab::Tab; + +pub struct Opt { + prev: bool, +} + +impl From 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)); + } + } +} diff --git a/yazi-core/src/tab/commands/find_do.rs b/yazi-core/src/tab/commands/find_do.rs new file mode 100644 index 000000000..8d8796f4e --- /dev/null +++ b/yazi-core/src/tab/commands/find_do.rs @@ -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!(); + } +} diff --git a/yazi-core/src/tab/commands/leave.rs b/yazi-core/src/tab/commands/leave.rs index bc85887cd..ac7fa4eb9 100644 --- a/yazi-core/src/tab/commands/leave.rs +++ b/yazi-core/src/tab/commands/leave.rs @@ -11,7 +11,8 @@ impl From for Opt { } impl Tab { - pub fn leave(&mut self, _: impl Into) { + #[yazi_macro::command] + pub fn leave(&mut self, _: Opt) { self .current .hovered() diff --git a/yazi-core/src/tab/commands/mod.rs b/yazi-core/src/tab/commands/mod.rs index 87f2fde61..c96ee8730 100644 --- a/yazi-core/src/tab/commands/mod.rs +++ b/yazi-core/src/tab/commands/mod.rs @@ -5,7 +5,10 @@ mod copy; mod enter; mod escape; mod filter; +mod filter_do; mod find; +mod find_arrow; +mod find_do; mod forward; mod hidden; mod leave; diff --git a/yazi-core/src/tab/commands/reveal.rs b/yazi-core/src/tab/commands/reveal.rs index 068509272..4d2aba1c5 100644 --- a/yazi-core/src/tab/commands/reveal.rs +++ b/yazi-core/src/tab/commands/reveal.rs @@ -22,9 +22,8 @@ impl From for Opt { } impl Tab { - pub fn reveal(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; - + #[yazi_macro::command] + pub fn reveal(&mut self, opt: Opt) { let Some(parent) = opt.target.parent_url() else { return; }; diff --git a/yazi-core/src/tab/commands/select.rs b/yazi-core/src/tab/commands/select.rs index 6de81ccff..5eccb2835 100644 --- a/yazi-core/src/tab/commands/select.rs +++ b/yazi-core/src/tab/commands/select.rs @@ -24,8 +24,8 @@ impl<'a> From for Opt<'a> { } impl<'a> Tab { - pub fn select(&mut self, opt: impl Into>) { - let opt = opt.into() as Opt; + #[yazi_macro::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 { return; diff --git a/yazi-core/src/tab/commands/select_all.rs b/yazi-core/src/tab/commands/select_all.rs index 043ff4424..26c8976a5 100644 --- a/yazi-core/src/tab/commands/select_all.rs +++ b/yazi-core/src/tab/commands/select_all.rs @@ -23,9 +23,10 @@ impl From> for Opt { } impl Tab { - pub fn select_all(&mut self, opt: impl Into) { + #[yazi_macro::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.into().state { + let (removal, addition): (Vec<_>, Vec<_>) = match opt.state { Some(true) => (vec![], iter.collect()), Some(false) => (iter.collect(), vec![]), None => iter.partition(|&u| self.selected.contains_key(u)), diff --git a/yazi-core/src/tab/commands/visual_mode.rs b/yazi-core/src/tab/commands/visual_mode.rs index 7e2eb0d28..57e148aa1 100644 --- a/yazi-core/src/tab/commands/visual_mode.rs +++ b/yazi-core/src/tab/commands/visual_mode.rs @@ -13,10 +13,9 @@ impl From for Opt { } impl Tab { - pub fn visual_mode(&mut self, opt: impl Into) { - let opt = opt.into() as Opt; + #[yazi_macro::command] + pub fn visual_mode(&mut self, opt: Opt) { let idx = self.current.cursor; - if opt.unset { self.mode = Mode::Unset(idx, BTreeSet::from([idx])); } else { diff --git a/yazi-core/src/tasks/commands/arrow.rs b/yazi-core/src/tasks/commands/arrow.rs index 8364bae11..efd214907 100644 --- a/yazi-core/src/tasks/commands/arrow.rs +++ b/yazi-core/src/tasks/commands/arrow.rs @@ -15,9 +15,10 @@ impl From for Opt { } impl Tasks { - pub fn arrow(&mut self, opt: impl Into) { + #[yazi_macro::command] + pub fn arrow(&mut self, opt: Opt) { let old = self.cursor; - if opt.into().step > 0 { + if opt.step > 0 { self.cursor += 1; } else { self.cursor = self.cursor.saturating_sub(1); diff --git a/yazi-core/src/tasks/commands/toggle.rs b/yazi-core/src/tasks/commands/toggle.rs index 1ffc9a567..f2d44a8db 100644 --- a/yazi-core/src/tasks/commands/toggle.rs +++ b/yazi-core/src/tasks/commands/toggle.rs @@ -12,7 +12,8 @@ impl From<()> for Opt { } impl Tasks { - pub fn toggle(&mut self, _: impl Into) { + #[yazi_macro::command] + pub fn toggle(&mut self, _: Opt) { self.visible = !self.visible; if self.visible { diff --git a/yazi-fm/Cargo.toml b/yazi-fm/Cargo.toml index cd2da255a..1b2f511db 100644 --- a/yazi-fm/Cargo.toml +++ b/yazi-fm/Cargo.toml @@ -19,6 +19,7 @@ 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" } diff --git a/yazi-fm/src/app/commands/mouse.rs b/yazi-fm/src/app/commands/mouse.rs index ba3ed71ae..528584a92 100644 --- a/yazi-fm/src/app/commands/mouse.rs +++ b/yazi-fm/src/app/commands/mouse.rs @@ -15,9 +15,9 @@ impl From for Opt { } impl App { - pub(crate) fn mouse(&mut self, opt: impl Into) { - let event = (opt.into() as Opt).event; - + #[yazi_macro::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 }; let Ok(evt) = yazi_plugin::bindings::MouseEvent::cast(&LUA, event) else { return }; diff --git a/yazi-fm/src/app/commands/resize.rs b/yazi-fm/src/app/commands/resize.rs index ffcae5b86..1bdabc95f 100644 --- a/yazi-fm/src/app/commands/resize.rs +++ b/yazi-fm/src/app/commands/resize.rs @@ -13,7 +13,8 @@ impl From<()> for Opt { } impl App { - pub(crate) fn resize(&mut self, _: impl Into) { + #[yazi_macro::command] + pub fn resize(&mut self, _: Opt) { self.cx.manager.active_mut().preview.reset(); self.render(); diff --git a/yazi-fm/src/app/commands/stop.rs b/yazi-fm/src/app/commands/stop.rs index 436eec52b..62a0b3121 100644 --- a/yazi-fm/src/app/commands/stop.rs +++ b/yazi-fm/src/app/commands/stop.rs @@ -12,7 +12,8 @@ impl From for Opt { } impl App { - pub(crate) fn stop(&mut self, opt: impl Into) { + #[yazi_macro::command] + pub fn stop(&mut self, opt: Opt) { self.cx.manager.active_mut().preview.reset_image(); // We need to destroy the `term` first before stopping the `signals` @@ -20,6 +21,6 @@ impl App { // while the app is being suspended. self.term = None; - self.signals.stop(opt.into().tx); + self.signals.stop(opt.tx); } } diff --git a/yazi-macro/Cargo.toml b/yazi-macro/Cargo.toml new file mode 100644 index 000000000..25ed4744c --- /dev/null +++ b/yazi-macro/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "yazi-macro" +version = "0.3.3" +edition = "2021" +license = "MIT" +authors = [ "sxyazi " ] +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" diff --git a/yazi-macro/src/lib.rs b/yazi-macro/src/lib.rs new file mode 100644 index 000000000..e1c930bfe --- /dev/null +++ b/yazi-macro/src/lib.rs @@ -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` + 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() +}