From c43d20bb002f90136ce63390bd3ee30dbf1a38d6 Mon Sep 17 00:00:00 2001 From: Jiayi Zhao Date: Tue, 8 Jan 2019 21:27:49 -0500 Subject: add support for opening multiple files --- src/joshuto/command.rs | 96 +++++++++++-------- src/joshuto/command/file_operation.rs | 19 +--- src/joshuto/command/open_file.rs | 173 +++++++++++++++++----------------- src/joshuto/unix.rs | 12 ++- 4 files changed, 155 insertions(+), 145 deletions(-) diff --git a/src/joshuto/command.rs b/src/joshuto/command.rs index 3973ba1..d836744 100644 --- a/src/joshuto/command.rs +++ b/src/joshuto/command.rs @@ -8,6 +8,7 @@ use std::fmt; use std::path; use joshuto; +use joshuto::structs; mod quit; pub use self::quit::Quit; @@ -81,43 +82,6 @@ impl std::fmt::Display for CommandKeybind { } } -#[allow(dead_code)] -pub fn split_shell_style(line: &String) -> Vec<&str> -{ - let mut args: Vec<&str> = Vec::new(); - let mut char_ind = line.char_indices(); - - while let Some((i, ch)) = char_ind.next() { - if ch.is_whitespace() { - continue; - } - if ch == '\'' { - while let Some((j, ch)) = char_ind.next() { - if ch == '\'' { - args.push(&line[i+1..j]); - break; - } - } - } else if ch == '"'{ - while let Some((j, ch)) = char_ind.next() { - if ch == '"' { - args.push(&line[i+1..j]); - break; - } - } - } else { - while let Some((j, ch)) = char_ind.next() { - if ch.is_whitespace() { - args.push(&line[i..j]); - break; - } - } - } - } - args -} - - pub fn from_args(command: &str, args: Option<&Vec>) -> Option> { match command { @@ -268,3 +232,61 @@ pub fn from_args(command: &str, args: Option<&Vec>) -> Option None, } } + +pub fn collect_selected_paths(dirlist: &structs::JoshutoDirList) + -> Option> +{ + if dirlist.index < 0 { + return None; + } + + if dirlist.selected == 0 { + Some(vec![dirlist.contents[dirlist.index as usize].path.clone()]) + } else { + let selected: Vec = dirlist.contents.iter() + .filter(|entry| entry.selected) + .map(|entry| entry.path.clone()).collect(); + if selected.len() > 0 { + Some(selected) + } else { + None + } + } +} + +#[allow(dead_code)] +pub fn split_shell_style(line: &String) -> Vec<&str> +{ + let mut args: Vec<&str> = Vec::new(); + let mut char_ind = line.char_indices(); + + while let Some((i, ch)) = char_ind.next() { + if ch.is_whitespace() { + continue; + } + if ch == '\'' { + while let Some((j, ch)) = char_ind.next() { + if ch == '\'' { + args.push(&line[i+1..j]); + break; + } + } + } else if ch == '"'{ + while let Some((j, ch)) = char_ind.next() { + if ch == '"' { + args.push(&line[i+1..j]); + break; + } + } + } else { + while let Some((j, ch)) = char_ind.next() { + if ch.is_whitespace() { + args.push(&line[i..j]); + break; + } + } + } + } + args +} + diff --git a/src/joshuto/command/file_operation.rs b/src/joshuto/command/file_operation.rs index f4ad86a..69d5557 100644 --- a/src/joshuto/command/file_operation.rs +++ b/src/joshuto/command/file_operation.rs @@ -28,24 +28,9 @@ fn set_file_op(operation: FileOp) *data = operation; } -pub fn collect_selected_paths(dirlist: &structs::JoshutoDirList) - -> Option> -{ - let selected: Vec = dirlist.contents.iter() - .filter(|entry| entry.selected) - .map(|entry| entry.path.clone()).collect(); - if selected.len() > 0 { - Some(selected) - } else if dirlist.index >= 0 { - Some(vec![dirlist.contents[dirlist.index as usize].path.clone()]) - } else { - None - } -} - fn repopulated_selected_files(dirlist: &structs::JoshutoDirList) -> bool { - if let Some(contents) = collect_selected_paths(dirlist) { + if let Some(contents) = command::collect_selected_paths(dirlist) { let mut data = selected_files.lock().unwrap(); *data = contents; return true; @@ -334,7 +319,7 @@ impl command::Runnable for DeleteFiles { let ch = ncurses::wgetch(context.views.bot_win.win); if ch == 'y' as i32 || ch == keymap::ENTER as i32 { if let Some(s) = context.tabs[context.tab_index].curr_list.as_ref() { - if let Some(paths) = collect_selected_paths(s) { + if let Some(paths) = command::collect_selected_paths(s) { Self::remove_files(paths, &context.views.bot_win); } } diff --git a/src/joshuto/command/open_file.rs b/src/joshuto/command/open_file.rs index 5d60ce3..683bf36 100644 --- a/src/joshuto/command/open_file.rs +++ b/src/joshuto/command/open_file.rs @@ -22,38 +22,10 @@ pub struct OpenFile; impl OpenFile { pub fn new() -> Self { OpenFile } pub fn command() -> &'static str { "open_file" } -} - -impl command::JoshutoCommand for OpenFile {} - -impl std::fmt::Display for OpenFile { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result - { - f.write_str(Self::command()) - } -} - -impl command::Runnable for OpenFile { - fn execute(&self, context: &mut joshuto::JoshutoContext) + pub fn open(paths: &Vec, context: &mut joshuto::JoshutoContext) { - let curr_tab = &mut context.tabs[context.tab_index]; - - let index: usize; - let path: path::PathBuf; - - if let Some(s) = curr_tab.curr_list.as_ref() { - if s.contents.len() == 0 { - return; - } else { - index = s.index as usize; - path = s.contents[index].path.clone(); - } - } else { - return; - } - - if path.is_file() { - let file_ext: Option<&str> = match path.extension() { + if paths[0].is_file() { + let file_ext: Option<&str> = match paths[0].extension() { Some(s) => s.to_str(), None => None, }; @@ -74,7 +46,7 @@ impl command::Runnable for OpenFile { if mimetype_options.len() > 0 { ncurses::savetty(); ncurses::endwin(); - unix::open_with_entry(path.as_path(), &mimetype_options[0]); + unix::open_with_entry(paths, &mimetype_options[0]); ncurses::resetty(); ncurses::refresh(); } else { @@ -82,64 +54,93 @@ impl command::Runnable for OpenFile { } ncurses::doupdate(); - } else if path.is_dir() { - match env::set_current_dir(&path) { - Ok(_) => {}, - Err(e) => { - ui::wprint_err(&context.views.bot_win, format!("{}: {:?}", e, path).as_str()); - return; - } + } else if paths[0].is_dir() { + Self::into_directory(&paths[0], context); + } + } + + fn into_directory(path: &path::PathBuf, context: &mut joshuto::JoshutoContext) + { + let curr_tab = &mut context.tabs[context.tab_index]; + + match env::set_current_dir(path) { + Ok(_) => {}, + Err(e) => { + ui::wprint_err(&context.views.bot_win, format!("{}: {:?}", e, path).as_str()); + return; } + } - { - let dir_list = curr_tab.parent_list.take(); - curr_tab.history.put_back(dir_list); + { + let dir_list = curr_tab.parent_list.take(); + curr_tab.history.put_back(dir_list); - let curr_list = curr_tab.curr_list.take(); - curr_tab.parent_list = curr_list; + let curr_list = curr_tab.curr_list.take(); + curr_tab.parent_list = curr_list; - let preview_list = curr_tab.preview_list.take(); - curr_tab.curr_list = preview_list; - } + let preview_list = curr_tab.preview_list.take(); + curr_tab.curr_list = preview_list; + } - /* update curr_path */ - match path.strip_prefix(curr_tab.curr_path.as_path()) { - Ok(s) => curr_tab.curr_path.push(s), - Err(e) => { - ui::wprint_err(&context.views.bot_win, e.to_string().as_str()); - return; - } + /* update curr_path */ + match path.strip_prefix(curr_tab.curr_path.as_path()) { + Ok(s) => curr_tab.curr_path.push(s), + Err(e) => { + ui::wprint_err(&context.views.bot_win, e.to_string().as_str()); + return; } + } - if let Some(s) = curr_tab.curr_list.as_ref() { - if s.contents.len() > 0 { - let dirent: &structs::JoshutoDirEntry = &s.contents[s.index as usize]; - let new_path: path::PathBuf = dirent.path.clone(); - - if new_path.is_dir() { - curr_tab.preview_list = match curr_tab.history.pop_or_create( - new_path.as_path(), &context.config_t.sort_type) { - Ok(s) => { Some(s) }, - Err(e) => { - ui::wprint_err(&context.views.right_win, - e.to_string().as_str()); - None - }, - }; - } else { - ncurses::werase(context.views.right_win.win); - } + if let Some(s) = curr_tab.curr_list.as_ref() { + if s.contents.len() > 0 { + let dirent: &structs::JoshutoDirEntry = &s.contents[s.index as usize]; + let new_path: path::PathBuf = dirent.path.clone(); + + if new_path.is_dir() { + curr_tab.preview_list = match curr_tab.history.pop_or_create( + new_path.as_path(), &context.config_t.sort_type) { + Ok(s) => { Some(s) }, + Err(e) => { + ui::wprint_err(&context.views.right_win, + e.to_string().as_str()); + None + }, + }; + } else { + ncurses::werase(context.views.right_win.win); } } + } - ui::redraw_view(&context.views.left_win, curr_tab.parent_list.as_ref()); - ui::redraw_view(&context.views.mid_win, curr_tab.curr_list.as_ref()); - ui::redraw_view(&context.views.right_win, curr_tab.preview_list.as_ref()); + ui::redraw_view(&context.views.left_win, curr_tab.parent_list.as_ref()); + ui::redraw_view(&context.views.mid_win, curr_tab.curr_list.as_ref()); + ui::redraw_view(&context.views.right_win, curr_tab.preview_list.as_ref()); - ui::redraw_status(&context.views, curr_tab.curr_list.as_ref(), &curr_tab.curr_path, - &context.username, &context.hostname); + ui::redraw_status(&context.views, curr_tab.curr_list.as_ref(), &curr_tab.curr_path, + &context.username, &context.hostname); - ncurses::doupdate(); + ncurses::doupdate(); + } +} + +impl command::JoshutoCommand for OpenFile {} + +impl std::fmt::Display for OpenFile { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result + { + f.write_str(Self::command()) + } +} + +impl command::Runnable for OpenFile { + fn execute(&self, context: &mut joshuto::JoshutoContext) + { + let paths: Option> = match context.tabs[context.tab_index].curr_list.as_ref() { + Some(s) => command::collect_selected_paths(s), + None => None, + }; + if let Some(paths) = paths { + Self::open(&paths, context); } } } @@ -151,13 +152,13 @@ impl OpenFileWith { pub fn new() -> Self { OpenFileWith } pub fn command() -> &'static str { "open_file_with" } - pub fn open_with(pathbuf: path::PathBuf, mimetype_t: &mimetype::JoshutoMimetype) + pub fn open_with(paths: &Vec, mimetype_t: &mimetype::JoshutoMimetype) { let mut term_rows: i32 = 0; let mut term_cols: i32 = 0; ncurses::getmaxyx(ncurses::stdscr(), &mut term_rows, &mut term_cols); - let file_ext: Option<&str> = match pathbuf.extension() { + let file_ext: Option<&str> = match paths[0].extension() { Some(s) => s.to_str(), None => None, }; @@ -207,7 +208,7 @@ impl OpenFileWith { if s < mimetype_options.len() { ncurses::savetty(); ncurses::endwin(); - unix::open_with_entry(pathbuf.as_path(), &mimetype_options[s]); + unix::open_with_entry(&paths, &mimetype_options[s]); ncurses::resetty(); ncurses::refresh(); } @@ -216,7 +217,7 @@ impl OpenFileWith { let args: Vec = user_input.split_whitespace().map(|x| String::from(x)).collect(); ncurses::savetty(); ncurses::endwin(); - unix::open_with_args(pathbuf.as_path(), &args); + unix::open_with_args(&paths, &args); ncurses::resetty(); ncurses::refresh(); } @@ -237,11 +238,9 @@ impl std::fmt::Display for OpenFileWith { impl command::Runnable for OpenFileWith { fn execute(&self, context: &mut joshuto::JoshutoContext) { - let curr_tab = &mut context.tabs[context.tab_index]; - - if let Some(s) = curr_tab.curr_list.as_ref() { - if let Some(direntry) = s.get_curr_entry() { - OpenFileWith::open_with(direntry.path.clone(), &context.mimetype_t); + if let Some(s) = context.tabs[context.tab_index].curr_list.as_ref() { + if let Some(paths) = command::collect_selected_paths(s) { + Self::open_with(&paths, &context.mimetype_t); } } } diff --git a/src/joshuto/unix.rs b/src/joshuto/unix.rs index e6dc17d..c28866a 100644 --- a/src/joshuto/unix.rs +++ b/src/joshuto/unix.rs @@ -97,7 +97,7 @@ pub fn stringify_mode(mode: u32) -> String mode_str } -pub fn open_with_entry(path: &path::Path, entry: &mimetype::JoshutoMimetypeEntry) +pub fn open_with_entry(paths: &Vec, entry: &mimetype::JoshutoMimetypeEntry) { let program = entry.program.clone(); @@ -108,7 +108,9 @@ pub fn open_with_entry(path: &path::Path, entry: &mimetype::JoshutoMimetypeEntry command.arg(args[i].clone()); } } - command.arg(path.as_os_str()); + for path in paths { + command.arg(path.as_os_str()); + } if let Some(true) = entry.silent { command.stdout(process::Stdio::null()); command.stderr(process::Stdio::null()); @@ -128,7 +130,7 @@ pub fn open_with_entry(path: &path::Path, entry: &mimetype::JoshutoMimetypeEntry } } -pub fn open_with_args(path: &path::Path, args: &Vec) +pub fn open_with_args(paths: &Vec, args: &Vec) { let program = args[0].clone(); let args_len = args.len(); @@ -137,7 +139,9 @@ pub fn open_with_args(path: &path::Path, args: &Vec) for i in 1..args_len { command.arg(args[i].clone()); } - command.arg(path.as_os_str()); + for path in paths { + command.arg(path.as_os_str()); + } match command.spawn() { Ok(mut handle) => { -- cgit v1.2.3