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
|
.exec
|
||||||
.iter()
|
.iter()
|
||||||
.map(|e| Exec {
|
.map(|e| Exec {
|
||||||
cmd: e.cmd.clone(),
|
cmd: e.cmd.clone(),
|
||||||
args: e.args.clone(),
|
args: e.args.clone(),
|
||||||
named: e.named.clone(),
|
named: e.named.clone(),
|
||||||
data: None,
|
..Default::default()
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ pub struct InputOpt {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct SelectOpt {
|
pub struct SelectCfg {
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub items: Vec<String>,
|
pub items: Vec<String>,
|
||||||
pub position: Position,
|
pub position: Position,
|
||||||
|
|
@ -122,7 +122,7 @@ impl InputOpt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SelectOpt {
|
impl SelectCfg {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn max_height(len: usize) -> u16 {
|
fn max_height(len: usize) -> u16 {
|
||||||
SELECT.open_offset.height.min(SELECT.border().saturating_add(len as 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 anyhow::Result;
|
||||||
use crossterm::event::KeyEvent;
|
use crossterm::event::KeyEvent;
|
||||||
use tokio::sync::{mpsc::{self, UnboundedSender}, oneshot};
|
use tokio::sync::{mpsc::{self, UnboundedSender}, oneshot};
|
||||||
use yazi_config::{open::Opener, popup::{InputOpt, SelectOpt}};
|
use yazi_config::{open::Opener, popup::InputOpt};
|
||||||
use yazi_shared::{fs::Url, Exec, InputError, Layer, RoCell};
|
use yazi_shared::{fs::Url, term::Term, Exec, InputError, Layer, RoCell};
|
||||||
|
|
||||||
use super::files::FilesOp;
|
use super::files::FilesOp;
|
||||||
use crate::{preview::PreviewLock, tasks::TasksProgress};
|
use crate::{preview::PreviewLock, tasks::TasksProgress};
|
||||||
|
|
@ -27,7 +27,6 @@ pub enum Event {
|
||||||
Preview(PreviewLock),
|
Preview(PreviewLock),
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
Select(SelectOpt, oneshot::Sender<Result<usize>>),
|
|
||||||
Input(InputOpt, mpsc::UnboundedSender<Result<String, InputError>>),
|
Input(InputOpt, mpsc::UnboundedSender<Result<String, InputError>>),
|
||||||
|
|
||||||
// Tasks
|
// Tasks
|
||||||
|
|
@ -44,7 +43,7 @@ impl Event {
|
||||||
|
|
||||||
pub async fn wait<T>(self, rx: oneshot::Receiver<T>) -> T {
|
pub async fn wait<T>(self, rx: oneshot::Receiver<T>) -> T {
|
||||||
TX.send(self).ok();
|
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();
|
$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)) => {{
|
(Input($opt:expr)) => {{
|
||||||
let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
|
let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
|
||||||
$crate::Event::Input($opt, tx).emit();
|
$crate::Event::Input($opt, tx).emit();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
|
|
||||||
use yazi_config::{popup::SelectOpt, OPEN};
|
use yazi_config::{popup::SelectCfg, OPEN};
|
||||||
use yazi_shared::{Exec, MIME_DIR};
|
use yazi_shared::{Exec, MIME_DIR};
|
||||||
|
|
||||||
use crate::{emit, external, manager::Manager};
|
use crate::{emit, external, manager::Manager, select::Select};
|
||||||
|
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
interactive: bool,
|
interactive: bool,
|
||||||
|
|
@ -20,7 +20,7 @@ impl Manager {
|
||||||
return;
|
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 {
|
if let Ok(choice) = result.await {
|
||||||
emit!(Open(files, Some(openers[choice].clone())));
|
emit!(Open(files, Some(openers[choice].clone())));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
mod arrow;
|
mod arrow;
|
||||||
mod close;
|
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 anyhow::Result;
|
||||||
use tokio::sync::oneshot::Sender;
|
use tokio::sync::oneshot::Sender;
|
||||||
use yazi_config::{popup::{Position, SelectOpt}, SELECT};
|
use yazi_config::{popup::Position, SELECT};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Select {
|
pub struct Select {
|
||||||
title: String,
|
pub(super) title: String,
|
||||||
pub(super) items: Vec<String>,
|
pub(super) items: Vec<String>,
|
||||||
pub position: Position,
|
pub position: Position,
|
||||||
|
|
||||||
|
|
@ -16,17 +16,6 @@ pub struct Select {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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]
|
#[inline]
|
||||||
pub fn window(&self) -> &[String] {
|
pub fn window(&self) -> &[String] {
|
||||||
let end = (self.offset + self.limit()).min(self.items.len());
|
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();
|
let cwd = self.cx.manager.cwd().as_os_str();
|
||||||
std::fs::write(p, cwd.as_encoded_bytes()).ok();
|
std::fs::write(p, cwd.as_encoded_bytes()).ok();
|
||||||
}
|
}
|
||||||
Term::goodbye(|| false).unwrap();
|
Term::goodbye(|| false);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dispatch_key(&mut self, key: KeyEvent) {
|
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) => {
|
Event::Input(opt, tx) => {
|
||||||
self.cx.input.show(opt, tx);
|
self.cx.input.show(opt, tx);
|
||||||
emit!(Render);
|
emit!(Render);
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,7 @@ impl<'a> Executor<'a> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
on!(show);
|
||||||
on!(close);
|
on!(close);
|
||||||
on!(arrow);
|
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)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Exec {
|
pub struct Exec {
|
||||||
pub cmd: String,
|
pub cmd: String,
|
||||||
pub args: Vec<String>,
|
pub args: Vec<String>,
|
||||||
pub named: BTreeMap<String, String>,
|
pub named: BTreeMap<String, String>,
|
||||||
pub data: Option<Box<dyn Any + Send>>,
|
pub data: RefCell<Option<Box<dyn Any + Send>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Exec {
|
impl Exec {
|
||||||
|
|
@ -35,6 +35,12 @@ impl Exec {
|
||||||
}
|
}
|
||||||
self
|
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 {
|
impl Display for Exec {
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ impl Term {
|
||||||
Ok(disable_raw_mode()?)
|
Ok(disable_raw_mode()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn goodbye(f: impl FnOnce() -> bool) -> Result<()> {
|
pub fn goodbye(f: impl FnOnce() -> bool) -> ! {
|
||||||
execute!(
|
execute!(
|
||||||
stdout(),
|
stdout(),
|
||||||
PopKeyboardEnhancementFlags,
|
PopKeyboardEnhancementFlags,
|
||||||
|
|
@ -53,8 +53,9 @@ impl Term {
|
||||||
LeaveAlternateScreen,
|
LeaveAlternateScreen,
|
||||||
crossterm::cursor::SetCursorStyle::DefaultUserShape,
|
crossterm::cursor::SetCursorStyle::DefaultUserShape,
|
||||||
crossterm::cursor::Show,
|
crossterm::cursor::Show,
|
||||||
)?;
|
)
|
||||||
disable_raw_mode()?;
|
.ok();
|
||||||
|
disable_raw_mode().ok();
|
||||||
std::process::exit(f() as i32);
|
std::process::exit(f() as i32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue