diff options
author | Jiayi Zhao <jeff.no.zhao@gmail.com> | 2019-05-27 08:11:16 -0400 |
---|---|---|
committer | Jiayi Zhao <jeff.no.zhao@gmail.com> | 2019-05-27 08:11:16 -0400 |
commit | 35579905606926893d4e7c0f3f58096c5b581444 (patch) | |
tree | 383c1283617c6deddf0d6263a1f61f5ebcaccd1d /src/commands/rename_file.rs | |
parent | ecc16f39e5c146e47e37bb327e86f97b7ade1ef9 (diff) |
refactor rename and search to make use of the command line
- update all other commands that make use of textfield to use new
interface
Diffstat (limited to 'src/commands/rename_file.rs')
-rw-r--r-- | src/commands/rename_file.rs | 237 |
1 files changed, 159 insertions, 78 deletions
diff --git a/src/commands/rename_file.rs b/src/commands/rename_file.rs index 558ce74..a5ec420 100644 --- a/src/commands/rename_file.rs +++ b/src/commands/rename_file.rs @@ -1,30 +1,31 @@ use std::path; -use crate::commands::{JoshutoCommand, JoshutoRunnable}; +use crate::commands::{CommandLine, JoshutoCommand, JoshutoRunnable}; use crate::context::JoshutoContext; use crate::error::JoshutoError; -use crate::textfield::JoshutoTextField; -use crate::ui; use crate::window::JoshutoView; -#[derive(Clone, Debug)] -pub enum RenameFileMethod { - Append, - Prepend, - Overwrite, -} +use rustyline::completion::{escape, Quote}; + +#[cfg(unix)] +static DEFAULT_BREAK_CHARS: [u8; 18] = [ + b' ', b'\t', b'\n', b'"', b'\\', b'\'', b'`', b'@', b'$', b'>', b'<', b'=', b';', b'|', b'&', + b'{', b'(', b'\0', +]; +#[cfg(unix)] +static ESCAPE_CHAR: Option<char> = Some('\\'); #[derive(Clone, Debug)] pub struct RenameFile { - method: RenameFileMethod, + path: path::PathBuf, } impl RenameFile { - pub fn new(method: RenameFileMethod) -> Self { - RenameFile { method } + pub fn new(path: path::PathBuf) -> Self { + RenameFile { path } } pub const fn command() -> &'static str { - "rename_file" + "rename" } pub fn rename_file( @@ -32,65 +33,20 @@ impl RenameFile { path: &path::PathBuf, context: &mut JoshutoContext, view: &JoshutoView, - initial: String, ) -> Result<(), std::io::Error> { - const PROMPT: &str = ":rename_file "; - let (term_rows, term_cols) = ui::getmaxyx(); - let user_input: Option<String> = { - let prefix: String; - let suffix: String; - match self.method { - RenameFileMethod::Append => { - if let Some(ext) = initial.rfind('.') { - prefix = String::from(&initial[0..ext]); - suffix = String::from(&initial[ext..]); - } else { - prefix = initial; - suffix = String::new(); - } - } - RenameFileMethod::Prepend => { - prefix = String::new(); - suffix = initial; - } - RenameFileMethod::Overwrite => { - prefix = String::new(); - suffix = String::new(); - } - } - let textfield = JoshutoTextField::new( - 1, - term_cols, - (term_rows as usize - 1, 0), - PROMPT.to_string(), - prefix, - suffix, - ); - textfield.readline() - }; - - if let Some(s) = user_input { - let mut new_path = path.parent().unwrap().to_path_buf(); - - new_path.push(s); - if new_path.exists() { - let err = std::io::Error::new( - std::io::ErrorKind::AlreadyExists, - "Filename already exists", - ); - return Err(err); - } - std::fs::rename(&path, &new_path)?; - let curr_tab = &mut context.tabs[context.curr_tab_index]; - curr_tab - .curr_list - .update_contents(&context.config_t.sort_option)?; - curr_tab.refresh_curr(&view.mid_win, context.config_t.scroll_offset); - curr_tab.refresh_preview(&view.right_win, &context.config_t); - } else { - let curr_tab = &context.tabs[context.curr_tab_index]; - curr_tab.refresh_file_status(&view.bot_win); + let new_path = &self.path; + if new_path.exists() { + let err = + std::io::Error::new(std::io::ErrorKind::AlreadyExists, "Filename already exists"); + return Err(err); } + std::fs::rename(&path, &new_path)?; + let curr_tab = &mut context.tabs[context.curr_tab_index]; + curr_tab + .curr_list + .update_contents(&context.config_t.sort_option)?; + curr_tab.refresh_curr(&view.mid_win, context.config_t.scroll_offset); + curr_tab.refresh_preview(&view.right_win, &context.config_t); Ok(()) } } @@ -110,22 +66,147 @@ impl JoshutoRunnable for RenameFile { view: &JoshutoView, ) -> Result<(), JoshutoError> { let mut path: Option<path::PathBuf> = None; - let mut file_name: Option<String> = None; let curr_list = &context.tabs[context.curr_tab_index].curr_list; if let Some(s) = curr_list.get_curr_ref() { path = Some(s.path.clone()); - file_name = Some(s.file_name_as_string.clone()); } + if let Some(path) = path { + match self.rename_file(&path, context, view) { + Ok(_) => {} + Err(e) => return Err(JoshutoError::IO(e)), + } + ncurses::doupdate(); + } + Ok(()) + } +} + +#[derive(Clone, Debug)] +pub struct RenameFileAppend; + +impl RenameFileAppend { + pub fn new() -> Self { + RenameFileAppend {} + } + pub const fn command() -> &'static str { + "rename_append" + } + + pub fn rename_file( + &self, + context: &mut JoshutoContext, + view: &JoshutoView, + file_name: String, + ) -> Result<(), JoshutoError> { + let prefix; + let suffix; + if let Some(ext) = file_name.rfind('.') { + prefix = format!("rename {}", &file_name[0..ext]); + suffix = String::from(&file_name[ext..]); + } else { + prefix = format!("rename {}", file_name); + suffix = String::new(); + } + + let command = CommandLine::new(prefix, suffix); + command.readline(context, view) + } +} + +impl JoshutoCommand for RenameFileAppend {} + +impl std::fmt::Display for RenameFileAppend { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", Self::command()) + } +} + +impl JoshutoRunnable for RenameFileAppend { + fn execute( + &self, + context: &mut JoshutoContext, + view: &JoshutoView, + ) -> Result<(), JoshutoError> { + let curr_list = &context.tabs[context.curr_tab_index].curr_list; + let file_name = match curr_list.get_curr_ref() { + Some(s) => { + let escaped = escape( + s.file_name_as_string.clone(), + ESCAPE_CHAR, + &DEFAULT_BREAK_CHARS, + Quote::None, + ); + Some(escaped) + } + None => None, + }; + if let Some(file_name) = file_name { - if let Some(path) = path { - match self.rename_file(&path, context, view, file_name.clone()) { - Ok(_) => {} - Err(e) => return Err(JoshutoError::IO(e)), - } - ncurses::doupdate(); + self.rename_file(context, view, file_name)?; + ncurses::doupdate(); + } + Ok(()) + } +} + +#[derive(Clone, Debug)] +pub struct RenameFilePrepend; + +impl RenameFilePrepend { + pub fn new() -> Self { + RenameFilePrepend {} + } + pub const fn command() -> &'static str { + "rename_prepend" + } + + pub fn rename_file( + &self, + context: &mut JoshutoContext, + view: &JoshutoView, + file_name: String, + ) -> Result<(), JoshutoError> { + let prefix = String::from("rename "); + let suffix = file_name; + + let command = CommandLine::new(prefix, suffix); + command.readline(context, view) + } +} + +impl JoshutoCommand for RenameFilePrepend {} + +impl std::fmt::Display for RenameFilePrepend { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", Self::command()) + } +} + +impl JoshutoRunnable for RenameFilePrepend { + fn execute( + &self, + context: &mut JoshutoContext, + view: &JoshutoView, + ) -> Result<(), JoshutoError> { + let curr_list = &context.tabs[context.curr_tab_index].curr_list; + let file_name = match curr_list.get_curr_ref() { + Some(s) => { + let escaped = escape( + s.file_name_as_string.clone(), + ESCAPE_CHAR, + &DEFAULT_BREAK_CHARS, + Quote::None, + ); + Some(escaped) } + None => None, + }; + + if let Some(file_name) = file_name { + self.rename_file(context, view, file_name)?; + ncurses::doupdate(); } Ok(()) } |