mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
193 lines
4.6 KiB
Rust
193 lines
4.6 KiB
Rust
use ratatui::{text::{Line, Text}, widgets::{Paragraph, Wrap}};
|
|
use yazi_shared::url::Url;
|
|
|
|
use super::{Offset, Origin, Position};
|
|
use crate::{CONFIRM, INPUT, PICK};
|
|
|
|
#[derive(Default)]
|
|
pub struct InputCfg {
|
|
pub title: String,
|
|
pub value: String,
|
|
pub cursor: Option<usize>,
|
|
pub position: Position,
|
|
pub realtime: bool,
|
|
pub completion: bool,
|
|
pub highlight: bool,
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct PickCfg {
|
|
pub title: String,
|
|
pub items: Vec<String>,
|
|
pub position: Position,
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct ConfirmCfg {
|
|
pub position: Position,
|
|
pub title: Line<'static>,
|
|
pub content: Paragraph<'static>,
|
|
pub list: Paragraph<'static>,
|
|
}
|
|
|
|
impl InputCfg {
|
|
pub fn cd() -> Self {
|
|
Self {
|
|
title: INPUT.cd_title.to_owned(),
|
|
position: Position::new(INPUT.cd_origin, INPUT.cd_offset),
|
|
completion: true,
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
pub fn create(dir: bool) -> Self {
|
|
Self {
|
|
title: INPUT.create_title[dir as usize].to_owned(),
|
|
position: Position::new(INPUT.create_origin, INPUT.create_offset),
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
pub fn rename() -> Self {
|
|
Self {
|
|
title: INPUT.rename_title.to_owned(),
|
|
position: Position::new(INPUT.rename_origin, INPUT.rename_offset),
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
pub fn filter() -> Self {
|
|
Self {
|
|
title: INPUT.filter_title.to_owned(),
|
|
position: Position::new(INPUT.filter_origin, INPUT.filter_offset),
|
|
realtime: true,
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
pub fn find(prev: bool) -> Self {
|
|
Self {
|
|
title: INPUT.find_title[prev as usize].to_owned(),
|
|
position: Position::new(INPUT.find_origin, INPUT.find_offset),
|
|
realtime: true,
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
pub fn search(name: &str) -> Self {
|
|
Self {
|
|
title: INPUT.search_title.replace("{n}", name),
|
|
position: Position::new(INPUT.search_origin, INPUT.search_offset),
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
pub fn shell(block: bool) -> Self {
|
|
Self {
|
|
title: INPUT.shell_title[block as usize].to_owned(),
|
|
position: Position::new(INPUT.shell_origin, INPUT.shell_offset),
|
|
highlight: true,
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn with_value(mut self, value: impl Into<String>) -> Self {
|
|
self.value = value.into();
|
|
self
|
|
}
|
|
|
|
#[inline]
|
|
pub fn with_cursor(mut self, cursor: Option<usize>) -> Self {
|
|
self.cursor = cursor;
|
|
self
|
|
}
|
|
}
|
|
|
|
impl ConfirmCfg {
|
|
fn new(
|
|
title: String,
|
|
(origin, offset): (Origin, Offset),
|
|
content: Option<Text<'static>>,
|
|
list: Option<Text<'static>>,
|
|
) -> Self {
|
|
Self {
|
|
position: Position::new(origin, offset),
|
|
title: Line::raw(title),
|
|
content: content.map(|c| Paragraph::new(c).wrap(Wrap { trim: false })).unwrap_or_default(),
|
|
list: list.map(|l| Paragraph::new(l).wrap(Wrap { trim: false })).unwrap_or_default(),
|
|
}
|
|
}
|
|
|
|
pub fn trash(urls: &[yazi_shared::url::Url]) -> Self {
|
|
Self::new(
|
|
Self::replace_number(&CONFIRM.trash_title, urls.len()),
|
|
(CONFIRM.trash_origin, CONFIRM.trash_offset),
|
|
None,
|
|
Self::truncate_list(urls.iter(), urls.len(), 100),
|
|
)
|
|
}
|
|
|
|
pub fn delete(urls: &[yazi_shared::url::Url]) -> Self {
|
|
Self::new(
|
|
Self::replace_number(&CONFIRM.delete_title, urls.len()),
|
|
(CONFIRM.delete_origin, CONFIRM.delete_offset),
|
|
None,
|
|
Self::truncate_list(urls.iter(), urls.len(), 100),
|
|
)
|
|
}
|
|
|
|
pub fn overwrite(url: &Url) -> Self {
|
|
Self::new(
|
|
CONFIRM.overwrite_title.to_owned(),
|
|
(CONFIRM.overwrite_origin, CONFIRM.overwrite_offset),
|
|
Some(Text::raw(&CONFIRM.overwrite_content)),
|
|
Some(url.to_string().into()),
|
|
)
|
|
}
|
|
|
|
pub fn quit(len: usize, names: Vec<String>) -> Self {
|
|
Self::new(
|
|
Self::replace_number(&CONFIRM.quit_title, len),
|
|
(CONFIRM.quit_origin, CONFIRM.quit_offset),
|
|
Some(Text::raw(&CONFIRM.quit_content)),
|
|
Self::truncate_list(names.into_iter(), len, 10),
|
|
)
|
|
}
|
|
|
|
fn replace_number(tpl: &str, n: usize) -> String {
|
|
tpl.replace("{n}", &n.to_string()).replace("{s}", if n > 1 { "s" } else { "" })
|
|
}
|
|
|
|
fn truncate_list(
|
|
it: impl Iterator<Item = impl Into<String>>,
|
|
len: usize,
|
|
max: usize,
|
|
) -> Option<Text<'static>> {
|
|
let mut lines = Vec::with_capacity(len.min(max + 1));
|
|
for (i, s) in it.enumerate() {
|
|
if i >= max {
|
|
lines.push(format!("... and {} more", len - max));
|
|
break;
|
|
}
|
|
lines.push(s.into());
|
|
}
|
|
Some(Text::from_iter(lines))
|
|
}
|
|
}
|
|
|
|
impl PickCfg {
|
|
#[inline]
|
|
fn max_height(len: usize) -> u16 {
|
|
PICK.open_offset.height.min(PICK.border().saturating_add(len as u16))
|
|
}
|
|
|
|
pub fn open(items: Vec<String>) -> Self {
|
|
let max_height = Self::max_height(items.len());
|
|
Self {
|
|
title: PICK.open_title.to_owned(),
|
|
items,
|
|
position: Position::new(PICK.open_origin, Offset { height: max_height, ..PICK.open_offset }),
|
|
}
|
|
}
|
|
}
|