diff options
author | qkzk <qu3nt1n@gmail.com> | 2022-10-16 20:30:33 +0200 |
---|---|---|
committer | qkzk <qu3nt1n@gmail.com> | 2022-10-16 20:30:33 +0200 |
commit | 3991d97879a4e8a4f97504cc45bd7eb4bdfbf14a (patch) | |
tree | e69200bb96a92e103b297fdba9ba26520914aff5 | |
parent | 104fe9c0f4513b3fe67f08038f8cc2018890d09d (diff) |
refactor bulkrename, bug fix wrong comparisonbulkrename
-rw-r--r-- | src/actioner.rs | 1 | ||||
-rw-r--r-- | src/bulkrename.rs | 61 | ||||
-rw-r--r-- | src/config.rs | 6 | ||||
-rw-r--r-- | src/event_char.rs | 2 | ||||
-rw-r--r-- | src/fileinfo.rs | 4 | ||||
-rw-r--r-- | src/help.rs | 1 | ||||
-rw-r--r-- | src/tabs.rs | 19 |
7 files changed, 79 insertions, 15 deletions
diff --git a/src/actioner.rs b/src/actioner.rs index 88d64c1..a75efb2 100644 --- a/src/actioner.rs +++ b/src/actioner.rs @@ -50,6 +50,7 @@ impl Actioner { (keybindings.preview, EventChar::Preview), (keybindings.history, EventChar::History), (keybindings.shortcut, EventChar::Shortcut), + (keybindings.bulkrename, EventChar::Bulkrename), ]); Self { binds, term } } diff --git a/src/bulkrename.rs b/src/bulkrename.rs index 99da1d0..f67bec0 100644 --- a/src/bulkrename.rs +++ b/src/bulkrename.rs @@ -1,6 +1,8 @@ use rand::Rng; -use std::io::{self, BufRead}; +use std::io::{self, BufRead, Write}; use std::path::PathBuf; +use std::thread; +use std::time::{Duration, SystemTime}; use crate::opener::{ExtensionKind, Opener}; @@ -8,20 +10,48 @@ use crate::opener::{ExtensionKind, Opener}; static TMP_FOLDER: &str = "/tmp"; -struct BulkRenamer { +pub struct Bulkrename { original_filepath: Vec<PathBuf>, temp_file: PathBuf, } -impl BulkRenamer { +impl Bulkrename { pub fn new(original_filepath: Vec<PathBuf>) -> Result<Self, io::Error> { - let temp_file = Self::create_random_file()?; + let temp_file = Self::generate_random_filepath()?; Ok(Self { original_filepath, temp_file, }) } + pub fn rename(&mut self, opener: &Opener) -> Result<(), io::Error> { + self.write_original_names()?; + 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.clone(), original_modification); + + self.rename_all(self.get_new_filenames()?)?; + self.delete_temp_file()?; + Ok(()) + } + + fn watch_modification_in_thread(filepath: PathBuf, original_modification: SystemTime) { + let handle = thread::spawn(move || loop { + if Self::is_file_modified(&filepath, original_modification.clone()) + .unwrap_or_else(|_| true) + { + break; + } + thread::sleep(Duration::from_millis(10)); + }); + handle.join().unwrap(); + } + + fn get_modified_date(filepath: &PathBuf) -> Result<SystemTime, io::Error> { + std::fs::metadata(filepath)?.modified() + } + fn random_name() -> String { let mut rand_str = String::with_capacity(10); rand_str.push_str("fm-"); @@ -32,19 +62,20 @@ impl BulkRenamer { rand_str } - fn create_random_file() -> Result<PathBuf, io::Error> { + fn generate_random_filepath() -> Result<PathBuf, io::Error> { let mut filepath = PathBuf::from(&TMP_FOLDER); filepath.push(Self::random_name()); - let _ = std::fs::File::create(&filepath)?; Ok(filepath) } fn write_original_names(&self) -> Result<(), io::Error> { - let filepath = &self.temp_file; + let mut file = std::fs::File::create(&self.temp_file)?; for path in self.original_filepath.iter() { if let Some(os_filename) = path.file_name() { if let Some(filename) = os_filename.to_str() { - std::fs::write(&filepath, filename)? + let b = filename.as_bytes(); + file.write_all(b)?; + file.write_all(&[b'\n'])?; } } } @@ -60,15 +91,15 @@ impl BulkRenamer { } fn is_file_modified( - filepath: PathBuf, + path: &PathBuf, original_modification: std::time::SystemTime, ) -> Result<bool, io::Error> { - let last_modification = std::fs::metadata(&filepath)?.modified()?; - Ok(last_modification <= original_modification) + let last_modification = Self::get_modified_date(path)?; + Ok(last_modification > original_modification) } - fn get_new_filenames(&self, filepath: PathBuf) -> Result<Vec<String>, io::Error> { - let file = std::fs::File::open(&filepath)?; + fn get_new_filenames(&self) -> Result<Vec<String>, io::Error> { + let file = std::fs::File::open(&self.temp_file)?; let reader = std::io::BufReader::new(file); let mut new_names = vec![]; @@ -93,12 +124,12 @@ impl BulkRenamer { fn rename_all(&self, new_filenames: Vec<String>) -> Result<(), io::Error> { for (path, filename) in self.original_filepath.iter().zip(new_filenames.iter()) { - self.rename(path, filename)? + self.rename_file(path, filename)? } Ok(()) } - fn rename(&self, path: &PathBuf, filename: &str) -> Result<(), io::Error> { + fn rename_file(&self, path: &PathBuf, filename: &str) -> Result<(), io::Error> { let mut parent = path.clone(); parent.pop(); Ok(std::fs::rename(path, parent.join(&filename))?) diff --git a/src/config.rs b/src/config.rs index a75daca..d343c91 100644 --- a/src/config.rs +++ b/src/config.rs @@ -200,6 +200,8 @@ pub struct Keybindings { pub history: char, /// Display predefined shortcuts pub shortcut: char, + /// Bulkrename + pub bulkrename: char, } impl Keybindings { @@ -287,6 +289,9 @@ impl Keybindings { if let Some(shortcut) = yaml["shortcut"].as_str().map(|s| s.to_string()) { self.shortcut = shortcut.chars().next().unwrap_or('G'); } + if let Some(bulkrename) = yaml["bulkrename"].as_str().map(|s| s.to_string()) { + self.bulkrename = bulkrename.chars().next().unwrap_or('B'); + } } /// Returns a new `Keybindings` instance with hardcoded values. @@ -319,6 +324,7 @@ impl Keybindings { preview: 'P', history: 'H', shortcut: 'G', + bulkrename: 'B', } } } diff --git a/src/event_char.rs b/src/event_char.rs index 7816e4a..88d9036 100644 --- a/src/event_char.rs +++ b/src/event_char.rs @@ -28,6 +28,7 @@ pub enum EventChar { Symlink, Preview, Shortcut, + Bulkrename, } impl EventChar { @@ -61,6 +62,7 @@ impl EventChar { EventChar::Symlink => tabs.event_symlink(), EventChar::Preview => current_status.event_preview(), EventChar::Shortcut => current_status.event_shortcut(), + EventChar::Bulkrename => tabs.event_bulkrename(), } } } diff --git a/src/fileinfo.rs b/src/fileinfo.rs index 02f77cf..55fe508 100644 --- a/src/fileinfo.rs +++ b/src/fileinfo.rs @@ -320,6 +320,10 @@ impl PathContent { Some(&self.files[self.selected]) } } + + pub fn contains(&self, path: &path::PathBuf) -> bool { + path.starts_with(&self.path) + } } /// Associates a filetype to `tuikit::prelude::Attr` : fg color, bg color and diff --git a/src/help.rs b/src/help.rs index 6ac506f..4dca4ef 100644 --- a/src/help.rs +++ b/src/help.rs @@ -37,6 +37,7 @@ Ctrl+f: fuzzy finder p: move to current dir x: delete flagged files S: symlink flagged files + B: Bulkrename - MODES - m: CHMOD diff --git a/src/tabs.rs b/src/tabs.rs index f8e9d40..d2b35e3 100644 --- a/src/tabs.rs +++ b/src/tabs.rs @@ -7,6 +7,7 @@ use std::path::{self, PathBuf}; use std::sync::Arc; use crate::args::Args; +use crate::bulkrename::Bulkrename; use crate::config::Config; use crate::fileinfo::PathContent; use crate::last_edition::LastEdition; @@ -220,6 +221,24 @@ impl Tabs { self.reset_statuses() } + pub fn event_bulkrename(&mut self) { + match Bulkrename::new(self.filtered_flagged_files()) { + Ok(mut renamer) => { + let _ = renamer.rename(&self.selected().opener); + } + Err(e) => eprintln!("{}", e), + } + } + + fn filtered_flagged_files(&mut self) -> Vec<PathBuf> { + let path_content = self.selected().path_content.clone(); + self.flagged + .iter() + .filter(|p| path_content.contains(p)) + .map(|p| p.to_owned()) + .collect() + } + fn exec_copy_paste(&mut self) { self.flagged.iter().for_each(|oldpath| { let newpath = self.statuses[self.index] |