diff options
author | Jiayi Zhao <jeff.no.zhao@gmail.com> | 2019-06-30 10:52:12 -0400 |
---|---|---|
committer | Jiayi Zhao <jeff.no.zhao@gmail.com> | 2019-06-30 10:52:12 -0400 |
commit | 242bae74d7b97e4542afbd9b1c708b45919e9695 (patch) | |
tree | 30523aa94179d7535982ac5dfb2c9d0c21c8a566 /src/commands/bulk_rename.rs | |
parent | 9a082fe7f0633593a6e07feb404f6434bb944511 (diff) |
add bulk_rename command
Diffstat (limited to 'src/commands/bulk_rename.rs')
-rw-r--r-- | src/commands/bulk_rename.rs | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/src/commands/bulk_rename.rs b/src/commands/bulk_rename.rs new file mode 100644 index 0000000..2db758f --- /dev/null +++ b/src/commands/bulk_rename.rs @@ -0,0 +1,127 @@ +use std::io::{BufRead, Write}; +use std::path; +use std::process; + +use rand::Rng; + +use crate::context::JoshutoContext; +use crate::error::{JoshutoError, JoshutoErrorKind, JoshutoResult}; +use crate::window::JoshutoView; +use crate::commands::{JoshutoCommand, JoshutoRunnable, ReloadDirList}; + +#[derive(Clone, Debug)] +pub struct BulkRename; + +impl BulkRename { + pub fn new() -> Self { + BulkRename {} + } + pub const fn command() -> &'static str { + "bulk_rename" + } + + pub fn bulk_rename(context: &mut JoshutoContext) -> JoshutoResult<()> { + const PREFIX: &str = "joshuto-"; + let editor = match std::env::var("EDITOR") { + Ok(s) => s, + Err(_) => return Err(JoshutoError::new( + JoshutoErrorKind::EnvVarNotPresent, + String::from("EDITOR environment variable not set"), + )), + }; + + let curr_tab = &context.tabs[context.curr_tab_index]; + + let paths = curr_tab.curr_list.get_selected_paths(); + let mut rand_str = String::with_capacity(PREFIX.len() + 10); + rand_str.push_str(PREFIX); + + rand::thread_rng() + .sample_iter(&rand::distributions::Alphanumeric) + .take(10) + .for_each(|ch| rand_str.push(ch)); + + let mut file_path = path::PathBuf::from("/tmp"); + file_path.push(rand_str); + + { + let mut file = std::fs::File::create(&file_path)?; + for path in &paths { + let file_name = path.file_name().unwrap(); + let file_name_as_bytes = file_name.to_str().unwrap().as_bytes(); + file.write(file_name_as_bytes)?; + file.write(&['\n' as u8])?; + } + } + + let mut command = process::Command::new(editor); + command.arg(&file_path); + + /* exit curses and launch program */ + { + ncurses::savetty(); + ncurses::endwin(); + let mut handle = command.spawn()?; + handle.wait()?; + } + + let mut paths_renamed: Vec<path::PathBuf> = Vec::with_capacity(paths.len()); + { + let file = std::fs::File::open(&file_path)?; + + let reader = std::io::BufReader::new(file); + for line in reader.lines() { + let line2 = line?; + let line = line2.trim(); + if line.len() == 0 { + continue; + } + let path = path::PathBuf::from(line); + paths_renamed.push(path); + } + } + + for (p, q) in paths.iter().zip(paths_renamed.iter()) { + println!("{:?} -> {:?}", p, q); + } + print!("Continue with rename? (y/N): "); + std::io::stdout().flush()?; + + let mut user_input = String::with_capacity(4); + std::io::stdin().read_line(&mut user_input)?; + user_input = user_input.to_lowercase(); + + let user_input_trimmed = user_input.trim(); + if user_input_trimmed == "y" || user_input_trimmed == "yes" { + for (p, q) in paths.iter().zip(paths_renamed.iter()) { + std::fs::rename(p, q)?; + } + } + std::fs::remove_file(file_path)?; + + /* restore ncurses */ + ncurses::resetty(); + ncurses::refresh(); + ncurses::doupdate(); + Ok(()) + } +} + +impl JoshutoCommand for BulkRename {} + +impl std::fmt::Display for BulkRename { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", Self::command()) + } +} + +impl JoshutoRunnable for BulkRename { + fn execute(&self, context: &mut JoshutoContext, view: &JoshutoView) -> JoshutoResult<()> { + Self::bulk_rename(context)?; + ReloadDirList::reload(context.curr_tab_index, context)?; + let curr_tab = &mut context.tabs[context.curr_tab_index]; + curr_tab.refresh(view, &context.config_t); + ncurses::doupdate(); + Ok(()) + } +} |