From b2d3e39e961f162f813e222952e16e9023e018de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E9=9B=85=20=C2=B7=20Misaki=20Masa?= Date: Sun, 1 Oct 2023 10:30:51 +0800 Subject: [PATCH] feat: new `force` option for creating and renaming (#208) --- app/src/executor.rs | 4 +-- core/src/manager/manager.rs | 55 +++++++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/app/src/executor.rs b/app/src/executor.rs index a406782c..d4dd0b21 100644 --- a/app/src/executor.rs +++ b/app/src/executor.rs @@ -124,8 +124,8 @@ impl Executor { let permanently = exec.named.contains_key("permanently"); cx.tasks.file_remove(targets, force, permanently) } - "create" => cx.manager.create(), - "rename" => cx.manager.rename(), + "create" => cx.manager.create(exec.named.contains_key("force")), + "rename" => cx.manager.rename(exec.named.contains_key("force")), "copy" => cx.manager.active().copy(exec.args.get(0).map(|s| s.as_str()).unwrap_or("")), "shell" => cx.manager.active().shell( exec.args.get(0).map(|e| e.as_str()).unwrap_or(""), diff --git a/core/src/manager/manager.rs b/core/src/manager/manager.rs index 373c418e..7e80a303 100644 --- a/core/src/manager/manager.rs +++ b/core/src/manager/manager.rs @@ -177,33 +177,40 @@ impl Manager { false } - pub fn create(&self) -> bool { + pub fn create(&self, force: bool) -> bool { let cwd = self.cwd().to_owned(); tokio::spawn(async move { let mut result = emit!(Input(InputOpt::top("Create:"))); + let Some(Ok(name)) = result.recv().await else { + return Ok(()); + }; - if let Some(Ok(name)) = result.recv().await { - let path = cwd.join(&name); - let hovered = path.components().take(cwd.components().count() + 1).collect::(); - - if name.ends_with('/') { - fs::create_dir_all(path).await?; - } else { - fs::create_dir_all(path.parent().unwrap()).await.ok(); - fs::File::create(path).await?; + let path = cwd.join(&name); + if !force && fs::symlink_metadata(&path).await.is_ok() { + match emit!(Input(InputOpt::top("Overwrite an existing file? (y/N)"))).recv().await { + Some(Ok(c)) if c == "y" || c == "Y" => (), + _ => return Ok(()), } + } - if let Ok(file) = File::from(Url::from(hovered)).await { - emit!(Hover(file)); - emit!(Refresh); - } + if name.ends_with('/') { + fs::create_dir_all(&path).await?; + } else { + fs::create_dir_all(&path.parent().unwrap()).await.ok(); + fs::File::create(&path).await?; + } + + let child = path.components().take(cwd.components().count() + 1).collect::(); + if let Ok(file) = File::from(Url::from(child)).await { + emit!(Hover(file)); + emit!(Refresh); } Ok::<(), Error>(()) }); false } - pub fn rename(&self) -> bool { + pub fn rename(&self, force: bool) -> bool { if self.active().in_selecting() { return self.bulk_rename(); } @@ -217,10 +224,22 @@ impl Manager { InputOpt::hovered("Rename:").with_value(hovered.file_name().unwrap().to_string_lossy()) )); - if let Some(Ok(new)) = result.recv().await { - let to = hovered.parent().unwrap().join(new); - fs::rename(&hovered, to).await.ok(); + let Some(Ok(name)) = result.recv().await else { + return; + }; + + let new = hovered.parent().unwrap().join(name); + if force || fs::symlink_metadata(&new).await.is_err() { + fs::rename(&hovered, new).await.ok(); + return; } + + let mut result = emit!(Input(InputOpt::hovered("Overwrite an existing file? (y/N)"))); + if let Some(Ok(choice)) = result.recv().await { + if choice == "y" || choice == "Y" { + fs::rename(&hovered, new).await.ok(); + } + }; }); false }