mirror of
https://github.com/sxyazi/yazi.git
synced 2024-12-03 01:22:50 +03:00
feat: add --empty
and --cursor
options to the rename
command (#513)
This commit is contained in:
parent
85334457f3
commit
ca78f4c9b0
@ -71,7 +71,7 @@ keymap = [
|
||||
{ on = [ "d" ], exec = [ "remove", "escape --visual --select" ], desc = "Move the files to the trash" },
|
||||
{ on = [ "D" ], exec = [ "remove --permanently", "escape --visual --select" ], desc = "Permanently delete the files" },
|
||||
{ on = [ "a" ], exec = "create", desc = "Create a file or directory (ends with / for directories)" },
|
||||
{ on = [ "r" ], exec = "rename", desc = "Rename a file or directory" },
|
||||
{ on = [ "r" ], exec = "rename --cursor=before_ext", desc = "Rename a file or directory" },
|
||||
{ on = [ ";" ], exec = "shell", desc = "Run a shell command" },
|
||||
{ on = [ ":" ], exec = "shell --block", desc = "Run a shell command (block the UI until the command finishes)" },
|
||||
{ on = [ "." ], exec = "hidden toggle", desc = "Toggle the visibility of hidden files" },
|
||||
|
@ -5,6 +5,7 @@ use crate::{INPUT, SELECT};
|
||||
pub struct InputCfg {
|
||||
pub title: String,
|
||||
pub value: String,
|
||||
pub cursor: Option<usize>,
|
||||
pub position: Position,
|
||||
pub realtime: bool,
|
||||
pub completion: bool,
|
||||
@ -130,6 +131,12 @@ impl InputCfg {
|
||||
self.value = value.into();
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_cursor(mut self, cursor: Option<usize>) -> Self {
|
||||
self.cursor = cursor;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl SelectCfg {
|
||||
|
@ -42,6 +42,12 @@ impl Input {
|
||||
|
||||
// Reset snaps
|
||||
self.snaps.reset(opt.cfg.value, self.limit());
|
||||
|
||||
// Set cursor after reset
|
||||
if let Some(cursor) = opt.cfg.cursor {
|
||||
self.snaps.current_mut().cursor = cursor;
|
||||
}
|
||||
|
||||
render!();
|
||||
}
|
||||
}
|
||||
|
@ -9,15 +9,37 @@ use yazi_shared::{event::Exec, fs::{max_common_root, File, FilesOp, Url}, term::
|
||||
|
||||
use crate::{input::Input, manager::Manager};
|
||||
|
||||
pub struct Opt {
|
||||
force: bool,
|
||||
pub struct Opt<'a> {
|
||||
force: bool,
|
||||
empty: &'a str,
|
||||
cursor: &'a str,
|
||||
}
|
||||
|
||||
impl From<&Exec> for Opt {
|
||||
fn from(e: &Exec) -> Self { Self { force: e.named.contains_key("force") } }
|
||||
impl<'a> From<&'a Exec> for Opt<'a> {
|
||||
fn from(e: &'a Exec) -> Self {
|
||||
Self {
|
||||
force: e.named.contains_key("force"),
|
||||
empty: e.named.get("empty").map(|s| s.as_str()).unwrap_or_default(),
|
||||
cursor: e.named.get("cursor").map(|s| s.as_str()).unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Manager {
|
||||
fn empty_url_part(url: &Url, by: &str) -> String {
|
||||
if by == "all" {
|
||||
return String::new();
|
||||
}
|
||||
|
||||
let ext = url.extension();
|
||||
match by {
|
||||
"name" => ext.map_or_else(String::new, |s| format!(".{}", s.to_string_lossy().to_string())),
|
||||
"ext" if ext.is_some() => format!("{}.", url.file_stem().unwrap().to_string_lossy()),
|
||||
"dot_ext" if ext.is_some() => url.file_stem().unwrap().to_string_lossy().to_string(),
|
||||
_ => url.file_name().map_or_else(String::new, |s| s.to_string_lossy().to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
async fn rename_and_hover(old: Url, new: Url) -> Result<()> {
|
||||
fs::rename(&old, &new).await?;
|
||||
if old.parent() != new.parent() {
|
||||
@ -29,7 +51,7 @@ impl Manager {
|
||||
Ok(Self::_hover(Some(new)))
|
||||
}
|
||||
|
||||
pub fn rename(&self, opt: impl Into<Opt>) {
|
||||
pub fn rename<'a>(&self, opt: impl Into<Opt<'a>>) {
|
||||
if self.active().in_selecting() {
|
||||
return self.bulk_rename();
|
||||
}
|
||||
@ -39,10 +61,15 @@ impl Manager {
|
||||
};
|
||||
|
||||
let opt = opt.into() as Opt;
|
||||
tokio::spawn(async move {
|
||||
let mut result =
|
||||
Input::_show(InputCfg::rename().with_value(hovered.file_name().unwrap().to_string_lossy()));
|
||||
let name = Self::empty_url_part(&hovered, opt.empty);
|
||||
let cursor = match opt.cursor {
|
||||
"start" => Some(0),
|
||||
"before_ext" => name.rfind('.').filter(|&n| n != 0),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
tokio::spawn(async move {
|
||||
let mut result = Input::_show(InputCfg::rename().with_value(name).with_cursor(cursor));
|
||||
let Some(Ok(name)) = result.recv().await else {
|
||||
return;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user