mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
..
This commit is contained in:
parent
4e9f39d6dc
commit
c95b613ed5
25 changed files with 154 additions and 278 deletions
|
|
@ -90,6 +90,16 @@ rename_title = "Rename:"
|
||||||
rename_position = "hovered"
|
rename_position = "hovered"
|
||||||
rename_offset = [ 0, 1, 50, 3 ]
|
rename_offset = [ 0, 1, 50, 3 ]
|
||||||
|
|
||||||
|
# trash
|
||||||
|
trash_title = "Move {n} selected file{s} to trash? (y/N)"
|
||||||
|
trash_position = "top-center"
|
||||||
|
trash_offset = [ 0, 2, 50, 3 ]
|
||||||
|
|
||||||
|
# delete
|
||||||
|
delete_title = "Delete {n} selected file{s} permanently? (y/N)"
|
||||||
|
delete_position = "top-center"
|
||||||
|
delete_offset = [ 0, 2, 50, 3 ]
|
||||||
|
|
||||||
# find
|
# find
|
||||||
find_title = [ "Find previous:", "Find next:" ]
|
find_title = [ "Find previous:", "Find next:" ]
|
||||||
find_position = "top-center"
|
find_position = "top-center"
|
||||||
|
|
@ -107,6 +117,11 @@ shell_position = "top-center"
|
||||||
shell_offset = [ 0, 2, 50, 3 ]
|
shell_offset = [ 0, 2, 50, 3 ]
|
||||||
shell_highlight = true
|
shell_highlight = true
|
||||||
|
|
||||||
|
# overwrite
|
||||||
|
overwrite_title = "Overwrite an existing file? (y/N)"
|
||||||
|
overwrite_position = "top-center"
|
||||||
|
overwrite_offset = [ 0, 2, 50, 3 ]
|
||||||
|
|
||||||
[select]
|
[select]
|
||||||
open_title = "Open with:"
|
open_title = "Open with:"
|
||||||
open_position = "hovered"
|
open_position = "hovered"
|
||||||
|
|
|
||||||
|
|
@ -6,23 +6,44 @@ use crate::MERGED_YAZI;
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Input {
|
pub struct Input {
|
||||||
// cd
|
// cd
|
||||||
pub cd_position: Position,
|
pub cd_title: String,
|
||||||
pub cd_offset: Offset,
|
pub cd_position: Position,
|
||||||
|
pub cd_offset: Offset,
|
||||||
|
|
||||||
// create
|
// create
|
||||||
|
pub create_title: String,
|
||||||
pub create_position: Position,
|
pub create_position: Position,
|
||||||
pub create_offset: Offset,
|
pub create_offset: Offset,
|
||||||
|
|
||||||
// rename
|
// rename
|
||||||
|
pub rename_title: String,
|
||||||
pub rename_position: Position,
|
pub rename_position: Position,
|
||||||
pub rename_offset: Offset,
|
pub rename_offset: Offset,
|
||||||
|
|
||||||
|
// trash
|
||||||
|
pub trash_title: String,
|
||||||
|
pub trash_position: Position,
|
||||||
|
pub trash_offset: Offset,
|
||||||
|
|
||||||
|
// delete
|
||||||
|
pub delete_title: String,
|
||||||
|
pub delete_position: Position,
|
||||||
|
pub delete_offset: Offset,
|
||||||
|
|
||||||
// find
|
// find
|
||||||
pub find_position: Position,
|
pub find_title: [String; 2],
|
||||||
pub find_offset: Offset,
|
pub find_position: Position,
|
||||||
|
pub find_offset: Offset,
|
||||||
|
|
||||||
// search
|
// search
|
||||||
|
pub search_title: String,
|
||||||
pub search_position: Position,
|
pub search_position: Position,
|
||||||
pub search_offset: Offset,
|
pub search_offset: Offset,
|
||||||
|
|
||||||
// shell
|
// shell
|
||||||
pub shell_position: Position,
|
pub shell_title: [String; 2],
|
||||||
pub shell_offset: Offset,
|
pub shell_position: Position,
|
||||||
|
pub shell_offset: Offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Input {
|
impl Default for Input {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
mod input;
|
mod input;
|
||||||
|
mod options;
|
||||||
mod position;
|
mod position;
|
||||||
mod select;
|
mod select;
|
||||||
|
|
||||||
pub use input::*;
|
pub use input::*;
|
||||||
|
pub use options::*;
|
||||||
pub use position::*;
|
pub use position::*;
|
||||||
pub use select::*;
|
pub use select::*;
|
||||||
|
|
|
||||||
63
yazi-config/src/popup/options.rs
Normal file
63
yazi-config/src/popup/options.rs
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
use super::Position;
|
||||||
|
|
||||||
|
pub struct InputOpt {
|
||||||
|
pub title: String,
|
||||||
|
pub value: String,
|
||||||
|
pub position: Position,
|
||||||
|
pub realtime: bool,
|
||||||
|
pub completion: bool,
|
||||||
|
pub highlight: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SelectOpt {
|
||||||
|
pub title: String,
|
||||||
|
pub items: Vec<String>,
|
||||||
|
pub position: Position,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InputOpt {
|
||||||
|
#[inline]
|
||||||
|
pub fn cd() -> Self { todo!() }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn create() -> Self { todo!() }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn rename() -> Self { todo!() }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn trash(n: usize) -> Self { todo!() }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn delete(n: usize) -> Self { todo!() }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn find(prev: bool) -> Self { todo!() }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn search() -> Self { todo!() }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
|
||||||
|
pub fn shell(block: bool) -> Self { todo!() }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn overwrite() -> Self { todo!() }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn with_value(mut self, value: impl Into<String>) -> Self {
|
||||||
|
self.value = value.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SelectOpt {
|
||||||
|
#[inline]
|
||||||
|
pub fn open() -> Self { todo!() }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn with_items(mut self, items: Vec<String>) -> Self {
|
||||||
|
self.items = items;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Default, Deserialize)]
|
||||||
pub enum Position {
|
pub enum Position {
|
||||||
#[serde(rename = "top-left")]
|
#[serde(rename = "top-left")]
|
||||||
TopLeft,
|
TopLeft,
|
||||||
|
|
@ -9,14 +9,17 @@ pub enum Position {
|
||||||
TopCenter,
|
TopCenter,
|
||||||
#[serde(rename = "top-right")]
|
#[serde(rename = "top-right")]
|
||||||
TopRight,
|
TopRight,
|
||||||
#[serde(rename = "center")]
|
|
||||||
Center,
|
|
||||||
#[serde(rename = "bottom-left")]
|
#[serde(rename = "bottom-left")]
|
||||||
BottomLeft,
|
BottomLeft,
|
||||||
#[serde(rename = "bottom-center")]
|
#[serde(rename = "bottom-center")]
|
||||||
BottomCenter,
|
BottomCenter,
|
||||||
#[serde(rename = "bottom-right")]
|
#[serde(rename = "bottom-right")]
|
||||||
BottomRight,
|
BottomRight,
|
||||||
|
|
||||||
|
#[serde(rename = "center")]
|
||||||
|
#[default]
|
||||||
|
Center,
|
||||||
#[serde(rename = "hovered")]
|
#[serde(rename = "hovered")]
|
||||||
Hovered,
|
Hovered,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use crate::MERGED_YAZI;
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Select {
|
pub struct Select {
|
||||||
// open
|
// open
|
||||||
|
pub open_title: String,
|
||||||
pub open_position: Position,
|
pub open_position: Position,
|
||||||
pub open_offset: Offset,
|
pub open_offset: Offset,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
use crossterm::terminal::WindowSize;
|
use crossterm::terminal::WindowSize;
|
||||||
use ratatui::prelude::Rect;
|
use ratatui::prelude::Rect;
|
||||||
|
use yazi_config::popup::Position;
|
||||||
use yazi_shared::Term;
|
use yazi_shared::Term;
|
||||||
|
|
||||||
use crate::{completion::Completion, help::Help, input::Input, manager::Manager, select::Select, tasks::Tasks, which::Which, Offset, Position};
|
use crate::{completion::Completion, help::Help, input::Input, manager::Manager, select::Select, tasks::Tasks, which::Which};
|
||||||
|
|
||||||
pub struct Ctx {
|
pub struct Ctx {
|
||||||
pub manager: Manager,
|
pub manager: Manager,
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ 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::{keymap::{Exec, KeymapLayer}, open::Opener};
|
use yazi_config::{keymap::{Exec, KeymapLayer}, open::Opener, popup::{InputOpt, SelectOpt}};
|
||||||
use yazi_shared::{InputError, RoCell, Url};
|
use yazi_shared::{InputError, RoCell, Url};
|
||||||
|
|
||||||
use super::{files::FilesOp, input::InputOpt, select::SelectOpt};
|
use super::files::FilesOp;
|
||||||
use crate::{preview::PreviewLock, tasks::TasksProgress};
|
use crate::{preview::PreviewLock, tasks::TasksProgress};
|
||||||
|
|
||||||
static TX: RoCell<UnboundedSender<Event>> = RoCell::new();
|
static TX: RoCell<UnboundedSender<Event>> = RoCell::new();
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@ use std::ops::Range;
|
||||||
|
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
use yazi_config::popup::{InputOpt, Position};
|
||||||
use yazi_shared::InputError;
|
use yazi_shared::InputError;
|
||||||
|
|
||||||
use super::{mode::InputMode, op::InputOp, InputOpt, InputSnap, InputSnaps};
|
use super::{mode::InputMode, op::InputOp, InputSnap, InputSnaps};
|
||||||
use crate::{external, Position};
|
use crate::external;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Input {
|
pub struct Input {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ mod commands;
|
||||||
mod input;
|
mod input;
|
||||||
mod mode;
|
mod mode;
|
||||||
mod op;
|
mod op;
|
||||||
mod option;
|
|
||||||
mod shell;
|
mod shell;
|
||||||
mod snap;
|
mod snap;
|
||||||
mod snaps;
|
mod snaps;
|
||||||
|
|
@ -10,6 +9,5 @@ mod snaps;
|
||||||
pub use input::*;
|
pub use input::*;
|
||||||
pub use mode::*;
|
pub use mode::*;
|
||||||
use op::*;
|
use op::*;
|
||||||
pub use option::*;
|
|
||||||
use snap::*;
|
use snap::*;
|
||||||
use snaps::*;
|
use snaps::*;
|
||||||
|
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
use yazi_config::popup::{Offset as CfgOffset, Position as CfgPosition};
|
|
||||||
|
|
||||||
use crate::{Position, Offset};
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct InputOpt {
|
|
||||||
pub title: String,
|
|
||||||
pub value: String,
|
|
||||||
pub position: Position,
|
|
||||||
pub realtime: bool,
|
|
||||||
pub completion: bool,
|
|
||||||
pub highlight: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! gen_method {
|
|
||||||
($func_name:ident, $position:ident) => {
|
|
||||||
pub fn $func_name(title: impl AsRef<str>, rect: Offset) -> InputOpt {
|
|
||||||
InputOpt {
|
|
||||||
title: title.as_ref().to_owned(),
|
|
||||||
position: Position::$position(rect),
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InputOpt {
|
|
||||||
gen_method!(top_left, TopLeft);
|
|
||||||
|
|
||||||
gen_method!(top_right, TopRight);
|
|
||||||
|
|
||||||
gen_method!(top_center, TopCenter);
|
|
||||||
|
|
||||||
gen_method!(center, Center);
|
|
||||||
|
|
||||||
gen_method!(bottom_center, BottomCenter);
|
|
||||||
|
|
||||||
gen_method!(bottom_left, BottomLeft);
|
|
||||||
|
|
||||||
gen_method!(bottom_right, BottomRight);
|
|
||||||
|
|
||||||
gen_method!(hovered, Hovered);
|
|
||||||
|
|
||||||
pub fn from_cfg(title: impl AsRef<str>, pos: &CfgPosition, rect: &CfgOffset) -> Self {
|
|
||||||
let rect =
|
|
||||||
Offset { x_offset: rect.x, y_offset: rect.y, width: rect.width, height: rect.height };
|
|
||||||
|
|
||||||
match pos {
|
|
||||||
CfgPosition::TopLeft => Self::top_left(title, rect),
|
|
||||||
CfgPosition::TopRight => Self::top_right(title, rect),
|
|
||||||
CfgPosition::TopCenter => Self::top_center(title, rect),
|
|
||||||
CfgPosition::Center => Self::center(title, rect),
|
|
||||||
CfgPosition::BottomCenter => Self::bottom_center(title, rect),
|
|
||||||
CfgPosition::BottomLeft => Self::bottom_left(title, rect),
|
|
||||||
CfgPosition::BottomRight => Self::bottom_right(title, rect),
|
|
||||||
CfgPosition::Hovered => Self::hovered(title, rect),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn with_value(mut self, value: impl AsRef<str>) -> Self {
|
|
||||||
self.value = value.as_ref().to_owned();
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn with_realtime(mut self) -> Self {
|
|
||||||
self.realtime = true;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn with_completion(mut self) -> Self {
|
|
||||||
self.completion = true;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn with_highlight(mut self) -> Self {
|
|
||||||
self.highlight = true;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -16,7 +16,6 @@ pub mod help;
|
||||||
mod highlighter;
|
mod highlighter;
|
||||||
pub mod input;
|
pub mod input;
|
||||||
pub mod manager;
|
pub mod manager;
|
||||||
mod position;
|
|
||||||
pub mod preview;
|
pub mod preview;
|
||||||
pub mod select;
|
pub mod select;
|
||||||
mod step;
|
mod step;
|
||||||
|
|
@ -28,7 +27,6 @@ pub use blocker::*;
|
||||||
pub use context::*;
|
pub use context::*;
|
||||||
pub use event::*;
|
pub use event::*;
|
||||||
pub use highlighter::*;
|
pub use highlighter::*;
|
||||||
pub use position::*;
|
|
||||||
pub use step::*;
|
pub use step::*;
|
||||||
|
|
||||||
pub fn init() { init_blocker(); }
|
pub fn init() { init_blocker(); }
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use std::path::{PathBuf, MAIN_SEPARATOR};
|
use std::path::{PathBuf, MAIN_SEPARATOR};
|
||||||
|
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
use yazi_config::keymap::Exec;
|
use yazi_config::{keymap::Exec, popup::InputOpt};
|
||||||
use yazi_shared::Url;
|
use yazi_shared::Url;
|
||||||
|
|
||||||
use crate::{emit, files::{File, FilesOp}, input::InputOpt, manager::Manager};
|
use crate::{emit, files::{File, FilesOp}, manager::Manager};
|
||||||
|
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
force: bool,
|
force: bool,
|
||||||
|
|
@ -19,20 +19,14 @@ impl Manager {
|
||||||
let opt = opt.into() as Opt;
|
let opt = opt.into() as Opt;
|
||||||
let cwd = self.cwd().to_owned();
|
let cwd = self.cwd().to_owned();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut result = emit!(Input(InputOpt::top_center("Create:", Default::default())));
|
let mut result = emit!(Input(InputOpt::create()));
|
||||||
let Some(Ok(name)) = result.recv().await else {
|
let Some(Ok(name)) = result.recv().await else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
let path = cwd.join(&name);
|
let path = cwd.join(&name);
|
||||||
if !opt.force && fs::symlink_metadata(&path).await.is_ok() {
|
if !opt.force && fs::symlink_metadata(&path).await.is_ok() {
|
||||||
match emit!(Input(InputOpt::top_center(
|
match emit!(Input(InputOpt::overwrite())).recv().await {
|
||||||
"Overwrite an existing file? (y/N)",
|
|
||||||
Default::default()
|
|
||||||
)))
|
|
||||||
.recv()
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Some(Ok(c)) if c == "y" || c == "Y" => (),
|
Some(Ok(c)) if c == "y" || c == "Y" => (),
|
||||||
_ => return Ok(()),
|
_ => return Ok(()),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
|
|
||||||
use yazi_config::{keymap::Exec, OPEN, SELECT};
|
use yazi_config::{keymap::Exec, popup::SelectOpt, OPEN, SELECT};
|
||||||
use yazi_shared::MIME_DIR;
|
use yazi_shared::MIME_DIR;
|
||||||
|
|
||||||
use crate::{emit, external, manager::Manager, select::SelectOpt};
|
use crate::{emit, external, manager::Manager};
|
||||||
|
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
interactive: bool,
|
interactive: bool,
|
||||||
|
|
@ -20,12 +20,8 @@ impl Manager {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = emit!(Select(SelectOpt::from_cfg(
|
let result =
|
||||||
"Open with:",
|
emit!(Select(SelectOpt::open().with_items(openers.iter().map(|o| o.desc.clone()).collect())));
|
||||||
openers.iter().map(|o| o.desc.clone()).collect(),
|
|
||||||
&SELECT.open_position,
|
|
||||||
&SELECT.open_offset
|
|
||||||
)));
|
|
||||||
|
|
||||||
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,6 +1,6 @@
|
||||||
use yazi_config::keymap::Exec;
|
use yazi_config::keymap::Exec;
|
||||||
|
|
||||||
use crate::{emit, input::InputOpt, manager::Manager, tasks::Tasks};
|
use crate::{emit, manager::Manager, tasks::Tasks};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ use std::{collections::BTreeSet, ffi::OsStr, io::{stdout, BufWriter, Write}, pat
|
||||||
|
|
||||||
use anyhow::{anyhow, bail, Result};
|
use anyhow::{anyhow, bail, Result};
|
||||||
use tokio::{fs::{self, OpenOptions}, io::{stdin, AsyncReadExt, AsyncWriteExt}};
|
use tokio::{fs::{self, OpenOptions}, io::{stdin, AsyncReadExt, AsyncWriteExt}};
|
||||||
use yazi_config::{keymap::Exec, INPUT, OPEN, PREVIEW};
|
use yazi_config::{keymap::Exec, popup::InputOpt, INPUT, OPEN, PREVIEW};
|
||||||
use yazi_shared::{max_common_root, Defer, Term, Url};
|
use yazi_shared::{max_common_root, Defer, Term, Url};
|
||||||
|
|
||||||
use crate::{emit, external::{self, ShellOpt}, files::{File, FilesOp}, input::InputOpt, manager::Manager, Event, BLOCKER};
|
use crate::{emit, external::{self, ShellOpt}, files::{File, FilesOp}, manager::Manager, Event, BLOCKER};
|
||||||
|
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
force: bool,
|
force: bool,
|
||||||
|
|
@ -42,10 +42,8 @@ impl Manager {
|
||||||
|
|
||||||
let opt = opt.into() as Opt;
|
let opt = opt.into() as Opt;
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut result = emit!(Input(
|
let mut result =
|
||||||
InputOpt::from_cfg("Rename:", &INPUT.rename_position, &INPUT.rename_offset)
|
emit!(Input(InputOpt::rename().with_value(hovered.file_name().unwrap().to_string_lossy())));
|
||||||
.with_value(hovered.file_name().unwrap().to_string_lossy())
|
|
||||||
));
|
|
||||||
|
|
||||||
let Some(Ok(name)) = result.recv().await else {
|
let Some(Ok(name)) = result.recv().await else {
|
||||||
return;
|
return;
|
||||||
|
|
@ -57,11 +55,7 @@ impl Manager {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = emit!(Input(InputOpt::from_cfg(
|
let mut result = emit!(Input(InputOpt::overwrite()));
|
||||||
"Overwrite an existing file? (y/N)",
|
|
||||||
&INPUT.rename_position,
|
|
||||||
&INPUT.rename_offset
|
|
||||||
)));
|
|
||||||
if let Some(Ok(choice)) = result.recv().await {
|
if let Some(Ok(choice)) = result.recv().await {
|
||||||
if choice == "y" || choice == "Y" {
|
if choice == "y" || choice == "Y" {
|
||||||
Self::rename_and_hover(hovered, Url::from(new)).await.ok();
|
Self::rename_and_hover(hovered, Url::from(new)).await.ok();
|
||||||
|
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
use ratatui::prelude::Rect;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct Offset {
|
|
||||||
pub x_offset: i16,
|
|
||||||
pub y_offset: i16,
|
|
||||||
pub width: u16,
|
|
||||||
pub height: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Offset {
|
|
||||||
fn default() -> Self { Self { x_offset: 0, y_offset: 2, width: 50, height: 3 } }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum Position {
|
|
||||||
TopLeft(Offset),
|
|
||||||
TopRight(Offset),
|
|
||||||
TopCenter(Offset),
|
|
||||||
Center(Offset),
|
|
||||||
BottomCenter(Offset),
|
|
||||||
BottomLeft(Offset),
|
|
||||||
BottomRight(Offset),
|
|
||||||
Hovered(Offset),
|
|
||||||
Sticky(Offset, Rect),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Position {
|
|
||||||
fn default() -> Self { Self::TopCenter(Offset::default()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Position {
|
|
||||||
#[inline]
|
|
||||||
pub fn offset(&self) -> &Offset {
|
|
||||||
match self {
|
|
||||||
Position::TopLeft(offset) => offset,
|
|
||||||
Position::TopRight(offset) => offset,
|
|
||||||
Position::TopCenter(offset) => offset,
|
|
||||||
Position::Center(offset) => offset,
|
|
||||||
Position::BottomCenter(offset) => offset,
|
|
||||||
Position::BottomLeft(offset) => offset,
|
|
||||||
Position::BottomRight(offset) => offset,
|
|
||||||
Position::Hovered(offset) => offset,
|
|
||||||
Position::Sticky(offset, _) => offset,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn dimension(&self) -> (u16, u16) { (self.offset().width, self.offset().height) }
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
mod commands;
|
mod commands;
|
||||||
mod option;
|
|
||||||
mod select;
|
mod select;
|
||||||
|
|
||||||
pub use option::*;
|
|
||||||
pub use select::*;
|
pub use select::*;
|
||||||
|
|
||||||
pub const SELECT_PADDING: u16 = 2;
|
pub const SELECT_PADDING: u16 = 2;
|
||||||
|
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
use yazi_config::popup::{Offset as CfgOffset, Position as CfgPosition};
|
|
||||||
|
|
||||||
use crate::{Position, Offset};
|
|
||||||
|
|
||||||
pub struct SelectOpt {
|
|
||||||
pub title: String,
|
|
||||||
pub items: Vec<String>,
|
|
||||||
pub position: Position,
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! gen_method {
|
|
||||||
($func_name:ident, $position:ident) => {
|
|
||||||
pub fn $func_name(title: &str, items: Vec<String>, rect: Offset) -> SelectOpt {
|
|
||||||
let height = 2
|
|
||||||
+ items.len().min(
|
|
||||||
5, // TODO: hardcode
|
|
||||||
) as u16;
|
|
||||||
Self {
|
|
||||||
title: title.to_owned(),
|
|
||||||
items,
|
|
||||||
position: Position::$position(Offset { height, ..rect }),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SelectOpt {
|
|
||||||
gen_method!(top_left, TopLeft);
|
|
||||||
|
|
||||||
gen_method!(top_right, TopRight);
|
|
||||||
|
|
||||||
gen_method!(top_center, TopCenter);
|
|
||||||
|
|
||||||
gen_method!(center, Center);
|
|
||||||
|
|
||||||
gen_method!(bottom_center, BottomCenter);
|
|
||||||
|
|
||||||
gen_method!(bottom_left, BottomLeft);
|
|
||||||
|
|
||||||
gen_method!(bottom_right, BottomRight);
|
|
||||||
|
|
||||||
gen_method!(hovered, Hovered);
|
|
||||||
|
|
||||||
pub fn from_cfg(title: &str, items: Vec<String>, pos: &CfgPosition, rect: &CfgOffset) -> Self {
|
|
||||||
let rect =
|
|
||||||
Offset { x_offset: rect.x, y_offset: rect.y, width: rect.width, height: rect.height };
|
|
||||||
|
|
||||||
match pos {
|
|
||||||
CfgPosition::TopLeft => Self::top_left(title, items, rect),
|
|
||||||
CfgPosition::TopRight => Self::top_right(title, items, rect),
|
|
||||||
CfgPosition::TopCenter => Self::top_center(title, items, rect),
|
|
||||||
CfgPosition::Center => Self::center(title, items, rect),
|
|
||||||
CfgPosition::BottomCenter => Self::bottom_center(title, items, rect),
|
|
||||||
CfgPosition::BottomLeft => Self::bottom_left(title, items, rect),
|
|
||||||
CfgPosition::BottomRight => Self::bottom_right(title, items, rect),
|
|
||||||
CfgPosition::Hovered => Self::hovered(title, items, rect),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use tokio::sync::oneshot::Sender;
|
use tokio::sync::oneshot::Sender;
|
||||||
|
use yazi_config::popup::{Position, SelectOpt};
|
||||||
use super::SelectOpt;
|
|
||||||
use crate::Position;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Select {
|
pub struct Select {
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ use std::{mem, time::Duration};
|
||||||
|
|
||||||
use tokio::{fs, pin};
|
use tokio::{fs, pin};
|
||||||
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
|
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
|
||||||
use yazi_config::{keymap::{Exec, KeymapLayer}, INPUT};
|
use yazi_config::{keymap::{Exec, KeymapLayer}, popup::InputOpt};
|
||||||
use yazi_shared::{expand_path, Debounce, InputError, Url};
|
use yazi_shared::{expand_path, Debounce, InputError, Url};
|
||||||
|
|
||||||
use crate::{emit, input::InputOpt, tab::Tab};
|
use crate::{emit, tab::Tab};
|
||||||
|
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
target: Url,
|
target: Url,
|
||||||
|
|
@ -65,11 +65,7 @@ impl Tab {
|
||||||
let opt = opt.into() as Opt;
|
let opt = opt.into() as Opt;
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let rx = emit!(Input(
|
let rx = emit!(Input(InputOpt::cd().with_value(opt.target.to_string_lossy())));
|
||||||
InputOpt::from_cfg("Change directory:", &INPUT.cd_position, &INPUT.cd_offset)
|
|
||||||
.with_value(opt.target.to_string_lossy())
|
|
||||||
.with_completion()
|
|
||||||
));
|
|
||||||
|
|
||||||
let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50));
|
let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50));
|
||||||
pin!(rx);
|
pin!(rx);
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ use std::time::Duration;
|
||||||
|
|
||||||
use tokio::pin;
|
use tokio::pin;
|
||||||
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
|
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
|
||||||
use yazi_config::{keymap::{Exec, KeymapLayer}, INPUT};
|
use yazi_config::{keymap::{Exec, KeymapLayer}, popup::InputOpt, INPUT};
|
||||||
use yazi_shared::{Debounce, InputError};
|
use yazi_shared::{Debounce, InputError};
|
||||||
|
|
||||||
use crate::{emit, input::InputOpt, tab::{Finder, FinderCase, Tab}};
|
use crate::{emit, tab::{Finder, FinderCase, Tab}};
|
||||||
|
|
||||||
pub struct Opt<'a> {
|
pub struct Opt<'a> {
|
||||||
query: Option<&'a str>,
|
query: Option<&'a str>,
|
||||||
|
|
@ -40,9 +40,7 @@ impl Tab {
|
||||||
let opt = opt.into() as Opt;
|
let opt = opt.into() as Opt;
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let title = if opt.prev { "Find previous:" } else { "Find next:" };
|
let title = if opt.prev { "Find previous:" } else { "Find next:" };
|
||||||
let rx = emit!(Input(
|
let rx = emit!(Input(InputOpt::find(opt.prev)));
|
||||||
InputOpt::from_cfg(title, &INPUT.find_position, &INPUT.find_offset).with_realtime()
|
|
||||||
));
|
|
||||||
|
|
||||||
let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50));
|
let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50));
|
||||||
pin!(rx);
|
pin!(rx);
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@ use std::{mem, time::Duration};
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
use tokio::pin;
|
use tokio::pin;
|
||||||
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
|
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
|
||||||
use yazi_config::{keymap::{Exec, KeymapLayer}, INPUT};
|
use yazi_config::{keymap::{Exec, KeymapLayer}, popup::InputOpt, INPUT};
|
||||||
|
|
||||||
use crate::{emit, external, files::FilesOp, input::InputOpt, tab::Tab};
|
use crate::{emit, external, files::FilesOp, tab::Tab};
|
||||||
|
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
pub type_: OptType,
|
pub type_: OptType,
|
||||||
|
|
@ -45,9 +45,7 @@ impl Tab {
|
||||||
let hidden = self.conf.show_hidden;
|
let hidden = self.conf.show_hidden;
|
||||||
|
|
||||||
self.search = Some(tokio::spawn(async move {
|
self.search = Some(tokio::spawn(async move {
|
||||||
let Some(Ok(subject)) = emit!(Input(InputOpt::from_cfg("Search:", &INPUT.cd_position, &INPUT.cd_offset))).recv().await else {
|
let Some(Ok(subject)) = emit!(Input(InputOpt::search())).recv().await else { bail!("") };
|
||||||
bail!("")
|
|
||||||
};
|
|
||||||
|
|
||||||
cwd = cwd.into_search(subject.clone());
|
cwd = cwd.into_search(subject.clone());
|
||||||
let rx = if opt.type_ == OptType::Rg {
|
let rx = if opt.type_ == OptType::Rg {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use yazi_config::{keymap::Exec, open::Opener, INPUT};
|
use yazi_config::{keymap::Exec, open::Opener, popup::InputOpt, INPUT};
|
||||||
|
|
||||||
use crate::{emit, input::InputOpt, tab::Tab};
|
use crate::{emit, tab::Tab};
|
||||||
|
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
cmd: String,
|
cmd: String,
|
||||||
|
|
@ -29,12 +29,7 @@ impl Tab {
|
||||||
let mut opt = opt.into() as Opt;
|
let mut opt = opt.into() as Opt;
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
if !opt.confirm || opt.cmd.is_empty() {
|
if !opt.confirm || opt.cmd.is_empty() {
|
||||||
let title = if opt.block { "Shell (block):" } else { "Shell:" };
|
let mut result = emit!(Input(InputOpt::shell(opt.block).with_value(opt.cmd)));
|
||||||
let mut result = emit!(Input(
|
|
||||||
InputOpt::from_cfg(title, &INPUT.shell_position, &INPUT.shell_offset)
|
|
||||||
.with_value(opt.cmd)
|
|
||||||
.with_highlight()
|
|
||||||
));
|
|
||||||
match result.recv().await {
|
match result.recv().await {
|
||||||
Some(Ok(e)) => opt.cmd = e,
|
Some(Ok(e)) => opt.cmd = e,
|
||||||
_ => return,
|
_ => return,
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@ use std::{collections::{BTreeMap, HashMap, HashSet}, ffi::OsStr, path::Path, syn
|
||||||
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
use yazi_config::{manager::SortBy, open::Opener, OPEN};
|
use yazi_config::{manager::SortBy, open::Opener, popup::InputOpt, OPEN};
|
||||||
use yazi_shared::{MimeKind, Term, Url};
|
use yazi_shared::{MimeKind, Term, Url};
|
||||||
|
|
||||||
use super::{running::Running, task::TaskSummary, Scheduler, TASKS_PADDING, TASKS_PERCENT};
|
use super::{running::Running, task::TaskSummary, Scheduler, TASKS_PADDING, TASKS_PERCENT};
|
||||||
use crate::{emit, files::{File, Files}, input::InputOpt};
|
use crate::{emit, files::{File, Files}};
|
||||||
|
|
||||||
pub struct Tasks {
|
pub struct Tasks {
|
||||||
pub(super) scheduler: Arc<Scheduler>,
|
pub(super) scheduler: Arc<Scheduler>,
|
||||||
|
|
@ -110,13 +110,11 @@ impl Tasks {
|
||||||
|
|
||||||
let scheduler = self.scheduler.clone();
|
let scheduler = self.scheduler.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let s = if targets.len() > 1 { "s" } else { "" };
|
let mut result = emit!(Input(if permanently {
|
||||||
let prompt = if permanently {
|
InputOpt::delete(targets.len())
|
||||||
format!("Delete {} selected file{s} permanently? (y/N)", targets.len())
|
|
||||||
} else {
|
} else {
|
||||||
format!("Move {} selected file{s} to trash? (y/N)", targets.len())
|
InputOpt::trash(targets.len())
|
||||||
};
|
}));
|
||||||
let mut result = emit!(Input(InputOpt::hovered(prompt, Default::default())));
|
|
||||||
|
|
||||||
if let Some(Ok(choice)) = result.recv().await {
|
if let Some(Ok(choice)) = result.recv().await {
|
||||||
if choice != "y" && choice != "Y" {
|
if choice != "y" && choice != "Y" {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue