diff --git a/yazi-adaptor/src/image.rs b/yazi-adaptor/src/image.rs index 61643206..ae887b93 100644 --- a/yazi-adaptor/src/image.rs +++ b/yazi-adaptor/src/image.rs @@ -3,7 +3,7 @@ use std::{fs::File, io::BufReader, path::{Path, PathBuf}}; use anyhow::Result; use image::{imageops::FilterType, io::Limits, DynamicImage, ImageFormat}; use yazi_config::{PREVIEW, TASKS}; -use yazi_shared::Term; +use yazi_shared::term::Term; pub struct Image; diff --git a/yazi-adaptor/src/iterm2.rs b/yazi-adaptor/src/iterm2.rs index d1655135..4ca13bc4 100644 --- a/yazi-adaptor/src/iterm2.rs +++ b/yazi-adaptor/src/iterm2.rs @@ -4,7 +4,7 @@ use anyhow::Result; use base64::{engine::general_purpose, Engine}; use image::{codecs::jpeg::JpegEncoder, DynamicImage}; use ratatui::prelude::Rect; -use yazi_shared::Term; +use yazi_shared::term::Term; use super::image::Image; use crate::{CLOSE, START}; diff --git a/yazi-adaptor/src/kitty.rs b/yazi-adaptor/src/kitty.rs index 64686a90..86a35880 100644 --- a/yazi-adaptor/src/kitty.rs +++ b/yazi-adaptor/src/kitty.rs @@ -4,7 +4,7 @@ use anyhow::Result; use base64::{engine::general_purpose, Engine}; use image::DynamicImage; use ratatui::prelude::Rect; -use yazi_shared::Term; +use yazi_shared::term::Term; use super::image::Image; use crate::{CLOSE, ESCAPE, START}; diff --git a/yazi-adaptor/src/kitty_old.rs b/yazi-adaptor/src/kitty_old.rs index 72e9f2fa..1dffaaa8 100644 --- a/yazi-adaptor/src/kitty_old.rs +++ b/yazi-adaptor/src/kitty_old.rs @@ -4,7 +4,7 @@ use anyhow::Result; use base64::{engine::general_purpose, Engine}; use image::DynamicImage; use ratatui::prelude::Rect; -use yazi_shared::Term; +use yazi_shared::term::Term; use super::image::Image; use crate::{CLOSE, ESCAPE, START}; diff --git a/yazi-adaptor/src/sixel.rs b/yazi-adaptor/src/sixel.rs index feb90ed8..ac899dcd 100644 --- a/yazi-adaptor/src/sixel.rs +++ b/yazi-adaptor/src/sixel.rs @@ -4,7 +4,7 @@ use anyhow::{bail, Result}; use color_quant::NeuQuant; use image::DynamicImage; use ratatui::prelude::Rect; -use yazi_shared::Term; +use yazi_shared::term::Term; use crate::{Image, CLOSE, ESCAPE, START}; diff --git a/yazi-config/src/boot/boot.rs b/yazi-config/src/boot/boot.rs index 9b025da6..60c64e0b 100644 --- a/yazi-config/src/boot/boot.rs +++ b/yazi-config/src/boot/boot.rs @@ -1,7 +1,7 @@ use std::{ffi::OsString, fs, path::PathBuf, process}; use clap::Parser; -use yazi_shared::{current_cwd, expand_path}; +use yazi_shared::fs::{current_cwd, expand_path}; use super::cli::Args; use crate::{Xdg, PREVIEW}; diff --git a/yazi-config/src/keymap/control.rs b/yazi-config/src/keymap/control.rs index 30789317..a3b1af64 100644 --- a/yazi-config/src/keymap/control.rs +++ b/yazi-config/src/keymap/control.rs @@ -1,20 +1,31 @@ use std::borrow::Cow; use serde::Deserialize; +use yazi_shared::event::Exec; -use super::{Exec, Key}; +use super::Key; -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] pub struct Control { pub on: Vec, - #[serde(deserialize_with = "Exec::deserialize")] + #[serde(deserialize_with = "super::exec_deserialize")] pub exec: Vec, pub desc: Option, } impl Control { - #[inline] - pub fn to_call(&self) -> Vec { self.exec.clone() } + pub fn to_call(&self) -> Vec { + self + .exec + .iter() + .map(|e| Exec { + cmd: e.cmd.clone(), + args: e.args.clone(), + named: e.named.clone(), + ..Default::default() + }) + .collect() + } } impl Control { diff --git a/yazi-config/src/keymap/exec.rs b/yazi-config/src/keymap/exec.rs index 9548470a..7c257c54 100644 --- a/yazi-config/src/keymap/exec.rs +++ b/yazi-config/src/keymap/exec.rs @@ -1,25 +1,22 @@ -use std::{collections::BTreeMap, fmt::{self, Debug, Display}}; +use std::fmt; -use anyhow::bail; +use anyhow::{bail, Result}; use serde::{de::{self, Visitor}, Deserializer}; +use yazi_shared::event::Exec; -#[derive(Clone, Debug)] -pub struct Exec { - pub cmd: String, - pub args: Vec, - pub named: BTreeMap, -} +pub(super) fn exec_deserialize<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + struct ExecVisitor; -impl TryFrom<&str> for Exec { - type Error = anyhow::Error; - - fn try_from(s: &str) -> Result { + fn parse(s: &str) -> Result { let s = shell_words::split(s)?; if s.is_empty() { bail!("`exec` cannot be empty"); } - let mut exec = Self { cmd: s[0].clone(), args: Vec::new(), named: BTreeMap::new() }; + let mut exec = Exec { cmd: s[0].clone(), ..Default::default() }; for arg in s.into_iter().skip(1) { if arg.starts_with("--") { let mut arg = arg.splitn(2, '='); @@ -32,86 +29,32 @@ impl TryFrom<&str> for Exec { } Ok(exec) } -} -impl Display for Exec { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.cmd)?; - 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}")?; - } - } - Ok(()) - } -} + impl<'de> Visitor<'de> for ExecVisitor { + type Value = Vec; -impl Exec { - pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> - where - D: Deserializer<'de>, - { - struct ExecVisitor; - - impl<'de> Visitor<'de> for ExecVisitor { - type Value = Vec; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a exec string, e.g. tab_switch 0") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: de::SeqAccess<'de>, - { - let mut execs = Vec::new(); - while let Some(value) = &seq.next_element::()? { - execs.push(Exec::try_from(value.as_str()).map_err(de::Error::custom)?); - } - Ok(execs) - } - - fn visit_str(self, value: &str) -> Result - where - E: de::Error, - { - Ok(vec![Exec::try_from(value).map_err(de::Error::custom)?]) - } + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a exec string, e.g. `tab_switch 0`") } - deserializer.deserialize_any(ExecVisitor) - } -} - -impl Exec { - #[inline] - pub fn call(cwd: &str, args: Vec) -> Self { - Exec { cmd: cwd.to_owned(), args, named: Default::default() } - } - - #[inline] - pub fn call_named(cwd: &str, named: BTreeMap) -> Self { - Exec { cmd: cwd.to_owned(), args: Default::default(), named } - } - - #[inline] - pub fn vec(self) -> Vec { vec![self] } - - #[inline] - pub fn with(mut self, name: impl ToString, value: impl ToString) -> Self { - self.named.insert(name.to_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()); + fn visit_seq(self, mut seq: A) -> Result + where + A: de::SeqAccess<'de>, + { + let mut execs = Vec::new(); + while let Some(value) = &seq.next_element::()? { + execs.push(parse(value).map_err(de::Error::custom)?); + } + Ok(execs) + } + + fn visit_str(self, value: &str) -> Result + where + E: de::Error, + { + Ok(vec![parse(value).map_err(de::Error::custom)?]) } - self } + + deserializer.deserialize_any(ExecVisitor) } diff --git a/yazi-config/src/keymap/keymap.rs b/yazi-config/src/keymap/keymap.rs index ca293d2f..2455dbb8 100644 --- a/yazi-config/src/keymap/keymap.rs +++ b/yazi-config/src/keymap/keymap.rs @@ -1,6 +1,5 @@ -use std::fmt::{self, Display}; - use serde::{Deserialize, Deserializer}; +use yazi_shared::Layer; use super::Control; use crate::MERGED_KEYMAP; @@ -63,41 +62,16 @@ impl Default for Keymap { impl Keymap { #[inline] - pub fn get(&self, layer: KeymapLayer) -> &Vec { + pub fn get(&self, layer: Layer) -> &Vec { match layer { - KeymapLayer::Manager => &self.manager, - KeymapLayer::Tasks => &self.tasks, - KeymapLayer::Select => &self.select, - KeymapLayer::Input => &self.input, - KeymapLayer::Help => &self.help, - KeymapLayer::Completion => &self.completion, - KeymapLayer::Which => unreachable!(), - } - } -} - -#[derive(Debug, Default, PartialEq, Eq, Hash, Clone, Copy)] -pub enum KeymapLayer { - #[default] - Manager, - Tasks, - Select, - Input, - Help, - Completion, - Which, -} - -impl Display for KeymapLayer { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - KeymapLayer::Manager => write!(f, "manager"), - KeymapLayer::Tasks => write!(f, "tasks"), - KeymapLayer::Select => write!(f, "select"), - KeymapLayer::Input => write!(f, "input"), - KeymapLayer::Help => write!(f, "help"), - KeymapLayer::Completion => write!(f, "completion"), - KeymapLayer::Which => write!(f, "which"), + Layer::App => unreachable!(), + Layer::Manager => &self.manager, + Layer::Tasks => &self.tasks, + Layer::Select => &self.select, + Layer::Input => &self.input, + Layer::Help => &self.help, + Layer::Completion => &self.completion, + Layer::Which => unreachable!(), } } } diff --git a/yazi-config/src/keymap/mod.rs b/yazi-config/src/keymap/mod.rs index 4ca907b5..c531882a 100644 --- a/yazi-config/src/keymap/mod.rs +++ b/yazi-config/src/keymap/mod.rs @@ -4,6 +4,7 @@ mod key; mod keymap; pub use control::*; +#[allow(unused_imports)] pub use exec::*; pub use key::*; pub use keymap::*; diff --git a/yazi-config/src/manager/layout.rs b/yazi-config/src/manager/layout.rs index 3123f2c7..61cbb346 100644 --- a/yazi-config/src/manager/layout.rs +++ b/yazi-config/src/manager/layout.rs @@ -2,7 +2,7 @@ use anyhow::bail; use crossterm::terminal::WindowSize; use ratatui::{prelude::Rect, widgets::{Block, Padding}}; use serde::{Deserialize, Serialize}; -use yazi_shared::Term; +use yazi_shared::term::Term; use crate::{PREVIEW, THEME}; diff --git a/yazi-config/src/plugins/plugins.rs b/yazi-config/src/plugins/plugins.rs index 1ff217a2..b2b95a78 100644 --- a/yazi-config/src/plugins/plugins.rs +++ b/yazi-config/src/plugins/plugins.rs @@ -2,7 +2,7 @@ use std::path::PathBuf; use serde::Deserialize; use validator::Validate; -use yazi_shared::expand_path; +use yazi_shared::fs::expand_path; use crate::MERGED_YAZI; diff --git a/yazi-config/src/popup/options.rs b/yazi-config/src/popup/options.rs index 472d45b5..177788c9 100644 --- a/yazi-config/src/popup/options.rs +++ b/yazi-config/src/popup/options.rs @@ -2,7 +2,7 @@ use super::{Offset, Position}; use crate::{INPUT, SELECT}; #[derive(Default)] -pub struct InputOpt { +pub struct InputCfg { pub title: String, pub value: String, pub position: Position, @@ -12,13 +12,13 @@ pub struct InputOpt { } #[derive(Default)] -pub struct SelectOpt { +pub struct SelectCfg { pub title: String, pub items: Vec, pub position: Position, } -impl InputOpt { +impl InputCfg { #[inline] pub fn cd() -> Self { Self { @@ -122,7 +122,7 @@ impl InputOpt { } } -impl SelectOpt { +impl SelectCfg { #[inline] fn max_height(len: usize) -> u16 { SELECT.open_offset.height.min(SELECT.border().saturating_add(len as u16)) diff --git a/yazi-config/src/popup/position.rs b/yazi-config/src/popup/position.rs index 4964e10b..a67e44da 100644 --- a/yazi-config/src/popup/position.rs +++ b/yazi-config/src/popup/position.rs @@ -1,6 +1,6 @@ use crossterm::terminal::WindowSize; use ratatui::layout::Rect; -use yazi_shared::Term; +use yazi_shared::term::Term; use super::{Offset, Origin}; diff --git a/yazi-config/src/preview/preview.rs b/yazi-config/src/preview/preview.rs index fd83cc3d..d22aa078 100644 --- a/yazi-config/src/preview/preview.rs +++ b/yazi-config/src/preview/preview.rs @@ -2,7 +2,7 @@ use std::{path::{Path, PathBuf}, time::{self, SystemTime}}; use md5::{Digest, Md5}; use serde::Deserialize; -use yazi_shared::expand_path; +use yazi_shared::fs::expand_path; use crate::{xdg::Xdg, MERGED_YAZI}; diff --git a/yazi-config/src/theme/theme.rs b/yazi-config/src/theme/theme.rs index 80d4f02c..ae5cfa75 100644 --- a/yazi-config/src/theme/theme.rs +++ b/yazi-config/src/theme/theme.rs @@ -2,7 +2,7 @@ use std::path::PathBuf; use serde::{Deserialize, Serialize}; use validator::Validate; -use yazi_shared::expand_path; +use yazi_shared::fs::expand_path; use super::{Filetype, Icon, Style}; use crate::{validation::check_validation, MERGED_THEME}; diff --git a/yazi-config/src/xdg.rs b/yazi-config/src/xdg.rs index bfeabfd9..d17e3409 100644 --- a/yazi-config/src/xdg.rs +++ b/yazi-config/src/xdg.rs @@ -1,6 +1,6 @@ use std::{env, path::PathBuf}; -use yazi_shared::expand_path; +use yazi_shared::fs::expand_path; pub(super) struct Xdg; diff --git a/yazi-core/src/completion/commands/arrow.rs b/yazi-core/src/completion/commands/arrow.rs index c5296585..9368b5dd 100644 --- a/yazi-core/src/completion/commands/arrow.rs +++ b/yazi-core/src/completion/commands/arrow.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::completion::Completion; diff --git a/yazi-core/src/completion/commands/close.rs b/yazi-core/src/completion/commands/close.rs index 4bd00452..fdd6f785 100644 --- a/yazi-core/src/completion/commands/close.rs +++ b/yazi-core/src/completion/commands/close.rs @@ -1,6 +1,6 @@ -use yazi_config::keymap::{Exec, KeymapLayer}; +use yazi_shared::{emit, event::Exec, Layer}; -use crate::{completion::Completion, emit, input::Input}; +use crate::{completion::Completion, input::Input}; pub struct Opt { submit: bool, @@ -13,7 +13,7 @@ impl From<&Exec> for Opt { impl Completion { #[inline] pub fn _close() { - emit!(Call(Exec::call("close", vec![]).vec(), KeymapLayer::Completion)); + emit!(Call(Exec::call("close", vec![]).vec(), Layer::Completion)); } pub fn close(&mut self, opt: impl Into) -> bool { diff --git a/yazi-core/src/completion/commands/show.rs b/yazi-core/src/completion/commands/show.rs index 102df4bf..5454b289 100644 --- a/yazi-core/src/completion/commands/show.rs +++ b/yazi-core/src/completion/commands/show.rs @@ -1,6 +1,6 @@ use std::{mem, ops::ControlFlow}; -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::completion::Completion; diff --git a/yazi-core/src/completion/commands/trigger.rs b/yazi-core/src/completion/commands/trigger.rs index 84ad2fa2..fc6749c3 100644 --- a/yazi-core/src/completion/commands/trigger.rs +++ b/yazi-core/src/completion/commands/trigger.rs @@ -1,9 +1,9 @@ use std::{mem, path::{MAIN_SEPARATOR, MAIN_SEPARATOR_STR}}; use tokio::fs; -use yazi_config::keymap::{Exec, KeymapLayer}; +use yazi_shared::{emit, event::Exec, Layer}; -use crate::{completion::Completion, emit}; +use crate::completion::Completion; pub struct Opt<'a> { word: &'a str, @@ -24,7 +24,7 @@ impl Completion { pub fn _trigger(word: &str, ticket: usize) { emit!(Call( Exec::call("trigger", vec![word.to_owned()]).with("ticket", ticket).vec(), - KeymapLayer::Completion + Layer::Completion )); } @@ -69,7 +69,7 @@ impl Completion { .with("word", child) .with("ticket", ticket) .vec(), - KeymapLayer::Completion + Layer::Completion )); } diff --git a/yazi-core/src/context.rs b/yazi-core/src/context.rs index 313ff4a3..b1b6d82c 100644 --- a/yazi-core/src/context.rs +++ b/yazi-core/src/context.rs @@ -1,5 +1,7 @@ use ratatui::prelude::Rect; +use tokio::sync::oneshot; use yazi_config::popup::{Origin, Position}; +use yazi_shared::{emit, event::Exec, Layer}; use crate::{completion::Completion, help::Help, input::Input, manager::Manager, select::Select, tasks::Tasks, which::Which}; @@ -26,6 +28,21 @@ impl Ctx { } } + #[inline] + pub async fn stop() { + let (tx, rx) = oneshot::channel::<()>(); + emit!(Call(Exec::call("stop", vec!["true".to_string()]).with_data(Some(tx)).vec(), Layer::App)); + rx.await.ok(); + } + + #[inline] + pub fn resume() { + emit!(Call( + Exec::call("stop", vec!["false".to_string()]).with_data(None::>).vec(), + Layer::App + )); + } + pub fn area(&self, position: &Position) -> Rect { if position.origin != Origin::Hovered { return position.rect(); diff --git a/yazi-core/src/event.rs b/yazi-core/src/event.rs deleted file mode 100644 index 485f7972..00000000 --- a/yazi-core/src/event.rs +++ /dev/null @@ -1,106 +0,0 @@ -use std::{collections::BTreeMap, ffi::OsString}; - -use anyhow::Result; -use crossterm::event::KeyEvent; -use tokio::sync::{mpsc::{self, UnboundedSender}, oneshot}; -use yazi_config::{keymap::{Exec, KeymapLayer}, open::Opener, popup::{InputOpt, SelectOpt}}; -use yazi_shared::{InputError, RoCell, Url}; - -use super::files::FilesOp; -use crate::{preview::PreviewLock, tasks::TasksProgress}; - -static TX: RoCell> = RoCell::new(); - -pub enum Event { - Quit(bool), // no-cwd-file - Key(KeyEvent), - Paste(String), - Render(String), - Resize(u16, u16), - Stop(bool, Option>), - Call(Vec, KeymapLayer), - - // Manager - Files(FilesOp), - Pages(usize), - Mimetype(BTreeMap), - Preview(PreviewLock), - - // Input - Select(SelectOpt, oneshot::Sender>), - Input(InputOpt, mpsc::UnboundedSender>), - - // Tasks - Open(Vec<(OsString, String)>, Option), - Progress(TasksProgress), -} - -impl Event { - #[inline] - pub fn init(tx: UnboundedSender) { TX.init(tx); } - - #[inline] - pub fn emit(self) { TX.send(self).ok(); } - - pub async fn wait(self, rx: oneshot::Receiver) -> T { - TX.send(self).ok(); - rx.await.unwrap_or_else(|_| std::process::exit(0)) - } -} - -#[macro_export] -macro_rules! emit { - (Quit($no_cwd_file:expr)) => { - $crate::Event::Quit($no_cwd_file).emit(); - }; - (Key($key:expr)) => { - $crate::Event::Key($key).emit(); - }; - (Render) => { - $crate::Event::Render(format!("{}:{}", file!(), line!())).emit(); - }; - (Resize($cols:expr, $rows:expr)) => { - $crate::Event::Resize($cols, $rows).emit(); - }; - (Stop($state:expr)) => {{ - let (tx, rx) = tokio::sync::oneshot::channel(); - $crate::Event::Stop($state, Some(tx)).wait(rx) - }}; - (Call($exec:expr, $layer:expr)) => { - $crate::Event::Call($exec, $layer).emit(); - }; - - (Files($op:expr)) => { - $crate::Event::Files($op).emit(); - }; - (Pages($page:expr)) => { - $crate::Event::Pages($page).emit(); - }; - (Mimetype($mimes:expr)) => { - $crate::Event::Mimetype($mimes).emit(); - }; - (Preview($lock:expr)) => { - $crate::Event::Preview($lock).emit(); - }; - - (Select($opt:expr)) => {{ - let (tx, rx) = tokio::sync::oneshot::channel(); - $crate::Event::Select($opt, tx).wait(rx) - }}; - (Input($opt:expr)) => {{ - let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); - $crate::Event::Input($opt, tx).emit(); - rx - }}; - - (Open($targets:expr, $opener:expr)) => { - $crate::Event::Open($targets, $opener).emit(); - }; - (Progress($progress:expr)) => { - $crate::Event::Progress($progress).emit(); - }; - - ($event:ident) => { - $crate::Event::$event.emit(); - }; -} diff --git a/yazi-core/src/external/fd.rs b/yazi-core/src/external/fd.rs index 1d1fec64..f299af76 100644 --- a/yazi-core/src/external/fd.rs +++ b/yazi-core/src/external/fd.rs @@ -2,9 +2,7 @@ use std::process::Stdio; use anyhow::Result; use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::{self, UnboundedReceiver}}; -use yazi_shared::Url; - -use crate::files::File; +use yazi_shared::{files::File, fs::Url}; pub struct FdOpt { pub cwd: Url, diff --git a/yazi-core/src/external/file.rs b/yazi-core/src/external/file.rs index b4b61d16..def1f72b 100644 --- a/yazi-core/src/external/file.rs +++ b/yazi-core/src/external/file.rs @@ -4,7 +4,7 @@ use anyhow::{bail, Result}; use futures::TryFutureExt; use tokio::process::Command; use tracing::error; -use yazi_shared::{MimeKind, Url}; +use yazi_shared::{fs::Url, MimeKind}; async fn _file(files: &[&Url]) -> Result> { if files.is_empty() { diff --git a/yazi-core/src/external/fzf.rs b/yazi-core/src/external/fzf.rs index dfe67329..dabfe8c5 100644 --- a/yazi-core/src/external/fzf.rs +++ b/yazi-core/src/external/fzf.rs @@ -2,7 +2,7 @@ use std::{path::Path, process::Stdio}; use anyhow::{bail, Result}; use tokio::process::Command; -use yazi_shared::Url; +use yazi_shared::fs::Url; pub struct FzfOpt { pub cwd: Url, diff --git a/yazi-core/src/external/rg.rs b/yazi-core/src/external/rg.rs index 9220c5b0..c240b66d 100644 --- a/yazi-core/src/external/rg.rs +++ b/yazi-core/src/external/rg.rs @@ -2,9 +2,7 @@ use std::process::Stdio; use anyhow::Result; use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::{self, UnboundedReceiver}}; -use yazi_shared::Url; - -use crate::files::File; +use yazi_shared::{files::File, fs::Url}; pub struct RgOpt { pub cwd: Url, diff --git a/yazi-core/src/external/zoxide.rs b/yazi-core/src/external/zoxide.rs index 11900af8..23d4ff2c 100644 --- a/yazi-core/src/external/zoxide.rs +++ b/yazi-core/src/external/zoxide.rs @@ -2,7 +2,7 @@ use std::process::Stdio; use anyhow::{bail, Result}; use tokio::process::Command; -use yazi_shared::Url; +use yazi_shared::fs::Url; pub struct ZoxideOpt { pub cwd: Url, diff --git a/yazi-core/src/files/files.rs b/yazi-core/src/files/files.rs index a11d89ad..ff79e141 100644 --- a/yazi-core/src/files/files.rs +++ b/yazi-core/src/files/files.rs @@ -3,9 +3,9 @@ use std::{collections::{BTreeMap, BTreeSet}, mem, ops::Deref, sync::atomic::Orde use anyhow::Result; use tokio::{fs, select, sync::mpsc::{self, UnboundedReceiver}}; use yazi_config::{manager::SortBy, MANAGER}; -use yazi_shared::Url; +use yazi_shared::{files::{File, FILES_TICKET}, fs::Url}; -use super::{File, FilesSorter, FILES_TICKET}; +use super::FilesSorter; pub struct Files { items: Vec, diff --git a/yazi-core/src/files/mod.rs b/yazi-core/src/files/mod.rs index 59df8d54..f6b8945d 100644 --- a/yazi-core/src/files/mod.rs +++ b/yazi-core/src/files/mod.rs @@ -1,9 +1,5 @@ -mod file; mod files; -mod op; mod sorter; -pub use file::*; pub use files::*; -pub use op::*; pub use sorter::*; diff --git a/yazi-core/src/files/sorter.rs b/yazi-core/src/files/sorter.rs index 580891bc..9eca8551 100644 --- a/yazi-core/src/files/sorter.rs +++ b/yazi-core/src/files/sorter.rs @@ -1,9 +1,7 @@ use std::{cmp::Ordering, collections::BTreeMap, mem}; use yazi_config::manager::SortBy; -use yazi_shared::{natsort, Url}; - -use super::File; +use yazi_shared::{files::File, fs::Url, natsort}; #[derive(Clone, Copy, Default, PartialEq)] pub struct FilesSorter { diff --git a/yazi-core/src/help/commands/arrow.rs b/yazi-core/src/help/commands/arrow.rs index af4ca625..b78dbfbb 100644 --- a/yazi-core/src/help/commands/arrow.rs +++ b/yazi-core/src/help/commands/arrow.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::help::Help; diff --git a/yazi-core/src/help/commands/escape.rs b/yazi-core/src/help/commands/escape.rs index e27cbec3..afde74e2 100644 --- a/yazi-core/src/help/commands/escape.rs +++ b/yazi-core/src/help/commands/escape.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::help::Help; diff --git a/yazi-core/src/help/commands/filter.rs b/yazi-core/src/help/commands/filter.rs index 0721bd43..b6580b2d 100644 --- a/yazi-core/src/help/commands/filter.rs +++ b/yazi-core/src/help/commands/filter.rs @@ -1,4 +1,5 @@ -use yazi_config::{keymap::Exec, popup::{Offset, Origin, Position}}; +use yazi_config::popup::{Offset, Origin, Position}; +use yazi_shared::event::Exec; use crate::{help::Help, input::Input}; diff --git a/yazi-core/src/help/help.rs b/yazi-core/src/help/help.rs index 4da65c18..455a2882 100644 --- a/yazi-core/src/help/help.rs +++ b/yazi-core/src/help/help.rs @@ -1,7 +1,7 @@ use crossterm::event::KeyCode; use unicode_width::UnicodeWidthStr; -use yazi_config::{keymap::{Control, Key, KeymapLayer}, KEYMAP}; -use yazi_shared::Term; +use yazi_config::{keymap::{Control, Key}, KEYMAP}; +use yazi_shared::{term::Term, Layer}; use super::HELP_MARGIN; use crate::input::Input; @@ -9,8 +9,8 @@ use crate::input::Input; #[derive(Default)] pub struct Help { pub visible: bool, - pub layer: KeymapLayer, - pub(super) bindings: Vec, + pub layer: Layer, + pub(super) bindings: Vec<&'static Control>, // Filter keyword: Option, @@ -24,7 +24,7 @@ impl Help { #[inline] pub fn limit() -> usize { Term::size().rows.saturating_sub(HELP_MARGIN) as usize } - pub fn toggle(&mut self, layer: KeymapLayer) -> bool { + pub fn toggle(&mut self, layer: Layer) -> bool { self.visible = !self.visible; self.layer = layer; @@ -44,9 +44,9 @@ impl Help { } if let Some(kw) = kw { - self.bindings = KEYMAP.get(self.layer).iter().filter(|&c| c.contains(kw)).cloned().collect(); + self.bindings = KEYMAP.get(self.layer).iter().filter(|&c| c.contains(kw)).collect(); } else { - self.bindings = KEYMAP.get(self.layer).clone(); + self.bindings = KEYMAP.get(self.layer).iter().collect(); } self.keyword = kw.map(|s| s.to_owned()); @@ -89,7 +89,7 @@ impl Help { // --- Bindings #[inline] - pub fn window(&self) -> &[Control] { + pub fn window(&self) -> &[&Control] { let end = (self.offset + Self::limit()).min(self.bindings.len()); &self.bindings[self.offset..end] } diff --git a/yazi-core/src/input/commands/backspace.rs b/yazi-core/src/input/commands/backspace.rs index 8828796a..1bb89a86 100644 --- a/yazi-core/src/input/commands/backspace.rs +++ b/yazi-core/src/input/commands/backspace.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::input::Input; diff --git a/yazi-core/src/input/commands/backward.rs b/yazi-core/src/input/commands/backward.rs index 4105e414..3fe3b0b7 100644 --- a/yazi-core/src/input/commands/backward.rs +++ b/yazi-core/src/input/commands/backward.rs @@ -1,5 +1,4 @@ -use yazi_config::keymap::Exec; -use yazi_shared::CharKind; +use yazi_shared::{event::Exec, CharKind}; use crate::input::Input; diff --git a/yazi-core/src/input/commands/close.rs b/yazi-core/src/input/commands/close.rs index 563d2630..594258af 100644 --- a/yazi-core/src/input/commands/close.rs +++ b/yazi-core/src/input/commands/close.rs @@ -1,5 +1,4 @@ -use yazi_config::keymap::Exec; -use yazi_shared::InputError; +use yazi_shared::{event::Exec, InputError}; use crate::{completion::Completion, input::Input}; diff --git a/yazi-core/src/input/commands/complete.rs b/yazi-core/src/input/commands/complete.rs index 7eeccd87..50752f8e 100644 --- a/yazi-core/src/input/commands/complete.rs +++ b/yazi-core/src/input/commands/complete.rs @@ -1,8 +1,8 @@ use std::path::MAIN_SEPARATOR; -use yazi_config::keymap::{Exec, KeymapLayer}; +use yazi_shared::{emit, event::Exec, Layer}; -use crate::{emit, input::Input}; +use crate::input::Input; pub struct Opt<'a> { word: &'a str, @@ -23,7 +23,7 @@ impl Input { pub fn _complete(word: &str, ticket: usize) { emit!(Call( Exec::call("complete", vec![word.to_owned()]).with("ticket", ticket).vec(), - KeymapLayer::Input + Layer::Input )); } diff --git a/yazi-core/src/input/commands/delete.rs b/yazi-core/src/input/commands/delete.rs index b36e6905..a46f6585 100644 --- a/yazi-core/src/input/commands/delete.rs +++ b/yazi-core/src/input/commands/delete.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::input::{op::InputOp, Input}; diff --git a/yazi-core/src/input/commands/escape.rs b/yazi-core/src/input/commands/escape.rs index 392dd179..4f09955f 100644 --- a/yazi-core/src/input/commands/escape.rs +++ b/yazi-core/src/input/commands/escape.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::{completion::Completion, input::{op::InputOp, Input, InputMode}}; diff --git a/yazi-core/src/input/commands/forward.rs b/yazi-core/src/input/commands/forward.rs index 523f1f63..fc07a27d 100644 --- a/yazi-core/src/input/commands/forward.rs +++ b/yazi-core/src/input/commands/forward.rs @@ -1,5 +1,4 @@ -use yazi_config::keymap::Exec; -use yazi_shared::CharKind; +use yazi_shared::{event::Exec, CharKind}; use crate::input::{op::InputOp, Input}; diff --git a/yazi-core/src/input/commands/insert.rs b/yazi-core/src/input/commands/insert.rs index ba7b87f0..db4d6c6e 100644 --- a/yazi-core/src/input/commands/insert.rs +++ b/yazi-core/src/input/commands/insert.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::input::{op::InputOp, Input, InputMode}; diff --git a/yazi-core/src/input/commands/kill.rs b/yazi-core/src/input/commands/kill.rs index 918943a9..759f8d22 100644 --- a/yazi-core/src/input/commands/kill.rs +++ b/yazi-core/src/input/commands/kill.rs @@ -1,7 +1,6 @@ use std::ops::RangeBounds; -use yazi_config::keymap::Exec; -use yazi_shared::CharKind; +use yazi_shared::{event::Exec, CharKind}; use crate::input::Input; diff --git a/yazi-core/src/input/commands/mod.rs b/yazi-core/src/input/commands/mod.rs index 9ad96381..8759bf85 100644 --- a/yazi-core/src/input/commands/mod.rs +++ b/yazi-core/src/input/commands/mod.rs @@ -10,6 +10,7 @@ mod kill; mod move_; mod paste; mod redo; +mod show; mod type_; mod undo; mod visual; diff --git a/yazi-core/src/input/commands/move_.rs b/yazi-core/src/input/commands/move_.rs index 4bccecd4..f2b20a3e 100644 --- a/yazi-core/src/input/commands/move_.rs +++ b/yazi-core/src/input/commands/move_.rs @@ -1,5 +1,5 @@ use unicode_width::UnicodeWidthStr; -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::input::{op::InputOp, snap::InputSnap, Input}; diff --git a/yazi-core/src/input/commands/paste.rs b/yazi-core/src/input/commands/paste.rs index 5145845d..47783b01 100644 --- a/yazi-core/src/input/commands/paste.rs +++ b/yazi-core/src/input/commands/paste.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::{external, input::{op::InputOp, Input}}; diff --git a/yazi-core/src/input/commands/redo.rs b/yazi-core/src/input/commands/redo.rs index 1722d664..9573f0e1 100644 --- a/yazi-core/src/input/commands/redo.rs +++ b/yazi-core/src/input/commands/redo.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::input::Input; diff --git a/yazi-core/src/input/commands/show.rs b/yazi-core/src/input/commands/show.rs new file mode 100644 index 00000000..ba9f74b9 --- /dev/null +++ b/yazi-core/src/input/commands/show.rs @@ -0,0 +1,50 @@ +use anyhow::anyhow; +use tokio::sync::mpsc; +use yazi_config::popup::InputCfg; +use yazi_shared::{emit, event::Exec, InputError, Layer}; + +use crate::input::Input; + +pub struct Opt { + cfg: InputCfg, + tx: mpsc::UnboundedSender>, +} + +impl TryFrom<&Exec> for Opt { + type Error = anyhow::Error; + + fn try_from(e: &Exec) -> Result { + e.take_data().ok_or_else(|| anyhow!("invalid data")) + } +} + +impl Input { + pub fn _show(cfg: InputCfg) -> mpsc::UnboundedReceiver> { + let (tx, rx) = mpsc::unbounded_channel(); + emit!(Call(Exec::call("show", vec![]).with_data(Opt { cfg, tx }).vec(), Layer::Input)); + rx + } + + pub fn show(&mut self, opt: impl TryInto) -> bool { + let Ok(opt) = opt.try_into() else { + return false; + }; + + self.close(false); + self.visible = true; + self.title = opt.cfg.title; + self.position = opt.cfg.position; + + // Typing + self.callback = Some(opt.tx); + self.realtime = opt.cfg.realtime; + self.completion = opt.cfg.completion; + + // Shell + self.highlight = opt.cfg.highlight; + + // Reset snaps + self.snaps.reset(opt.cfg.value, self.limit()); + true + } +} diff --git a/yazi-core/src/input/commands/type_.rs b/yazi-core/src/input/commands/type_.rs index db9296df..e693a825 100644 --- a/yazi-core/src/input/commands/type_.rs +++ b/yazi-core/src/input/commands/type_.rs @@ -1,4 +1,5 @@ -use yazi_config::keymap::{Exec, Key}; +use yazi_config::keymap::Key; +use yazi_shared::event::Exec; use crate::input::{Input, InputMode}; diff --git a/yazi-core/src/input/commands/undo.rs b/yazi-core/src/input/commands/undo.rs index 6ef8d81e..12f63ceb 100644 --- a/yazi-core/src/input/commands/undo.rs +++ b/yazi-core/src/input/commands/undo.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::input::{Input, InputMode}; diff --git a/yazi-core/src/input/commands/visual.rs b/yazi-core/src/input/commands/visual.rs index 81d1d7c0..0ce945ac 100644 --- a/yazi-core/src/input/commands/visual.rs +++ b/yazi-core/src/input/commands/visual.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::input::{op::InputOp, Input, InputMode}; diff --git a/yazi-core/src/input/commands/yank.rs b/yazi-core/src/input/commands/yank.rs index e8c32c6c..c56f653b 100644 --- a/yazi-core/src/input/commands/yank.rs +++ b/yazi-core/src/input/commands/yank.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::input::{op::InputOp, Input}; diff --git a/yazi-core/src/input/input.rs b/yazi-core/src/input/input.rs index 0709f4e1..07fae677 100644 --- a/yazi-core/src/input/input.rs +++ b/yazi-core/src/input/input.rs @@ -2,7 +2,7 @@ use std::ops::Range; use tokio::sync::mpsc::UnboundedSender; use unicode_width::UnicodeWidthStr; -use yazi_config::{popup::{InputOpt, Position}, INPUT}; +use yazi_config::{popup::Position, INPUT}; use yazi_shared::InputError; use super::{mode::InputMode, op::InputOp, InputSnap, InputSnaps}; @@ -19,7 +19,7 @@ pub struct Input { // Typing pub(super) callback: Option>>, - realtime: bool, + pub(super) realtime: bool, pub(super) completion: bool, // Shell @@ -27,24 +27,6 @@ pub struct Input { } impl Input { - pub fn show(&mut self, opt: InputOpt, tx: UnboundedSender>) { - self.close(false); - self.visible = true; - self.title = opt.title; - self.position = opt.position; - - // Typing - self.callback = Some(tx); - self.realtime = opt.realtime; - self.completion = opt.completion; - - // Shell - self.highlight = opt.highlight; - - // Reset snaps - self.snaps.reset(opt.value, self.limit()); - } - #[inline] pub(super) fn limit(&self) -> usize { self.position.offset.width.saturating_sub(INPUT.border()) as usize diff --git a/yazi-core/src/lib.rs b/yazi-core/src/lib.rs index 04664cdf..ef525620 100644 --- a/yazi-core/src/lib.rs +++ b/yazi-core/src/lib.rs @@ -9,7 +9,6 @@ mod blocker; pub mod completion; mod context; -mod event; pub mod external; pub mod files; pub mod help; @@ -25,7 +24,6 @@ pub mod which; pub use blocker::*; pub use context::*; -pub use event::*; pub use highlighter::*; pub use step::*; diff --git a/yazi-core/src/manager/commands/close.rs b/yazi-core/src/manager/commands/close.rs index 45eaa08c..7249a111 100644 --- a/yazi-core/src/manager/commands/close.rs +++ b/yazi-core/src/manager/commands/close.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::{manager::Manager, tasks::Tasks}; diff --git a/yazi-core/src/manager/commands/create.rs b/yazi-core/src/manager/commands/create.rs index 64fbad46..890dd79c 100644 --- a/yazi-core/src/manager/commands/create.rs +++ b/yazi-core/src/manager/commands/create.rs @@ -1,10 +1,10 @@ use std::path::{PathBuf, MAIN_SEPARATOR}; use tokio::fs; -use yazi_config::{keymap::Exec, popup::InputOpt}; -use yazi_shared::Url; +use yazi_config::popup::InputCfg; +use yazi_shared::{emit, event::Exec, files::{File, FilesOp}, fs::Url}; -use crate::{emit, files::{File, FilesOp}, manager::Manager}; +use crate::{input::Input, manager::Manager}; pub struct Opt { force: bool, @@ -19,14 +19,14 @@ impl Manager { let opt = opt.into() as Opt; let cwd = self.cwd().to_owned(); tokio::spawn(async move { - let mut result = emit!(Input(InputOpt::create())); + let mut result = Input::_show(InputCfg::create()); let Some(Ok(name)) = result.recv().await else { return Ok(()); }; let path = cwd.join(&name); if !opt.force && fs::symlink_metadata(&path).await.is_ok() { - match emit!(Input(InputOpt::overwrite())).recv().await { + match Input::_show(InputCfg::overwrite()).recv().await { Some(Ok(c)) if c == "y" || c == "Y" => (), _ => return Ok(()), } diff --git a/yazi-core/src/manager/commands/hover.rs b/yazi-core/src/manager/commands/hover.rs index a68c7e90..33188093 100644 --- a/yazi-core/src/manager/commands/hover.rs +++ b/yazi-core/src/manager/commands/hover.rs @@ -1,9 +1,8 @@ use std::collections::BTreeSet; -use yazi_config::keymap::{Exec, KeymapLayer}; -use yazi_shared::Url; +use yazi_shared::{emit, event::Exec, fs::Url, Layer}; -use crate::{emit, manager::Manager}; +use crate::manager::Manager; pub struct Opt { url: Option, @@ -18,7 +17,7 @@ impl Manager { pub fn _hover(url: Option) { emit!(Call( Exec::call("hover", url.map_or_else(Vec::new, |u| vec![u.to_string()])).vec(), - KeymapLayer::Manager + Layer::Manager )); } diff --git a/yazi-core/src/manager/commands/link.rs b/yazi-core/src/manager/commands/link.rs index 74be120e..2933aa6d 100644 --- a/yazi-core/src/manager/commands/link.rs +++ b/yazi-core/src/manager/commands/link.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::{manager::Manager, tasks::Tasks}; diff --git a/yazi-core/src/manager/commands/open.rs b/yazi-core/src/manager/commands/open.rs index d436c3f6..db801322 100644 --- a/yazi-core/src/manager/commands/open.rs +++ b/yazi-core/src/manager/commands/open.rs @@ -1,9 +1,9 @@ use std::ffi::OsString; -use yazi_config::{keymap::Exec, popup::SelectOpt, OPEN}; -use yazi_shared::MIME_DIR; +use yazi_config::{popup::SelectCfg, OPEN}; +use yazi_shared::{event::Exec, MIME_DIR}; -use crate::{emit, external, manager::Manager}; +use crate::{external, manager::Manager, select::Select, tasks::Tasks}; pub struct Opt { interactive: bool, @@ -20,9 +20,9 @@ impl Manager { return; } - let result = emit!(Select(SelectOpt::open(openers.iter().map(|o| o.desc.clone()).collect()))); + let result = Select::_show(SelectCfg::open(openers.iter().map(|o| o.desc.clone()).collect())); if let Ok(choice) = result.await { - emit!(Open(files, Some(openers[choice].clone()))); + Tasks::_open(files, Some(openers[choice].clone())); } } @@ -63,7 +63,7 @@ impl Manager { return; } - emit!(Open(files, None)); + Tasks::_open(files, None); }); false } diff --git a/yazi-core/src/manager/commands/paste.rs b/yazi-core/src/manager/commands/paste.rs index 31877e3a..88c9fe9a 100644 --- a/yazi-core/src/manager/commands/paste.rs +++ b/yazi-core/src/manager/commands/paste.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::{manager::Manager, tasks::Tasks}; diff --git a/yazi-core/src/manager/commands/peek.rs b/yazi-core/src/manager/commands/peek.rs index bfafb5d5..500ad8d0 100644 --- a/yazi-core/src/manager/commands/peek.rs +++ b/yazi-core/src/manager/commands/peek.rs @@ -1,7 +1,7 @@ -use yazi_config::{keymap::{Exec, KeymapLayer}, MANAGER}; -use yazi_shared::{Url, MIME_DIR}; +use yazi_config::MANAGER; +use yazi_shared::{emit, event::Exec, fs::Url, Layer, MIME_DIR}; -use crate::{emit, manager::Manager}; +use crate::manager::Manager; #[derive(Debug)] pub struct Opt { @@ -31,7 +31,7 @@ impl Manager { .with("only-if", only_if.to_string()) .with_bool("upper-bound", true) .vec(), - KeymapLayer::Manager + Layer::Manager )); } diff --git a/yazi-core/src/manager/commands/quit.rs b/yazi-core/src/manager/commands/quit.rs index e4f70fc0..4a77f6cb 100644 --- a/yazi-core/src/manager/commands/quit.rs +++ b/yazi-core/src/manager/commands/quit.rs @@ -1,6 +1,7 @@ -use yazi_config::{keymap::Exec, popup::InputOpt}; +use yazi_config::popup::InputCfg; +use yazi_shared::{emit, event::Exec}; -use crate::{emit, manager::Manager, tasks::Tasks}; +use crate::{input::Input, manager::Manager, tasks::Tasks}; #[derive(Default)] pub struct Opt { @@ -24,7 +25,7 @@ impl Manager { } tokio::spawn(async move { - let mut result = emit!(Input(InputOpt::quit(tasks))); + let mut result = Input::_show(InputCfg::quit(tasks)); if let Some(Ok(choice)) = result.recv().await { if choice == "y" || choice == "Y" { emit!(Quit(opt.no_cwd_file)); diff --git a/yazi-core/src/manager/commands/refresh.rs b/yazi-core/src/manager/commands/refresh.rs index aaff66f4..a3691fe5 100644 --- a/yazi-core/src/manager/commands/refresh.rs +++ b/yazi-core/src/manager/commands/refresh.rs @@ -1,8 +1,8 @@ use std::env; -use yazi_config::keymap::{Exec, KeymapLayer}; +use yazi_shared::{emit, event::Exec, Layer}; -use crate::{emit, manager::Manager}; +use crate::manager::Manager; pub struct Opt; @@ -13,7 +13,7 @@ impl From<&Exec> for Opt { impl Manager { #[inline] pub fn _refresh() { - emit!(Call(Exec::call("refresh", vec![]).vec(), KeymapLayer::Manager)); + emit!(Call(Exec::call("refresh", vec![]).vec(), Layer::Manager)); } pub fn refresh(&mut self, _: impl Into) -> bool { diff --git a/yazi-core/src/manager/commands/remove.rs b/yazi-core/src/manager/commands/remove.rs index 7f9c4e6b..6716688a 100644 --- a/yazi-core/src/manager/commands/remove.rs +++ b/yazi-core/src/manager/commands/remove.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::{manager::Manager, tasks::Tasks}; diff --git a/yazi-core/src/manager/commands/rename.rs b/yazi-core/src/manager/commands/rename.rs index 8391e894..60a7a904 100644 --- a/yazi-core/src/manager/commands/rename.rs +++ b/yazi-core/src/manager/commands/rename.rs @@ -2,10 +2,10 @@ use std::{collections::BTreeMap, ffi::OsStr, io::{stdout, BufWriter, Write}, pat use anyhow::{anyhow, bail, Result}; use tokio::{fs::{self, OpenOptions}, io::{stdin, AsyncReadExt, AsyncWriteExt}}; -use yazi_config::{keymap::Exec, popup::InputOpt, OPEN, PREVIEW}; -use yazi_shared::{max_common_root, Defer, Term, Url}; +use yazi_config::{popup::InputCfg, OPEN, PREVIEW}; +use yazi_shared::{emit, event::Exec, files::{File, FilesOp}, fs::{max_common_root, Url}, term::Term, Defer}; -use crate::{emit, external::{self, ShellOpt}, files::{File, FilesOp}, manager::Manager, Event, BLOCKER}; +use crate::{external::{self, ShellOpt}, input::Input, manager::Manager, Ctx, BLOCKER}; pub struct Opt { force: bool, @@ -39,7 +39,7 @@ impl Manager { let opt = opt.into() as Opt; tokio::spawn(async move { let mut result = - emit!(Input(InputOpt::rename().with_value(hovered.file_name().unwrap().to_string_lossy()))); + Input::_show(InputCfg::rename().with_value(hovered.file_name().unwrap().to_string_lossy())); let Some(Ok(name)) = result.recv().await else { return; @@ -51,7 +51,7 @@ impl Manager { return; } - let mut result = emit!(Input(InputOpt::overwrite())); + let mut result = Input::_show(InputCfg::overwrite()); if let Some(Ok(choice)) = result.recv().await { if choice == "y" || choice == "Y" { Self::rename_and_hover(hovered, Url::from(new)).await.ok(); @@ -86,10 +86,10 @@ impl Manager { let _guard = BLOCKER.acquire().await.unwrap(); let _defer = Defer::new(|| { - Event::Stop(false, None).emit(); + Ctx::resume(); tokio::spawn(fs::remove_file(tmp.clone())) }); - emit!(Stop(true)).await; + Ctx::stop().await; let mut child = external::shell(ShellOpt { cmd: (*opener.exec).into(), diff --git a/yazi-core/src/manager/commands/suspend.rs b/yazi-core/src/manager/commands/suspend.rs index f88bed06..f3db2bf1 100644 --- a/yazi-core/src/manager/commands/suspend.rs +++ b/yazi-core/src/manager/commands/suspend.rs @@ -1,6 +1,6 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; -use crate::manager::Manager; +use crate::{manager::Manager, Ctx}; pub struct Opt; impl From<&Exec> for Opt { @@ -11,7 +11,7 @@ impl Manager { pub fn suspend(&mut self, _: impl Into) -> bool { #[cfg(unix)] tokio::spawn(async move { - crate::emit!(Stop(true)).await; + Ctx::stop().await; unsafe { libc::raise(libc::SIGTSTP) }; }); false diff --git a/yazi-core/src/manager/commands/tab_close.rs b/yazi-core/src/manager/commands/tab_close.rs index addd3e7c..eb4083ca 100644 --- a/yazi-core/src/manager/commands/tab_close.rs +++ b/yazi-core/src/manager/commands/tab_close.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::manager::Tabs; diff --git a/yazi-core/src/manager/commands/tab_create.rs b/yazi-core/src/manager/commands/tab_create.rs index e125a6c5..8fa89d39 100644 --- a/yazi-core/src/manager/commands/tab_create.rs +++ b/yazi-core/src/manager/commands/tab_create.rs @@ -1,5 +1,4 @@ -use yazi_config::keymap::Exec; -use yazi_shared::Url; +use yazi_shared::{event::Exec, fs::Url}; use crate::{manager::Tabs, tab::Tab}; diff --git a/yazi-core/src/manager/commands/tab_swap.rs b/yazi-core/src/manager/commands/tab_swap.rs index 00a52207..e7f02425 100644 --- a/yazi-core/src/manager/commands/tab_swap.rs +++ b/yazi-core/src/manager/commands/tab_swap.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::manager::Tabs; diff --git a/yazi-core/src/manager/commands/tab_switch.rs b/yazi-core/src/manager/commands/tab_switch.rs index 27c7bafa..4eeb41fe 100644 --- a/yazi-core/src/manager/commands/tab_switch.rs +++ b/yazi-core/src/manager/commands/tab_switch.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::manager::Tabs; diff --git a/yazi-core/src/manager/commands/yank.rs b/yazi-core/src/manager/commands/yank.rs index bd43646a..cb07bea5 100644 --- a/yazi-core/src/manager/commands/yank.rs +++ b/yazi-core/src/manager/commands/yank.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::manager::Manager; diff --git a/yazi-core/src/manager/manager.rs b/yazi-core/src/manager/manager.rs index 9846a00e..269042a5 100644 --- a/yazi-core/src/manager/manager.rs +++ b/yazi-core/src/manager/manager.rs @@ -1,9 +1,9 @@ use std::collections::{BTreeMap, HashMap, HashSet}; -use yazi_shared::Url; +use yazi_shared::{files::{File, FilesOp}, fs::Url}; use super::{Tabs, Watcher}; -use crate::{files::{File, FilesOp}, tab::{Folder, Tab}, tasks::Tasks}; +use crate::{tab::{Folder, Tab}, tasks::Tasks}; pub struct Manager { pub tabs: Tabs, diff --git a/yazi-core/src/manager/tabs.rs b/yazi-core/src/manager/tabs.rs index a235fcaa..0f8a882d 100644 --- a/yazi-core/src/manager/tabs.rs +++ b/yazi-core/src/manager/tabs.rs @@ -1,5 +1,5 @@ use yazi_config::BOOT; -use yazi_shared::Url; +use yazi_shared::fs::Url; use crate::{manager::Manager, tab::Tab}; diff --git a/yazi-core/src/manager/watcher.rs b/yazi-core/src/manager/watcher.rs index 3d862a57..785b2e2b 100644 --- a/yazi-core/src/manager/watcher.rs +++ b/yazi-core/src/manager/watcher.rs @@ -5,9 +5,9 @@ use notify::{event::{MetadataKind, ModifyKind}, EventKind, RecommendedWatcher, R use parking_lot::RwLock; use tokio::{fs, pin, sync::mpsc::{self, UnboundedReceiver}}; use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt}; -use yazi_shared::Url; +use yazi_shared::{emit, files::{File, FilesOp}, fs::Url}; -use crate::{emit, external, files::{File, Files, FilesOp}}; +use crate::{external, files::Files}; pub struct Watcher { watcher: RecommendedWatcher, diff --git a/yazi-core/src/preview/preview.rs b/yazi-core/src/preview/preview.rs index 5ba3e75b..32804d57 100644 --- a/yazi-core/src/preview/preview.rs +++ b/yazi-core/src/preview/preview.rs @@ -4,10 +4,10 @@ use tokio::{pin, task::JoinHandle}; use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt}; use yazi_adaptor::ADAPTOR; use yazi_config::MANAGER; -use yazi_shared::{Cha, MimeKind, PeekError, Url}; +use yazi_shared::{emit, event::{PreviewData, PreviewLock}, files::FilesOp, fs::{Cha, Url}, MimeKind, PeekError}; use super::Provider; -use crate::{emit, files::{Files, FilesOp}, manager::Manager, Highlighter}; +use crate::{files::Files, manager::Manager, Highlighter}; #[derive(Default)] pub struct Preview { @@ -17,20 +17,6 @@ pub struct Preview { handle: Option>, } -pub struct PreviewLock { - pub url: Url, - pub cha: Option, - pub skip: usize, - pub data: PreviewData, -} - -#[derive(Debug)] -pub enum PreviewData { - Folder, - Text(String), - Image, -} - impl Preview { pub fn go(&mut self, url: &Url, cha: Cha, mime: &str) { if self.content_unchanged(url, &cha) { @@ -152,11 +138,3 @@ impl Preview { } } } - -impl PreviewLock { - #[inline] - pub fn is_image(&self) -> bool { matches!(self.data, PreviewData::Image) } - - #[inline] - pub fn is_folder(&self) -> bool { matches!(self.data, PreviewData::Folder) } -} diff --git a/yazi-core/src/preview/provider.rs b/yazi-core/src/preview/provider.rs index 191dc76d..9fa4adfc 100644 --- a/yazi-core/src/preview/provider.rs +++ b/yazi-core/src/preview/provider.rs @@ -3,9 +3,8 @@ use std::path::Path; use tokio::fs; use yazi_adaptor::ADAPTOR; use yazi_config::{MANAGER, PREVIEW}; -use yazi_shared::{MimeKind, PeekError}; +use yazi_shared::{event::PreviewData, MimeKind, PeekError}; -use super::PreviewData; use crate::{external, Highlighter}; pub(super) struct Provider; diff --git a/yazi-core/src/select/commands/arrow.rs b/yazi-core/src/select/commands/arrow.rs index e06a3ddc..66f51fa2 100644 --- a/yazi-core/src/select/commands/arrow.rs +++ b/yazi-core/src/select/commands/arrow.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::select::Select; diff --git a/yazi-core/src/select/commands/close.rs b/yazi-core/src/select/commands/close.rs index edc575df..5977cc29 100644 --- a/yazi-core/src/select/commands/close.rs +++ b/yazi-core/src/select/commands/close.rs @@ -1,5 +1,5 @@ use anyhow::anyhow; -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::select::Select; diff --git a/yazi-core/src/select/commands/mod.rs b/yazi-core/src/select/commands/mod.rs index 9225a7a8..d36c6ae8 100644 --- a/yazi-core/src/select/commands/mod.rs +++ b/yazi-core/src/select/commands/mod.rs @@ -1,2 +1,3 @@ mod arrow; mod close; +mod show; diff --git a/yazi-core/src/select/commands/show.rs b/yazi-core/src/select/commands/show.rs new file mode 100644 index 00000000..5abf8d6d --- /dev/null +++ b/yazi-core/src/select/commands/show.rs @@ -0,0 +1,42 @@ +use anyhow::{anyhow, Result}; +use tokio::sync::oneshot; +use yazi_config::popup::SelectCfg; +use yazi_shared::{emit, event::Exec, term::Term, Layer}; + +use crate::select::Select; + +pub struct Opt { + cfg: SelectCfg, + tx: oneshot::Sender>, +} + +impl TryFrom<&Exec> for Opt { + type Error = anyhow::Error; + + fn try_from(e: &Exec) -> Result { + e.take_data().ok_or_else(|| anyhow!("invalid data")) + } +} + +impl Select { + pub async fn _show(cfg: SelectCfg) -> Result { + let (tx, rx) = oneshot::channel(); + emit!(Call(Exec::call("show", vec![]).with_data(Opt { cfg, tx }).vec(), Layer::Select)); + rx.await.unwrap_or_else(|_| Term::goodbye(|| false)) + } + + pub fn show(&mut self, opt: impl TryInto) -> bool { + let Ok(opt) = opt.try_into() else { + return false; + }; + + self.close(false); + self.title = opt.cfg.title; + self.items = opt.cfg.items; + self.position = opt.cfg.position; + + self.callback = Some(opt.tx); + self.visible = true; + true + } +} diff --git a/yazi-core/src/select/select.rs b/yazi-core/src/select/select.rs index 5946c42b..26e4f4fa 100644 --- a/yazi-core/src/select/select.rs +++ b/yazi-core/src/select/select.rs @@ -1,10 +1,10 @@ use anyhow::Result; use tokio::sync::oneshot::Sender; -use yazi_config::{popup::{Position, SelectOpt}, SELECT}; +use yazi_config::{popup::Position, SELECT}; #[derive(Default)] pub struct Select { - title: String, + pub(super) title: String, pub(super) items: Vec, pub position: Position, @@ -16,17 +16,6 @@ pub struct Select { } impl Select { - pub fn show(&mut self, opt: SelectOpt, tx: Sender>) { - self.close(false); - - self.title = opt.title; - self.items = opt.items; - self.position = opt.position; - - self.callback = Some(tx); - self.visible = true; - } - #[inline] pub fn window(&self) -> &[String] { let end = (self.offset + self.limit()).min(self.items.len()); diff --git a/yazi-core/src/tab/commands/arrow.rs b/yazi-core/src/tab/commands/arrow.rs index 6119f067..098c7f53 100644 --- a/yazi-core/src/tab/commands/arrow.rs +++ b/yazi-core/src/tab/commands/arrow.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::{manager::Manager, tab::Tab, Step}; diff --git a/yazi-core/src/tab/commands/backstack.rs b/yazi-core/src/tab/commands/backstack.rs index c565ca51..0ddab3f5 100644 --- a/yazi-core/src/tab/commands/backstack.rs +++ b/yazi-core/src/tab/commands/backstack.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::tab::Tab; diff --git a/yazi-core/src/tab/commands/cd.rs b/yazi-core/src/tab/commands/cd.rs index ebdce216..c4e3f40b 100644 --- a/yazi-core/src/tab/commands/cd.rs +++ b/yazi-core/src/tab/commands/cd.rs @@ -2,10 +2,10 @@ use std::{mem, time::Duration}; use tokio::{fs, pin}; use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt}; -use yazi_config::{keymap::{Exec, KeymapLayer}, popup::InputOpt}; -use yazi_shared::{expand_path, Debounce, InputError, Url}; +use yazi_config::popup::InputCfg; +use yazi_shared::{emit, event::Exec, fs::{expand_path, Url}, Debounce, InputError, Layer}; -use crate::{completion::Completion, emit, manager::Manager, tab::Tab}; +use crate::{completion::Completion, input::Input, manager::Manager, tab::Tab}; pub struct Opt { target: Url, @@ -29,7 +29,7 @@ impl From for Opt { impl Tab { #[inline] pub fn _cd(target: &Url) { - emit!(Call(Exec::call("cd", vec![target.to_string()]).vec(), KeymapLayer::Manager)); + emit!(Call(Exec::call("cd", vec![target.to_string()]).vec(), Layer::Manager)); } pub fn cd(&mut self, opt: impl Into) -> bool { @@ -72,7 +72,7 @@ impl Tab { let opt = opt.into() as Opt; tokio::spawn(async move { - let rx = emit!(Input(InputOpt::cd().with_value(opt.target.to_string_lossy()))); + let rx = Input::_show(InputCfg::cd().with_value(opt.target.to_string_lossy())); let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50)); pin!(rx); diff --git a/yazi-core/src/tab/commands/copy.rs b/yazi-core/src/tab/commands/copy.rs index bc864585..805619fa 100644 --- a/yazi-core/src/tab/commands/copy.rs +++ b/yazi-core/src/tab/commands/copy.rs @@ -1,6 +1,6 @@ use std::ffi::{OsStr, OsString}; -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::{external, tab::Tab}; diff --git a/yazi-core/src/tab/commands/enter.rs b/yazi-core/src/tab/commands/enter.rs index 65f9ce24..a8a04e2b 100644 --- a/yazi-core/src/tab/commands/enter.rs +++ b/yazi-core/src/tab/commands/enter.rs @@ -1,6 +1,6 @@ use std::mem; -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::{manager::Manager, tab::Tab}; diff --git a/yazi-core/src/tab/commands/escape.rs b/yazi-core/src/tab/commands/escape.rs index e8e7eca5..c6e13721 100644 --- a/yazi-core/src/tab/commands/escape.rs +++ b/yazi-core/src/tab/commands/escape.rs @@ -1,5 +1,5 @@ use bitflags::bitflags; -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::tab::{Mode, Tab}; diff --git a/yazi-core/src/tab/commands/find.rs b/yazi-core/src/tab/commands/find.rs index 53dd0ef4..e95a330f 100644 --- a/yazi-core/src/tab/commands/find.rs +++ b/yazi-core/src/tab/commands/find.rs @@ -2,10 +2,10 @@ use std::time::Duration; use tokio::pin; use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt}; -use yazi_config::{keymap::{Exec, KeymapLayer}, popup::InputOpt}; -use yazi_shared::{Debounce, InputError}; +use yazi_config::popup::InputCfg; +use yazi_shared::{emit, event::Exec, Debounce, InputError, Layer}; -use crate::{emit, tab::{Finder, FinderCase, Tab}}; +use crate::{input::Input, tab::{Finder, FinderCase, Tab}}; pub struct Opt<'a> { query: Option<&'a str>, @@ -39,7 +39,7 @@ impl Tab { pub fn find<'a>(&mut self, opt: impl Into>) -> bool { let opt = opt.into() as Opt; tokio::spawn(async move { - let rx = emit!(Input(InputOpt::find(opt.prev))); + let rx = Input::_show(InputCfg::find(opt.prev)); let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50)); pin!(rx); @@ -51,7 +51,7 @@ impl Tab { .with_bool("smart", opt.case == FinderCase::Smart) .with_bool("insensitive", opt.case == FinderCase::Insensitive) .vec(), - KeymapLayer::Manager + Layer::Manager )); } }); diff --git a/yazi-core/src/tab/commands/hidden.rs b/yazi-core/src/tab/commands/hidden.rs index f66b3cba..916e6ef1 100644 --- a/yazi-core/src/tab/commands/hidden.rs +++ b/yazi-core/src/tab/commands/hidden.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::{manager::Manager, tab::Tab}; diff --git a/yazi-core/src/tab/commands/jump.rs b/yazi-core/src/tab/commands/jump.rs index e69314cb..3cb3e69d 100644 --- a/yazi-core/src/tab/commands/jump.rs +++ b/yazi-core/src/tab/commands/jump.rs @@ -1,7 +1,6 @@ -use yazi_config::keymap::Exec; -use yazi_shared::{ends_with_slash, Defer}; +use yazi_shared::{event::Exec, fs::ends_with_slash, Defer}; -use crate::{emit, external::{self, FzfOpt, ZoxideOpt}, tab::Tab, Event, BLOCKER}; +use crate::{external::{self, FzfOpt, ZoxideOpt}, tab::Tab, Ctx, BLOCKER}; pub struct Opt { type_: OptType, @@ -36,8 +35,8 @@ impl Tab { let cwd = self.current.cwd.clone(); tokio::spawn(async move { let _guard = BLOCKER.acquire().await.unwrap(); - let _defer = Defer::new(|| Event::Stop(false, None).emit()); - emit!(Stop(true)).await; + let _defer = Defer::new(Ctx::resume); + Ctx::stop().await; let result = if opt.type_ == OptType::Fzf { external::fzf(FzfOpt { cwd }).await diff --git a/yazi-core/src/tab/commands/leave.rs b/yazi-core/src/tab/commands/leave.rs index f07480eb..04769e1f 100644 --- a/yazi-core/src/tab/commands/leave.rs +++ b/yazi-core/src/tab/commands/leave.rs @@ -1,6 +1,6 @@ use std::mem; -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::{manager::Manager, tab::Tab}; diff --git a/yazi-core/src/tab/commands/linemode.rs b/yazi-core/src/tab/commands/linemode.rs index 36feab95..12a1049c 100644 --- a/yazi-core/src/tab/commands/linemode.rs +++ b/yazi-core/src/tab/commands/linemode.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::tab::Tab; diff --git a/yazi-core/src/tab/commands/reveal.rs b/yazi-core/src/tab/commands/reveal.rs index 00f481c4..4c7bda76 100644 --- a/yazi-core/src/tab/commands/reveal.rs +++ b/yazi-core/src/tab/commands/reveal.rs @@ -1,7 +1,6 @@ -use yazi_config::keymap::{Exec, KeymapLayer}; -use yazi_shared::{expand_path, Url}; +use yazi_shared::{emit, event::Exec, files::{File, FilesOp}, fs::{expand_path, Url}, Layer}; -use crate::{emit, files::{File, FilesOp}, manager::Manager, tab::Tab}; +use crate::{manager::Manager, tab::Tab}; pub struct Opt { target: Url, @@ -24,7 +23,7 @@ impl From for Opt { impl Tab { #[inline] pub fn _reveal(target: &Url) { - emit!(Call(Exec::call("reveal", vec![target.to_string()]).vec(), KeymapLayer::Manager)); + emit!(Call(Exec::call("reveal", vec![target.to_string()]).vec(), Layer::Manager)); } pub fn reveal(&mut self, opt: impl Into) -> bool { diff --git a/yazi-core/src/tab/commands/search.rs b/yazi-core/src/tab/commands/search.rs index 6d60aafb..49b51471 100644 --- a/yazi-core/src/tab/commands/search.rs +++ b/yazi-core/src/tab/commands/search.rs @@ -3,9 +3,10 @@ use std::{mem, time::Duration}; use anyhow::bail; use tokio::pin; use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt}; -use yazi_config::{keymap::Exec, popup::InputOpt}; +use yazi_config::popup::InputCfg; +use yazi_shared::{emit, event::Exec, files::FilesOp}; -use crate::{emit, external, files::FilesOp, manager::Manager, tab::Tab}; +use crate::{external, input::Input, manager::Manager, tab::Tab}; pub struct Opt { pub type_: OptType, @@ -45,7 +46,7 @@ impl Tab { let hidden = self.conf.show_hidden; self.search = Some(tokio::spawn(async move { - let Some(Ok(subject)) = emit!(Input(InputOpt::search())).recv().await else { bail!("") }; + let Some(Ok(subject)) = Input::_show(InputCfg::search()).recv().await else { bail!("") }; cwd = cwd.into_search(subject.clone()); let rx = if opt.type_ == OptType::Rg { diff --git a/yazi-core/src/tab/commands/select.rs b/yazi-core/src/tab/commands/select.rs index 5d7cac87..eb18b091 100644 --- a/yazi-core/src/tab/commands/select.rs +++ b/yazi-core/src/tab/commands/select.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::tab::Tab; diff --git a/yazi-core/src/tab/commands/shell.rs b/yazi-core/src/tab/commands/shell.rs index fb309e72..f98c4a89 100644 --- a/yazi-core/src/tab/commands/shell.rs +++ b/yazi-core/src/tab/commands/shell.rs @@ -1,6 +1,7 @@ -use yazi_config::{keymap::Exec, open::Opener, popup::InputOpt}; +use yazi_config::{open::Opener, popup::InputCfg}; +use yazi_shared::event::Exec; -use crate::{emit, tab::Tab}; +use crate::{input::Input, tab::Tab, tasks::Tasks}; pub struct Opt { cmd: String, @@ -29,14 +30,14 @@ impl Tab { let mut opt = opt.into() as Opt; tokio::spawn(async move { if !opt.confirm || opt.cmd.is_empty() { - let mut result = emit!(Input(InputOpt::shell(opt.block).with_value(opt.cmd))); + let mut result = Input::_show(InputCfg::shell(opt.block).with_value(opt.cmd)); match result.recv().await { Some(Ok(e)) => opt.cmd = e, _ => return, } } - emit!(Open( + Tasks::_open( selected, Some(Opener { exec: opt.cmd, @@ -45,8 +46,8 @@ impl Tab { desc: Default::default(), for_: None, spread: true, - }) - )); + }), + ); }); false diff --git a/yazi-core/src/tab/commands/sort.rs b/yazi-core/src/tab/commands/sort.rs index 73793607..f8e3eea1 100644 --- a/yazi-core/src/tab/commands/sort.rs +++ b/yazi-core/src/tab/commands/sort.rs @@ -1,6 +1,7 @@ use std::str::FromStr; -use yazi_config::{keymap::Exec, manager::SortBy}; +use yazi_config::manager::SortBy; +use yazi_shared::event::Exec; use crate::tab::Tab; diff --git a/yazi-core/src/tab/commands/visual_mode.rs b/yazi-core/src/tab/commands/visual_mode.rs index 15ac386b..470f6649 100644 --- a/yazi-core/src/tab/commands/visual_mode.rs +++ b/yazi-core/src/tab/commands/visual_mode.rs @@ -1,6 +1,6 @@ use std::collections::BTreeSet; -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::tab::{Mode, Tab}; diff --git a/yazi-core/src/tab/finder.rs b/yazi-core/src/tab/finder.rs index db6112b0..8ed6101c 100644 --- a/yazi-core/src/tab/finder.rs +++ b/yazi-core/src/tab/finder.rs @@ -2,7 +2,7 @@ use std::{collections::BTreeMap, ffi::OsStr, ops::Range}; use anyhow::Result; use regex::bytes::{Regex, RegexBuilder}; -use yazi_shared::Url; +use yazi_shared::fs::Url; use crate::files::Files; diff --git a/yazi-core/src/tab/folder.rs b/yazi-core/src/tab/folder.rs index 923def05..623b907d 100644 --- a/yazi-core/src/tab/folder.rs +++ b/yazi-core/src/tab/folder.rs @@ -1,8 +1,8 @@ use ratatui::layout::Rect; use yazi_config::MANAGER; -use yazi_shared::Url; +use yazi_shared::{emit, files::{File, FilesOp}, fs::Url}; -use crate::{emit, files::{File, Files, FilesOp}, Step}; +use crate::{files::Files, Step}; #[derive(Default)] pub struct Folder { diff --git a/yazi-core/src/tab/tab.rs b/yazi-core/src/tab/tab.rs index 393fb714..d1ddd9dc 100644 --- a/yazi-core/src/tab/tab.rs +++ b/yazi-core/src/tab/tab.rs @@ -2,10 +2,10 @@ use std::{borrow::Cow, collections::BTreeMap}; use anyhow::Result; use tokio::task::JoinHandle; -use yazi_shared::Url; +use yazi_shared::{event::PreviewLock, files::File, fs::Url}; use super::{Backstack, Config, Finder, Folder, Mode}; -use crate::{files::File, preview::{Preview, PreviewLock}}; +use crate::preview::Preview; pub struct Tab { pub mode: Mode, diff --git a/yazi-core/src/tasks/commands/arrow.rs b/yazi-core/src/tasks/commands/arrow.rs index 22333208..a662f5fe 100644 --- a/yazi-core/src/tasks/commands/arrow.rs +++ b/yazi-core/src/tasks/commands/arrow.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::tasks::Tasks; diff --git a/yazi-core/src/tasks/commands/cancel.rs b/yazi-core/src/tasks/commands/cancel.rs index ea028859..013d10ed 100644 --- a/yazi-core/src/tasks/commands/cancel.rs +++ b/yazi-core/src/tasks/commands/cancel.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::tasks::Tasks; diff --git a/yazi-core/src/tasks/commands/inspect.rs b/yazi-core/src/tasks/commands/inspect.rs index 6649a6e8..349dabff 100644 --- a/yazi-core/src/tasks/commands/inspect.rs +++ b/yazi-core/src/tasks/commands/inspect.rs @@ -2,10 +2,9 @@ use std::io::{stdout, Write}; use crossterm::terminal::{disable_raw_mode, enable_raw_mode}; use tokio::{io::{stdin, AsyncReadExt}, select, sync::mpsc, time}; -use yazi_config::keymap::Exec; -use yazi_shared::{Defer, Term}; +use yazi_shared::{event::Exec, term::Term, Defer}; -use crate::{emit, tasks::Tasks, Event, BLOCKER}; +use crate::{tasks::Tasks, Ctx, BLOCKER}; pub struct Opt; @@ -32,10 +31,10 @@ impl Tasks { task.logs.clone() }; - emit!(Stop(true)).await; + Ctx::stop().await; let _defer = Defer::new(|| { disable_raw_mode().ok(); - Event::Stop(false, None).emit(); + Ctx::resume(); }); Term::clear(&mut stdout()).ok(); diff --git a/yazi-core/src/tasks/commands/mod.rs b/yazi-core/src/tasks/commands/mod.rs index e6c3cafd..987a842b 100644 --- a/yazi-core/src/tasks/commands/mod.rs +++ b/yazi-core/src/tasks/commands/mod.rs @@ -1,4 +1,6 @@ mod arrow; mod cancel; mod inspect; +mod open; mod toggle; +mod update; diff --git a/yazi-core/src/tasks/commands/open.rs b/yazi-core/src/tasks/commands/open.rs new file mode 100644 index 00000000..513945f4 --- /dev/null +++ b/yazi-core/src/tasks/commands/open.rs @@ -0,0 +1,51 @@ +use std::ffi::OsString; + +use anyhow::anyhow; +use yazi_config::{open::Opener, BOOT}; +use yazi_shared::{emit, event::Exec, Layer}; + +use crate::tasks::Tasks; + +pub struct Opt { + targets: Vec<(OsString, String)>, + opener: Option, +} + +impl TryFrom<&Exec> for Opt { + type Error = anyhow::Error; + + fn try_from(e: &Exec) -> Result { + e.take_data().ok_or_else(|| anyhow!("invalid data")) + } +} + +impl Tasks { + pub fn _open(targets: Vec<(OsString, String)>, opener: Option) { + emit!(Call(Exec::call("open", vec![]).with_data(Opt { targets, opener }).vec(), Layer::Tasks)); + } + + pub fn open(&mut self, opt: impl TryInto) -> bool { + let Ok(opt) = opt.try_into() else { + return false; + }; + + if let Some(p) = &BOOT.chooser_file { + let paths = opt.targets.into_iter().fold(OsString::new(), |mut s, (p, _)| { + s.push(p); + s.push("\n"); + s + }); + + std::fs::write(p, paths.as_encoded_bytes()).ok(); + emit!(Quit(false)); + return false; + } + + if let Some(opener) = opt.opener { + self.file_open_with(&opener, &opt.targets.into_iter().map(|(f, _)| f).collect::>()); + } else { + self.file_open(&opt.targets); + } + false + } +} diff --git a/yazi-core/src/tasks/commands/toggle.rs b/yazi-core/src/tasks/commands/toggle.rs index ad7a4cda..b97c5ba5 100644 --- a/yazi-core/src/tasks/commands/toggle.rs +++ b/yazi-core/src/tasks/commands/toggle.rs @@ -1,4 +1,4 @@ -use yazi_config::keymap::Exec; +use yazi_shared::event::Exec; use crate::tasks::Tasks; diff --git a/yazi-core/src/tasks/commands/update.rs b/yazi-core/src/tasks/commands/update.rs new file mode 100644 index 00000000..8f3d0f57 --- /dev/null +++ b/yazi-core/src/tasks/commands/update.rs @@ -0,0 +1,31 @@ +use anyhow::anyhow; +use yazi_shared::{emit, event::Exec, Layer}; + +use crate::tasks::{Tasks, TasksProgress}; + +pub struct Opt { + progress: TasksProgress, +} + +impl TryFrom<&Exec> for Opt { + type Error = anyhow::Error; + + fn try_from(e: &Exec) -> Result { + e.take_data().ok_or_else(|| anyhow!("invalid data")) + } +} + +impl Tasks { + pub fn _update(progress: TasksProgress) { + emit!(Call(Exec::call("update", vec![]).with_data(Opt { progress }).vec(), Layer::Tasks)); + } + + pub fn update(&mut self, opt: impl TryInto) -> bool { + let Ok(opt) = opt.try_into() else { + return false; + }; + + self.progress = opt.progress; + true + } +} diff --git a/yazi-core/src/tasks/scheduler.rs b/yazi-core/src/tasks/scheduler.rs index f5499136..0309892f 100644 --- a/yazi-core/src/tasks/scheduler.rs +++ b/yazi-core/src/tasks/scheduler.rs @@ -4,10 +4,10 @@ use futures::{future::BoxFuture, FutureExt}; use parking_lot::RwLock; use tokio::{fs, select, sync::{mpsc::{self, UnboundedReceiver}, oneshot}, time::sleep}; use yazi_config::{open::Opener, TASKS}; -use yazi_shared::{unique_path, Throttle, Url}; +use yazi_shared::{fs::{unique_path, Url}, Throttle}; use super::{workers::{File, FileOpDelete, FileOpLink, FileOpPaste, FileOpTrash, Precache, PrecacheOpMime, PrecacheOpSize, Process, ProcessOpOpen}, Running, TaskOp, TaskStage, TasksProgress}; -use crate::emit; +use crate::tasks::Tasks; pub struct Scheduler { file: Arc, @@ -157,7 +157,7 @@ impl Scheduler { let new = TasksProgress::from(&*running.read()); if last != new { last = new; - emit!(Progress(new)); + Tasks::_update(new); } } }); diff --git a/yazi-core/src/tasks/tasks.rs b/yazi-core/src/tasks/tasks.rs index 765f69c0..0c573463 100644 --- a/yazi-core/src/tasks/tasks.rs +++ b/yazi-core/src/tasks/tasks.rs @@ -2,11 +2,11 @@ use std::{collections::{BTreeMap, HashMap, HashSet}, ffi::OsStr, path::Path, syn use serde::Serialize; use tracing::debug; -use yazi_config::{manager::SortBy, open::Opener, popup::InputOpt, OPEN}; -use yazi_shared::{MimeKind, Term, Url}; +use yazi_config::{manager::SortBy, open::Opener, popup::InputCfg, OPEN}; +use yazi_shared::{files::File, fs::Url, term::Term, MimeKind}; use super::{running::Running, task::TaskSummary, Scheduler, TASKS_PADDING, TASKS_PERCENT}; -use crate::{emit, files::{File, Files}}; +use crate::{files::Files, input::Input}; pub struct Tasks { pub(super) scheduler: Arc, @@ -110,11 +110,11 @@ impl Tasks { let scheduler = self.scheduler.clone(); tokio::spawn(async move { - let mut result = emit!(Input(if permanently { - InputOpt::delete(targets.len()) + let mut result = Input::_show(if permanently { + InputCfg::delete(targets.len()) } else { - InputOpt::trash(targets.len()) - })); + InputCfg::trash(targets.len()) + }); if let Some(Ok(choice)) = result.recv().await { if choice != "y" && choice != "Y" { diff --git a/yazi-core/src/tasks/workers/file.rs b/yazi-core/src/tasks/workers/file.rs index 8239d967..56ae4d58 100644 --- a/yazi-core/src/tasks/workers/file.rs +++ b/yazi-core/src/tasks/workers/file.rs @@ -5,7 +5,7 @@ use futures::{future::BoxFuture, FutureExt}; use tokio::{fs, io::{self, ErrorKind::{AlreadyExists, NotFound}}, sync::mpsc}; use tracing::warn; use yazi_config::TASKS; -use yazi_shared::{calculate_size, copy_with_progress, path_relative_to, Url}; +use yazi_shared::fs::{calculate_size, copy_with_progress, path_relative_to, Url}; use crate::tasks::TaskOp; diff --git a/yazi-core/src/tasks/workers/precache.rs b/yazi-core/src/tasks/workers/precache.rs index abe6fe71..a3239ee4 100644 --- a/yazi-core/src/tasks/workers/precache.rs +++ b/yazi-core/src/tasks/workers/precache.rs @@ -5,9 +5,9 @@ use parking_lot::Mutex; use tokio::{fs, sync::mpsc}; use yazi_adaptor::Image; use yazi_config::PREVIEW; -use yazi_shared::{calculate_size, Throttle, Url}; +use yazi_shared::{emit, files::FilesOp, fs::{calculate_size, Url}, Throttle}; -use crate::{emit, external, files::FilesOp, tasks::TaskOp}; +use crate::{external, tasks::TaskOp}; pub(crate) struct Precache { tx: async_channel::Sender, diff --git a/yazi-core/src/tasks/workers/process.rs b/yazi-core/src/tasks/workers/process.rs index 885aea36..3707d655 100644 --- a/yazi-core/src/tasks/workers/process.rs +++ b/yazi-core/src/tasks/workers/process.rs @@ -3,7 +3,7 @@ use std::{ffi::OsString, mem}; use anyhow::Result; use tokio::{io::{AsyncBufReadExt, BufReader}, select, sync::{mpsc, oneshot}}; -use crate::{emit, external::{self, ShellOpt}, tasks::TaskOp, BLOCKER}; +use crate::{external::{self, ShellOpt}, tasks::TaskOp, Ctx, BLOCKER}; pub(crate) struct Process { sch: mpsc::UnboundedSender, @@ -37,7 +37,7 @@ impl Process { let opt = ShellOpt::from(&mut task); if task.block { let _guard = BLOCKER.acquire().await.unwrap(); - emit!(Stop(true)).await; + Ctx::stop().await; match external::shell(opt) { Ok(mut child) => { @@ -49,7 +49,7 @@ impl Process { self.fail(task.id, format!("Failed to spawn process: {e}"))?; } } - return Ok(emit!(Stop(false)).await); + return Ok(Ctx::resume()); } if task.orphan { diff --git a/yazi-core/src/which/which.rs b/yazi-core/src/which/which.rs index ab7c7dbd..b70dcc18 100644 --- a/yazi-core/src/which/which.rs +++ b/yazi-core/src/which/which.rs @@ -1,29 +1,27 @@ use std::mem; -use yazi_config::{keymap::{Control, Key, KeymapLayer}, KEYMAP}; - -use crate::emit; +use yazi_config::{keymap::{Control, Key}, KEYMAP}; +use yazi_shared::{emit, Layer}; pub struct Which { - layer: KeymapLayer, + layer: Layer, pub times: usize, - pub cands: Vec, + pub cands: Vec<&'static Control>, pub visible: bool, } impl Default for Which { fn default() -> Self { - Self { layer: KeymapLayer::Manager, times: 0, cands: Default::default(), visible: false } + Self { layer: Layer::Manager, times: 0, cands: Default::default(), visible: false } } } impl Which { - pub fn show(&mut self, key: &Key, layer: KeymapLayer) -> bool { + pub fn show(&mut self, key: &Key, layer: Layer) -> bool { self.layer = layer; self.times = 1; - self.cands = - KEYMAP.get(layer).iter().filter(|s| s.on.len() > 1 && &s.on[0] == key).cloned().collect(); + self.cands = KEYMAP.get(layer).iter().filter(|s| s.on.len() > 1 && &s.on[0] == key).collect(); self.visible = true; true } diff --git a/yazi-fm/src/app.rs b/yazi-fm/src/app/app.rs similarity index 67% rename from yazi-fm/src/app.rs rename to yazi-fm/src/app/app.rs index b34584e5..29c6b32b 100644 --- a/yazi-fm/src/app.rs +++ b/yazi-fm/src/app/app.rs @@ -1,23 +1,22 @@ -use std::{ffi::OsString, sync::atomic::Ordering}; +use std::sync::atomic::Ordering; use anyhow::{Ok, Result}; use crossterm::event::KeyEvent; use ratatui::{backend::Backend, prelude::Rect}; -use tokio::sync::oneshot; -use yazi_config::{keymap::{Exec, Key, KeymapLayer}, BOOT}; -use yazi_core::{emit, files::FilesOp, input::InputMode, manager::Manager, preview::COLLISION, Ctx, Event}; -use yazi_shared::Term; +use yazi_config::{keymap::Key, BOOT}; +use yazi_core::{input::InputMode, preview::COLLISION, Ctx}; +use yazi_shared::{emit, event::{Event, Exec}, files::FilesOp, term::Term, Layer}; use crate::{Executor, Logs, Panic, Root, Signals}; -pub(super) struct App { - cx: Ctx, - term: Option, - signals: Signals, +pub(crate) struct App { + pub(crate) cx: Ctx, + pub(crate) term: Option, + pub(crate) signals: Signals, } impl App { - pub(super) async fn run() -> Result<()> { + pub(crate) async fn run() -> Result<()> { Panic::install(); let _log = Logs::init()?; let term = Term::start()?; @@ -35,7 +34,6 @@ impl App { Event::Paste(str) => app.dispatch_paste(str), Event::Render(_) => app.dispatch_render()?, Event::Resize(cols, rows) => app.dispatch_resize(cols, rows), - Event::Stop(state, tx) => app.dispatch_stop(state, tx), Event::Call(exec, layer) => app.dispatch_call(exec, layer), event => app.dispatch_module(event), } @@ -48,12 +46,12 @@ impl App { let cwd = self.cx.manager.cwd().as_os_str(); std::fs::write(p, cwd.as_encoded_bytes()).ok(); } - Term::goodbye(|| false).unwrap(); + Term::goodbye(|| false); } fn dispatch_key(&mut self, key: KeyEvent) { let key = Key::from(key); - if Executor::new(&mut self.cx).handle(key) { + if Executor::new(self).handle(key) { emit!(Render); } } @@ -121,25 +119,9 @@ impl App { emit!(Render); } - fn dispatch_stop(&mut self, state: bool, tx: Option>) { - self.cx.manager.active_mut().preview.reset_image(); - if state { - self.signals.stop_term(true); - self.term = None; - } else { - self.term = Some(Term::start().unwrap()); - self.signals.stop_term(false); - emit!(Render); - Manager::_hover(None); - } - if let Some(tx) = tx { - tx.send(()).ok(); - } - } - #[inline] - fn dispatch_call(&mut self, exec: Vec, layer: KeymapLayer) { - if Executor::new(&mut self.cx).dispatch(&exec, layer) { + fn dispatch_call(&mut self, exec: Vec, layer: Layer) { + if Executor::new(self).dispatch(&exec, layer) { emit!(Render); } } @@ -176,39 +158,6 @@ impl App { emit!(Render); } } - - Event::Select(opt, tx) => { - self.cx.select.show(opt, tx); - emit!(Render); - } - Event::Input(opt, tx) => { - self.cx.input.show(opt, tx); - emit!(Render); - } - - Event::Open(targets, opener) => { - if let Some(p) = &BOOT.chooser_file { - let paths = targets.into_iter().fold(OsString::new(), |mut s, (p, _)| { - s.push(p); - s.push("\n"); - s - }); - - std::fs::write(p, paths.as_encoded_bytes()).ok(); - return emit!(Quit(false)); - } - - if let Some(opener) = opener { - tasks.file_open_with(&opener, &targets.into_iter().map(|(f, _)| f).collect::>()); - } else { - tasks.file_open(&targets); - } - } - Event::Progress(progress) => { - tasks.progress = progress; - emit!(Render); - } - _ => unreachable!(), } } diff --git a/yazi-fm/src/app/commands/mod.rs b/yazi-fm/src/app/commands/mod.rs new file mode 100644 index 00000000..eeec0cfb --- /dev/null +++ b/yazi-fm/src/app/commands/mod.rs @@ -0,0 +1 @@ +mod stop; diff --git a/yazi-fm/src/app/commands/stop.rs b/yazi-fm/src/app/commands/stop.rs new file mode 100644 index 00000000..591335cc --- /dev/null +++ b/yazi-fm/src/app/commands/stop.rs @@ -0,0 +1,42 @@ +use anyhow::Result; +use tokio::sync::oneshot; +use yazi_core::manager::Manager; +use yazi_shared::{emit, event::Exec, term::Term}; + +use crate::app::App; + +pub struct Opt { + state: bool, + tx: Option>, +} + +impl TryFrom<&Exec> for Opt { + type Error = anyhow::Error; + + fn try_from(e: &Exec) -> Result { + Ok(Self { state: e.args.first().map_or(false, |s| s == "true"), tx: e.take_data() }) + } +} + +impl App { + pub(crate) fn stop(&mut self, opt: impl TryInto) -> bool { + let Ok(opt) = opt.try_into() else { + return false; + }; + + self.cx.manager.active_mut().preview.reset_image(); + if opt.state { + self.signals.stop_term(true); + self.term = None; + } else { + self.term = Some(Term::start().unwrap()); + self.signals.stop_term(false); + emit!(Render); + Manager::_hover(None); + } + if let Some(tx) = opt.tx { + tx.send(()).ok(); + } + false + } +} diff --git a/yazi-fm/src/app/mod.rs b/yazi-fm/src/app/mod.rs new file mode 100644 index 00000000..a64137a6 --- /dev/null +++ b/yazi-fm/src/app/mod.rs @@ -0,0 +1,4 @@ +mod app; +mod commands; + +pub(crate) use app::*; diff --git a/yazi-fm/src/executor.rs b/yazi-fm/src/executor.rs index d73d21b5..8628aec6 100644 --- a/yazi-fm/src/executor.rs +++ b/yazi-fm/src/executor.rs @@ -1,50 +1,55 @@ -use yazi_config::{keymap::{Control, Exec, Key, KeymapLayer}, KEYMAP}; -use yazi_core::{input::InputMode, Ctx}; +use yazi_config::{keymap::{Control, Key}, KEYMAP}; +use yazi_core::input::InputMode; +use yazi_shared::{event::Exec, Layer}; + +use crate::app::App; pub(super) struct Executor<'a> { - cx: &'a mut Ctx, + app: &'a mut App, } impl<'a> Executor<'a> { #[inline] - pub(super) fn new(cx: &'a mut Ctx) -> Self { Self { cx } } + pub(super) fn new(app: &'a mut App) -> Self { Self { app } } pub(super) fn handle(&mut self, key: Key) -> bool { - if self.cx.which.visible { - return self.cx.which.press(key); + let cx = &mut self.app.cx; + + if cx.which.visible { + return cx.which.press(key); } - if self.cx.help.visible && self.cx.help.type_(&key) { + if cx.help.visible && cx.help.type_(&key) { return true; } - if self.cx.input.visible && self.cx.input.type_(&key) { + if cx.input.visible && cx.input.type_(&key) { return true; } - let b = if self.cx.completion.visible { - self.matches(KeymapLayer::Completion, key).or_else(|| self.matches(KeymapLayer::Input, key)) - } else if self.cx.help.visible { - self.matches(KeymapLayer::Help, key) - } else if self.cx.input.visible { - self.matches(KeymapLayer::Input, key) - } else if self.cx.select.visible { - self.matches(KeymapLayer::Select, key) - } else if self.cx.tasks.visible { - self.matches(KeymapLayer::Tasks, key) + let b = if cx.completion.visible { + self.matches(Layer::Completion, key).or_else(|| self.matches(Layer::Input, key)) + } else if cx.help.visible { + self.matches(Layer::Help, key) + } else if cx.input.visible { + self.matches(Layer::Input, key) + } else if cx.select.visible { + self.matches(Layer::Select, key) + } else if cx.tasks.visible { + self.matches(Layer::Tasks, key) } else { - self.matches(KeymapLayer::Manager, key) + self.matches(Layer::Manager, key) }; b == Some(true) } #[inline] - fn matches(&mut self, layer: KeymapLayer, key: Key) -> Option { + fn matches(&mut self, layer: Layer, key: Key) -> Option { for Control { on, exec, .. } in KEYMAP.get(layer) { if on.is_empty() || on[0] != key { continue; } return Some(if on.len() > 1 { - self.cx.which.show(&key, layer) + self.app.cx.which.show(&key, layer) } else { self.dispatch(exec, layer) }); @@ -53,37 +58,52 @@ impl<'a> Executor<'a> { } #[inline] - pub(super) fn dispatch(&mut self, exec: &[Exec], layer: KeymapLayer) -> bool { + pub(super) fn dispatch(&mut self, exec: &[Exec], layer: Layer) -> bool { let mut render = false; for e in exec { render |= match layer { - KeymapLayer::Manager => self.manager(e), - KeymapLayer::Tasks => self.tasks(e), - KeymapLayer::Select => self.select(e), - KeymapLayer::Input => self.input(e), - KeymapLayer::Help => self.help(e), - KeymapLayer::Completion => self.completion(e), - KeymapLayer::Which => unreachable!(), + Layer::App => self.app(e), + Layer::Manager => self.manager(e), + Layer::Tasks => self.tasks(e), + Layer::Select => self.select(e), + Layer::Input => self.input(e), + Layer::Help => self.help(e), + Layer::Completion => self.completion(e), + Layer::Which => unreachable!(), }; } render } + fn app(&mut self, exec: &Exec) -> bool { + macro_rules! on { + ($name:ident) => { + if exec.cmd == stringify!($name) { + return self.app.$name(exec); + } + }; + } + + on!(stop); + + false + } + fn manager(&mut self, exec: &Exec) -> bool { macro_rules! on { (MANAGER, $name:ident $(,$args:expr)*) => { if exec.cmd == stringify!($name) { - return self.cx.manager.$name(exec, $($args),*); + return self.app.cx.manager.$name(exec, $($args),*); } }; (ACTIVE, $name:ident) => { if exec.cmd == stringify!($name) { - return self.cx.manager.active_mut().$name(exec); + return self.app.cx.manager.active_mut().$name(exec); } }; (TABS, $name:ident) => { if exec.cmd == concat!("tab_", stringify!($name)) { - return self.cx.manager.tabs.$name(exec); + return self.app.cx.manager.tabs.$name(exec); } }; } @@ -91,8 +111,8 @@ impl<'a> Executor<'a> { on!(MANAGER, peek); on!(MANAGER, hover); on!(MANAGER, refresh); - on!(MANAGER, quit, &self.cx.tasks); - on!(MANAGER, close, &self.cx.tasks); + on!(MANAGER, quit, &self.app.cx.tasks); + on!(MANAGER, close, &self.app.cx.tasks); on!(MANAGER, suspend); on!(ACTIVE, escape); @@ -113,9 +133,9 @@ impl<'a> Executor<'a> { // Operation on!(MANAGER, open); on!(MANAGER, yank); - on!(MANAGER, paste, &self.cx.tasks); - on!(MANAGER, link, &self.cx.tasks); - on!(MANAGER, remove, &self.cx.tasks); + on!(MANAGER, paste, &self.app.cx.tasks); + on!(MANAGER, link, &self.app.cx.tasks); + on!(MANAGER, remove, &self.app.cx.tasks); on!(MANAGER, create); on!(MANAGER, rename); on!(ACTIVE, copy); @@ -141,9 +161,9 @@ impl<'a> Executor<'a> { match exec.cmd.as_bytes() { // Tasks - b"tasks_show" => self.cx.tasks.toggle(()), + b"tasks_show" => self.app.cx.tasks.toggle(()), // Help - b"help" => self.cx.help.toggle(KeymapLayer::Manager), + b"help" => self.app.cx.help.toggle(Layer::Manager), _ => false, } } @@ -152,23 +172,25 @@ impl<'a> Executor<'a> { macro_rules! on { ($name:ident) => { if exec.cmd == stringify!($name) { - return self.cx.tasks.$name(exec); + return self.app.cx.tasks.$name(exec); } }; ($name:ident, $alias:literal) => { if exec.cmd == $alias { - return self.cx.tasks.$name(exec); + return self.app.cx.tasks.$name(exec); } }; } + on!(update); + on!(open); on!(toggle, "close"); on!(arrow); on!(inspect); on!(cancel); match exec.cmd.as_str() { - "help" => self.cx.help.toggle(KeymapLayer::Tasks), + "help" => self.app.cx.help.toggle(Layer::Tasks), _ => false, } } @@ -177,16 +199,17 @@ impl<'a> Executor<'a> { macro_rules! on { ($name:ident) => { if exec.cmd == stringify!($name) { - return self.cx.select.$name(exec); + return self.app.cx.select.$name(exec); } }; } + on!(show); on!(close); on!(arrow); match exec.cmd.as_str() { - "help" => self.cx.help.toggle(KeymapLayer::Select), + "help" => self.app.cx.help.toggle(Layer::Select), _ => false, } } @@ -195,16 +218,17 @@ impl<'a> Executor<'a> { macro_rules! on { ($name:ident) => { if exec.cmd == stringify!($name) { - return self.cx.input.$name(exec); + return self.app.cx.input.$name(exec); } }; ($name:ident, $alias:literal) => { if exec.cmd == $alias { - return self.cx.input.$name(exec); + return self.app.cx.input.$name(exec); } }; } + on!(show); on!(close); on!(escape); on!(move_, "move"); @@ -213,13 +237,13 @@ impl<'a> Executor<'a> { if exec.cmd.as_str() == "complete" { return if exec.named.contains_key("trigger") { - self.cx.completion.trigger(exec) + self.app.cx.completion.trigger(exec) } else { - self.cx.input.complete(exec) + self.app.cx.input.complete(exec) }; } - match self.cx.input.mode() { + match self.app.cx.input.mode() { InputMode::Normal => { on!(insert); on!(visual); @@ -232,7 +256,7 @@ impl<'a> Executor<'a> { on!(redo); match exec.cmd.as_str() { - "help" => self.cx.help.toggle(KeymapLayer::Input), + "help" => self.app.cx.help.toggle(Layer::Input), _ => false, } } @@ -249,7 +273,7 @@ impl<'a> Executor<'a> { macro_rules! on { ($name:ident) => { if exec.cmd == stringify!($name) { - return self.cx.help.$name(exec); + return self.app.cx.help.$name(exec); } }; } @@ -259,7 +283,7 @@ impl<'a> Executor<'a> { on!(filter); match exec.cmd.as_str() { - "close" => self.cx.help.toggle(KeymapLayer::Help), + "close" => self.app.cx.help.toggle(Layer::Help), _ => false, } } @@ -268,7 +292,7 @@ impl<'a> Executor<'a> { macro_rules! on { ($name:ident) => { if exec.cmd == stringify!($name) { - return self.cx.completion.$name(exec); + return self.app.cx.completion.$name(exec); } }; } @@ -279,7 +303,7 @@ impl<'a> Executor<'a> { on!(arrow); match exec.cmd.as_str() { - "help" => self.cx.help.toggle(KeymapLayer::Completion), + "help" => self.app.cx.help.toggle(Layer::Completion), _ => false, } } diff --git a/yazi-fm/src/input/input.rs b/yazi-fm/src/input/input.rs index bf779176..c1858fa7 100644 --- a/yazi-fm/src/input/input.rs +++ b/yazi-fm/src/input/input.rs @@ -4,7 +4,7 @@ use ansi_to_tui::IntoText; use ratatui::{buffer::Buffer, layout::Rect, text::{Line, Text}, widgets::{Block, BorderType, Borders, Paragraph, Widget}}; use yazi_config::THEME; use yazi_core::{input::InputMode, Ctx}; -use yazi_shared::Term; +use yazi_shared::term::Term; use crate::widgets; diff --git a/yazi-fm/src/main.rs b/yazi-fm/src/main.rs index 0dbe25b4..8af3c9f4 100644 --- a/yazi-fm/src/main.rs +++ b/yazi-fm/src/main.rs @@ -14,7 +14,6 @@ mod tasks; mod which; mod widgets; -use app::*; use executor::*; use logs::*; use panic::*; @@ -34,5 +33,5 @@ async fn main() -> anyhow::Result<()> { yazi_adaptor::init(); - App::run().await + app::App::run().await } diff --git a/yazi-fm/src/panic.rs b/yazi-fm/src/panic.rs index dc870f6f..f0773886 100644 --- a/yazi-fm/src/panic.rs +++ b/yazi-fm/src/panic.rs @@ -1,4 +1,4 @@ -use yazi_shared::Term; +use yazi_shared::term::Term; pub(super) struct Panic; @@ -8,7 +8,7 @@ impl Panic { let hook = std::panic::take_hook(); std::panic::set_hook(Box::new(move |info| { - _ = Term::goodbye(|| { + Term::goodbye(|| { hook(info); true }); diff --git a/yazi-fm/src/signals.rs b/yazi-fm/src/signals.rs index ea98c2a1..1ce4c9e1 100644 --- a/yazi-fm/src/signals.rs +++ b/yazi-fm/src/signals.rs @@ -2,7 +2,7 @@ use anyhow::Result; use crossterm::event::{Event as CrosstermEvent, EventStream, KeyEvent, KeyEventKind}; use futures::StreamExt; use tokio::{select, sync::{mpsc::{self, UnboundedReceiver, UnboundedSender}, oneshot}, task::JoinHandle}; -use yazi_core::Event; +use yazi_shared::event::Event; pub(super) struct Signals { tx: UnboundedSender, @@ -50,6 +50,7 @@ impl Signals { #[cfg(unix)] fn spawn_system_task(&self) -> Result> { use libc::{SIGCONT, SIGHUP, SIGINT, SIGQUIT, SIGTERM}; + use yazi_core::Ctx; let tx = self.tx.clone(); let mut signals = signal_hook_tokio::Signals::new([ @@ -67,9 +68,7 @@ impl Signals { break; } } - SIGCONT => { - tx.send(Event::Stop(false, None)).ok(); - } + SIGCONT => Ctx::resume(), _ => {} } } diff --git a/yazi-fm/src/which/layout.rs b/yazi-fm/src/which/layout.rs index d9f5f93f..745570f7 100644 --- a/yazi-fm/src/which/layout.rs +++ b/yazi-fm/src/which/layout.rs @@ -17,7 +17,7 @@ impl Widget for Which<'_> { fn render(self, area: Rect, buf: &mut Buffer) { let which = &self.cx.which; let mut cands: (Vec<_>, Vec<_>, Vec<_>) = Default::default(); - for (i, c) in which.cands.iter().enumerate() { + for (i, &c) in which.cands.iter().enumerate() { match i % 3 { 0 => cands.0.push(c), 1 => cands.1.push(c), diff --git a/yazi-plugin/src/bindings/active.rs b/yazi-plugin/src/bindings/active.rs index 1823009a..c0d3246f 100644 --- a/yazi-plugin/src/bindings/active.rs +++ b/yazi-plugin/src/bindings/active.rs @@ -104,7 +104,7 @@ impl<'a, 'b> Active<'a, 'b> { fn file( &self, idx: usize, - inner: &'a yazi_core::files::File, + inner: &'a yazi_shared::files::File, folder: &'a yazi_core::tab::Folder, ) -> mlua::Result> { let ud = self.scope.create_any_userdata_ref(inner)?; diff --git a/yazi-plugin/src/bindings/files.rs b/yazi-plugin/src/bindings/files.rs index 99bdfb67..0962183b 100644 --- a/yazi-plugin/src/bindings/files.rs +++ b/yazi-plugin/src/bindings/files.rs @@ -6,10 +6,10 @@ use yazi_config::THEME; use super::{Range, Url}; use crate::{layout::Style, LUA}; -pub struct File(yazi_core::files::File); +pub struct File(yazi_shared::files::File); -impl From<&yazi_core::files::File> for File { - fn from(value: &yazi_core::files::File) -> Self { Self(value.clone()) } +impl From<&yazi_shared::files::File> for File { + fn from(value: &yazi_shared::files::File) -> Self { Self(value.clone()) } } impl UserData for File { @@ -47,7 +47,7 @@ impl Files { }); })?; - LUA.register_userdata_type::(|reg| { + LUA.register_userdata_type::(|reg| { reg.add_field_method_get("url", |_, me| Ok(Url::from(&me.url))); reg.add_field_method_get("link_to", |_, me| Ok(me.link_to().map(Url::from))); reg.add_field_method_get("is_link", |_, me| Ok(me.is_link())); @@ -76,7 +76,7 @@ impl Files { reg.add_method("permissions", |_, me, ()| { Ok( #[cfg(unix)] - Some(yazi_shared::permissions(me.permissions)), + Some(yazi_shared::fs::permissions(me.permissions)), #[cfg(windows)] None::, ) @@ -87,7 +87,7 @@ impl Files { Ok(me.url.file_name().map(|n| n.to_string_lossy().to_string())) }); reg.add_function("size", |_, me: AnyUserData| { - let file = me.borrow::()?; + let file = me.borrow::()?; if !file.is_dir() { return Ok(Some(file.len)); } @@ -97,7 +97,7 @@ impl Files { }); reg.add_function("mime", |_, me: AnyUserData| { let manager = me.named_user_value::>("manager")?; - let file = me.borrow::()?; + let file = me.borrow::()?; Ok(manager.mimetype.get(&file.url).cloned()) }); reg.add_function("prefix", |_, me: AnyUserData| { @@ -106,7 +106,7 @@ impl Files { return Ok(None); } - let file = me.borrow::()?; + let file = me.borrow::()?; let mut p = file.url.strip_prefix(&folder.cwd).unwrap_or(&file.url).components(); p.next_back(); Ok(Some(p.as_path().to_string_lossy().to_string())) @@ -122,7 +122,7 @@ impl Files { }); reg.add_function("style", |_, me: AnyUserData| { let manager = me.named_user_value::>("manager")?; - let file = me.borrow::()?; + let file = me.borrow::()?; let mime = manager.mimetype.get(&file.url); Ok( THEME @@ -134,12 +134,12 @@ impl Files { }); reg.add_function("is_hovered", |_, me: AnyUserData| { let folder = me.named_user_value::>("folder")?; - let file = me.borrow::()?; + let file = me.borrow::()?; Ok(matches!(folder.hovered(), Some(f) if f.url == file.url)) }); reg.add_function("is_yanked", |_, me: AnyUserData| { let manager = me.named_user_value::>("manager")?; - let file = me.borrow::()?; + let file = me.borrow::()?; Ok(if !manager.yanked.1.contains(&file.url) { 0u8 } else if manager.yanked.0 { @@ -151,7 +151,7 @@ impl Files { reg.add_function("is_selected", |_, me: AnyUserData| { let manager = me.named_user_value::>("manager")?; let folder = me.named_user_value::>("folder")?; - let file = me.borrow::()?; + let file = me.borrow::()?; let selected = folder.files.is_selected(&file.url); Ok(if !manager.active().mode.is_visual() { @@ -167,7 +167,7 @@ impl Files { return Ok(None); }; - let file = me.borrow::()?; + let file = me.borrow::()?; if let Some(idx) = finder.matched_idx(&file.url) { return Some( lua.create_sequence_from([idx.into_lua(lua)?, finder.matched().len().into_lua(lua)?]), @@ -182,7 +182,7 @@ impl Files { return Ok(None); }; - let file = me.borrow::()?; + let file = me.borrow::()?; let Some(h) = file.name().and_then(|n| finder.highlighted(n)) else { return Ok(None); }; diff --git a/yazi-plugin/src/bindings/shared.rs b/yazi-plugin/src/bindings/shared.rs index 96e39120..348c96ef 100644 --- a/yazi-plugin/src/bindings/shared.rs +++ b/yazi-plugin/src/bindings/shared.rs @@ -18,10 +18,10 @@ where } // --- Url -pub struct Url(yazi_shared::Url); +pub struct Url(yazi_shared::fs::Url); -impl From<&yazi_shared::Url> for Url { - fn from(value: &yazi_shared::Url) -> Self { Self(value.clone()) } +impl From<&yazi_shared::fs::Url> for Url { + fn from(value: &yazi_shared::fs::Url) -> Self { Self(value.clone()) } } impl UserData for Url { diff --git a/yazi-plugin/src/components/preview.rs b/yazi-plugin/src/components/preview.rs index 440e97f0..74840c0b 100644 --- a/yazi-plugin/src/components/preview.rs +++ b/yazi-plugin/src/components/preview.rs @@ -1,6 +1,7 @@ use ansi_to_tui::IntoText; use ratatui::{buffer::Buffer, layout::Rect, widgets::{Paragraph, Widget}}; -use yazi_core::{preview::PreviewData, Ctx}; +use yazi_core::Ctx; +use yazi_shared::event::PreviewData; use super::Folder; diff --git a/yazi-shared/src/fns.rs b/yazi-shared/src/env.rs similarity index 100% rename from yazi-shared/src/fns.rs rename to yazi-shared/src/env.rs diff --git a/yazi-shared/src/event/event.rs b/yazi-shared/src/event/event.rs new file mode 100644 index 00000000..ec665a58 --- /dev/null +++ b/yazi-shared/src/event/event.rs @@ -0,0 +1,100 @@ +use std::collections::BTreeMap; + +use crossterm::event::KeyEvent; +use tokio::sync::{mpsc::UnboundedSender, oneshot}; + +use super::Exec; +use crate::{files::FilesOp, fs::{Cha, Url}, term::Term, Layer, RoCell}; + +static TX: RoCell> = RoCell::new(); + +pub enum Event { + Quit(bool), // no-cwd-file + Key(KeyEvent), + Paste(String), + Render(String), + Resize(u16, u16), + Call(Vec, Layer), + + // Manager + Files(FilesOp), + Pages(usize), + Mimetype(BTreeMap), + Preview(PreviewLock), +} + +impl Event { + #[inline] + pub fn init(tx: UnboundedSender) { TX.init(tx); } + + #[inline] + pub fn emit(self) { TX.send(self).ok(); } + + pub async fn wait(self, rx: oneshot::Receiver) -> T { + TX.send(self).ok(); + rx.await.unwrap_or_else(|_| Term::goodbye(|| false)) + } +} + +#[macro_export] +macro_rules! emit { + (Quit($no_cwd_file:expr)) => { + $crate::event::Event::Quit($no_cwd_file).emit(); + }; + (Key($key:expr)) => { + $crate::event::Event::Key($key).emit(); + }; + (Render) => { + $crate::event::Event::Render(format!("{}:{}", file!(), line!())).emit(); + }; + (Resize($cols:expr, $rows:expr)) => { + $crate::event::Event::Resize($cols, $rows).emit(); + }; + (Call($exec:expr, $layer:expr)) => { + $crate::event::Event::Call($exec, $layer).emit(); + }; + + (Files($op:expr)) => { + $crate::event::Event::Files($op).emit(); + }; + (Pages($page:expr)) => { + $crate::event::Event::Pages($page).emit(); + }; + (Mimetype($mimes:expr)) => { + $crate::event::Event::Mimetype($mimes).emit(); + }; + (Preview($lock:expr)) => { + $crate::event::Event::Preview($lock).emit(); + }; + + (Open($targets:expr, $opener:expr)) => { + $crate::event::Event::Open($targets, $opener).emit(); + }; + + ($event:ident) => { + $crate::event::Event::$event.emit(); + }; +} + +// TODO: remove this +pub struct PreviewLock { + pub url: Url, + pub cha: Option, + pub skip: usize, + pub data: PreviewData, +} + +#[derive(Debug)] +pub enum PreviewData { + Folder, + Text(String), + Image, +} + +impl PreviewLock { + #[inline] + pub fn is_image(&self) -> bool { matches!(self.data, PreviewData::Image) } + + #[inline] + pub fn is_folder(&self) -> bool { matches!(self.data, PreviewData::Folder) } +} diff --git a/yazi-shared/src/event/exec.rs b/yazi-shared/src/event/exec.rs new file mode 100644 index 00000000..ee28c6d7 --- /dev/null +++ b/yazi-shared/src/event/exec.rs @@ -0,0 +1,65 @@ +use std::{any::Any, cell::RefCell, collections::BTreeMap, fmt::{self, Display}}; + +#[derive(Debug, Default)] +pub struct Exec { + pub cmd: String, + pub args: Vec, + pub named: BTreeMap, + pub data: RefCell>>, +} + +impl Exec { + #[inline] + pub fn call(cwd: &str, args: Vec) -> Self { + Exec { cmd: cwd.to_owned(), args, ..Default::default() } + } + + #[inline] + pub fn call_named(cwd: &str, named: BTreeMap) -> Self { + Exec { cmd: cwd.to_owned(), named, ..Default::default() } + } + + #[inline] + pub fn vec(self) -> Vec { vec![self] } + + #[inline] + pub fn with(mut self, name: impl ToString, value: impl ToString) -> Self { + self.named.insert(name.to_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 + } + + #[inline] + pub fn with_data(mut self, data: impl Any + Send) -> Self { + self.data = RefCell::new(Some(Box::new(data))); + self + } + + #[inline] + pub fn take_data(&self) -> Option { + self.data.replace(None).and_then(|d| d.downcast::().ok()).map(|d| *d) + } +} + +impl Display for Exec { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.cmd)?; + 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}")?; + } + } + Ok(()) + } +} diff --git a/yazi-shared/src/event/mod.rs b/yazi-shared/src/event/mod.rs new file mode 100644 index 00000000..b85f499c --- /dev/null +++ b/yazi-shared/src/event/mod.rs @@ -0,0 +1,7 @@ +#![allow(clippy::module_inception)] + +mod event; +mod exec; + +pub use event::*; +pub use exec::*; diff --git a/yazi-core/src/files/file.rs b/yazi-shared/src/files/file.rs similarity index 98% rename from yazi-core/src/files/file.rs rename to yazi-shared/src/files/file.rs index 732e448f..44294727 100644 --- a/yazi-core/src/files/file.rs +++ b/yazi-shared/src/files/file.rs @@ -2,7 +2,8 @@ use std::{borrow::Cow, collections::BTreeMap, ffi::OsStr, fs::Metadata, ops::Der use anyhow::Result; use tokio::fs; -use yazi_shared::{Cha, ChaKind, Url}; + +use crate::fs::{Cha, ChaKind, Url}; #[derive(Clone, Debug, Default)] pub struct File { diff --git a/yazi-shared/src/files/mod.rs b/yazi-shared/src/files/mod.rs new file mode 100644 index 00000000..600b5425 --- /dev/null +++ b/yazi-shared/src/files/mod.rs @@ -0,0 +1,5 @@ +mod file; +mod op; + +pub use file::*; +pub use op::*; diff --git a/yazi-core/src/files/op.rs b/yazi-shared/src/files/op.rs similarity index 88% rename from yazi-core/src/files/op.rs rename to yazi-shared/src/files/op.rs index 3337c16b..db245387 100644 --- a/yazi-core/src/files/op.rs +++ b/yazi-shared/src/files/op.rs @@ -1,11 +1,9 @@ use std::{collections::{BTreeMap, BTreeSet}, sync::atomic::{AtomicU64, Ordering}}; -use yazi_shared::Url; - use super::File; -use crate::emit; +use crate::{emit, fs::Url}; -pub(super) static FILES_TICKET: AtomicU64 = AtomicU64::new(0); +pub static FILES_TICKET: AtomicU64 = AtomicU64::new(0); #[derive(Debug)] pub enum FilesOp { diff --git a/yazi-shared/src/cha.rs b/yazi-shared/src/fs/cha.rs similarity index 100% rename from yazi-shared/src/cha.rs rename to yazi-shared/src/fs/cha.rs diff --git a/yazi-shared/src/fs.rs b/yazi-shared/src/fs/fns.rs similarity index 100% rename from yazi-shared/src/fs.rs rename to yazi-shared/src/fs/fns.rs diff --git a/yazi-shared/src/fs/mod.rs b/yazi-shared/src/fs/mod.rs new file mode 100644 index 00000000..685326a8 --- /dev/null +++ b/yazi-shared/src/fs/mod.rs @@ -0,0 +1,9 @@ +mod cha; +mod fns; +mod path; +mod url; + +pub use cha::*; +pub use fns::*; +pub use path::*; +pub use url::*; diff --git a/yazi-shared/src/path.rs b/yazi-shared/src/fs/path.rs similarity index 99% rename from yazi-shared/src/path.rs rename to yazi-shared/src/fs/path.rs index eadf83cf..da57046f 100644 --- a/yazi-shared/src/path.rs +++ b/yazi-shared/src/fs/path.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, env, ffi::OsString, path::{Component, Path, PathBuf, MAIN use tokio::fs; -use crate::Url; +use crate::fs::Url; #[inline] pub fn current_cwd() -> Option { diff --git a/yazi-shared/src/url.rs b/yazi-shared/src/fs/url.rs similarity index 100% rename from yazi-shared/src/url.rs rename to yazi-shared/src/fs/url.rs diff --git a/yazi-shared/src/layer.rs b/yazi-shared/src/layer.rs new file mode 100644 index 00000000..06311cfd --- /dev/null +++ b/yazi-shared/src/layer.rs @@ -0,0 +1,29 @@ +use std::fmt::{self, Display}; + +#[derive(Debug, Default, PartialEq, Eq, Hash, Clone, Copy)] +pub enum Layer { + #[default] + App, + Manager, + Tasks, + Select, + Input, + Help, + Completion, + Which, +} + +impl Display for Layer { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::App => write!(f, "app"), + Self::Manager => write!(f, "manager"), + Self::Tasks => write!(f, "tasks"), + Self::Select => write!(f, "select"), + Self::Input => write!(f, "input"), + Self::Help => write!(f, "help"), + Self::Completion => write!(f, "completion"), + Self::Which => write!(f, "which"), + } + } +} diff --git a/yazi-shared/src/lib.rs b/yazi-shared/src/lib.rs index 1edcaaa2..df211bd1 100644 --- a/yazi-shared/src/lib.rs +++ b/yazi-shared/src/lib.rs @@ -1,33 +1,29 @@ #![allow(clippy::option_map_unit_fn)] -mod cha; mod chars; mod debounce; mod defer; +mod env; mod errors; -mod fns; -mod fs; +pub mod event; +pub mod files; +pub mod fs; +mod layer; mod mime; mod natsort; -mod path; mod ro_cell; -mod term; +pub mod term; mod throttle; mod time; -mod url; -pub use cha::*; pub use chars::*; pub use debounce::*; pub use defer::*; +pub use env::*; pub use errors::*; -pub use fns::*; -pub use fs::*; +pub use layer::*; pub use mime::*; pub use natsort::*; -pub use path::*; pub use ro_cell::*; -pub use term::*; pub use throttle::*; pub use time::*; -pub use url::*; diff --git a/yazi-shared/src/term/cursor.rs b/yazi-shared/src/term/cursor.rs index ba1237a2..ed08737c 100644 --- a/yazi-shared/src/term/cursor.rs +++ b/yazi-shared/src/term/cursor.rs @@ -3,7 +3,7 @@ use std::io::{stdout, Write}; use anyhow::Result; use crossterm::{cursor::{MoveTo, RestorePosition, SavePosition, SetCursorStyle}, execute, queue}; -use crate::Term; +use super::Term; impl Term { #[inline] diff --git a/yazi-shared/src/term/term.rs b/yazi-shared/src/term/term.rs index 1098c4b1..86d6f683 100644 --- a/yazi-shared/src/term/term.rs +++ b/yazi-shared/src/term/term.rs @@ -44,7 +44,7 @@ impl Term { Ok(disable_raw_mode()?) } - pub fn goodbye(f: impl FnOnce() -> bool) -> Result<()> { + pub fn goodbye(f: impl FnOnce() -> bool) -> ! { execute!( stdout(), PopKeyboardEnhancementFlags, @@ -53,8 +53,9 @@ impl Term { LeaveAlternateScreen, crossterm::cursor::SetCursorStyle::DefaultUserShape, crossterm::cursor::Show, - )?; - disable_raw_mode()?; + ) + .ok(); + disable_raw_mode().ok(); std::process::exit(f() as i32); }