diff options
Diffstat (limited to 'src/bulkrename.rs')
-rw-r--r-- | src/bulkrename.rs | 124 |
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); |