Implement empty and cursor flags

This commit is contained in:
Akmadan23 2024-01-15 13:40:46 +01:00 committed by sxyazi
parent 9bd7b52697
commit 41554b8f61
No known key found for this signature in database
2 changed files with 75 additions and 17 deletions

View file

@ -133,8 +133,8 @@ impl InputCfg {
} }
#[inline] #[inline]
pub fn with_cursor(mut self, cursor: usize) -> Self { pub fn with_cursor(mut self, cursor: Option<usize>) -> Self {
self.cursor = Some(cursor); self.cursor = cursor;
self self
} }
} }

View file

@ -9,22 +9,52 @@ use yazi_shared::{event::Exec, fs::{max_common_root, File, FilesOp, Url}, term::
use crate::{input::Input, manager::Manager}; use crate::{input::Input, manager::Manager};
enum EmptyOpt {
None,
All,
Name,
Ext,
DotExt,
}
enum CursorOpt {
None,
Append,
Prepend,
}
pub struct Opt { pub struct Opt {
force: bool, force: bool,
replace: bool, empty: EmptyOpt,
keep_ext: bool, cursor: CursorOpt,
} }
impl From<&Exec> for Opt { impl From<&Exec> for Opt {
fn from(e: &Exec) -> Self { fn from(e: &Exec) -> Self {
Self { Self {
force: e.named.contains_key("force"), force: e.named.contains_key("force"),
replace: e.named.contains_key("replace"), empty: match e.named.get("empty").map(|s| s.as_str()).unwrap_or_default() {
keep_ext: e.named.contains_key("keep-ext"), "all" => EmptyOpt::All,
"name" => EmptyOpt::Name,
"ext" => EmptyOpt::Ext,
"dot-ext" => EmptyOpt::DotExt,
_ => EmptyOpt::None,
},
cursor: match e.named.get("cursor").map(|s| s.as_str()).unwrap_or_default() {
"append" => CursorOpt::Append,
"prepend" => CursorOpt::Prepend,
_ => CursorOpt::None,
},
} }
} }
} }
fn get_parts_and_len(s: &str) -> (Vec<&str>, usize) {
let parts: Vec<_> = s.split('.').collect();
let len = parts.len();
(parts, len)
}
impl Manager { impl Manager {
async fn rename_and_hover(old: Url, new: Url) -> Result<()> { async fn rename_and_hover(old: Url, new: Url) -> Result<()> {
fs::rename(&old, &new).await?; fs::rename(&old, &new).await?;
@ -49,18 +79,46 @@ impl Manager {
let opt = opt.into() as Opt; let opt = opt.into() as Opt;
tokio::spawn(async move { tokio::spawn(async move {
let full_name = hovered.file_name().unwrap().to_string_lossy(); let full_name = hovered.file_name().unwrap().to_string_lossy();
let (initial_value, cursor_start) = if opt.keep_ext {
let last = full_name.split('.').last(); let initial_name = match &opt.empty {
if last == Some(&full_name) { EmptyOpt::None => full_name.into(),
("".into(), None) EmptyOpt::All => "".into(),
} else { EmptyOpt::Name => {
(format!(".{}", last.unwrap()), Some(0)) let ext = full_name.split('.').last().unwrap_or_default();
if ext == &full_name {
"".into()
} else {
format!(".{ext}")
}
}
x => {
let (name_parts, len) = get_parts_and_len(&full_name);
if len > 1 {
let partial_name = name_parts[..len - 1].join(".");
match x {
EmptyOpt::Ext => format!("{partial_name}."),
EmptyOpt::DotExt => partial_name,
_ => panic!() // impossible
}
} else {
full_name.into()
}
} }
} else {
(opt.replace.then(|| "").unwrap_or(&full_name).into(), None)
}; };
let mut result = Input::_show(InputCfg::rename().with_value(initial_value)); let cursor = match opt.cursor {
CursorOpt::Append => None,
CursorOpt::Prepend => Some(0),
CursorOpt::None => match opt.empty {
EmptyOpt::None => {
let (name_parts, len) = get_parts_and_len(&initial_name);
Some(name_parts[..len - 1].join(".").len())
}
_ => None
}
};
let mut result = Input::_show(InputCfg::rename().with_value(initial_name).with_cursor(cursor));
let Some(Ok(name)) = result.recv().await else { let Some(Ok(name)) = result.recv().await else {
return; return;
}; };