summaryrefslogtreecommitdiffstats
path: root/src/file_browser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/file_browser.rs')
-rw-r--r--src/file_browser.rs182
1 files changed, 181 insertions, 1 deletions
diff --git a/src/file_browser.rs b/src/file_browser.rs
index 408b0c7..1ca9046 100644
--- a/src/file_browser.rs
+++ b/src/file_browser.rs
@@ -1,10 +1,12 @@
use termion::event::Key;
use pathbuftools::PathBufTools;
+use osstrtools::OsStrTools;
use std::io::Write;
use std::sync::{Arc, Mutex, RwLock};
use std::path::PathBuf;
use std::ffi::OsString;
+use std::os::unix::ffi::OsStringExt;
use std::collections::HashSet;
use crate::files::{File, Files};
@@ -437,6 +439,19 @@ impl FileBrowser {
Ok(())
}
+ pub fn main_widget_goto_wait(&mut self, dir :&File) -> HResult<()> {
+ self.main_widget_goto(&dir)?;
+
+ // replace this with on_ready_mut() later
+ let pause = std::time::Duration::from_millis(10);
+ while self.main_widget().is_err() {
+ self.main_async_widget_mut()?.refresh().log();
+ std::thread::sleep(pause);
+ }
+
+ Ok(())
+ }
+
pub fn main_widget_goto(&mut self, dir: &File) -> HResult<()> {
self.cache_files().log();
@@ -825,6 +840,170 @@ impl FileBrowser {
Ok(())
}
+ fn external_select(&mut self) -> HResult<()> {
+ let shell = std::env::var("SHELL").unwrap_or("bash".into());
+ let cmd = self.core
+ .config.read()?
+ .get()?
+ .select_cmd
+ .clone();
+
+ self.core.get_sender().send(Events::InputEnabled(false))?;
+ self.core.screen.drop_screen();
+ self.preview_widget().map(|preview| preview.cancel_animation()).log();
+
+ let cmd_result = std::process::Command::new(shell)
+ .arg("-c")
+ .arg(&cmd)
+ .stdin(std::process::Stdio::inherit())
+ .stdout(std::process::Stdio::piped())
+ .stderr(std::process::Stdio::inherit())
+ .output();
+
+ self.core.screen.reset_screen().log();
+ self.clear().log();
+ self.core.get_sender().send(Events::InputEnabled(true))?;
+
+ match cmd_result {
+ Ok(cmd_result) => {
+ if cmd_result.status.success() {
+ let cwd = &self.cwd.path;
+
+ let paths = OsString::from_vec(cmd_result.stdout)
+ .split_lines()
+ .iter()
+ .map(|output| {
+ let path = PathBuf::from(output);
+ if path.is_absolute() {
+ path
+ } else {
+ cwd.join(path)
+ }
+ })
+ .collect::<Vec<PathBuf>>();
+
+ if paths.len() == 1 {
+ let path = &paths[0];
+ if path.exists() {
+ if path.is_dir() {
+ let dir = File::new_from_path(&path, None)?;
+
+ self.main_widget_goto(&dir).log();
+ } else if path.is_file() {
+ let file = File::new_from_path(&path, None)?;
+ let dir = file.parent_as_file()?;
+
+ self.main_widget_goto_wait(&dir).log();
+
+ self.main_widget_mut()?.select_file(&file);
+ }
+ } else {
+ let msg = format!("Can't access path: {}!",
+ path.to_string_lossy());
+ self.show_status(&msg).log();
+ }
+ } else {
+ let mut last_file = None;
+ for file_path in paths {
+ if !file_path.exists() {
+ let msg = format!("Can't find: {}",
+ file_path .to_string_lossy());
+ self.show_status(&msg).log();
+ continue;
+ }
+
+ let dir_path = file_path.parent()?;
+ if self.cwd.path != dir_path {
+ let file_dir = File::new_from_path(&dir_path, None);
+
+ self.main_widget_goto_wait(&file_dir?).log();
+ }
+
+ self.main_widget_mut()?
+ .content
+ .find_file_with_path(&file_path)
+ .map(|file| {
+ file.toggle_selection();
+ last_file = Some(file.clone());
+ });
+ }
+
+ self.main_widget_mut().map(|w| {
+ last_file.map(|f| w.select_file(&f));
+ w.content.set_dirty();
+ }).log();
+ }
+ } else {
+ self.show_status("External program failed!").log();
+ }
+ }
+ Err(_) => self.show_status("Can't run external program!").log()
+ }
+
+ Ok(())
+ }
+
+ fn external_cd(&mut self) -> HResult<()> {
+ let shell = std::env::var("SHELL").unwrap_or("bash".into());
+ let cmd = self.core
+ .config.read()?
+ .get()?
+ .cd_cmd
+ .clone();
+
+ self.core.get_sender().send(Events::InputEnabled(false))?;
+ self.core.screen.drop_screen();
+ self.preview_widget().map(|preview| preview.cancel_animation()).log();
+
+ let cmd_result = std::process::Command::new(shell)
+ .arg("-c")
+ .arg(cmd)
+ .stdin(std::process::Stdio::inherit())
+ .stdout(std::process::Stdio::piped())
+ .stderr(std::process::Stdio::inherit())
+ .output();
+
+ self.core.screen.reset_screen().log();
+ self.clear().log();
+ self.core.get_sender().send(Events::InputEnabled(true))?;
+
+ match cmd_result {
+ Ok(cmd_result) => {
+ if cmd_result.status.success() {
+ let cwd = &self.cwd.path;
+
+ let path_string = OsString::from_vec(cmd_result.stdout);
+ let path_string = path_string.trim_end_newlines();
+ let path = PathBuf::from(path_string);
+ let path = if path.is_absolute() {
+ path
+ } else {
+ cwd.join(path)
+ };
+
+ if path.exists() {
+ if path.is_dir() {
+ let dir = File::new_from_path(&path, None)?;
+ self.main_widget_goto(&dir).log();
+ }
+ else {
+ let msg = format!("Can't access path: {}!",
+ path.to_string_lossy());
+ self.show_status(&msg).log();
+ }
+
+ } else {
+ self.show_status("External program failed!").log();
+ }
+ }
+ }
+ Err(_) => self.show_status("Can't run external program!").log()
+ }
+
+ Ok(())
+ }
+
+
fn exec_cmd(&mut self,
tab_dirs: Vec<File>,
tab_files: Vec<Vec<File>>) -> HResult<()> {
@@ -1031,6 +1210,8 @@ impl Widget for FileBrowser {
fn on_key(&mut self, key: Key) -> HResult<()> {
match key {
+ Key::Alt(' ') => self.external_select()?,
+ Key::Alt('/') => self.external_cd()?,
Key::Char('/') => { self.turbo_cd()?; },
Key::Char('q') => HError::quit()?,
Key::Char('Q') => { self.quit_with_dir()?; },
@@ -1040,7 +1221,6 @@ impl Widget for FileBrowser {
Key::Char('-') => { self.goto_prev_cwd()?; },
Key::Char('`') => { self.goto_bookmark()?; },
Key::Char('m') => { self.add_bookmark()?; },
-
Key::Char('w') => { self.show_procview()?; },
Key::Char('g') => self.show_log()?,
Key::Char('z') => self.run_subshell()?,