From 8ed0def9c6ad0a8f9adca3bc88fc2ba421ce885b Mon Sep 17 00:00:00 2001 From: sxyazi Date: Wed, 17 Apr 2024 16:41:01 +0800 Subject: [PATCH] feat: expand the types supported by the event system --- yazi-config/src/keymap/control.rs | 4 +- yazi-config/src/keymap/run.rs | 28 ++++--- yazi-core/src/completion/commands/arrow.rs | 2 +- yazi-core/src/completion/commands/close.rs | 2 +- yazi-core/src/completion/commands/show.rs | 10 ++- yazi-core/src/completion/commands/trigger.rs | 4 +- yazi-core/src/folder/filter.rs | 2 +- yazi-core/src/help/commands/arrow.rs | 2 +- yazi-core/src/input/commands/backspace.rs | 2 +- yazi-core/src/input/commands/close.rs | 2 +- yazi-core/src/input/commands/complete.rs | 4 +- yazi-core/src/input/commands/delete.rs | 4 +- yazi-core/src/input/commands/forward.rs | 2 +- yazi-core/src/input/commands/insert.rs | 2 +- yazi-core/src/input/commands/kill.rs | 2 +- yazi-core/src/input/commands/move_.rs | 4 +- yazi-core/src/input/commands/paste.rs | 2 +- yazi-core/src/manager/commands/create.rs | 2 +- yazi-core/src/manager/commands/hover.rs | 2 +- yazi-core/src/manager/commands/link.rs | 4 +- yazi-core/src/manager/commands/open.rs | 5 +- yazi-core/src/manager/commands/paste.rs | 4 +- yazi-core/src/manager/commands/peek.rs | 8 +- yazi-core/src/manager/commands/quit.rs | 2 +- yazi-core/src/manager/commands/remove.rs | 4 +- yazi-core/src/manager/commands/rename.rs | 6 +- yazi-core/src/manager/commands/seek.rs | 2 +- yazi-core/src/manager/commands/tab_close.rs | 2 +- yazi-core/src/manager/commands/tab_create.rs | 4 +- yazi-core/src/manager/commands/tab_swap.rs | 2 +- yazi-core/src/manager/commands/tab_switch.rs | 4 +- .../src/manager/commands/update_paged.rs | 4 +- yazi-core/src/manager/commands/yank.rs | 2 +- yazi-core/src/notify/commands/tick.rs | 2 +- yazi-core/src/select/commands/arrow.rs | 2 +- yazi-core/src/select/commands/close.rs | 2 +- yazi-core/src/tab/commands/arrow.rs | 2 +- yazi-core/src/tab/commands/cd.rs | 4 +- yazi-core/src/tab/commands/copy.rs | 2 +- yazi-core/src/tab/commands/escape.rs | 18 +++-- yazi-core/src/tab/commands/filter.rs | 4 +- yazi-core/src/tab/commands/find.rs | 8 +- yazi-core/src/tab/commands/hidden.rs | 4 +- yazi-core/src/tab/commands/jump.rs | 4 +- yazi-core/src/tab/commands/linemode.rs | 2 +- yazi-core/src/tab/commands/reveal.rs | 2 +- yazi-core/src/tab/commands/search.rs | 2 +- yazi-core/src/tab/commands/select.rs | 4 +- yazi-core/src/tab/commands/select_all.rs | 4 +- yazi-core/src/tab/commands/shell.rs | 8 +- yazi-core/src/tab/commands/sort.rs | 12 +-- yazi-core/src/tab/commands/visual_mode.rs | 2 +- yazi-core/src/tasks/commands/arrow.rs | 2 +- yazi-core/src/which/commands/callback.rs | 2 +- yazi-core/src/which/commands/show.rs | 4 +- yazi-fm/src/executor.rs | 2 +- yazi-plugin/src/opt.rs | 6 +- yazi-plugin/src/utils/call.rs | 15 ++-- yazi-shared/src/event/arg.rs | 76 +++++++++++++++++++ yazi-shared/src/event/cmd.rs | 71 ++++++++++------- yazi-shared/src/event/mod.rs | 2 + 61 files changed, 246 insertions(+), 157 deletions(-) create mode 100644 yazi-shared/src/event/arg.rs diff --git a/yazi-config/src/keymap/control.rs b/yazi-config/src/keymap/control.rs index a236e5a0..adbfb626 100644 --- a/yazi-config/src/keymap/control.rs +++ b/yazi-config/src/keymap/control.rs @@ -15,9 +15,7 @@ pub struct Control { impl Control { #[inline] - pub fn to_seq(&self) -> VecDeque { - self.run.iter().map(|e| e.clone_without_data()).collect() - } + pub fn to_seq(&self) -> VecDeque { self.run.iter().map(|c| c.shallow_clone()).collect() } } impl Control { diff --git a/yazi-config/src/keymap/run.rs b/yazi-config/src/keymap/run.rs index c4bdfbeb..f2f6ccd4 100644 --- a/yazi-config/src/keymap/run.rs +++ b/yazi-config/src/keymap/run.rs @@ -1,8 +1,8 @@ -use std::fmt; +use std::{fmt, mem}; use anyhow::{bail, Result}; use serde::{de::{self, Visitor}, Deserializer}; -use yazi_shared::event::Cmd; +use yazi_shared::event::{Arg, Cmd}; pub(super) fn run_deserialize<'de, D>(deserializer: D) -> Result, D::Error> where @@ -11,20 +11,24 @@ where struct RunVisitor; fn parse(s: &str) -> Result { - let s = shell_words::split(s)?; - if s.is_empty() { + let mut args = shell_words::split(s)?; + if args.is_empty() { bail!("`run` cannot be empty"); } - let mut cmd = Cmd { name: s[0].clone(), ..Default::default() }; - for arg in s.into_iter().skip(1) { - if arg.starts_with("--") { - let mut arg = arg.splitn(2, '='); - let key = arg.next().unwrap().trim_start_matches('-'); - let val = arg.next().unwrap_or("").to_string(); - cmd.named.insert(key.to_string(), val); + let mut cmd = Cmd { name: mem::take(&mut args[0]), ..Default::default() }; + for (i, arg) in args.into_iter().skip(1).enumerate() { + if !arg.starts_with("--") { + cmd.args.insert(i.to_string(), Arg::String(arg)); + continue; + } + + let mut parts = arg.splitn(2, '='); + let key = parts.next().unwrap().trim_start_matches('-').to_owned(); + if let Some(val) = parts.next() { + cmd.args.insert(key, Arg::String(val.to_owned())); } else { - cmd.args.push(arg); + cmd.args.insert(key, Arg::Boolean(true)); } } Ok(cmd) diff --git a/yazi-core/src/completion/commands/arrow.rs b/yazi-core/src/completion/commands/arrow.rs index 5598be2d..2aaca25c 100644 --- a/yazi-core/src/completion/commands/arrow.rs +++ b/yazi-core/src/completion/commands/arrow.rs @@ -8,7 +8,7 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { - Self { step: c.take_first().and_then(|s| s.parse().ok()).unwrap_or(0) } + Self { step: c.take_first_str().and_then(|s| s.parse().ok()).unwrap_or(0) } } } diff --git a/yazi-core/src/completion/commands/close.rs b/yazi-core/src/completion/commands/close.rs index a884587a..c3117ba2 100644 --- a/yazi-core/src/completion/commands/close.rs +++ b/yazi-core/src/completion/commands/close.rs @@ -8,7 +8,7 @@ pub struct Opt { } impl From for Opt { - fn from(c: Cmd) -> Self { Self { submit: c.named.contains_key("submit") } } + fn from(c: Cmd) -> Self { Self { submit: c.get_bool("submit") } } } impl Completion { diff --git a/yazi-core/src/completion/commands/show.rs b/yazi-core/src/completion/commands/show.rs index 0ba8a25d..86476b43 100644 --- a/yazi-core/src/completion/commands/show.rs +++ b/yazi-core/src/completion/commands/show.rs @@ -16,10 +16,12 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { Self { - cache: mem::take(&mut c.args), - cache_name: c.take_name("cache-name").unwrap_or_default(), - word: c.take_name("word").unwrap_or_default(), - ticket: c.take_name("ticket").and_then(|v| v.parse().ok()).unwrap_or(0), + // cache: mem::take(&mut c.args), + // TODO: Fix this + cache: vec![], + cache_name: c.take_name_str("cache-name").unwrap_or_default(), + word: c.take_name_str("word").unwrap_or_default(), + ticket: c.take_name_str("ticket").and_then(|v| v.parse().ok()).unwrap_or(0), } } } diff --git a/yazi-core/src/completion/commands/trigger.rs b/yazi-core/src/completion/commands/trigger.rs index d3d7054f..ab46984a 100644 --- a/yazi-core/src/completion/commands/trigger.rs +++ b/yazi-core/src/completion/commands/trigger.rs @@ -19,8 +19,8 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { Self { - word: c.take_first().unwrap_or_default(), - ticket: c.take_name("ticket").and_then(|s| s.parse().ok()).unwrap_or(0), + word: c.take_first_str().unwrap_or_default(), + ticket: c.take_name_str("ticket").and_then(|s| s.parse().ok()).unwrap_or(0), } } } diff --git a/yazi-core/src/folder/filter.rs b/yazi-core/src/folder/filter.rs index 61d909e5..0c40bf89 100644 --- a/yazi-core/src/folder/filter.rs +++ b/yazi-core/src/folder/filter.rs @@ -45,7 +45,7 @@ pub enum FilterCase { impl From<&Cmd> for FilterCase { fn from(c: &Cmd) -> Self { - match (c.named.contains_key("smart"), c.named.contains_key("insensitive")) { + match (c.get_bool("smart"), c.get_bool("insensitive")) { (true, _) => Self::Smart, (_, false) => Self::Sensitive, (_, true) => Self::Insensitive, diff --git a/yazi-core/src/help/commands/arrow.rs b/yazi-core/src/help/commands/arrow.rs index 8cef1f11..bd98a156 100644 --- a/yazi-core/src/help/commands/arrow.rs +++ b/yazi-core/src/help/commands/arrow.rs @@ -8,7 +8,7 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { - Self { step: c.take_first().and_then(|s| s.parse().ok()).unwrap_or(0) } + Self { step: c.take_first_str().and_then(|s| s.parse().ok()).unwrap_or(0) } } } impl From for Opt { diff --git a/yazi-core/src/input/commands/backspace.rs b/yazi-core/src/input/commands/backspace.rs index 3796771f..5377529a 100644 --- a/yazi-core/src/input/commands/backspace.rs +++ b/yazi-core/src/input/commands/backspace.rs @@ -7,7 +7,7 @@ pub struct Opt { } impl From for Opt { - fn from(c: Cmd) -> Self { Self { under: c.named.contains_key("under") } } + fn from(c: Cmd) -> Self { Self { under: c.get_bool("under") } } } impl From for Opt { fn from(under: bool) -> Self { Self { under } } diff --git a/yazi-core/src/input/commands/close.rs b/yazi-core/src/input/commands/close.rs index 38e6c215..c27927b3 100644 --- a/yazi-core/src/input/commands/close.rs +++ b/yazi-core/src/input/commands/close.rs @@ -8,7 +8,7 @@ pub struct Opt { } impl From for Opt { - fn from(c: Cmd) -> Self { Self { submit: c.named.contains_key("submit") } } + fn from(c: Cmd) -> Self { Self { submit: c.get_bool("submit") } } } impl From for Opt { fn from(submit: bool) -> Self { Self { submit } } diff --git a/yazi-core/src/input/commands/complete.rs b/yazi-core/src/input/commands/complete.rs index a14a30fc..82c592c4 100644 --- a/yazi-core/src/input/commands/complete.rs +++ b/yazi-core/src/input/commands/complete.rs @@ -18,8 +18,8 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { Self { - word: c.take_first().unwrap_or_default(), - ticket: c.take_name("ticket").and_then(|s| s.parse().ok()).unwrap_or(0), + word: c.take_first_str().unwrap_or_default(), + ticket: c.take_name_str("ticket").and_then(|s| s.parse().ok()).unwrap_or(0), } } } diff --git a/yazi-core/src/input/commands/delete.rs b/yazi-core/src/input/commands/delete.rs index 415df466..367bd7d3 100644 --- a/yazi-core/src/input/commands/delete.rs +++ b/yazi-core/src/input/commands/delete.rs @@ -8,9 +8,7 @@ pub struct Opt { } impl From for Opt { - fn from(c: Cmd) -> Self { - Self { cut: c.named.contains_key("cut"), insert: c.named.contains_key("insert") } - } + fn from(c: Cmd) -> Self { Self { cut: c.get_bool("cut"), insert: c.get_bool("insert") } } } impl Input { diff --git a/yazi-core/src/input/commands/forward.rs b/yazi-core/src/input/commands/forward.rs index 339c2177..44514a89 100644 --- a/yazi-core/src/input/commands/forward.rs +++ b/yazi-core/src/input/commands/forward.rs @@ -7,7 +7,7 @@ pub struct Opt { } impl From for Opt { - fn from(c: Cmd) -> Self { Self { end_of_word: c.named.contains_key("end-of-word") } } + fn from(c: Cmd) -> Self { Self { end_of_word: c.get_bool("end-of-word") } } } impl Input { diff --git a/yazi-core/src/input/commands/insert.rs b/yazi-core/src/input/commands/insert.rs index c5289b65..28d860e8 100644 --- a/yazi-core/src/input/commands/insert.rs +++ b/yazi-core/src/input/commands/insert.rs @@ -7,7 +7,7 @@ pub struct Opt { } impl From for Opt { - fn from(c: Cmd) -> Self { Self { append: c.named.contains_key("append") } } + fn from(c: Cmd) -> Self { Self { append: c.get_bool("append") } } } impl From for Opt { fn from(append: bool) -> Self { Self { append } } diff --git a/yazi-core/src/input/commands/kill.rs b/yazi-core/src/input/commands/kill.rs index eeac2245..754f04de 100644 --- a/yazi-core/src/input/commands/kill.rs +++ b/yazi-core/src/input/commands/kill.rs @@ -9,7 +9,7 @@ pub struct Opt { } impl From for Opt { - fn from(mut c: Cmd) -> Self { Self { kind: c.take_first().unwrap_or_default() } } + fn from(mut c: Cmd) -> Self { Self { kind: c.take_first_str().unwrap_or_default() } } } impl Input { diff --git a/yazi-core/src/input/commands/move_.rs b/yazi-core/src/input/commands/move_.rs index 0e032b35..2c0536c6 100644 --- a/yazi-core/src/input/commands/move_.rs +++ b/yazi-core/src/input/commands/move_.rs @@ -11,8 +11,8 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { Self { - step: c.take_first().and_then(|s| s.parse().ok()).unwrap_or(0), - in_operating: c.named.contains_key("in-operating"), + step: c.take_first_str().and_then(|s| s.parse().ok()).unwrap_or(0), + in_operating: c.get_bool("in-operating"), } } } diff --git a/yazi-core/src/input/commands/paste.rs b/yazi-core/src/input/commands/paste.rs index c8962116..58417341 100644 --- a/yazi-core/src/input/commands/paste.rs +++ b/yazi-core/src/input/commands/paste.rs @@ -7,7 +7,7 @@ pub struct Opt { } impl From for Opt { - fn from(c: Cmd) -> Self { Self { before: c.named.contains_key("before") } } + fn from(c: Cmd) -> Self { Self { before: c.get_bool("before") } } } impl Input { diff --git a/yazi-core/src/manager/commands/create.rs b/yazi-core/src/manager/commands/create.rs index 6aa886d9..7dc0a5d6 100644 --- a/yazi-core/src/manager/commands/create.rs +++ b/yazi-core/src/manager/commands/create.rs @@ -12,7 +12,7 @@ pub struct Opt { } impl From for Opt { - fn from(c: Cmd) -> Self { Self { force: c.named.contains_key("force") } } + fn from(c: Cmd) -> Self { Self { force: c.get_bool("force") } } } impl Manager { diff --git a/yazi-core/src/manager/commands/hover.rs b/yazi-core/src/manager/commands/hover.rs index 94df57d0..287e36d9 100644 --- a/yazi-core/src/manager/commands/hover.rs +++ b/yazi-core/src/manager/commands/hover.rs @@ -9,7 +9,7 @@ pub struct Opt { } impl From for Opt { - fn from(mut c: Cmd) -> Self { Self { url: c.take_first().map(Url::from) } } + fn from(mut c: Cmd) -> Self { Self { url: c.take_first_str().map(Url::from) } } } impl From> for Opt { fn from(url: Option) -> Self { Self { url } } diff --git a/yazi-core/src/manager/commands/link.rs b/yazi-core/src/manager/commands/link.rs index 2329782f..bb8935c1 100644 --- a/yazi-core/src/manager/commands/link.rs +++ b/yazi-core/src/manager/commands/link.rs @@ -8,9 +8,7 @@ pub struct Opt { } impl From for Opt { - fn from(c: Cmd) -> Self { - Self { relative: c.named.contains_key("relative"), force: c.named.contains_key("force") } - } + fn from(c: Cmd) -> Self { Self { relative: c.get_bool("relative"), force: c.get_bool("force") } } } impl Manager { diff --git a/yazi-core/src/manager/commands/open.rs b/yazi-core/src/manager/commands/open.rs index 1f1de96e..60d0af98 100644 --- a/yazi-core/src/manager/commands/open.rs +++ b/yazi-core/src/manager/commands/open.rs @@ -17,10 +17,7 @@ pub struct Opt { impl From for Opt { fn from(c: Cmd) -> Self { - Self { - interactive: c.named.contains_key("interactive"), - hovered: c.named.contains_key("hovered"), - } + Self { interactive: c.get_bool("interactive"), hovered: c.get_bool("hovered") } } } diff --git a/yazi-core/src/manager/commands/paste.rs b/yazi-core/src/manager/commands/paste.rs index f551f023..c85ed632 100644 --- a/yazi-core/src/manager/commands/paste.rs +++ b/yazi-core/src/manager/commands/paste.rs @@ -8,9 +8,7 @@ pub struct Opt { } impl From for Opt { - fn from(c: Cmd) -> Self { - Self { force: c.named.contains_key("force"), follow: c.named.contains_key("follow") } - } + fn from(c: Cmd) -> Self { Self { force: c.get_bool("force"), follow: c.get_bool("follow") } } } impl Manager { diff --git a/yazi-core/src/manager/commands/peek.rs b/yazi-core/src/manager/commands/peek.rs index 217c0067..36bff3f9 100644 --- a/yazi-core/src/manager/commands/peek.rs +++ b/yazi-core/src/manager/commands/peek.rs @@ -13,10 +13,10 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { Self { - skip: c.take_first().and_then(|s| s.parse().ok()), - force: c.named.contains_key("force"), - only_if: c.take_name("only-if").map(Url::from), - upper_bound: c.named.contains_key("upper-bound"), + skip: c.take_first_str().and_then(|s| s.parse().ok()), + force: c.get_bool("force"), + only_if: c.take_name_str("only-if").map(Url::from), + upper_bound: c.get_bool("upper-bound"), } } } diff --git a/yazi-core/src/manager/commands/quit.rs b/yazi-core/src/manager/commands/quit.rs index 7fd09b27..9f5f3483 100644 --- a/yazi-core/src/manager/commands/quit.rs +++ b/yazi-core/src/manager/commands/quit.rs @@ -12,7 +12,7 @@ impl From<()> for Opt { fn from(_: ()) -> Self { Self::default() } } impl From for Opt { - fn from(c: Cmd) -> Self { Self { no_cwd_file: c.named.contains_key("no-cwd-file") } } + fn from(c: Cmd) -> Self { Self { no_cwd_file: c.get_bool("no-cwd-file") } } } impl Manager { diff --git a/yazi-core/src/manager/commands/remove.rs b/yazi-core/src/manager/commands/remove.rs index 356f926a..521c6e3e 100644 --- a/yazi-core/src/manager/commands/remove.rs +++ b/yazi-core/src/manager/commands/remove.rs @@ -13,8 +13,8 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { Self { - force: c.named.contains_key("force"), - permanently: c.named.contains_key("permanently"), + force: c.get_bool("force"), + permanently: c.get_bool("permanently"), targets: c.take_data().unwrap_or_default(), } } diff --git a/yazi-core/src/manager/commands/rename.rs b/yazi-core/src/manager/commands/rename.rs index af0c28ee..e786bead 100644 --- a/yazi-core/src/manager/commands/rename.rs +++ b/yazi-core/src/manager/commands/rename.rs @@ -18,9 +18,9 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { Self { - force: c.named.contains_key("force"), - empty: c.take_name("empty").unwrap_or_default(), - cursor: c.take_name("cursor").unwrap_or_default(), + force: c.get_bool("force"), + empty: c.take_name_str("empty").unwrap_or_default(), + cursor: c.take_name_str("cursor").unwrap_or_default(), } } } diff --git a/yazi-core/src/manager/commands/seek.rs b/yazi-core/src/manager/commands/seek.rs index ef7f6e3a..936d7b9e 100644 --- a/yazi-core/src/manager/commands/seek.rs +++ b/yazi-core/src/manager/commands/seek.rs @@ -11,7 +11,7 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { - Self { units: c.take_first().and_then(|s| s.parse().ok()).unwrap_or(0) } + Self { units: c.take_first_str().and_then(|s| s.parse().ok()).unwrap_or(0) } } } diff --git a/yazi-core/src/manager/commands/tab_close.rs b/yazi-core/src/manager/commands/tab_close.rs index 4d28c19d..90cf441b 100644 --- a/yazi-core/src/manager/commands/tab_close.rs +++ b/yazi-core/src/manager/commands/tab_close.rs @@ -8,7 +8,7 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { - Self { idx: c.take_first().and_then(|i| i.parse().ok()).unwrap_or(0) } + Self { idx: c.take_first_str().and_then(|i| i.parse().ok()).unwrap_or(0) } } } diff --git a/yazi-core/src/manager/commands/tab_create.rs b/yazi-core/src/manager/commands/tab_create.rs index b5f28aa9..10bf033a 100644 --- a/yazi-core/src/manager/commands/tab_create.rs +++ b/yazi-core/src/manager/commands/tab_create.rs @@ -13,11 +13,11 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { - if c.named.contains_key("current") { + if c.get_bool("current") { Self { url: Default::default(), current: true } } else { Self { - url: c.take_first().map_or_else(|| Url::from(&BOOT.cwd), Url::from), + url: c.take_first_str().map_or_else(|| Url::from(&BOOT.cwd), Url::from), current: false, } } diff --git a/yazi-core/src/manager/commands/tab_swap.rs b/yazi-core/src/manager/commands/tab_swap.rs index 2dec19e1..4f066047 100644 --- a/yazi-core/src/manager/commands/tab_swap.rs +++ b/yazi-core/src/manager/commands/tab_swap.rs @@ -8,7 +8,7 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { - Self { step: c.take_first().and_then(|s| s.parse().ok()).unwrap_or(0) } + Self { step: c.take_first_str().and_then(|s| s.parse().ok()).unwrap_or(0) } } } diff --git a/yazi-core/src/manager/commands/tab_switch.rs b/yazi-core/src/manager/commands/tab_switch.rs index 049a0e3e..ed99615f 100644 --- a/yazi-core/src/manager/commands/tab_switch.rs +++ b/yazi-core/src/manager/commands/tab_switch.rs @@ -10,8 +10,8 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { Self { - step: c.take_first().and_then(|s| s.parse().ok()).unwrap_or(0), - relative: c.named.contains_key("relative"), + step: c.take_first_str().and_then(|s| s.parse().ok()).unwrap_or(0), + relative: c.get_bool("relative"), } } } diff --git a/yazi-core/src/manager/commands/update_paged.rs b/yazi-core/src/manager/commands/update_paged.rs index fea90818..165f8693 100644 --- a/yazi-core/src/manager/commands/update_paged.rs +++ b/yazi-core/src/manager/commands/update_paged.rs @@ -11,8 +11,8 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { Self { - page: c.take_first().and_then(|s| s.parse().ok()), - only_if: c.take_name("only-if").map(Url::from), + page: c.take_first_str().and_then(|s| s.parse().ok()), + only_if: c.take_name_str("only-if").map(Url::from), } } } diff --git a/yazi-core/src/manager/commands/yank.rs b/yazi-core/src/manager/commands/yank.rs index 0532e291..676387b9 100644 --- a/yazi-core/src/manager/commands/yank.rs +++ b/yazi-core/src/manager/commands/yank.rs @@ -8,7 +8,7 @@ pub struct Opt { } impl From for Opt { - fn from(c: Cmd) -> Self { Self { cut: c.named.contains_key("cut") } } + fn from(c: Cmd) -> Self { Self { cut: c.get_bool("cut") } } } impl Manager { diff --git a/yazi-core/src/notify/commands/tick.rs b/yazi-core/src/notify/commands/tick.rs index ba8536cf..b48260e7 100644 --- a/yazi-core/src/notify/commands/tick.rs +++ b/yazi-core/src/notify/commands/tick.rs @@ -13,7 +13,7 @@ impl TryFrom for Opt { type Error = (); fn try_from(mut c: Cmd) -> Result { - let interval = c.take_first().and_then(|s| s.parse::().ok()).ok_or(())?; + let interval = c.take_first_str().and_then(|s| s.parse::().ok()).ok_or(())?; if interval < 0.0 { return Err(()); } diff --git a/yazi-core/src/select/commands/arrow.rs b/yazi-core/src/select/commands/arrow.rs index 1373e4f2..a434cc82 100644 --- a/yazi-core/src/select/commands/arrow.rs +++ b/yazi-core/src/select/commands/arrow.rs @@ -8,7 +8,7 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { - Self { step: c.take_first().and_then(|s| s.parse().ok()).unwrap_or(0) } + Self { step: c.take_first_str().and_then(|s| s.parse().ok()).unwrap_or(0) } } } diff --git a/yazi-core/src/select/commands/close.rs b/yazi-core/src/select/commands/close.rs index b4c60c8a..01fd9066 100644 --- a/yazi-core/src/select/commands/close.rs +++ b/yazi-core/src/select/commands/close.rs @@ -8,7 +8,7 @@ pub struct Opt { } impl From for Opt { - fn from(c: Cmd) -> Self { Self { submit: c.named.contains_key("submit") } } + fn from(c: Cmd) -> Self { Self { submit: c.get_bool("submit") } } } impl From for Opt { fn from(submit: bool) -> Self { Self { submit } } diff --git a/yazi-core/src/tab/commands/arrow.rs b/yazi-core/src/tab/commands/arrow.rs index 13c64378..bf789cac 100644 --- a/yazi-core/src/tab/commands/arrow.rs +++ b/yazi-core/src/tab/commands/arrow.rs @@ -10,7 +10,7 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { - Self { step: c.take_first().and_then(|s| s.parse().ok()).unwrap_or_default() } + Self { step: c.take_first_str().and_then(|s| s.parse().ok()).unwrap_or_default() } } } diff --git a/yazi-core/src/tab/commands/cd.rs b/yazi-core/src/tab/commands/cd.rs index 379f4903..1990ee75 100644 --- a/yazi-core/src/tab/commands/cd.rs +++ b/yazi-core/src/tab/commands/cd.rs @@ -16,12 +16,12 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { - let mut target = Url::from(c.take_first().unwrap_or_default()); + let mut target = Url::from(c.take_first_str().unwrap_or_default()); if target.is_regular() { target.set_path(expand_path(&target)) } - Self { target, interactive: c.named.contains_key("interactive") } + Self { target, interactive: c.get_bool("interactive") } } } impl From for Opt { diff --git a/yazi-core/src/tab/commands/copy.rs b/yazi-core/src/tab/commands/copy.rs index f2af284d..22344720 100644 --- a/yazi-core/src/tab/commands/copy.rs +++ b/yazi-core/src/tab/commands/copy.rs @@ -9,7 +9,7 @@ pub struct Opt { } impl From for Opt { - fn from(mut c: Cmd) -> Self { Self { type_: c.take_first().unwrap_or_default() } } + fn from(mut c: Cmd) -> Self { Self { type_: c.take_first_str().unwrap_or_default() } } } impl Tab { diff --git a/yazi-core/src/tab/commands/escape.rs b/yazi-core/src/tab/commands/escape.rs index 10015872..23bbc0d2 100644 --- a/yazi-core/src/tab/commands/escape.rs +++ b/yazi-core/src/tab/commands/escape.rs @@ -16,14 +16,16 @@ bitflags! { impl From for Opt { fn from(c: Cmd) -> Self { - c.named.iter().fold(Opt::empty(), |acc, (k, _)| match k.as_str() { - "all" => Self::all(), - "find" => acc | Self::FIND, - "visual" => acc | Self::VISUAL, - "select" => acc | Self::SELECT, - "filter" => acc | Self::FILTER, - "search" => acc | Self::SEARCH, - _ => acc, + c.args.iter().fold(Opt::empty(), |acc, (k, v)| { + match (k.as_str(), v.as_bool().unwrap_or(false)) { + ("all", true) => Self::all(), + ("find", true) => acc | Self::FIND, + ("visual", true) => acc | Self::VISUAL, + ("select", true) => acc | Self::SELECT, + ("filter", true) => acc | Self::FILTER, + ("search", true) => acc | Self::SEARCH, + _ => acc, + } }) } } diff --git a/yazi-core/src/tab/commands/filter.rs b/yazi-core/src/tab/commands/filter.rs index 56000b00..0516a0b6 100644 --- a/yazi-core/src/tab/commands/filter.rs +++ b/yazi-core/src/tab/commands/filter.rs @@ -18,9 +18,9 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { Self { - query: c.take_first().unwrap_or_default(), + query: c.take_first_str().unwrap_or_default(), case: FilterCase::from(&c), - done: c.named.contains_key("done"), + done: c.get_bool("done"), } } } diff --git a/yazi-core/src/tab/commands/find.rs b/yazi-core/src/tab/commands/find.rs index 950a73cc..d4b02dc4 100644 --- a/yazi-core/src/tab/commands/find.rs +++ b/yazi-core/src/tab/commands/find.rs @@ -16,11 +16,7 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { - Self { - query: c.take_first(), - prev: c.named.contains_key("previous"), - case: FilterCase::from(&c), - } + Self { query: c.take_first_str(), prev: c.get_bool("previous"), case: FilterCase::from(&c) } } } @@ -29,7 +25,7 @@ pub struct ArrowOpt { } impl From for ArrowOpt { - fn from(c: Cmd) -> Self { Self { prev: c.named.contains_key("previous") } } + fn from(c: Cmd) -> Self { Self { prev: c.get_bool("previous") } } } impl Tab { diff --git a/yazi-core/src/tab/commands/hidden.rs b/yazi-core/src/tab/commands/hidden.rs index 6e71d8d2..62b6e93c 100644 --- a/yazi-core/src/tab/commands/hidden.rs +++ b/yazi-core/src/tab/commands/hidden.rs @@ -4,8 +4,8 @@ use yazi_shared::event::Cmd; use crate::tab::Tab; impl Tab { - pub fn hidden(&mut self, c: Cmd) { - self.conf.show_hidden = match c.args.first().map(|s| s.as_str()) { + pub fn hidden(&mut self, mut c: Cmd) { + self.conf.show_hidden = match c.take_first_str().as_deref() { Some("show") => true, Some("hide") => false, _ => !self.conf.show_hidden, diff --git a/yazi-core/src/tab/commands/jump.rs b/yazi-core/src/tab/commands/jump.rs index 47bd0976..810abbbf 100644 --- a/yazi-core/src/tab/commands/jump.rs +++ b/yazi-core/src/tab/commands/jump.rs @@ -17,9 +17,9 @@ pub enum OptType { } impl From for Opt { - fn from(c: Cmd) -> Self { + fn from(mut c: Cmd) -> Self { Self { - type_: match c.args.first().map(|s| s.as_str()) { + type_: match c.take_first_str().as_deref() { Some("fzf") => OptType::Fzf, Some("zoxide") => OptType::Zoxide, _ => OptType::None, diff --git a/yazi-core/src/tab/commands/linemode.rs b/yazi-core/src/tab/commands/linemode.rs index b4852200..123995f2 100644 --- a/yazi-core/src/tab/commands/linemode.rs +++ b/yazi-core/src/tab/commands/linemode.rs @@ -5,7 +5,7 @@ use crate::tab::Tab; impl Tab { pub fn linemode(&mut self, mut c: Cmd) { render!(self.conf.patch(|new| { - let Some(mode) = c.take_first() else { + let Some(mode) = c.take_first_str() else { return; }; if !mode.is_empty() && mode.len() <= 20 { diff --git a/yazi-core/src/tab/commands/reveal.rs b/yazi-core/src/tab/commands/reveal.rs index cf49d736..44f9c38c 100644 --- a/yazi-core/src/tab/commands/reveal.rs +++ b/yazi-core/src/tab/commands/reveal.rs @@ -9,7 +9,7 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { - let mut target = Url::from(c.take_first().unwrap_or_default()); + let mut target = Url::from(c.take_first_str().unwrap_or_default()); if target.is_regular() { target.set_path(expand_path(&target)) } diff --git a/yazi-core/src/tab/commands/search.rs b/yazi-core/src/tab/commands/search.rs index 4f71ffc0..d4119e90 100644 --- a/yazi-core/src/tab/commands/search.rs +++ b/yazi-core/src/tab/commands/search.rs @@ -42,7 +42,7 @@ pub struct Opt { } impl From for Opt { - fn from(mut c: Cmd) -> Self { Self { type_: c.take_first().unwrap_or_default().into() } } + fn from(mut c: Cmd) -> Self { Self { type_: c.take_first_str().unwrap_or_default().into() } } } impl Tab { diff --git a/yazi-core/src/tab/commands/select.rs b/yazi-core/src/tab/commands/select.rs index 10a9d987..b4ad21c6 100644 --- a/yazi-core/src/tab/commands/select.rs +++ b/yazi-core/src/tab/commands/select.rs @@ -13,8 +13,8 @@ pub struct Opt<'a> { impl<'a> From for Opt<'a> { fn from(mut c: Cmd) -> Self { Self { - url: c.take_name("url").map(|s| Cow::Owned(Url::from(s))), - state: match c.named.get("state").map(|s| s.as_str()) { + url: c.take_name_str("url").map(|s| Cow::Owned(Url::from(s))), + state: match c.take_name_str("state").as_deref() { Some("true") => Some(true), Some("false") => Some(false), _ => None, diff --git a/yazi-core/src/tab/commands/select_all.rs b/yazi-core/src/tab/commands/select_all.rs index f081bbde..a3a9b61d 100644 --- a/yazi-core/src/tab/commands/select_all.rs +++ b/yazi-core/src/tab/commands/select_all.rs @@ -8,9 +8,9 @@ pub struct Opt { } impl From for Opt { - fn from(c: Cmd) -> Self { + fn from(mut c: Cmd) -> Self { Self { - state: match c.named.get("state").map(|s| s.as_str()) { + state: match c.take_name_str("state").as_deref() { Some("true") => Some(true), Some("false") => Some(false), _ => None, diff --git a/yazi-core/src/tab/commands/shell.rs b/yazi-core/src/tab/commands/shell.rs index ec566163..a66e525a 100644 --- a/yazi-core/src/tab/commands/shell.rs +++ b/yazi-core/src/tab/commands/shell.rs @@ -16,10 +16,10 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { Self { - run: c.take_first().unwrap_or_default(), - block: c.named.contains_key("block"), - orphan: c.named.contains_key("orphan"), - confirm: c.named.contains_key("confirm"), + run: c.take_first_str().unwrap_or_default(), + block: c.get_bool("block"), + orphan: c.get_bool("orphan"), + confirm: c.get_bool("confirm"), } } } diff --git a/yazi-core/src/tab/commands/sort.rs b/yazi-core/src/tab/commands/sort.rs index c36321db..c7aebf77 100644 --- a/yazi-core/src/tab/commands/sort.rs +++ b/yazi-core/src/tab/commands/sort.rs @@ -7,13 +7,13 @@ use yazi_shared::event::Cmd; use crate::{tab::Tab, tasks::Tasks}; impl Tab { - pub fn sort(&mut self, c: Cmd, tasks: &Tasks) { - if let Some(by) = c.args.first() { - self.conf.sort_by = SortBy::from_str(by).unwrap_or_default(); + pub fn sort(&mut self, mut c: Cmd, tasks: &Tasks) { + if let Some(by) = c.take_first_str() { + self.conf.sort_by = SortBy::from_str(&by).unwrap_or_default(); } - self.conf.sort_sensitive = c.named.contains_key("sensitive"); - self.conf.sort_reverse = c.named.contains_key("reverse"); - self.conf.sort_dir_first = c.named.contains_key("dir-first"); + self.conf.sort_sensitive = c.get_bool("sensitive"); + self.conf.sort_reverse = c.get_bool("reverse"); + self.conf.sort_dir_first = c.get_bool("dir-first"); self.apply_files_attrs(); ManagerProxy::update_paged(); diff --git a/yazi-core/src/tab/commands/visual_mode.rs b/yazi-core/src/tab/commands/visual_mode.rs index 8e19ace5..606a7e62 100644 --- a/yazi-core/src/tab/commands/visual_mode.rs +++ b/yazi-core/src/tab/commands/visual_mode.rs @@ -9,7 +9,7 @@ pub struct Opt { } impl From for Opt { - fn from(c: Cmd) -> Self { Self { unset: c.named.contains_key("unset") } } + fn from(c: Cmd) -> Self { Self { unset: c.get_bool("unset") } } } impl Tab { diff --git a/yazi-core/src/tasks/commands/arrow.rs b/yazi-core/src/tasks/commands/arrow.rs index 9b68c9fe..baf1859c 100644 --- a/yazi-core/src/tasks/commands/arrow.rs +++ b/yazi-core/src/tasks/commands/arrow.rs @@ -8,7 +8,7 @@ pub struct Opt { impl From for Opt { fn from(mut c: Cmd) -> Self { - Self { step: c.take_first().and_then(|s| s.parse().ok()).unwrap_or(0) } + Self { step: c.take_first_str().and_then(|s| s.parse().ok()).unwrap_or(0) } } } diff --git a/yazi-core/src/which/commands/callback.rs b/yazi-core/src/which/commands/callback.rs index ef0fc5fe..6c2ce1aa 100644 --- a/yazi-core/src/which/commands/callback.rs +++ b/yazi-core/src/which/commands/callback.rs @@ -15,7 +15,7 @@ impl TryFrom for Opt { fn try_from(mut c: Cmd) -> Result { Ok(Self { tx: c.take_data().ok_or(())?, - idx: c.take_first().and_then(|s| s.parse().ok()).ok_or(())?, + idx: c.take_first_str().and_then(|s| s.parse().ok()).ok_or(())?, }) } } diff --git a/yazi-core/src/which/commands/show.rs b/yazi-core/src/which/commands/show.rs index 22994c6d..8cae69f0 100644 --- a/yazi-core/src/which/commands/show.rs +++ b/yazi-core/src/which/commands/show.rs @@ -17,8 +17,8 @@ impl TryFrom for Opt { fn try_from(mut c: Cmd) -> Result { Ok(Self { cands: c.take_data().unwrap_or_default(), - layer: Layer::from_str(&c.take_name("layer").unwrap_or_default())?, - silent: c.named.contains_key("silent"), + layer: Layer::from_str(&c.take_name_str("layer").unwrap_or_default())?, + silent: c.get_bool("silent"), }) } } diff --git a/yazi-fm/src/executor.rs b/yazi-fm/src/executor.rs index 1c347bdf..b7a056ca 100644 --- a/yazi-fm/src/executor.rs +++ b/yazi-fm/src/executor.rs @@ -214,7 +214,7 @@ impl<'a> Executor<'a> { on!(forward); if cmd.name.as_str() == "complete" { - return if cmd.named.contains_key("trigger") { + return if cmd.get_bool("trigger") { self.app.cx.completion.trigger(cmd) } else { self.app.cx.input.complete(cmd) diff --git a/yazi-plugin/src/opt.rs b/yazi-plugin/src/opt.rs index d97b5c70..6e4742e4 100644 --- a/yazi-plugin/src/opt.rs +++ b/yazi-plugin/src/opt.rs @@ -19,16 +19,16 @@ impl TryFrom for Opt { type Error = anyhow::Error; fn try_from(mut c: Cmd) -> Result { - let Some(name) = c.take_first().filter(|s| !s.is_empty()) else { + let Some(name) = c.take_first_str().filter(|s| !s.is_empty()) else { bail!("plugin name cannot be empty"); }; let mut data: OptData = c.take_data().unwrap_or_default(); - if let Some(args) = c.named.get("args") { + if let Some(args) = c.get_str("args") { data.args = shell_words::split(args)?.into_iter().map(ValueSendable::String).collect(); } - Ok(Self { name, sync: c.named.contains_key("sync"), data }) + Ok(Self { name, sync: c.get_bool("sync"), data }) } } diff --git a/yazi-plugin/src/utils/call.rs b/yazi-plugin/src/utils/call.rs index 860de583..185d0eab 100644 --- a/yazi-plugin/src/utils/call.rs +++ b/yazi-plugin/src/utils/call.rs @@ -40,13 +40,16 @@ impl Utils { #[inline] fn create_cmd(name: String, table: Table, data: Option) -> mlua::Result { - let (args, named) = Self::parse_args(table)?; - let mut cmd = Cmd { name, args, named, ..Default::default() }; + // TODO: Fix this + return Ok(Cmd { name, args: Default::default(), data: None }); - if let Some(data) = data.and_then(|v| ValueSendable::try_from(v).ok()) { - cmd = cmd.with_data(data); - } - Ok(cmd) + // let (args, named) = Self::parse_args(table)?; + // let mut cmd = Cmd { name, args, named, ..Default::default() }; + + // if let Some(data) = data.and_then(|v| ValueSendable::try_from(v).ok()) { + // cmd = cmd.with_data(data); + // } + // Ok(cmd) } pub(super) fn call(lua: &Lua, ya: &Table) -> mlua::Result<()> { diff --git a/yazi-shared/src/event/arg.rs b/yazi-shared/src/event/arg.rs new file mode 100644 index 00000000..d7b6cc0a --- /dev/null +++ b/yazi-shared/src/event/arg.rs @@ -0,0 +1,76 @@ +use std::collections::HashMap; + +use anyhow::bail; +use serde::{Deserialize, Serialize}; + +use crate::OrderedFloat; + +// --- Arg +#[derive(Debug, Serialize, Deserialize)] +#[serde(untagged)] +pub enum Arg { + Nil, + Boolean(bool), + Integer(i64), + Number(f64), + String(String), + Table(HashMap), +} + +impl Arg { + #[inline] + pub fn as_bool(&self) -> Option { + match self { + Self::Boolean(b) => Some(*b), + _ => None, + } + } + + #[inline] + pub fn as_str(&self) -> Option<&str> { + match self { + Self::String(s) => Some(s), + _ => None, + } + } + + pub fn into_table_string(self) -> HashMap { + let Self::Table(table) = self else { + return Default::default(); + }; + + let mut map = HashMap::with_capacity(table.len()); + for pair in table { + if let (ArgKey::String(k), Self::String(v)) = pair { + map.insert(k, v); + } + } + map + } +} + +// --- Key +#[derive(Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] +#[serde(untagged)] +pub enum ArgKey { + Nil, + Boolean(bool), + Integer(i64), + Number(OrderedFloat), + String(String), +} + +impl TryInto for Arg { + type Error = anyhow::Error; + + fn try_into(self) -> Result { + Ok(match self { + Self::Nil => ArgKey::Nil, + Self::Boolean(v) => ArgKey::Boolean(v), + Self::Integer(v) => ArgKey::Integer(v), + Self::Number(v) => ArgKey::Number(OrderedFloat::new(v)), + Self::String(v) => ArgKey::String(v), + Self::Table(_) => bail!("table is not supported"), + }) + } +} diff --git a/yazi-shared/src/event/cmd.rs b/yazi-shared/src/event/cmd.rs index f37c1941..729e07c1 100644 --- a/yazi-shared/src/event/cmd.rs +++ b/yazi-shared/src/event/cmd.rs @@ -1,11 +1,12 @@ -use std::{any::Any, collections::HashMap, fmt::{self, Display}, mem}; +use std::{any::Any, collections::HashMap, fmt::{self, Display}}; + +use super::Arg; #[derive(Debug, Default)] pub struct Cmd { - pub name: String, - pub args: Vec, - pub named: HashMap, - pub data: Option>, + pub name: String, + pub args: HashMap, + pub data: Option>, } impl Cmd { @@ -14,20 +15,22 @@ impl Cmd { #[inline] pub fn args(name: &str, args: Vec) -> Self { - Self { name: name.to_owned(), args, ..Default::default() } + Self { + name: name.to_owned(), + args: args.into_iter().enumerate().map(|(i, s)| (i.to_string(), Arg::String(s))).collect(), + ..Default::default() + } } #[inline] pub fn with(mut self, name: impl ToString, value: impl ToString) -> Self { - self.named.insert(name.to_string(), value.to_string()); + self.args.insert(name.to_string(), Arg::String(value.to_string())); self } #[inline] pub fn with_bool(mut self, name: impl ToString, state: bool) -> Self { - if state { - self.named.insert(name.to_string(), Default::default()); - } + self.args.insert(name.to_string(), Arg::Boolean(state)); self } @@ -37,40 +40,52 @@ impl Cmd { self } + #[inline] + pub fn get_str(&self, name: &str) -> Option<&str> { self.args.get(name).and_then(Arg::as_str) } + + #[inline] + pub fn get_bool(&self, name: &str) -> bool { + self.args.get(name).and_then(Arg::as_bool).unwrap_or(false) + } + #[inline] pub fn take_data(&mut self) -> Option { self.data.take().and_then(|d| d.downcast::().ok()).map(|d| *d) } #[inline] - pub fn take_first(&mut self) -> Option { - if self.args.is_empty() { None } else { Some(mem::take(&mut self.args[0])) } + pub fn take_first_str(&mut self) -> Option { + if let Some(Arg::String(s)) = self.args.remove("0") { Some(s) } else { None } } #[inline] - pub fn take_name(&mut self, name: &str) -> Option { self.named.remove(name) } + pub fn take_name_str(&mut self, name: &str) -> Option { + if let Some(Arg::String(s)) = self.args.remove(name) { Some(s) } else { None } + } - #[inline] - pub fn clone_without_data(&self) -> Self { - Self { - name: self.name.clone(), - args: self.args.clone(), - named: self.named.clone(), - data: None, - } + pub fn shallow_clone(&self) -> Self { + let args = self + .args + .iter() + .filter_map(|(k, v)| v.as_str().map(|s| (k.clone(), Arg::String(s.to_owned())))) + .collect(); + + Self { name: self.name.clone(), args, data: None } } } impl Display for Cmd { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.name)?; - if !self.args.is_empty() { - write!(f, " {}", self.args.join(" "))?; - } - for (k, v) in &self.named { - write!(f, " --{k}")?; - if !v.is_empty() { - write!(f, "={v}")?; + for (k, v) in &self.args { + if k.as_bytes().first().is_some_and(|b| b.is_ascii_digit()) { + if let Some(s) = v.as_str() { + write!(f, " {s}")?; + } + } else if v.as_bool().is_some_and(|b| b) { + write!(f, " --{k}")?; + } else if let Some(s) = v.as_str() { + write!(f, " --{k}={s}")?; } } Ok(()) diff --git a/yazi-shared/src/event/mod.rs b/yazi-shared/src/event/mod.rs index 2e32f12f..b5b599b1 100644 --- a/yazi-shared/src/event/mod.rs +++ b/yazi-shared/src/event/mod.rs @@ -1,9 +1,11 @@ #![allow(clippy::module_inception)] +mod arg; mod cmd; mod event; mod render; +pub use arg::*; pub use cmd::*; pub use event::*; pub use render::*;