mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
parent
ab7acfec5c
commit
564af8827e
19 changed files with 339 additions and 68 deletions
|
|
@ -16,6 +16,25 @@ cache_dir = ""
|
|||
ueberzug_scale = 1
|
||||
ueberzug_offset = [ 0, 0, 0, 0 ]
|
||||
|
||||
[input]
|
||||
cd_position = "top"
|
||||
cd_offset = [0, 2, 50, 3]
|
||||
|
||||
search_position = "top"
|
||||
search_offset = [0, 2, 50, 3]
|
||||
|
||||
find_position = "top"
|
||||
find_offset = [0, 2, 50, 3]
|
||||
|
||||
shell_position = "top"
|
||||
shell_offset = [0, 2, 50, 3]
|
||||
|
||||
create_position = "top"
|
||||
create_offset = [0, 2, 50, 3]
|
||||
|
||||
rename_position = "hovered"
|
||||
rename_offset = [0, 1, 50, 3]
|
||||
|
||||
[opener]
|
||||
edit = [
|
||||
{ exec = '$EDITOR "$@"', block = true, for = "unix" },
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ pub mod manager;
|
|||
pub mod open;
|
||||
mod pattern;
|
||||
pub mod plugins;
|
||||
pub mod popup;
|
||||
mod preset;
|
||||
pub mod preview;
|
||||
mod tasks;
|
||||
|
|
@ -32,6 +33,7 @@ pub static PLUGINS: RoCell<plugins::Plugins> = RoCell::new();
|
|||
pub static PREVIEW: RoCell<preview::Preview> = RoCell::new();
|
||||
pub static TASKS: RoCell<tasks::Tasks> = RoCell::new();
|
||||
pub static THEME: RoCell<theme::Theme> = RoCell::new();
|
||||
pub static INPUTBOX: RoCell<popup::Input> = RoCell::new();
|
||||
|
||||
pub static BOOT: RoCell<boot::Boot> = RoCell::new();
|
||||
|
||||
|
|
@ -48,6 +50,7 @@ pub fn init() {
|
|||
PREVIEW.with(Default::default);
|
||||
TASKS.with(Default::default);
|
||||
THEME.with(Default::default);
|
||||
INPUTBOX.with(Default::default);
|
||||
|
||||
BOOT.with(Default::default);
|
||||
}
|
||||
|
|
|
|||
38
yazi-config/src/popup/input.rs
Normal file
38
yazi-config/src/popup/input.rs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
use super::position::{Offset, Position};
|
||||
use crate::MERGED_YAZI;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct Input {
|
||||
// cd
|
||||
pub cd_position: Position,
|
||||
pub cd_offset: Offset,
|
||||
// search
|
||||
pub search_position: Position,
|
||||
pub search_offset: Offset,
|
||||
// find
|
||||
pub find_position: Position,
|
||||
pub find_offset: Offset,
|
||||
// shell
|
||||
pub shell_position: Position,
|
||||
pub shell_offset: Offset,
|
||||
// create
|
||||
pub create_position: Position,
|
||||
pub create_offset: Offset,
|
||||
// rename
|
||||
pub rename_position: Position,
|
||||
pub rename_offset: Offset,
|
||||
}
|
||||
|
||||
impl Default for Input {
|
||||
fn default() -> Self {
|
||||
#[derive(Deserialize)]
|
||||
struct Outer {
|
||||
input: Input,
|
||||
}
|
||||
|
||||
// TODO:
|
||||
toml::from_str::<Outer>(&MERGED_YAZI).unwrap().input
|
||||
}
|
||||
}
|
||||
7
yazi-config/src/popup/mod.rs
Normal file
7
yazi-config/src/popup/mod.rs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
mod input;
|
||||
mod position;
|
||||
mod select;
|
||||
|
||||
pub use input::*;
|
||||
pub use position::*;
|
||||
pub use select::*;
|
||||
51
yazi-config/src/popup/position.rs
Normal file
51
yazi-config/src/popup/position.rs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
use anyhow::bail;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub enum Position {
|
||||
#[serde(rename = "top-left")]
|
||||
TopLeft,
|
||||
#[serde(rename = "top-right")]
|
||||
TopRight,
|
||||
#[serde(rename = "top")]
|
||||
Top,
|
||||
#[serde(rename = "center")]
|
||||
Center,
|
||||
#[serde(rename = "bottom")]
|
||||
Bottom,
|
||||
#[serde(rename = "bottom-left")]
|
||||
BottomLeft,
|
||||
#[serde(rename = "bottom-right")]
|
||||
BottomRight,
|
||||
#[serde(rename = "hovered")]
|
||||
Hovered,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(try_from = "Vec<i16>")]
|
||||
pub struct Offset {
|
||||
pub x: i16,
|
||||
pub y: i16,
|
||||
pub width: u16,
|
||||
pub height: u16,
|
||||
}
|
||||
|
||||
impl TryFrom<Vec<i16>> for Offset {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(values: Vec<i16>) -> Result<Self, Self::Error> {
|
||||
if values.len() != 4 {
|
||||
bail!("invalid offset: {:?}", values);
|
||||
}
|
||||
if values[2] < 0 || values[3] < 0 {
|
||||
bail!("invalid offset: {:?}", values);
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
x: values[0],
|
||||
y: values[1],
|
||||
width: values[2] as u16,
|
||||
height: values[3] as u16,
|
||||
})
|
||||
}
|
||||
}
|
||||
1
yazi-config/src/popup/select.rs
Normal file
1
yazi-config/src/popup/select.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
// TODO:
|
||||
|
|
@ -2,7 +2,7 @@ use crossterm::terminal::WindowSize;
|
|||
use ratatui::prelude::Rect;
|
||||
use yazi_shared::Term;
|
||||
|
||||
use crate::{completion::Completion, help::Help, input::Input, manager::Manager, select::Select, tasks::Tasks, which::Which, Position};
|
||||
use crate::{completion::Completion, help::Help, input::Input, manager::Manager, select::Select, tasks::Tasks, which::Which, Position, RectShim};
|
||||
|
||||
pub struct Ctx {
|
||||
pub manager: Manager,
|
||||
|
|
@ -30,29 +30,114 @@ impl Ctx {
|
|||
pub fn area(&self, pos: &Position) -> Rect {
|
||||
let WindowSize { columns, rows, .. } = Term::size();
|
||||
|
||||
let (x, y) = match pos {
|
||||
Position::Top(Rect { mut x, mut y, width, height }) => {
|
||||
x = x.min(columns.saturating_sub(*width));
|
||||
y = y.min(rows.saturating_sub(*height));
|
||||
((columns / 2).saturating_sub(width / 2) + x, y)
|
||||
let (x, y) = match *pos {
|
||||
Position::TopLeft(RectShim { x_offset, y_offset, width, height }) => {
|
||||
let right_max = columns.saturating_sub(width);
|
||||
let bottom_max = rows.saturating_sub(height);
|
||||
|
||||
let base_x = 0_u16;
|
||||
let base_y = 0_u16;
|
||||
|
||||
let x = base_x.saturating_add_signed(x_offset).max(0).min(right_max);
|
||||
let y = base_y.saturating_add_signed(y_offset).max(0).min(bottom_max);
|
||||
|
||||
(x, y)
|
||||
}
|
||||
Position::Sticky(Rect { mut x, y, width, height }, r) => {
|
||||
x = x.min(columns.saturating_sub(*width));
|
||||
if y + height + r.y + r.height > rows {
|
||||
(x + r.x, r.y.saturating_sub(height.saturating_sub(*y)))
|
||||
} else {
|
||||
(x + r.x, y + r.y + r.height)
|
||||
Position::TopRight(RectShim { x_offset, y_offset, width, height }) => {
|
||||
let right_max = columns.saturating_sub(width);
|
||||
let bottom_max = rows.saturating_sub(height);
|
||||
|
||||
let base_x = right_max;
|
||||
let base_y = 0_u16;
|
||||
|
||||
let x = base_x.saturating_add_signed(x_offset).max(0).min(right_max);
|
||||
let y = base_y.saturating_add_signed(y_offset).max(0).min(bottom_max);
|
||||
|
||||
(x, y)
|
||||
}
|
||||
Position::Top(RectShim { x_offset, y_offset, width, height }) => {
|
||||
let right_max = columns.saturating_sub(width);
|
||||
let bottom_max = rows.saturating_sub(height);
|
||||
|
||||
let base_x = (columns / 2).saturating_sub(width / 2);
|
||||
let base_y = 0_u16;
|
||||
|
||||
let x = base_x.saturating_add_signed(x_offset).max(0).min(right_max);
|
||||
let y = base_y.saturating_add_signed(y_offset).max(0).min(bottom_max);
|
||||
|
||||
(x, y)
|
||||
}
|
||||
Position::Hovered(rect) => {
|
||||
Position::Center(RectShim { x_offset, y_offset, width, height }) => {
|
||||
let right_max = columns.saturating_sub(width);
|
||||
let bottom_max = rows.saturating_sub(height);
|
||||
|
||||
let base_x = (columns / 2).saturating_sub(width / 2);
|
||||
let base_y = (bottom_max / 2).saturating_sub(height / 2);
|
||||
|
||||
let x = base_x.saturating_add_signed(x_offset).max(0).min(right_max);
|
||||
let y = base_y.saturating_add_signed(y_offset).max(0).min(bottom_max);
|
||||
|
||||
(x, y)
|
||||
}
|
||||
Position::Bottom(RectShim { x_offset, y_offset, width, height }) => {
|
||||
let right_max = columns.saturating_sub(width);
|
||||
let bottom_max = rows.saturating_sub(height);
|
||||
|
||||
let base_x = (columns / 2).saturating_sub(width / 2);
|
||||
let base_y = bottom_max;
|
||||
|
||||
let x = base_x.saturating_add_signed(x_offset).max(0).min(right_max);
|
||||
let y = base_y.saturating_add_signed(y_offset).max(0).min(bottom_max);
|
||||
|
||||
(x, y)
|
||||
}
|
||||
Position::BottomLeft(RectShim { x_offset, y_offset, width, height }) => {
|
||||
let right_max = columns.saturating_sub(width);
|
||||
let bottom_max = rows.saturating_sub(height);
|
||||
|
||||
let base_x = 0_u16;
|
||||
let base_y = bottom_max;
|
||||
|
||||
let x = base_x.saturating_add_signed(x_offset).max(0).min(right_max);
|
||||
let y = base_y.saturating_add_signed(y_offset).max(0).min(bottom_max);
|
||||
|
||||
(x, y)
|
||||
}
|
||||
Position::BottomRight(RectShim { x_offset, y_offset, width, height }) => {
|
||||
let right_max = columns.saturating_sub(width);
|
||||
let bottom_max = rows.saturating_sub(height);
|
||||
|
||||
let base_x = right_max;
|
||||
let base_y = bottom_max;
|
||||
|
||||
let x = base_x.saturating_add_signed(x_offset).max(0).min(right_max);
|
||||
let y = base_y.saturating_add_signed(y_offset).max(0).min(bottom_max);
|
||||
|
||||
(x, y)
|
||||
}
|
||||
Position::Hovered(rect_shim) => {
|
||||
return self.area(&if let Some(r) =
|
||||
self.manager.hovered().and_then(|h| self.manager.current().rect_current(&h.url))
|
||||
{
|
||||
Position::Sticky(*rect, r)
|
||||
Position::Sticky(rect_shim, r)
|
||||
} else {
|
||||
Position::Top(*rect)
|
||||
Position::Top(rect_shim)
|
||||
});
|
||||
}
|
||||
Position::Sticky(RectShim { x_offset, y_offset, width, height }, r) => {
|
||||
// TODO:
|
||||
unimplemented!("Position::Sticky is not implemented");
|
||||
// let mut x = columns.saturating_sub(width);
|
||||
// x = x.saturating_add_signed(x_offset);
|
||||
// let mut y = r.y;
|
||||
// y = y.saturating_add_signed(y_offset);
|
||||
|
||||
// if y + height + r.height > rows {
|
||||
// (x + r.x, r.y.saturating_sub(height.saturating_sub(y)))
|
||||
// } else {
|
||||
// (x + r.x, y + r.height)
|
||||
// }
|
||||
}
|
||||
};
|
||||
|
||||
let (w, h) = pos.dimension();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use ratatui::prelude::Rect;
|
||||
use yazi_config::popup::{Offset as CfgOffset, Position as CfgPosition};
|
||||
|
||||
use crate::Position;
|
||||
use crate::{Position, RectShim};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct InputOpt {
|
||||
|
|
@ -12,23 +12,48 @@ pub struct InputOpt {
|
|||
pub highlight: bool,
|
||||
}
|
||||
|
||||
impl InputOpt {
|
||||
pub fn top(title: impl AsRef<str>) -> Self {
|
||||
Self {
|
||||
macro_rules! gen_method {
|
||||
($func_name:ident, $position:ident) => {
|
||||
pub fn $func_name(title: impl AsRef<str>, rect: RectShim) -> InputOpt {
|
||||
InputOpt {
|
||||
title: title.as_ref().to_owned(),
|
||||
position: Position::Top(/* TODO: hardcode */ Rect { x: 0, y: 2, width: 50, height: 3 }),
|
||||
position: Position::$position(rect),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn hovered(title: impl AsRef<str>) -> Self {
|
||||
Self {
|
||||
title: title.as_ref().to_owned(),
|
||||
position: Position::Hovered(
|
||||
// TODO: hardcode
|
||||
Rect { x: 0, y: 1, width: 50, height: 3 },
|
||||
),
|
||||
..Default::default()
|
||||
impl InputOpt {
|
||||
gen_method!(top_left, TopLeft);
|
||||
|
||||
gen_method!(top_right, TopRight);
|
||||
|
||||
gen_method!(top, Top);
|
||||
|
||||
gen_method!(center, Center);
|
||||
|
||||
gen_method!(bottom, Bottom);
|
||||
|
||||
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 =
|
||||
RectShim { 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::Top => Self::top(title, rect),
|
||||
CfgPosition::Center => Self::center(title, rect),
|
||||
CfgPosition::Bottom => Self::bottom(title, rect),
|
||||
CfgPosition::BottomLeft => Self::bottom_left(title, rect),
|
||||
CfgPosition::BottomRight => Self::bottom_right(title, rect),
|
||||
CfgPosition::Hovered => Self::hovered(title, rect),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,14 +19,17 @@ impl Manager {
|
|||
let opt = opt.into() as Opt;
|
||||
let cwd = self.cwd().to_owned();
|
||||
tokio::spawn(async move {
|
||||
let mut result = emit!(Input(InputOpt::top("Create:")));
|
||||
let mut result = emit!(Input(InputOpt::top("Create:", Default::default())));
|
||||
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::top("Overwrite an existing file? (y/N)"))).recv().await {
|
||||
match emit!(Input(InputOpt::top("Overwrite an existing file? (y/N)", Default::default())))
|
||||
.recv()
|
||||
.await
|
||||
{
|
||||
Some(Ok(c)) if c == "y" || c == "Y" => (),
|
||||
_ => return Ok(()),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,10 @@ impl Manager {
|
|||
}
|
||||
|
||||
tokio::spawn(async move {
|
||||
let mut result =
|
||||
emit!(Input(InputOpt::top(format!("{tasks} tasks running, sure to quit? (y/N)"))));
|
||||
let mut result = emit!(Input(InputOpt::top(
|
||||
format!("{tasks} tasks running, sure to quit? (y/N)",),
|
||||
Default::default()
|
||||
)));
|
||||
|
||||
if let Some(Ok(choice)) = result.recv().await {
|
||||
if choice == "y" || choice == "Y" {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::{collections::BTreeSet, 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, OPEN, PREVIEW};
|
||||
use yazi_config::{keymap::Exec, INPUTBOX, OPEN, PREVIEW};
|
||||
use yazi_shared::{max_common_root, Defer, Term, Url};
|
||||
|
||||
use crate::{emit, external::{self, ShellOpt}, files::{File, FilesOp}, input::InputOpt, manager::Manager, Event, BLOCKER};
|
||||
|
|
@ -43,7 +43,8 @@ impl Manager {
|
|||
let opt = opt.into() as Opt;
|
||||
tokio::spawn(async move {
|
||||
let mut result = emit!(Input(
|
||||
InputOpt::hovered("Rename:").with_value(hovered.file_name().unwrap().to_string_lossy())
|
||||
InputOpt::from_cfg("Rename:", &INPUTBOX.rename_position, &INPUTBOX.rename_offset)
|
||||
.with_value(hovered.file_name().unwrap().to_string_lossy())
|
||||
));
|
||||
|
||||
let Some(Ok(name)) = result.recv().await else {
|
||||
|
|
@ -56,7 +57,11 @@ impl Manager {
|
|||
return;
|
||||
}
|
||||
|
||||
let mut result = emit!(Input(InputOpt::hovered("Overwrite an existing file? (y/N)")));
|
||||
let mut result = emit!(Input(InputOpt::from_cfg(
|
||||
"Overwrite an existing file? (y/N)",
|
||||
&INPUTBOX.rename_position,
|
||||
&INPUTBOX.rename_offset
|
||||
)));
|
||||
if let Some(Ok(choice)) = result.recv().await {
|
||||
if choice == "y" || choice == "Y" {
|
||||
Self::rename_and_hover(hovered, Url::from(new)).await.ok();
|
||||
|
|
|
|||
|
|
@ -1,22 +1,47 @@
|
|||
use ratatui::prelude::Rect;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct RectShim {
|
||||
pub x_offset: i16,
|
||||
pub y_offset: i16,
|
||||
pub width: u16,
|
||||
pub height: u16,
|
||||
}
|
||||
|
||||
impl Default for RectShim {
|
||||
fn default() -> Self { Self { x_offset: 0, y_offset: 2, width: 50, height: 3 } }
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Position {
|
||||
Top(Rect),
|
||||
Sticky(Rect, Rect),
|
||||
Hovered(Rect),
|
||||
TopLeft(RectShim),
|
||||
TopRight(RectShim),
|
||||
Top(RectShim),
|
||||
Center(RectShim),
|
||||
Bottom(RectShim),
|
||||
BottomLeft(RectShim),
|
||||
BottomRight(RectShim),
|
||||
Hovered(RectShim),
|
||||
Sticky(RectShim, Rect),
|
||||
}
|
||||
|
||||
impl Default for Position {
|
||||
fn default() -> Self { Self::Top(Rect::default()) }
|
||||
fn default() -> Self { Self::Top(RectShim::default()) }
|
||||
}
|
||||
|
||||
impl Position {
|
||||
#[inline]
|
||||
pub fn rect(&self) -> Rect {
|
||||
pub fn rect(&self) -> &RectShim {
|
||||
match self {
|
||||
Position::Top(rect) => *rect,
|
||||
Position::Sticky(rect, _) => *rect,
|
||||
Position::Hovered(rect) => *rect,
|
||||
Position::TopLeft(rect) => rect,
|
||||
Position::TopRight(rect) => rect,
|
||||
Position::Top(rect) => rect,
|
||||
Position::Center(rect) => rect,
|
||||
Position::Bottom(rect) => rect,
|
||||
Position::BottomLeft(rect) => rect,
|
||||
Position::BottomRight(rect) => rect,
|
||||
Position::Hovered(rect) => rect,
|
||||
Position::Sticky(rect, _) => rect,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use ratatui::prelude::Rect;
|
||||
|
||||
use crate::Position;
|
||||
use crate::{Position, RectShim};
|
||||
|
||||
pub struct SelectOpt {
|
||||
pub title: String,
|
||||
|
|
@ -14,7 +14,10 @@ impl SelectOpt {
|
|||
Self {
|
||||
title: title.to_owned(),
|
||||
items,
|
||||
position: Position::Top(/* TODO: hardcode */ Rect { x: 0, y: 2, width: 50, height }),
|
||||
position: Position::Top(
|
||||
// TODO:
|
||||
RectShim { x_offset: 0, y_offset: 2, width: 50, height },
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -24,8 +27,8 @@ impl SelectOpt {
|
|||
title: title.to_owned(),
|
||||
items,
|
||||
position: Position::Hovered(
|
||||
// TODO: hardcode
|
||||
Rect { x: 0, y: 1, width: 50, height },
|
||||
// TODO:
|
||||
RectShim { x_offset: 0, y_offset: 1, width: 50, height },
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::{mem, time::Duration};
|
|||
|
||||
use tokio::{fs, pin};
|
||||
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
|
||||
use yazi_config::keymap::{Exec, KeymapLayer};
|
||||
use yazi_config::{keymap::{Exec, KeymapLayer}, INPUTBOX};
|
||||
use yazi_shared::{expand_path, Debounce, InputError, Url};
|
||||
|
||||
use crate::{emit, input::InputOpt, tab::Tab};
|
||||
|
|
@ -66,7 +66,7 @@ impl Tab {
|
|||
|
||||
tokio::spawn(async move {
|
||||
let rx = emit!(Input(
|
||||
InputOpt::top("Change directory:")
|
||||
InputOpt::from_cfg("Change directory:", &INPUTBOX.cd_position, &INPUTBOX.cd_offset)
|
||||
.with_value(opt.target.to_string_lossy())
|
||||
.with_completion()
|
||||
));
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::time::Duration;
|
|||
|
||||
use tokio::pin;
|
||||
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
|
||||
use yazi_config::keymap::{Exec, KeymapLayer};
|
||||
use yazi_config::{keymap::{Exec, KeymapLayer}, INPUTBOX};
|
||||
use yazi_shared::{Debounce, InputError};
|
||||
|
||||
use crate::{emit, input::InputOpt, tab::{Finder, FinderCase, Tab}};
|
||||
|
|
@ -39,8 +39,9 @@ impl Tab {
|
|||
pub fn find<'a>(&mut self, opt: impl Into<Opt<'a>>) -> bool {
|
||||
let opt = opt.into() as Opt;
|
||||
tokio::spawn(async move {
|
||||
let title = if opt.prev { "Find previous:" } else { "Find next:" };
|
||||
let rx = emit!(Input(
|
||||
InputOpt::top(if opt.prev { "Find previous:" } else { "Find next:" }).with_realtime()
|
||||
InputOpt::from_cfg(title, &INPUTBOX.find_position, &INPUTBOX.find_offset).with_realtime()
|
||||
));
|
||||
|
||||
let rx = Debounce::new(UnboundedReceiverStream::new(rx), Duration::from_millis(50));
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::{mem, time::Duration};
|
|||
use anyhow::bail;
|
||||
use tokio::pin;
|
||||
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
|
||||
use yazi_config::keymap::{Exec, KeymapLayer};
|
||||
use yazi_config::{keymap::{Exec, KeymapLayer}, INPUTBOX};
|
||||
|
||||
use crate::{emit, external, files::FilesOp, input::InputOpt, tab::Tab};
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ impl Tab {
|
|||
let hidden = self.conf.show_hidden;
|
||||
|
||||
self.search = Some(tokio::spawn(async move {
|
||||
let Some(Ok(subject)) = emit!(Input(InputOpt::top("Search:"))).recv().await else {
|
||||
let Some(Ok(subject)) = emit!(Input(InputOpt::from_cfg("Search:", &INPUTBOX.cd_position, &INPUTBOX.cd_offset))).recv().await else {
|
||||
bail!("")
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use yazi_config::{keymap::Exec, open::Opener};
|
||||
use yazi_config::{keymap::Exec, open::Opener, INPUTBOX};
|
||||
|
||||
use crate::{emit, input::InputOpt, tab::Tab};
|
||||
|
||||
|
|
@ -29,8 +29,9 @@ impl Tab {
|
|||
let mut opt = opt.into() as Opt;
|
||||
tokio::spawn(async move {
|
||||
if !opt.confirm || opt.cmd.is_empty() {
|
||||
let title = if opt.block { "Shell (block):" } else { "Shell:" };
|
||||
let mut result = emit!(Input(
|
||||
InputOpt::top(if opt.block { "Shell (block):" } else { "Shell:" })
|
||||
InputOpt::from_cfg(title, &INPUTBOX.shell_position, &INPUTBOX.shell_offset)
|
||||
.with_value(opt.cmd)
|
||||
.with_highlight()
|
||||
));
|
||||
|
|
|
|||
|
|
@ -111,11 +111,12 @@ impl Tasks {
|
|||
let scheduler = self.scheduler.clone();
|
||||
tokio::spawn(async move {
|
||||
let s = if targets.len() > 1 { "s" } else { "" };
|
||||
let mut result = emit!(Input(InputOpt::hovered(if permanently {
|
||||
let prompt = if permanently {
|
||||
format!("Delete {} selected file{s} permanently? (y/N)", targets.len())
|
||||
} else {
|
||||
format!("Move {} selected file{s} to trash? (y/N)", targets.len())
|
||||
})));
|
||||
};
|
||||
let mut result = emit!(Input(InputOpt::hovered(prompt, Default::default())));
|
||||
|
||||
if let Some(Ok(choice)) = result.recv().await {
|
||||
if choice != "y" && choice != "Y" {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::path::MAIN_SEPARATOR;
|
|||
|
||||
use ratatui::{buffer::Buffer, layout::Rect, widgets::{Block, BorderType, Borders, Clear, List, ListItem, Widget}};
|
||||
use yazi_config::THEME;
|
||||
use yazi_core::{Ctx, Position};
|
||||
use yazi_core::{Ctx, Position, RectShim};
|
||||
|
||||
pub(crate) struct Completion<'a> {
|
||||
cx: &'a Ctx,
|
||||
|
|
@ -40,9 +40,10 @@ impl<'a> Widget for Completion<'a> {
|
|||
|
||||
let input_area = self.cx.area(&self.cx.input.position);
|
||||
let mut area = self.cx.area(&Position::Sticky(
|
||||
Rect {
|
||||
x: 1,
|
||||
y: 0,
|
||||
// TODO:
|
||||
RectShim {
|
||||
x_offset: 1,
|
||||
y_offset: 0,
|
||||
width: input_area.width.saturating_sub(2),
|
||||
height: items.len() as u16 + 2,
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue