summaryrefslogtreecommitdiffstats
path: root/src/bulkrename.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bulkrename.rs')
-rw-r--r--src/bulkrename.rs124
1 files changed, 115 insertions, 9 deletions
diff --git a/src/bulkrename.rs b/src/bulkrename.rs
index 8b0bfbf..634a13c 100644
--- a/src/bulkrename.rs
+++ b/src/bulkrename.rs
@@ -1,3 +1,4 @@
+use log::info;
use rand::Rng;
use std::io::{BufRead, Write};
use std::path::{Path, PathBuf};
@@ -6,23 +7,37 @@ use std::time::{Duration, SystemTime};
use crate::constant_strings_paths::TMP_FOLDER_PATH;
use crate::fm_error::{FmError, FmResult};
+use crate::impl_selectable_content;
use crate::opener::Opener;
+use crate::status::Status;
/// Struct holding informations about files about to be renamed.
/// We only need to know which are the original filenames and which
/// temporary file is used to modify them.
/// This feature is a poor clone of ranger's one.
pub struct Bulkrename<'a> {
- original_filepath: Vec<&'a Path>,
+ original_filepath: Option<Vec<&'a Path>>,
+ parent_dir: Option<&'a str>,
temp_file: PathBuf,
}
impl<'a> Bulkrename<'a> {
/// Creates a new Bulkrename instance.
- pub fn new(original_filepath: Vec<&'a Path>) -> FmResult<Self> {
+ pub fn renamer(original_filepath: Vec<&'a Path>) -> FmResult<Self> {
let temp_file = Self::generate_random_filepath()?;
Ok(Self {
- original_filepath,
+ original_filepath: Some(original_filepath),
+ parent_dir: None,
+ temp_file,
+ })
+ }
+
+ pub fn creator(path_str: &'a str) -> FmResult<Self> {
+ let temp_file = Self::generate_random_filepath()?;
+ info!("created {temp_file:?}");
+ Ok(Self {
+ original_filepath: None,
+ parent_dir: Some(path_str),
temp_file,
})
}
@@ -31,7 +46,7 @@ impl<'a> Bulkrename<'a> {
/// The tempory file is opened with our `Opener` crate, allowing us
/// to use the default text file editor.
/// Filenames are sanitized before processing.
- pub fn rename(&mut self, opener: &Opener) -> FmResult<()> {
+ fn rename(&mut self, opener: &Opener) -> FmResult<()> {
self.write_original_names()?;
let original_modification = Self::get_modified_date(&self.temp_file)?;
self.open_temp_file_with_editor(opener)?;
@@ -42,6 +57,17 @@ impl<'a> Bulkrename<'a> {
self.delete_temp_file()
}
+ fn create_files(&mut self, opener: &Opener) -> FmResult<()> {
+ self.create_random_file()?;
+ let original_modification = Self::get_modified_date(&self.temp_file)?;
+ self.open_temp_file_with_editor(opener)?;
+
+ Self::watch_modification_in_thread(&self.temp_file, original_modification)?;
+
+ self.create_all_files(&self.get_new_filenames()?)?;
+ self.delete_temp_file()
+ }
+
fn watch_modification_in_thread(
filepath: &Path,
original_modification: SystemTime,
@@ -77,9 +103,15 @@ impl<'a> Bulkrename<'a> {
Ok(filepath)
}
+ fn create_random_file(&self) -> FmResult<()> {
+ std::fs::File::create(&self.temp_file)?;
+ Ok(())
+ }
+
fn write_original_names(&self) -> FmResult<()> {
let mut file = std::fs::File::create(&self.temp_file)?;
- for path in self.original_filepath.iter() {
+
+ for path in self.original_filepath.clone().unwrap().iter() {
let Some(os_filename) = path.file_name() else { return Ok(()) };
let Some(filename) = os_filename.to_str() else {return Ok(()) };
let b = filename.as_bytes();
@@ -90,6 +122,7 @@ impl<'a> Bulkrename<'a> {
}
fn open_temp_file_with_editor(&self, opener: &Opener) -> FmResult<()> {
+ info!("opening tempory file {:?}", self.temp_file);
opener.open(&self.temp_file)
}
@@ -111,8 +144,10 @@ impl<'a> Bulkrename<'a> {
.map(|line| line.trim().to_owned())
.filter(|line| !line.is_empty())
.collect();
- if new_names.len() < self.original_filepath.len() {
- return Err(FmError::custom("new filenames", "not enough filenames"));
+ if let Some(original_filepath) = self.original_filepath.clone() {
+ if new_names.len() < original_filepath.len() {
+ return Err(FmError::custom("new filenames", "not enough filenames"));
+ }
}
Ok(new_names)
}
@@ -123,9 +158,47 @@ impl<'a> Bulkrename<'a> {
}
fn rename_all(&self, new_filenames: Vec<String>) -> FmResult<()> {
- for (path, filename) in self.original_filepath.iter().zip(new_filenames.iter()) {
- self.rename_file(path, &sanitize_filename::sanitize(filename))?
+ let mut counter = 0;
+ for (path, filename) in self
+ .original_filepath
+ .clone()
+ .unwrap()
+ .iter()
+ .zip(new_filenames.iter())
+ {
+ let new_name = sanitize_filename::sanitize(filename);
+ self.rename_file(path, &new_name)?;
+ counter += 1;
+ info!(target: "special", "Bulk renamed {path} to {new_name}", path=path.display())
}
+ info!(target: "special", "Bulk renamed {counter} files");
+ Ok(())
+ }
+
+ fn create_all_files(&self, new_filenames: &[String]) -> FmResult<()> {
+ let mut counter = 0;
+ for filename in new_filenames.iter() {
+ let mut new_path = std::path::PathBuf::from(self.parent_dir.unwrap());
+ if !filename.ends_with('/') {
+ new_path.push(filename);
+ let Some(parent) = new_path.parent() else { return Ok(()); };
+ info!("Bulk new files. Creating parent: {}", parent.display());
+ if std::fs::create_dir_all(parent).is_err() {
+ continue;
+ };
+ info!("creating: {new_path:?}");
+ std::fs::File::create(&new_path)?;
+ info!(target:"special", "Bulk created {new_path}", new_path=new_path.display());
+ counter += 1;
+ } else {
+ new_path.push(filename);
+ info!("Bulk creating dir: {}", new_path.display());
+ std::fs::create_dir_all(&new_path)?;
+ info!(target:"special", "Bulk created {new_path}", new_path=new_path.display());
+ counter += 1;
+ }
+ }
+ info!(target: "special", "Bulk created {counter} files");
Ok(())
}
@@ -136,3 +209,36 @@ impl<'a> Bulkrename<'a> {
Ok(())
}
}
+
+pub struct Bulk {
+ pub content: Vec<String>,
+ index: usize,
+}
+
+impl Default for Bulk {
+ fn default() -> Self {
+ Self {
+ content: vec![
+ "Rename files".to_owned(),
+ "New files or folders. End folder with a slash '/'".to_owned(),
+ ],
+ index: 0,
+ }
+ }
+}
+
+impl Bulk {
+ /// Execute the selected bulk method depending on the index.
+ /// First method is a rename of selected files,
+ /// Second is the creation of files,
+ /// Third is the creation of folders.
+ pub fn execute_bulk(&self, status: &Status) -> FmResult<()> {
+ match self.index {
+ 0 => Bulkrename::renamer(status.filtered_flagged_files())?.rename(&status.opener),
+ 1 => Bulkrename::creator(status.selected_path_str())?.create_files(&status.opener),
+ _ => Ok(()),
+ }
+ }
+}
+
+impl_selectable_content!(String, Bulk);