summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiayi Zhao <jeff.no.zhao@gmail.com>2019-01-08 21:27:49 -0500
committerJiayi Zhao <jeff.no.zhao@gmail.com>2019-01-08 21:27:49 -0500
commitc43d20bb002f90136ce63390bd3ee30dbf1a38d6 (patch)
treeb8d81098b2c4abe9c0c507e42d756292acb5a6c8
parent4a7c0820b8b3b2f8696815df4d9e42022d9ad5df (diff)
add support for opening multiple files
-rw-r--r--src/joshuto/command.rs96
-rw-r--r--src/joshuto/command/file_operation.rs19
-rw-r--r--src/joshuto/command/open_file.rs173
-rw-r--r--src/joshuto/unix.rs12
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<String>>) -> Option<Box<dyn JoshutoCommand>>
{
match command {
@@ -268,3 +232,61 @@ pub fn from_args(command: &str, args: Option<&Vec<String>>) -> Option<Box<dyn Jo
_ => None,
}
}
+
+pub fn collect_selected_paths(dirlist: &structs::JoshutoDirList)
+ -> Option<Vec<path::PathBuf>>
+{
+ if dirlist.index < 0 {
+ return None;
+ }
+
+ if dirlist.selected == 0 {
+ Some(vec![dirlist.contents[dirlist.index as usize].path.clone()])
+ } else {
+ let selected: Vec<path::PathBuf> = 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<Vec<path::PathBuf>>
-{
- let selected: Vec<path::PathBuf> = 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<path::PathBuf>, 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<Vec<path::PathBuf>> = 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<path::PathBuf>, 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<String> = 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<path::PathBuf>, 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<String>)
+pub fn open_with_args(paths: &Vec<path::PathBuf>, args: &Vec<String>)
{
let program = args[0].clone();
let args_len = args.len();
@@ -137,7 +139,9 @@ pub fn open_with_args(path: &path::Path, args: &Vec<String>)
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) => {