mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
..
This commit is contained in:
parent
dee464d261
commit
4dd014b416
11 changed files with 76 additions and 39 deletions
|
|
@ -19,10 +19,10 @@ impl Control {
|
|||
.exec
|
||||
.iter()
|
||||
.map(|e| Exec {
|
||||
cmd: e.cmd.clone(),
|
||||
args: e.args.clone(),
|
||||
cmd: e.cmd.clone(),
|
||||
args: e.args.clone(),
|
||||
named: e.named.clone(),
|
||||
data: None,
|
||||
..Default::default()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ pub struct InputOpt {
|
|||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct SelectOpt {
|
||||
pub struct SelectCfg {
|
||||
pub title: String,
|
||||
pub items: Vec<String>,
|
||||
pub position: Position,
|
||||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ use std::{collections::BTreeMap, ffi::OsString};
|
|||
use anyhow::Result;
|
||||
use crossterm::event::KeyEvent;
|
||||
use tokio::sync::{mpsc::{self, UnboundedSender}, oneshot};
|
||||
use yazi_config::{open::Opener, popup::{InputOpt, SelectOpt}};
|
||||
use yazi_shared::{fs::Url, Exec, InputError, Layer, RoCell};
|
||||
use yazi_config::{open::Opener, popup::InputOpt};
|
||||
use yazi_shared::{fs::Url, term::Term, Exec, InputError, Layer, RoCell};
|
||||
|
||||
use super::files::FilesOp;
|
||||
use crate::{preview::PreviewLock, tasks::TasksProgress};
|
||||
|
|
@ -27,7 +27,6 @@ pub enum Event {
|
|||
Preview(PreviewLock),
|
||||
|
||||
// Input
|
||||
Select(SelectOpt, oneshot::Sender<Result<usize>>),
|
||||
Input(InputOpt, mpsc::UnboundedSender<Result<String, InputError>>),
|
||||
|
||||
// Tasks
|
||||
|
|
@ -44,7 +43,7 @@ impl Event {
|
|||
|
||||
pub async fn wait<T>(self, rx: oneshot::Receiver<T>) -> T {
|
||||
TX.send(self).ok();
|
||||
rx.await.unwrap_or_else(|_| std::process::exit(0))
|
||||
rx.await.unwrap_or_else(|_| Term::goodbye(|| false))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -83,10 +82,6 @@ macro_rules! emit {
|
|||
$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();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use std::ffi::OsString;
|
||||
|
||||
use yazi_config::{popup::SelectOpt, OPEN};
|
||||
use yazi_config::{popup::SelectCfg, OPEN};
|
||||
use yazi_shared::{Exec, MIME_DIR};
|
||||
|
||||
use crate::{emit, external, manager::Manager};
|
||||
use crate::{emit, external, manager::Manager, select::Select};
|
||||
|
||||
pub struct Opt {
|
||||
interactive: bool,
|
||||
|
|
@ -20,7 +20,7 @@ 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())));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
mod arrow;
|
||||
mod close;
|
||||
mod show;
|
||||
|
|
|
|||
48
yazi-core/src/select/commands/show.rs
Normal file
48
yazi-core/src/select/commands/show.rs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
use anyhow::{bail, Result};
|
||||
use tokio::sync::oneshot;
|
||||
use yazi_config::popup::SelectCfg;
|
||||
use yazi_shared::{term::Term, Exec, Layer};
|
||||
|
||||
use crate::{emit, select::Select};
|
||||
|
||||
pub struct Opt {
|
||||
cfg: SelectCfg,
|
||||
tx: oneshot::Sender<Result<usize>>,
|
||||
}
|
||||
|
||||
impl TryFrom<&Exec> for Opt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(e: &Exec) -> Result<Self, Self::Error> {
|
||||
let Some(data) = e.data.borrow_mut().take() else {
|
||||
bail!("missing data");
|
||||
};
|
||||
let Ok(opt) = data.downcast::<Opt>() else {
|
||||
bail!("invalid data");
|
||||
};
|
||||
Ok(*opt)
|
||||
}
|
||||
}
|
||||
|
||||
impl Select {
|
||||
pub async fn _show(cfg: SelectCfg) -> Result<usize> {
|
||||
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<Opt>) -> 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
|
||||
}
|
||||
}
|
||||
|
|
@ -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<String>,
|
||||
pub position: Position,
|
||||
|
||||
|
|
@ -16,17 +16,6 @@ pub struct Select {
|
|||
}
|
||||
|
||||
impl Select {
|
||||
pub fn show(&mut self, opt: SelectOpt, tx: Sender<Result<usize>>) {
|
||||
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());
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ 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) {
|
||||
|
|
@ -177,10 +177,6 @@ impl App {
|
|||
}
|
||||
}
|
||||
|
||||
Event::Select(opt, tx) => {
|
||||
self.cx.select.show(opt, tx);
|
||||
emit!(Render);
|
||||
}
|
||||
Event::Input(opt, tx) => {
|
||||
self.cx.input.show(opt, tx);
|
||||
emit!(Render);
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ impl<'a> Executor<'a> {
|
|||
};
|
||||
}
|
||||
|
||||
on!(show);
|
||||
on!(close);
|
||||
on!(arrow);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use std::{any::Any, collections::BTreeMap, fmt::{self, Display}};
|
||||
use std::{any::Any, cell::RefCell, collections::BTreeMap, fmt::{self, Display}};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Exec {
|
||||
pub cmd: String,
|
||||
pub args: Vec<String>,
|
||||
pub named: BTreeMap<String, String>,
|
||||
pub data: Option<Box<dyn Any + Send>>,
|
||||
pub data: RefCell<Option<Box<dyn Any + Send>>>,
|
||||
}
|
||||
|
||||
impl Exec {
|
||||
|
|
@ -35,6 +35,12 @@ impl Exec {
|
|||
}
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_data(mut self, data: impl Any + Send) -> Self {
|
||||
self.data = RefCell::new(Some(Box::new(data)));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Exec {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue