Skip to content

Commit

Permalink
feat: add --empty and --cursor options to the rename command (#513
Browse files Browse the repository at this point in the history
)
  • Loading branch information
Akmadan23 authored Jan 15, 2024
1 parent 8533445 commit ca78f4c
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 9 deletions.
2 changes: 1 addition & 1 deletion yazi-config/preset/keymap.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" },
Expand Down
7 changes: 7 additions & 0 deletions yazi-config/src/popup/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down
6 changes: 6 additions & 0 deletions yazi-core/src/input/commands/show.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!();
}
}
43 changes: 35 additions & 8 deletions yazi-core/src/manager/commands/rename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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();
}
Expand All @@ -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;
};
Expand Down

0 comments on commit ca78f4c

Please sign in to comment.