diff options
author | Noah Too <krivahtoo@gmail.com> | 2022-06-22 18:03:43 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-22 11:03:43 -0400 |
commit | ba9a5726ab31071c83e83fc808a910fccdbd86f7 (patch) | |
tree | c04165a357b9d355d07be3ad4f1bca8fe9f8e54c /src/commands | |
parent | f22eecdd3b7addb9b20ec4510106c6ee339d215e (diff) |
Add `flat` command (#177)
* add `flat` command
* fix bulk_rename command
* fix `open_file` commands
* update docs
* fix errors found by clippy
* fix errors found by clippy::unnecessary-to-owned
* fix open and open_with commands
* fix: crash on root dirs
Diffstat (limited to 'src/commands')
-rw-r--r-- | src/commands/bulk_rename.rs | 22 | ||||
-rw-r--r-- | src/commands/flat.rs | 80 | ||||
-rw-r--r-- | src/commands/mod.rs | 1 | ||||
-rw-r--r-- | src/commands/open_file.rs | 48 | ||||
-rw-r--r-- | src/commands/show_tasks.rs | 36 |
5 files changed, 134 insertions, 53 deletions
diff --git a/src/commands/bulk_rename.rs b/src/commands/bulk_rename.rs index 43facee..096869e 100644 --- a/src/commands/bulk_rename.rs +++ b/src/commands/bulk_rename.rs @@ -33,18 +33,18 @@ pub fn _bulk_rename(context: &mut AppContext) -> JoshutoResult { let mut file_path = path::PathBuf::from(&tmp_directory); file_path.push(rand_str); - let paths = context + let entries = context .tab_context_ref() .curr_tab_ref() .curr_list_ref() - .map_or(vec![], |s| s.get_selected_paths()); + .map_or(vec![], |s| s.iter_selected().collect()); /* write file names into temporary file to edit */ { let mut file = fs::File::create(&file_path)?; - for path in paths.iter() { - let file_name = path.file_name().unwrap(); - let file_name_as_bytes = file_name.to_str().unwrap().as_bytes(); + for path in entries.iter() { + let file_name = path.file_name(); + let file_name_as_bytes = file_name.as_bytes(); file.write_all(file_name_as_bytes)?; file.write_all(&[b'\n'])?; } @@ -66,7 +66,7 @@ pub fn _bulk_rename(context: &mut AppContext) -> JoshutoResult { } } - let mut paths_renamed: Vec<path::PathBuf> = Vec::with_capacity(paths.len()); + let mut paths_renamed: Vec<path::PathBuf> = Vec::with_capacity(entries.len()); { let file = std::fs::File::open(&file_path)?; @@ -82,7 +82,7 @@ pub fn _bulk_rename(context: &mut AppContext) -> JoshutoResult { } std::fs::remove_file(&file_path)?; } - if paths_renamed.len() < paths.len() { + if paths_renamed.len() < entries.len() { return Err(JoshutoError::new( JoshutoErrorKind::Io(io::ErrorKind::InvalidInput), "Insufficient inputs".to_string(), @@ -90,8 +90,8 @@ pub fn _bulk_rename(context: &mut AppContext) -> JoshutoResult { } println!("{}", termion::clear::All); - for (p, q) in paths.iter().zip(paths_renamed.iter()) { - println!("{:?} -> {:?}", p, q); + for (p, q) in entries.iter().zip(paths_renamed.iter()) { + println!("{:?} -> {:?}", p.file_name(), q); } print!("Continue with rename? (Y/n): "); std::io::stdout().flush()?; @@ -102,11 +102,11 @@ pub fn _bulk_rename(context: &mut AppContext) -> JoshutoResult { let user_input_trimmed = user_input.trim(); if user_input_trimmed != "n" || user_input_trimmed != "no" { - for (p, q) in paths.iter().zip(paths_renamed.iter()) { + for (p, q) in entries.iter().zip(paths_renamed.iter()) { let mut handle = process::Command::new("mv") .arg("-iv") .arg("--") - .arg(p) + .arg(p.file_name()) .arg(q) .spawn()?; handle.wait()?; diff --git a/src/commands/flat.rs b/src/commands/flat.rs new file mode 100644 index 0000000..632b321 --- /dev/null +++ b/src/commands/flat.rs @@ -0,0 +1,80 @@ +use std::io; +use std::path::Path; + +use crate::config::option::DisplayOption; +use crate::context::AppContext; +use crate::error::JoshutoResult; +use crate::fs::{JoshutoDirEntry, JoshutoDirList, JoshutoMetadata}; + +use walkdir::WalkDir; + +fn _is_hidden(entry: &walkdir::DirEntry) -> bool { + entry + .file_name() + .to_str() + .map(|s| s.starts_with('.')) + .unwrap_or(false) +} + +pub fn _walk_directory( + path: &Path, + options: &DisplayOption, + depth: usize, +) -> io::Result<Vec<JoshutoDirEntry>> { + let results: Vec<JoshutoDirEntry> = WalkDir::new(path) + .max_depth(depth) + .into_iter() + .filter_entry(|e| { + if options.show_hidden() { + true + } else { + !_is_hidden(e) + } + }) + .filter(|e| { + if let Ok(e) = e.as_ref() { + e.path().to_str().cmp(&path.to_str()).is_ne() + } else { + true + } + }) + .filter_map(|res| JoshutoDirEntry::from_walk(&res.ok()?, path, options).ok()) + .collect(); + + Ok(results) +} + +pub fn flatten(depth: usize, context: &mut AppContext) -> JoshutoResult { + let path = context.tab_context_ref().curr_tab_ref().cwd().to_path_buf(); + + let options = context.config_ref().display_options_ref().clone(); + + let mut index: Option<usize> = context + .tab_context_ref() + .curr_tab_ref() + .curr_list_ref() + .map(|lst| lst.get_index()) + .unwrap_or(None); + let viewport_index: usize = context + .tab_context_ref() + .curr_tab_ref() + .curr_list_ref() + .map(|lst| lst.first_index_for_viewport()) + .unwrap_or(0); + + let mut contents = _walk_directory(path.as_path(), &options, depth)?; + let history = context.tab_context_mut().curr_tab_mut().history_mut(); + + if contents.is_empty() { + index = None; + } + + let sort_options = options.sort_options_ref(); + contents.sort_by(|f1, f2| sort_options.compare(f1, f2)); + + let metadata = JoshutoMetadata::from(path.as_path())?; + let dirlist = JoshutoDirList::new(path.clone(), contents, index, viewport_index, metadata); + history.insert(path, dirlist); + + Ok(()) +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 1f447c2..f4e0ee5 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -4,6 +4,7 @@ pub mod command_line; pub mod cursor_move; pub mod delete_files; pub mod file_ops; +pub mod flat; pub mod line_nums; pub mod new_directory; pub mod numbered_command; diff --git a/src/commands/open_file.rs b/src/commands/open_file.rs index 24acae1..dfcbb9a 100644 --- a/src/commands/open_file.rs +++ b/src/commands/open_file.rs @@ -26,7 +26,7 @@ pub fn get_options<'a>(path: &path::Path) -> Vec<&'a AppMimetypeEntry> { pub fn open(context: &mut AppContext, backend: &mut TuiBackend) -> JoshutoResult { let curr_list = context.tab_context_ref().curr_tab_ref().curr_list_ref(); - let entry = curr_list.and_then(|s| s.curr_entry_ref()); + let entry = curr_list.and_then(|s| s.curr_entry_ref().cloned()); match entry { None => (), @@ -35,16 +35,15 @@ pub fn open(context: &mut AppContext, backend: &mut TuiBackend) -> JoshutoResult change_directory::cd(path.as_path(), context)?; reload::soft_reload(context.tab_context_ref().index, context)?; } - Some(_) => { - let paths = curr_list.map_or_else(Vec::new, |s| s.get_selected_paths()); - let path = paths.get(0).ok_or_else(|| { - JoshutoError::new( - JoshutoErrorKind::Io(io::ErrorKind::NotFound), - String::from("No files selected"), - ) - })?; - - let files: Vec<&std::ffi::OsStr> = paths.iter().filter_map(|e| e.file_name()).collect(); + Some(entry) => { + let paths = curr_list.map_or_else(Vec::new, |s| s.iter_selected().cloned().collect()); + let path = if paths.is_empty() { + entry.file_path() + } else { + paths.get(0).unwrap().file_path() + }; + + let files: Vec<&str> = paths.iter().map(|e| e.file_name()).collect(); let options = get_options(path); let option = options.iter().find(|option| option.program_exists()); @@ -160,20 +159,25 @@ where } pub fn open_with_interactive(context: &mut AppContext, backend: &mut TuiBackend) -> JoshutoResult { - let paths = context + let mut paths = context .tab_context_ref() .curr_tab_ref() .curr_list_ref() - .map_or(vec![], |s| s.get_selected_paths()); + .map_or(vec![], |s| s.iter_selected().cloned().collect()); if paths.is_empty() { - return Err(JoshutoError::new( - JoshutoErrorKind::Io(io::ErrorKind::NotFound), - String::from("No files selected"), - )); + paths.push( + context + .tab_context_ref() + .curr_tab_ref() + .curr_list_ref() + .and_then(|s| s.curr_entry_ref()) + .unwrap() + .clone(), + ); } - let files: Vec<&std::ffi::OsStr> = paths.iter().filter_map(|e| e.file_name()).collect(); - let options = get_options(paths[0].as_path()); + let files: Vec<&str> = paths.iter().map(|e| e.file_name()).collect(); + let options = get_options(paths[0].file_path()); open_with_helper(context, backend, options, &files)?; Ok(()) @@ -188,7 +192,7 @@ pub fn open_with_index( .tab_context_ref() .curr_tab_ref() .curr_list_ref() - .map_or(vec![], |s| s.get_selected_paths()); + .map_or(vec![], |s| s.iter_selected().cloned().collect()); if paths.is_empty() { return Err(JoshutoError::new( @@ -196,8 +200,8 @@ pub fn open_with_index( String::from("No files selected"), )); } - let files: Vec<&std::ffi::OsStr> = paths.iter().filter_map(|e| e.file_name()).collect(); - let options = get_options(paths[0].as_path()); + let files: Vec<&str> = paths.iter().map(|e| e.file_name()).collect(); + let options = get_options(paths[0].file_path()); if index >= options.len() { return Err(JoshutoError::new( diff --git a/src/commands/show_tasks.rs b/src/commands/show_tasks.rs index ae2a43a..4b22860 100644 --- a/src/commands/show_tasks.rs +++ b/src/commands/show_tasks.rs @@ -21,29 +21,25 @@ pub fn show_tasks( if let Ok(event) = context.poll_event() { match event { AppEvent::Termion(key) => { - match key { - key => match keymap_t.task_view.get(&key) { - None => { - context - .message_queue_mut() - .push_info(format!("Unmapped input: {}", key.to_string())); + let key = key; + match keymap_t.task_view.get(&key) { + None => { + context + .message_queue_mut() + .push_info(format!("Unmapped input: {}", key.to_string())); + } + Some(CommandKeybind::SimpleKeybind(command)) => { + if let Command::ShowTasks = command { + break; } - Some(CommandKeybind::SimpleKeybind(command)) => match command { - Command::ShowTasks => break, - _ => {} - }, - Some(CommandKeybind::CompositeKeybind(m)) => { - let cmd = - process_event::get_input_while_composite(backend, context, m); + } + Some(CommandKeybind::CompositeKeybind(m)) => { + let cmd = process_event::get_input_while_composite(backend, context, m); - if let Some(command) = cmd { - match command { - Command::ShowTasks => break, - _ => {} - } - } + if let Some(Command::ShowTasks) = cmd { + break; } - }, + } } context.flush_event(); } |