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 | |
parent | 9a082fe7f0633593a6e07feb404f6434bb944511 (diff) |
add bulk_rename command
Diffstat (limited to 'src/commands')
-rw-r--r-- | src/commands/bulk_rename.rs | 127 | ||||
-rw-r--r-- | src/commands/cursor_move.rs | 7 | ||||
-rw-r--r-- | src/commands/delete_files.rs | 7 | ||||
-rw-r--r-- | src/commands/mod.rs | 5 |
4 files changed, 143 insertions, 3 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(()) + } +} diff --git a/src/commands/cursor_move.rs b/src/commands/cursor_move.rs index 1ed3537..adc7266 100644 --- a/src/commands/cursor_move.rs +++ b/src/commands/cursor_move.rs @@ -22,7 +22,12 @@ pub fn cursor_move(mut new_index: usize, context: &mut JoshutoContext, view: &Jo } } - curr_tab.refresh(&view, &context.config_t); + curr_tab.refresh_curr(&view.mid_win, &context.config_t); + if context.config_t.show_preview { + curr_tab.refresh_preview(&view.right_win, &context.config_t); + } + curr_tab.refresh_path_status(&view.top_win, &context.config_t); + curr_tab.refresh_file_status(&view.bot_win); ncurses::doupdate(); } diff --git a/src/commands/delete_files.rs b/src/commands/delete_files.rs index ac66c9d..adaed07 100644 --- a/src/commands/delete_files.rs +++ b/src/commands/delete_files.rs @@ -77,7 +77,12 @@ impl JoshutoRunnable for DeleteFiles { fn execute(&self, context: &mut JoshutoContext, view: &JoshutoView) -> JoshutoResult<()> { Self::delete_files(context, view)?; let curr_tab = &mut context.tabs[context.curr_tab_index]; - curr_tab.refresh(view, &context.config_t); + curr_tab.refresh_curr(&view.mid_win, &context.config_t); + if context.config_t.show_preview { + curr_tab.refresh_preview(&view.right_win, &context.config_t); + } + curr_tab.refresh_path_status(&view.top_win, &context.config_t); + curr_tab.refresh_file_status(&view.bot_win); ncurses::doupdate(); Ok(()) } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 1656af9..1009c69 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,3 +1,4 @@ +mod bulk_rename; mod change_directory; mod command_line; mod cursor_move; @@ -16,6 +17,7 @@ mod show_hidden; mod tab_operations; mod tab_switch; +pub use self::bulk_rename::BulkRename; pub use self::change_directory::ChangeDirectory; pub use self::command_line::CommandLine; pub use self::cursor_move::{ @@ -70,11 +72,12 @@ impl std::fmt::Display for CommandKeybind { pub fn from_args(command: &str, args: &[&str]) -> JoshutoResult<Box<JoshutoCommand>> { match command { + "bulk_rename" => Ok(Box::new(self::BulkRename::new())), "cd" => match args.len() { 0 => match HOME_DIR.as_ref() { Some(s) => Ok(Box::new(self::ChangeDirectory::new(s.clone()))), None => Err(JoshutoError::new( - JoshutoErrorKind::EnvVarNotFound, + JoshutoErrorKind::EnvVarNotPresent, format!("{}: Cannot find home directory", command), )), }, |