feat: allow to specify layer for keymap commands (#2399)

This commit is contained in:
三咲雅 · Misaki Masa 2025-02-26 03:01:17 +08:00 committed by GitHub
parent 235f6888d4
commit 953d567c63
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
54 changed files with 263 additions and 284 deletions

View file

@ -321,7 +321,7 @@ keymap = [
{ on = "<F1>", run = "help", desc = "Open help" },
]
[completion]
[cmp]
keymap = [
{ on = "<C-c>", run = "close", desc = "Cancel completion" },

View file

@ -173,7 +173,7 @@ selected = { reversed = true }
# : Completion {{{
[completion]
[cmp]
border = { fg = "blue" }
active = { reversed = true }
inactive = {}

View file

@ -173,7 +173,7 @@ selected = { reversed = true }
# : Completion {{{
[completion]
[cmp]
border = { fg = "blue" }
active = { reversed = true }
inactive = {}

View file

@ -2,7 +2,7 @@ use std::{borrow::Cow, hash::{Hash, Hasher}, sync::OnceLock};
use regex::Regex;
use serde::Deserialize;
use yazi_shared::event::Cmd;
use yazi_shared::{Layer, event::Cmd};
use super::Key;
@ -42,15 +42,25 @@ impl Chord {
pub fn desc_or_run(&self) -> Cow<str> { self.desc().unwrap_or_else(|| self.run().into()) }
#[inline]
pub fn noop(&self) -> bool {
self.run.len() == 1 && self.run[0].name == "noop" && self.run[0].args.is_empty()
}
pub fn contains(&self, s: &str) -> bool {
let s = s.to_lowercase();
self.desc().map(|d| d.to_lowercase().contains(&s)) == Some(true)
|| self.run().to_lowercase().contains(&s)
|| self.on().to_lowercase().contains(&s)
}
#[inline]
pub(super) fn noop(&self) -> bool {
self.run.len() == 1 && self.run[0].name == "noop" && self.run[0].args.is_empty()
}
#[inline]
pub(super) fn with_layer(mut self, layer: Layer) -> Self {
for c in &mut self.run {
if c.layer == Default::default() {
c.layer = layer;
}
}
self
}
}

View file

@ -10,21 +10,21 @@ use crate::{Preset, keymap::Key};
#[derive(Debug)]
pub struct Keymap {
pub mgr: Vec<Chord>,
pub tasks: Vec<Chord>,
pub spot: Vec<Chord>,
pub pick: Vec<Chord>,
pub input: Vec<Chord>,
pub confirm: Vec<Chord>,
pub help: Vec<Chord>,
pub completion: Vec<Chord>,
pub mgr: Vec<Chord>,
pub tasks: Vec<Chord>,
pub spot: Vec<Chord>,
pub pick: Vec<Chord>,
pub input: Vec<Chord>,
pub confirm: Vec<Chord>,
pub help: Vec<Chord>,
pub cmp: Vec<Chord>,
}
impl Keymap {
#[inline]
pub fn get(&self, layer: Layer) -> &[Chord] {
match layer {
Layer::App => unreachable!(),
Layer::App => &[],
Layer::Mgr => &self.mgr,
Layer::Tasks => &self.tasks,
Layer::Spot => &self.spot,
@ -32,8 +32,8 @@ impl Keymap {
Layer::Input => &self.input,
Layer::Confirm => &self.confirm,
Layer::Help => &self.help,
Layer::Completion => &self.completion,
Layer::Which => unreachable!(),
Layer::Cmp => &self.cmp,
Layer::Which => &[],
}
}
}
@ -54,14 +54,14 @@ impl<'de> Deserialize<'de> for Keymap {
#[derive(Deserialize)]
struct Shadow {
#[serde(rename = "manager")]
mgr: Inner, // TODO: remove serde(rename)
tasks: Inner,
spot: Inner,
pick: Inner,
input: Inner,
confirm: Inner,
help: Inner,
completion: Inner,
mgr: Inner, // TODO: remove serde(rename)
tasks: Inner,
spot: Inner,
pick: Inner,
input: Inner,
confirm: Inner,
help: Inner,
cmp: Inner,
}
#[derive(Deserialize)]
struct Inner {
@ -72,7 +72,7 @@ impl<'de> Deserialize<'de> for Keymap {
append_keymap: IndexSet<Chord>,
}
fn mix(a: IndexSet<Chord>, b: IndexSet<Chord>, c: IndexSet<Chord>) -> Vec<Chord> {
fn mix(l: Layer, a: IndexSet<Chord>, b: IndexSet<Chord>, c: IndexSet<Chord>) -> Vec<Chord> {
#[inline]
fn on(Chord { on, .. }: &Chord) -> [Key; 2] {
[on.first().copied().unwrap_or_default(), on.get(1).copied().unwrap_or_default()]
@ -87,27 +87,28 @@ impl<'de> Deserialize<'de> for Keymap {
c.into_iter().filter(|v| !b_seen.contains(&on(v))),
)
.filter(|chord| !chord.noop())
.map(|chord| chord.with_layer(l))
.collect()
}
let shadow = Shadow::deserialize(deserializer)?;
Ok(Self {
#[rustfmt::skip]
mgr: mix(shadow.mgr.prepend_keymap, shadow.mgr.keymap, shadow.mgr.append_keymap),
mgr: mix(Layer::Mgr, shadow.mgr.prepend_keymap, shadow.mgr.keymap, shadow.mgr.append_keymap),
#[rustfmt::skip]
tasks: mix(shadow.tasks.prepend_keymap, shadow.tasks.keymap, shadow.tasks.append_keymap),
tasks: mix(Layer::Tasks, shadow.tasks.prepend_keymap, shadow.tasks.keymap, shadow.tasks.append_keymap),
#[rustfmt::skip]
spot: mix(shadow.spot.prepend_keymap, shadow.spot.keymap, shadow.spot.append_keymap),
spot: mix(Layer::Spot, shadow.spot.prepend_keymap, shadow.spot.keymap, shadow.spot.append_keymap),
#[rustfmt::skip]
pick: mix(shadow.pick.prepend_keymap, shadow.pick.keymap, shadow.pick.append_keymap),
pick: mix(Layer::Pick, shadow.pick.prepend_keymap, shadow.pick.keymap, shadow.pick.append_keymap),
#[rustfmt::skip]
input: mix(shadow.input.prepend_keymap, shadow.input.keymap, shadow.input.append_keymap),
input: mix(Layer::Input, shadow.input.prepend_keymap, shadow.input.keymap, shadow.input.append_keymap),
#[rustfmt::skip]
confirm: mix(shadow.confirm.prepend_keymap, shadow.confirm.keymap, shadow.confirm.append_keymap),
confirm: mix(Layer::Confirm, shadow.confirm.prepend_keymap, shadow.confirm.keymap, shadow.confirm.append_keymap),
#[rustfmt::skip]
help: mix(shadow.help.prepend_keymap, shadow.help.keymap, shadow.help.append_keymap),
help: mix(Layer::Help, shadow.help.prepend_keymap, shadow.help.keymap, shadow.help.append_keymap),
#[rustfmt::skip]
completion: mix(shadow.completion.prepend_keymap, shadow.completion.keymap, shadow.completion.append_keymap),
cmp: mix(Layer::Cmp, shadow.cmp.prepend_keymap, shadow.cmp.keymap, shadow.cmp.append_keymap),
})
}
}

View file

@ -9,20 +9,20 @@ use super::{Filetype, Flavor, Icons};
#[derive(Deserialize, Serialize)]
pub struct Theme {
pub flavor: Flavor,
pub flavor: Flavor,
#[serde(rename = "manager")]
pub mgr: Mgr, // TODO: Remove `serde(rename)`
pub mode: Mode,
pub status: Status,
pub which: Which,
pub confirm: Confirm,
pub spot: Spot,
pub notify: Notify,
pub pick: Pick,
pub input: Input,
pub completion: Completion,
pub tasks: Tasks,
pub help: Help,
pub mgr: Mgr, // TODO: Remove `serde(rename)`
pub mode: Mode,
pub status: Status,
pub which: Which,
pub confirm: Confirm,
pub spot: Spot,
pub notify: Notify,
pub pick: Pick,
pub input: Input,
pub cmp: Cmp,
pub tasks: Tasks,
pub help: Help,
// File-specific styles
#[serde(rename = "filetype", deserialize_with = "Filetype::deserialize", skip_serializing)]
@ -178,7 +178,7 @@ pub struct Input {
}
#[derive(Deserialize, Serialize)]
pub struct Completion {
pub struct Cmp {
pub border: Style,
pub active: Style,
pub inactive: Style,

View file

@ -1,7 +1,7 @@
use std::{collections::HashMap, path::PathBuf};
#[derive(Default)]
pub struct Completion {
pub struct Cmp {
pub(super) caches: HashMap<PathBuf, Vec<String>>,
pub(super) cands: Vec<String>,
pub(super) offset: usize,
@ -11,7 +11,7 @@ pub struct Completion {
pub visible: bool,
}
impl Completion {
impl Cmp {
// --- Cands
#[inline]
pub fn window(&self) -> &[String] {

View file

@ -1,7 +1,7 @@
use yazi_macro::render;
use yazi_shared::event::{CmdCow, Data};
use crate::completion::Completion;
use crate::cmp::Cmp;
struct Opt {
step: isize,
@ -11,7 +11,7 @@ impl From<CmdCow> for Opt {
fn from(c: CmdCow) -> Self { Self { step: c.first().and_then(Data::as_isize).unwrap_or(0) } }
}
impl Completion {
impl Cmp {
#[yazi_codegen::command]
pub fn arrow(&mut self, opt: Opt) {
if opt.step > 0 {

View file

@ -2,7 +2,7 @@ use yazi_macro::render;
use yazi_proxy::InputProxy;
use yazi_shared::event::CmdCow;
use crate::completion::Completion;
use crate::cmp::Cmp;
struct Opt {
submit: bool,
@ -15,7 +15,7 @@ impl From<bool> for Opt {
fn from(submit: bool) -> Self { Self { submit } }
}
impl Completion {
impl Cmp {
#[yazi_codegen::command]
pub fn close(&mut self, opt: Opt) {
if let Some(s) = self.selected().filter(|_| opt.submit) {

View file

@ -3,7 +3,7 @@ use std::{borrow::Cow, mem, ops::ControlFlow, path::PathBuf};
use yazi_macro::render;
use yazi_shared::event::{Cmd, CmdCow, Data};
use crate::completion::Completion;
use crate::cmp::Cmp;
const LIMIT: usize = 30;
@ -29,7 +29,7 @@ impl From<Cmd> for Opt {
fn from(c: Cmd) -> Self { Self::from(CmdCow::from(c)) }
}
impl Completion {
impl Cmp {
#[yazi_codegen::command]
pub fn show(&mut self, opt: Opt) {
if self.ticket != opt.ticket {

View file

@ -3,9 +3,9 @@ use std::{borrow::Cow, mem, path::{MAIN_SEPARATOR_STR, PathBuf}};
use tokio::fs;
use yazi_fs::{CWD, expand_path};
use yazi_macro::{emit, render};
use yazi_shared::{Layer, event::{Cmd, CmdCow, Data}};
use yazi_shared::event::{Cmd, CmdCow, Data};
use crate::completion::Completion;
use crate::cmp::Cmp;
struct Opt {
word: Cow<'static, str>,
@ -21,7 +21,7 @@ impl From<CmdCow> for Opt {
}
}
impl Completion {
impl Cmp {
#[yazi_codegen::command]
pub fn trigger(&mut self, opt: Opt) {
if opt.ticket < self.ticket {
@ -55,12 +55,11 @@ impl Completion {
if !cache.is_empty() {
emit!(Call(
Cmd::new("show")
Cmd::new("cmp:show")
.with_any("cache", cache)
.with_any("cache-name", parent)
.with("word", word)
.with("ticket", ticket),
Layer::Completion
.with("ticket", ticket)
));
}
@ -95,7 +94,7 @@ mod tests {
use super::*;
fn compare(s: &str, parent: &str, child: &str) -> bool {
let (p, c) = Completion::split_path(s).unwrap();
let (p, c) = Cmp::split_path(s).unwrap();
let p = p.strip_prefix(yazi_fs::CWD.load().as_ref()).unwrap_or(&p);
p == Path::new(parent) && c == child
}

3
yazi-core/src/cmp/mod.rs Normal file
View file

@ -0,0 +1,3 @@
yazi_macro::mod_pub!(commands);
yazi_macro::mod_flat!(cmp);

View file

@ -1,3 +0,0 @@
yazi_macro::mod_pub!(commands);
yazi_macro::mod_flat!(completion);

View file

@ -1,5 +1,5 @@
use yazi_macro::render;
use yazi_proxy::CompletionProxy;
use yazi_proxy::CmpProxy;
use yazi_shared::{errors::InputError, event::CmdCow};
use crate::input::Input;
@ -19,7 +19,7 @@ impl Input {
#[yazi_codegen::command]
pub fn close(&mut self, opt: Opt) {
if self.completion {
CompletionProxy::close();
CmpProxy::close();
}
if let Some(cb) = self.callback.take() {

View file

@ -1,5 +1,5 @@
use yazi_macro::render;
use yazi_proxy::CompletionProxy;
use yazi_proxy::CmpProxy;
use yazi_shared::event::CmdCow;
use crate::input::{Input, InputMode, op::InputOp};
@ -29,7 +29,7 @@ impl Input {
self.move_(-1);
if self.completion {
CompletionProxy::close();
CmpProxy::close();
}
}
InputMode::Replace => {

View file

@ -6,7 +6,7 @@
clippy::unit_arg
)]
yazi_macro::mod_pub!(completion confirm help input mgr notify pick spot tab tasks which);
yazi_macro::mod_pub!(cmp confirm help input mgr notify pick spot tab tasks which);
pub fn init() {
mgr::WATCHED.with(<_>::default);

View file

@ -1,7 +1,7 @@
use std::time::Instant;
use yazi_macro::emit;
use yazi_shared::{Layer, event::Cmd};
use yazi_shared::event::Cmd;
use crate::notify::{Message, Notify};
@ -14,7 +14,7 @@ impl Notify {
if self.messages.iter().all(|m| m != &msg) {
self.messages.push(msg);
emit!(Call(Cmd::args("update_notify", &[0]), Layer::App));
emit!(Call(Cmd::args("app:update_notify", &[0])));
}
}
}

View file

@ -2,7 +2,7 @@ use std::time::Duration;
use ratatui::layout::Rect;
use yazi_macro::emit;
use yazi_shared::{Layer, event::{Cmd, CmdCow, Data}};
use yazi_shared::event::{Cmd, CmdCow, Data};
use crate::notify::Notify;
@ -69,7 +69,7 @@ impl Notify {
self.tick_handle = Some(tokio::spawn(async move {
tokio::time::sleep(interval).await;
emit!(Call(Cmd::args("update_notify", &[interval.as_secs_f64()]), Layer::App));
emit!(Call(Cmd::args("app:update_notify", &[interval.as_secs_f64()])));
}));
}
}

View file

@ -6,7 +6,7 @@ use yazi_config::popup::InputCfg;
use yazi_dds::Pubsub;
use yazi_fs::expand_path;
use yazi_macro::render;
use yazi_proxy::{CompletionProxy, InputProxy, MgrProxy, TabProxy};
use yazi_proxy::{CmpProxy, InputProxy, MgrProxy, TabProxy};
use yazi_shared::{Debounce, errors::InputError, event::CmdCow, url::Url};
use crate::tab::Tab;
@ -98,7 +98,7 @@ impl Tab {
}
}
Err(InputError::Completed(before, ticket)) => {
CompletionProxy::trigger(&before, ticket);
CmpProxy::trigger(&before, ticket);
}
_ => break,
}

View file

@ -6,7 +6,7 @@ use yazi_config::popup::InputCfg;
use yazi_fs::FilterCase;
use yazi_macro::emit;
use yazi_proxy::InputProxy;
use yazi_shared::{Debounce, Layer, errors::InputError, event::{Cmd, CmdCow}};
use yazi_shared::{Debounce, errors::InputError, event::{Cmd, CmdCow}};
use crate::tab::Tab;
@ -41,11 +41,10 @@ impl Tab {
let (Ok(s) | Err(InputError::Typed(s))) = result else { continue };
emit!(Call(
Cmd::args("filter_do", &[s])
Cmd::args("mgr:filter_do", &[s])
.with_bool("smart", opt.case == FilterCase::Smart)
.with_bool("insensitive", opt.case == FilterCase::Insensitive)
.with_bool("done", done),
Layer::Mgr
.with_bool("done", done)
));
}
});

View file

@ -6,7 +6,7 @@ use yazi_config::popup::InputCfg;
use yazi_fs::FilterCase;
use yazi_macro::emit;
use yazi_proxy::InputProxy;
use yazi_shared::{Debounce, Layer, errors::InputError, event::{Cmd, CmdCow}};
use yazi_shared::{Debounce, errors::InputError, event::{Cmd, CmdCow}};
use crate::tab::Tab;
@ -33,11 +33,10 @@ impl Tab {
while let Some(Ok(s)) | Some(Err(InputError::Typed(s))) = rx.next().await {
emit!(Call(
Cmd::args("find_do", &[s])
Cmd::args("mgr:find_do", &[s])
.with_bool("previous", opt.prev)
.with_bool("smart", opt.case == FilterCase::Smart)
.with_bool("insensitive", opt.case == FilterCase::Insensitive),
Layer::Mgr
.with_bool("insensitive", opt.case == FilterCase::Insensitive)
));
}
});

View file

@ -5,7 +5,7 @@ use tokio::{task::JoinHandle, time::sleep};
use yazi_adapter::Dimension;
use yazi_macro::emit;
use yazi_scheduler::{Ongoing, Scheduler, TaskSummary};
use yazi_shared::{Layer, event::Cmd};
use yazi_shared::event::Cmd;
use super::{TASKS_BORDER, TASKS_PADDING, TASKS_PERCENT, TasksProgress};
@ -32,7 +32,7 @@ impl Tasks {
let new = TasksProgress::from(&*ongoing.lock());
if last != new {
last = new;
emit!(Call(Cmd::new("update_progress").with_any("progress", new), Layer::App));
emit!(Call(Cmd::new("app:update_progress").with_any("progress", new)));
}
}
});

View file

@ -1,5 +1,3 @@
use std::str::FromStr;
use yazi_config::{KEYMAP, keymap::{Chord, Key}};
use yazi_macro::render;
use yazi_shared::{Layer, event::CmdCow};
@ -8,7 +6,6 @@ use crate::which::{Which, WhichSorter};
pub struct Opt {
cands: Vec<Chord>,
layer: Layer,
silent: bool,
}
@ -16,11 +13,7 @@ impl TryFrom<CmdCow> for Opt {
type Error = anyhow::Error;
fn try_from(mut c: CmdCow) -> Result<Self, Self::Error> {
Ok(Self {
cands: c.take_any("candidates").unwrap_or_default(),
layer: Layer::from_str(&c.take_str("layer").unwrap_or_default())?,
silent: c.bool("silent"),
})
Ok(Self { cands: c.take_any("candidates").unwrap_or_default(), silent: c.bool("silent") })
}
}
@ -34,7 +27,6 @@ impl Which {
return;
}
self.layer = opt.layer;
self.times = 0;
self.cands = opt.cands.into_iter().map(|c| c.into()).collect();
@ -44,7 +36,6 @@ impl Which {
}
pub fn show_with(&mut self, key: Key, layer: Layer) {
self.layer = layer;
self.times = 1;
self.cands = KEYMAP
.get(layer)

View file

@ -1,12 +1,10 @@
use yazi_config::keymap::{ChordCow, Key};
use yazi_macro::{emit, render_and};
use yazi_shared::Layer;
#[derive(Default)]
pub struct Which {
pub(super) layer: Layer,
pub times: usize,
pub cands: Vec<ChordCow>,
pub times: usize,
pub cands: Vec<ChordCow>,
// Visibility
pub visible: bool,
@ -21,10 +19,10 @@ impl Which {
if self.cands.is_empty() {
self.reset();
} else if self.cands.len() == 1 {
emit!(Seq(self.cands.remove(0).into_seq(), self.layer));
emit!(Seq(self.cands.remove(0).into_seq()));
self.reset();
} else if let Some(i) = self.cands.iter().position(|c| c.on.len() == self.times) {
emit!(Seq(self.cands.remove(i).into_seq(), self.layer));
emit!(Seq(self.cands.remove(i).into_seq()));
self.reset();
}

View file

@ -3,7 +3,7 @@ use std::{fmt::Display, io::Write, str::FromStr};
use anyhow::{Result, anyhow};
use yazi_boot::BOOT;
use yazi_macro::emit;
use yazi_shared::{Layer, event::Cmd};
use yazi_shared::event::Cmd;
use crate::{ID, body::Body};
@ -47,7 +47,7 @@ impl<'a> Payload<'a> {
impl Payload<'static> {
pub(super) fn emit(self) {
self.try_flush();
emit!(Call(Cmd::new("accept_payload").with_any("payload", self), Layer::App));
emit!(Call(Cmd::new("app:accept_payload").with_any("payload", self)));
}
}

View file

@ -5,7 +5,7 @@ use crossterm::event::KeyEvent;
use yazi_config::keymap::Key;
use yazi_core::input::InputMode;
use yazi_macro::emit;
use yazi_shared::{Layer, event::{CmdCow, Event, NEED_RENDER}};
use yazi_shared::event::{CmdCow, Event, NEED_RENDER};
use crate::{Ctx, Executor, Router, Signals, Term, lives::Lives};
@ -53,8 +53,8 @@ impl App {
#[inline]
fn dispatch(&mut self, event: Event) -> Result<()> {
match event {
Event::Call(cmd, layer) => self.dispatch_call(cmd, layer),
Event::Seq(cmds, layer) => self.dispatch_seq(cmds, layer),
Event::Call(cmd) => self.dispatch_call(cmd),
Event::Seq(cmds) => self.dispatch_seq(cmds),
Event::Render => self.dispatch_render(),
Event::Key(key) => self.dispatch_key(key),
Event::Mouse(mouse) => self.mouse(mouse),
@ -66,17 +66,15 @@ impl App {
}
#[inline]
fn dispatch_call(&mut self, cmd: CmdCow, layer: Layer) {
Executor::new(self).execute(cmd, layer);
}
fn dispatch_call(&mut self, cmd: CmdCow) { Executor::new(self).execute(cmd); }
#[inline]
fn dispatch_seq(&mut self, mut cmds: Vec<CmdCow>, layer: Layer) {
fn dispatch_seq(&mut self, mut cmds: Vec<CmdCow>) {
if let Some(last) = cmds.pop() {
Executor::new(self).execute(last, layer);
Executor::new(self).execute(last);
}
if !cmds.is_empty() {
emit!(Seq(cmds, layer));
emit!(Seq(cmds));
}
}

View file

@ -6,34 +6,31 @@ use yazi_config::{THEME, popup::{Offset, Position}};
use crate::Ctx;
pub(crate) struct Completion<'a> {
pub(crate) struct Cmp<'a> {
cx: &'a Ctx,
}
impl<'a> Completion<'a> {
impl<'a> Cmp<'a> {
pub(crate) fn new(cx: &'a Ctx) -> Self { Self { cx } }
}
impl Widget for Completion<'_> {
impl Widget for Cmp<'_> {
fn render(self, rect: Rect, buf: &mut Buffer) {
let items: Vec<_> = self
.cx
.completion
.cmp
.window()
.iter()
.enumerate()
.map(|(i, x)| {
let icon = if x.ends_with(MAIN_SEPARATOR) {
&THEME.completion.icon_folder
} else {
&THEME.completion.icon_file
};
let icon =
if x.ends_with(MAIN_SEPARATOR) { &THEME.cmp.icon_folder } else { &THEME.cmp.icon_file };
let mut item = ListItem::new(format!(" {icon} {x}"));
if i == self.cx.completion.rel_cursor() {
item = item.style(THEME.completion.active);
if i == self.cx.cmp.rel_cursor() {
item = item.style(THEME.cmp.active);
} else {
item = item.style(THEME.completion.inactive);
item = item.style(THEME.cmp.inactive);
}
item
@ -57,9 +54,7 @@ impl Widget for Completion<'_> {
yazi_plugin::elements::Clear::default().render(area, buf);
List::new(items)
.block(
Block::bordered().border_type(BorderType::Rounded).border_style(THEME.completion.border),
)
.block(Block::bordered().border_type(BorderType::Rounded).border_style(THEME.cmp.border))
.render(area, buf);
}
}

1
yazi-fm/src/cmp/mod.rs Normal file
View file

@ -0,0 +1 @@
yazi_macro::mod_flat!(cmp);

View file

@ -1 +0,0 @@
yazi_macro::mod_flat!(completion);

View file

@ -1,31 +1,31 @@
use ratatui::layout::Rect;
use yazi_core::{completion::Completion, confirm::Confirm, help::Help, input::Input, mgr::Mgr, notify::Notify, pick::Pick, tab::{Folder, Tab}, tasks::Tasks, which::Which};
use yazi_core::{cmp::Cmp, confirm::Confirm, help::Help, input::Input, mgr::Mgr, notify::Notify, pick::Pick, tab::{Folder, Tab}, tasks::Tasks, which::Which};
use yazi_shared::Layer;
pub struct Ctx {
pub mgr: Mgr,
pub tasks: Tasks,
pub pick: Pick,
pub input: Input,
pub confirm: Confirm,
pub help: Help,
pub completion: Completion,
pub which: Which,
pub notify: Notify,
pub mgr: Mgr,
pub tasks: Tasks,
pub pick: Pick,
pub input: Input,
pub confirm: Confirm,
pub help: Help,
pub cmp: Cmp,
pub which: Which,
pub notify: Notify,
}
impl Ctx {
pub fn make() -> Self {
Self {
mgr: Mgr::make(),
tasks: Tasks::serve(),
pick: Default::default(),
input: Default::default(),
confirm: Default::default(),
help: Default::default(),
completion: Default::default(),
which: Default::default(),
notify: Default::default(),
mgr: Mgr::make(),
tasks: Tasks::serve(),
pick: Default::default(),
input: Default::default(),
confirm: Default::default(),
help: Default::default(),
cmp: Default::default(),
which: Default::default(),
notify: Default::default(),
}
}
@ -45,8 +45,8 @@ impl Ctx {
pub fn layer(&self) -> Layer {
if self.which.visible {
Layer::Which
} else if self.completion.visible {
Layer::Completion
} else if self.cmp.visible {
Layer::Cmp
} else if self.help.visible {
Layer::Help
} else if self.confirm.visible {

View file

@ -12,8 +12,8 @@ impl<'a> Executor<'a> {
pub(super) fn new(app: &'a mut App) -> Self { Self { app } }
#[inline]
pub(super) fn execute(&mut self, cmd: CmdCow, layer: Layer) {
match layer {
pub(super) fn execute(&mut self, cmd: CmdCow) {
match cmd.layer {
Layer::App => self.app(cmd),
Layer::Mgr => self.mgr(cmd),
Layer::Tasks => self.tasks(cmd),
@ -22,7 +22,7 @@ impl<'a> Executor<'a> {
Layer::Input => self.input(cmd),
Layer::Confirm => self.confirm(cmd),
Layer::Help => self.help(cmd),
Layer::Completion => self.completion(cmd),
Layer::Cmp => self.cmp(cmd),
Layer::Which => self.which(cmd),
}
}
@ -249,7 +249,7 @@ impl<'a> Executor<'a> {
if cmd.name.as_str() == "complete" {
return if cmd.bool("trigger") {
self.app.cx.completion.trigger(cmd)
self.app.cx.cmp.trigger(cmd)
} else {
self.app.cx.input.complete(cmd)
};
@ -319,11 +319,11 @@ impl<'a> Executor<'a> {
}
}
fn completion(&mut self, cmd: CmdCow) {
fn cmp(&mut self, cmd: CmdCow) {
macro_rules! on {
($name:ident) => {
if cmd.name == stringify!($name) {
return self.app.cx.completion.$name(cmd);
return self.app.cx.cmp.$name(cmd);
}
};
}
@ -336,7 +336,7 @@ impl<'a> Executor<'a> {
match cmd.name.as_str() {
"close_input" => self.app.cx.input.close(cmd),
// Help
"help" => self.app.cx.help.toggle(Layer::Completion),
"help" => self.app.cx.help.toggle(Layer::Cmp),
// Plugin
"plugin" => self.app.plugin(cmd),
_ => {}

View file

@ -4,7 +4,7 @@
#[global_allocator]
static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
yazi_macro::mod_pub!(app completion confirm help input lives mgr notify pick spot tasks which);
yazi_macro::mod_pub!(app cmp confirm help input lives mgr notify pick spot tasks which);
yazi_macro::mod_flat!(context executor logs panic root router signals term);

View file

@ -3,7 +3,7 @@ use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
use tracing::error;
use yazi_plugin::{LUA, elements::render_once};
use super::{completion, confirm, help, input, mgr, pick, spot, tasks, which};
use super::{cmp, confirm, help, input, mgr, pick, spot, tasks, which};
use crate::Ctx;
pub(super) struct Root<'a> {
@ -60,8 +60,8 @@ impl Widget for Root<'_> {
help::Help::new(self.cx).render(area, buf);
}
if self.cx.completion.visible {
completion::Completion::new(self.cx).render(area, buf);
if self.cx.cmp.visible {
cmp::Cmp::new(self.cx).render(area, buf);
}
if self.cx.which.visible {

View file

@ -30,7 +30,7 @@ impl<'a> Router<'a> {
L::Mgr | L::Tasks | L::Spot | L::Pick | L::Input | L::Confirm | L::Help => {
self.matches(layer, key)
}
L::Completion => self.matches(L::Completion, key) || self.matches(L::Input, key),
L::Cmp => self.matches(L::Cmp, key) || self.matches(L::Input, key),
L::Which => cx.which.type_(key),
}
}
@ -45,7 +45,7 @@ impl<'a> Router<'a> {
if on.len() > 1 {
self.app.cx.which.show_with(key, layer);
} else {
emit!(Seq(ChordCow::from(chord).into_seq(), layer));
emit!(Seq(ChordCow::from(chord).into_seq()));
}
return true;
}

View file

@ -1,6 +1,6 @@
use std::collections::{HashMap, HashSet};
use yazi_shared::{Id, Ids, Layer, event::Cmd, url::{Url, UrnBuf}};
use yazi_shared::{Id, Ids, event::Cmd, url::{Url, UrnBuf}};
use super::{Cha, File};
@ -39,11 +39,8 @@ impl FilesOp {
#[inline]
pub fn emit(self) {
yazi_shared::event::Event::Call(
Cmd::new("update_files").with_any("op", self).into(),
Layer::Mgr,
)
.emit();
yazi_shared::event::Event::Call(Cmd::new("mgr:update_files").with_any("op", self).into())
.emit();
}
pub fn prepare(cwd: &Url) -> Id {

View file

@ -3,11 +3,11 @@ macro_rules! emit {
(Quit($opt:expr)) => {
yazi_shared::event::Event::Quit($opt).emit();
};
(Call($cmd:expr, $layer:expr)) => {
yazi_shared::event::Event::Call(yazi_shared::event::CmdCow::from($cmd), $layer).emit();
(Call($cmd:expr)) => {
yazi_shared::event::Event::Call(yazi_shared::event::CmdCow::from($cmd)).emit();
};
(Seq($cmds:expr, $layer:expr)) => {
yazi_shared::event::Event::Seq($cmds, $layer).emit();
(Seq($cmds:expr)) => {
yazi_shared::event::Event::Seq($cmds).emit();
};
($event:ident) => {
yazi_shared::event::Event::$event.emit();

View file

@ -40,21 +40,21 @@ impl Utils {
pub(super) fn app_emit(lua: &Lua) -> mlua::Result<Function> {
lua.create_function(|_, (name, args): (String, Table)| {
emit!(Call(Cmd { name, args: Sendable::table_to_args(args)? }, Layer::App));
emit!(Call(Cmd { name, args: Sendable::table_to_args(args)?, layer: Layer::App }));
Ok(())
})
}
pub(super) fn mgr_emit(lua: &Lua) -> mlua::Result<Function> {
lua.create_function(|_, (name, args): (String, Table)| {
emit!(Call(Cmd { name, args: Sendable::table_to_args(args)? }, Layer::Mgr));
emit!(Call(Cmd { name, args: Sendable::table_to_args(args)?, layer: Layer::Mgr }));
Ok(())
})
}
pub(super) fn input_emit(lua: &Lua) -> mlua::Result<Function> {
lua.create_function(|_, (name, args): (String, Table)| {
emit!(Call(Cmd { name, args: Sendable::table_to_args(args)? }, Layer::Input));
emit!(Call(Cmd { name, args: Sendable::table_to_args(args)?, layer: Layer::Input }));
Ok(())
})
}

View file

@ -6,7 +6,7 @@ use tokio_stream::wrappers::UnboundedReceiverStream;
use yazi_config::{keymap::{Chord, Key}, popup::{ConfirmCfg, InputCfg}};
use yazi_macro::emit;
use yazi_proxy::{AppProxy, ConfirmProxy, InputProxy};
use yazi_shared::{Debounce, Layer, event::Cmd};
use yazi_shared::{Debounce, event::Cmd};
use super::Utils;
use crate::{bindings::InputRx, elements::{Line, Pos, Text}};
@ -21,18 +21,16 @@ impl Utils {
let cand = cand?;
cands.push(Chord {
on: Self::parse_keys(cand.raw_get("on")?)?,
run: vec![Cmd::args("callback", &[i]).with_any("tx", tx.clone())],
run: vec![Cmd::args("which:callback", &[i]).with_any("tx", tx.clone())],
desc: cand.raw_get("desc").ok(),
});
}
drop(tx);
emit!(Call(
Cmd::new("show")
.with("layer", Layer::Which)
Cmd::new("which:show")
.with_any("candidates", cands)
.with_bool("silent", t.raw_get("silent").unwrap_or_default()),
Layer::Which
.with_bool("silent", t.raw_get("silent").unwrap_or_default())
));
Ok(rx.recv().await.map(|idx| idx + 1))

View file

@ -1,7 +1,7 @@
use mlua::{AnyUserData, Function, IntoLuaMulti, Lua, Table, Value};
use yazi_config::{PREVIEW, preview::PreviewWrap};
use yazi_macro::emit;
use yazi_shared::{Layer, errors::PeekError, event::Cmd};
use yazi_shared::{errors::PeekError, event::Cmd};
use super::Utils;
use crate::{elements::{Area, Rect, Renderable, Text, WRAP, WRAP_NO}, external::Highlighter, file::FileRef};
@ -54,7 +54,7 @@ impl Utils {
wrap: if PREVIEW.wrap == PreviewWrap::Yes { WRAP } else { WRAP_NO },
})];
emit!(Call(Cmd::new("update_peeked").with_any("lock", lock), Layer::Mgr));
emit!(Call(Cmd::new("mgr:update_peeked").with_any("lock", lock)));
(Value::Nil, Value::Nil).into_lua_multi(&lua)
})
}
@ -64,7 +64,7 @@ impl Utils {
let mut lock = PreviewLock::try_from(t)?;
lock.data = widgets.into_iter().map(Renderable::try_from).collect::<mlua::Result<_>>()?;
emit!(Call(Cmd::new("update_peeked").with_any("lock", lock), Layer::Mgr));
emit!(Call(Cmd::new("mgr:update_peeked").with_any("lock", lock)));
Ok(())
})
}

View file

@ -1,7 +1,7 @@
use mlua::{AnyUserData, Function, Lua, Table};
use yazi_config::THEME;
use yazi_macro::emit;
use yazi_shared::{Layer, event::Cmd};
use yazi_shared::event::Cmd;
use super::Utils;
use crate::{elements::Renderable, file::FileRef};
@ -80,7 +80,7 @@ impl Utils {
}),
Renderable::Table(table),
];
emit!(Call(Cmd::new("update_spotted").with_any("lock", lock), Layer::Mgr));
emit!(Call(Cmd::new("mgr:update_spotted").with_any("lock", lock)));
Ok(())
})
@ -91,7 +91,7 @@ impl Utils {
let mut lock = SpotLock::try_from(t)?;
lock.data = widgets.into_iter().map(Renderable::try_from).collect::<mlua::Result<_>>()?;
emit!(Call(Cmd::new("update_spotted").with_any("lock", lock), Layer::Mgr));
emit!(Call(Cmd::new("mgr:update_spotted").with_any("lock", lock)));
Ok(())
})
}

View file

@ -2,7 +2,7 @@ use std::time::Duration;
use tokio::sync::oneshot;
use yazi_macro::emit;
use yazi_shared::{Layer, event::Cmd};
use yazi_shared::event::Cmd;
use crate::options::{NotifyLevel, NotifyOpt, PluginOpt};
@ -12,18 +12,18 @@ impl AppProxy {
#[inline]
pub async fn stop() {
let (tx, rx) = oneshot::channel::<()>();
emit!(Call(Cmd::new("stop").with_any("tx", tx), Layer::App));
emit!(Call(Cmd::new("app:stop").with_any("tx", tx)));
rx.await.ok();
}
#[inline]
pub fn resume() {
emit!(Call(Cmd::new("resume"), Layer::App));
emit!(Call(Cmd::new("app:resume")));
}
#[inline]
pub fn notify(opt: NotifyOpt) {
emit!(Call(Cmd::new("notify").with_any("option", opt), Layer::App));
emit!(Call(Cmd::new("app:notify").with_any("option", opt)));
}
#[inline]
@ -48,11 +48,11 @@ impl AppProxy {
#[inline]
pub fn plugin(opt: PluginOpt) {
emit!(Call(Cmd::new("plugin").with_any("opt", opt), Layer::App));
emit!(Call(Cmd::new("app:plugin").with_any("opt", opt)));
}
#[inline]
pub fn plugin_do(opt: PluginOpt) {
emit!(Call(Cmd::new("plugin_do").with_any("opt", opt), Layer::App));
emit!(Call(Cmd::new("app:plugin_do").with_any("opt", opt)));
}
}

16
yazi-proxy/src/cmp.rs Normal file
View file

@ -0,0 +1,16 @@
use yazi_macro::emit;
use yazi_shared::event::Cmd;
pub struct CmpProxy;
impl CmpProxy {
#[inline]
pub fn close() {
emit!(Call(Cmd::new("cmp:close")));
}
#[inline]
pub fn trigger(word: &str, ticket: usize) {
emit!(Call(Cmd::args("cmp:trigger", &[word]).with("ticket", ticket)));
}
}

View file

@ -1,16 +0,0 @@
use yazi_macro::emit;
use yazi_shared::{Layer, event::Cmd};
pub struct CompletionProxy;
impl CompletionProxy {
#[inline]
pub fn close() {
emit!(Call(Cmd::new("close"), Layer::Completion));
}
#[inline]
pub fn trigger(word: &str, ticket: usize) {
emit!(Call(Cmd::args("trigger", &[word]).with("ticket", ticket), Layer::Completion));
}
}

View file

@ -1,7 +1,7 @@
use tokio::sync::oneshot;
use yazi_config::popup::ConfirmCfg;
use yazi_macro::emit;
use yazi_shared::{Layer, event::Cmd};
use yazi_shared::event::Cmd;
pub struct ConfirmProxy;
@ -12,7 +12,7 @@ impl ConfirmProxy {
#[inline]
pub fn show_rx(cfg: ConfirmCfg) -> oneshot::Receiver<bool> {
let (tx, rx) = oneshot::channel();
emit!(Call(Cmd::new("show").with_any("tx", tx).with_any("cfg", cfg), Layer::Confirm));
emit!(Call(Cmd::new("confirm:show").with_any("tx", tx).with_any("cfg", cfg)));
rx
}
}

View file

@ -1,7 +1,7 @@
use tokio::sync::mpsc;
use yazi_config::popup::InputCfg;
use yazi_macro::emit;
use yazi_shared::{Layer, errors::InputError, event::Cmd};
use yazi_shared::{errors::InputError, event::Cmd};
pub struct InputProxy;
@ -9,12 +9,12 @@ impl InputProxy {
#[inline]
pub fn show(cfg: InputCfg) -> mpsc::UnboundedReceiver<Result<String, InputError>> {
let (tx, rx) = mpsc::unbounded_channel();
emit!(Call(Cmd::new("show").with_any("tx", tx).with_any("cfg", cfg), Layer::Input));
emit!(Call(Cmd::new("input:show").with_any("tx", tx).with_any("cfg", cfg)));
rx
}
#[inline]
pub fn complete(word: &str, ticket: usize) {
emit!(Call(Cmd::args("complete", &[word]).with("ticket", ticket), Layer::Input));
emit!(Call(Cmd::args("input:complete", &[word]).with("ticket", ticket)));
}
}

View file

@ -2,6 +2,6 @@ mod macros;
yazi_macro::mod_pub!(options);
yazi_macro::mod_flat!(app completion confirm input mgr pick semaphore tab tasks);
yazi_macro::mod_flat!(app cmp confirm input mgr pick semaphore tab tasks);
pub fn init() { crate::init_semaphore(); }

View file

@ -1,5 +1,5 @@
use yazi_macro::emit;
use yazi_shared::{Id, Layer, event::Cmd, url::Url};
use yazi_shared::{Id, event::Cmd, url::Url};
use crate::options::OpenDoOpt;
@ -8,55 +8,48 @@ pub struct MgrProxy;
impl MgrProxy {
#[inline]
pub fn spot(skip: Option<usize>) {
emit!(Call(Cmd::new("spot").with_opt("skip", skip), Layer::Mgr));
emit!(Call(Cmd::new("mgr:spot").with_opt("skip", skip)));
}
#[inline]
pub fn peek(force: bool) {
emit!(Call(Cmd::new("peek").with_bool("force", force), Layer::Mgr));
emit!(Call(Cmd::new("mgr:peek").with_bool("force", force)));
}
#[inline]
pub fn hover(url: Option<Url>, tab: Id) {
emit!(Call(
Cmd::args("hover", &url.map_or_else(Vec::new, |u| vec![u])).with("tab", tab),
Layer::Mgr
));
emit!(Call(Cmd::args("mgr:hover", &url.map_or_else(Vec::new, |u| vec![u])).with("tab", tab)));
}
#[inline]
pub fn refresh() {
emit!(Call(Cmd::new("refresh"), Layer::Mgr));
emit!(Call(Cmd::new("mgr:refresh")));
}
#[inline]
pub fn open_do(opt: OpenDoOpt) {
emit!(Call(Cmd::new("open_do").with_any("option", opt), Layer::Mgr));
emit!(Call(Cmd::new("mgr:open_do").with_any("option", opt)));
}
#[inline]
pub fn remove_do(targets: Vec<Url>, permanently: bool) {
emit!(Call(
Cmd::new("remove_do").with_bool("permanently", permanently).with_any("targets", targets),
Layer::Mgr
Cmd::new("mgr:remove_do").with_bool("permanently", permanently).with_any("targets", targets)
));
}
#[inline]
pub fn update_tasks(url: &Url) {
emit!(Call(Cmd::new("update_tasks").with_any("urls", vec![url.clone()]), Layer::Mgr));
emit!(Call(Cmd::new("mgr:update_tasks").with_any("urls", vec![url.clone()])));
}
#[inline]
pub fn update_paged() {
emit!(Call(Cmd::new("update_paged"), Layer::Mgr));
emit!(Call(Cmd::new("mgr:update_paged")));
}
#[inline]
pub fn update_paged_by(page: usize, only_if: &Url) {
emit!(Call(
Cmd::args("update_paged", &[page]).with_any("only-if", only_if.clone()),
Layer::Mgr
));
emit!(Call(Cmd::args("mgr:update_paged", &[page]).with_any("only-if", only_if.clone())));
}
}

View file

@ -1,7 +1,7 @@
use tokio::sync::oneshot;
use yazi_config::popup::PickCfg;
use yazi_macro::emit;
use yazi_shared::{Layer, event::Cmd};
use yazi_shared::event::Cmd;
pub struct PickProxy;
@ -9,7 +9,7 @@ impl PickProxy {
#[inline]
pub async fn show(cfg: PickCfg) -> anyhow::Result<usize> {
let (tx, rx) = oneshot::channel();
emit!(Call(Cmd::new("show").with_any("tx", tx).with_any("cfg", cfg), Layer::Pick));
emit!(Call(Cmd::new("pick:show").with_any("tx", tx).with_any("cfg", cfg)));
rx.await?
}
}

View file

@ -1,5 +1,5 @@
use yazi_macro::emit;
use yazi_shared::{Layer, event::Cmd, url::Url};
use yazi_shared::{event::Cmd, url::Url};
use crate::options::SearchOpt;
@ -8,25 +8,24 @@ pub struct TabProxy;
impl TabProxy {
#[inline]
pub fn cd(target: &Url) {
emit!(Call(Cmd::args("cd", &[target]), Layer::Mgr));
emit!(Call(Cmd::args("mgr:cd", &[target])));
}
#[inline]
pub fn reveal(target: &Url) {
emit!(Call(Cmd::args("reveal", &[target]), Layer::Mgr));
emit!(Call(Cmd::args("mgr:reveal", &[target])));
}
#[inline]
pub fn arrow(step: isize) {
emit!(Call(Cmd::args("arrow", &[step]), Layer::Mgr));
emit!(Call(Cmd::args("mgr:arrow", &[step])));
}
#[inline]
pub fn search_do(opt: SearchOpt) {
emit!(Call(
// TODO: use second positional argument instead of `args` parameter
Cmd::args("search_do", &[opt.subject]).with("via", opt.via).with("args", opt.args_raw),
Layer::Mgr
Cmd::args("mgr:search_do", &[opt.subject]).with("via", opt.via).with("args", opt.args_raw)
));
}
}

View file

@ -3,7 +3,7 @@ use std::{borrow::Cow, ffi::OsString};
use tokio::sync::oneshot;
use yazi_config::open::Opener;
use yazi_macro::emit;
use yazi_shared::{Layer, event::Cmd, url::Url};
use yazi_shared::{event::Cmd, url::Url};
use crate::options::{OpenWithOpt, ProcessExecOpt};
@ -12,24 +12,22 @@ pub struct TasksProxy;
impl TasksProxy {
#[inline]
pub fn open_with(opener: Cow<'static, Opener>, cwd: Url, targets: Vec<Url>) {
emit!(Call(
Cmd::new("open_with").with_any("option", OpenWithOpt { opener, cwd, targets }),
Layer::Tasks
));
emit!(Call(Cmd::new("tasks:open_with").with_any("option", OpenWithOpt {
opener,
cwd,
targets
})));
}
#[inline]
pub async fn process_exec(opener: Cow<'static, Opener>, cwd: Url, args: Vec<OsString>) {
let (tx, rx) = oneshot::channel();
emit!(Call(
Cmd::new("process_exec").with_any("option", ProcessExecOpt {
cwd,
opener,
args,
done: Some(tx)
}),
Layer::Tasks
));
emit!(Call(Cmd::new("tasks:process_exec").with_any("option", ProcessExecOpt {
cwd,
opener,
args,
done: Some(tx)
})));
rx.await.ok();
}
}

View file

@ -1,31 +1,36 @@
use std::{any::Any, borrow::Cow, collections::HashMap, fmt::{self, Display}, mem, str::FromStr};
use std::{any::Any, borrow::Cow, collections::HashMap, fmt::{self, Display}, str::FromStr};
use anyhow::{Result, bail};
use serde::{Deserialize, de};
use super::{Data, DataKey};
use crate::url::Url;
use crate::{Layer, url::Url};
#[derive(Debug, Default)]
pub struct Cmd {
pub name: String,
pub args: HashMap<DataKey, Data>,
pub name: String,
pub args: HashMap<DataKey, Data>,
pub layer: Layer,
}
impl Cmd {
#[inline]
pub fn new(name: &str) -> Self { Self { name: name.to_owned(), ..Default::default() } }
pub fn new(s: &str) -> Self {
let (layer, name) = match s.split_once(':') {
Some((l, n)) => (Layer::from_str(l).unwrap_or_default(), n),
None => (Layer::default(), s),
};
Self { name: name.to_owned(), args: Default::default(), layer }
}
#[inline]
pub fn args(name: &str, args: &[impl ToString]) -> Self {
Self {
name: name.to_owned(),
args: args
.iter()
.enumerate()
.map(|(i, s)| (DataKey::Integer(i as i64), Data::String(s.to_string())))
.collect(),
}
let mut me = Self::new(name);
me.args = args
.iter()
.enumerate()
.map(|(i, s)| (DataKey::Integer(i as i64), Data::String(s.to_string())))
.collect();
me
}
// --- With
@ -170,15 +175,14 @@ impl FromStr for Cmd {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut args = crate::shell::split_unix(s)?;
let args = crate::shell::split_unix(s)?;
if args.is_empty() || args[0].is_empty() {
bail!("command name cannot be empty");
}
Ok(Cmd {
name: mem::take(&mut args[0]),
args: Cmd::parse_args(args.into_iter().skip(1), true)?,
})
let mut me = Self::new(&args[0]);
me.args = Cmd::parse_args(args.into_iter().skip(1), true)?;
Ok(me)
}
}

View file

@ -4,15 +4,15 @@ use crossterm::event::{KeyEvent, MouseEvent};
use tokio::sync::mpsc;
use super::CmdCow;
use crate::{Layer, RoCell};
use crate::RoCell;
static TX: RoCell<mpsc::UnboundedSender<Event>> = RoCell::new();
static RX: RoCell<mpsc::UnboundedReceiver<Event>> = RoCell::new();
#[derive(Debug)]
pub enum Event {
Call(CmdCow, Layer),
Seq(Vec<CmdCow>, Layer),
Call(CmdCow),
Seq(Vec<CmdCow>),
Render,
Key(KeyEvent),
Mouse(MouseEvent),

View file

@ -14,7 +14,7 @@ pub enum Layer {
Input,
Confirm,
Help,
Completion,
Cmp,
Which,
}
@ -29,7 +29,7 @@ impl Display for Layer {
Self::Input => "input",
Self::Confirm => "confirm",
Self::Help => "help",
Self::Completion => "completion",
Self::Cmp => "cmp",
Self::Which => "which",
})
}