diff options
Diffstat (limited to 'src/proclist.rs')
-rw-r--r-- | src/proclist.rs | 166 |
1 files changed, 62 insertions, 104 deletions
diff --git a/src/proclist.rs b/src/proclist.rs index b6926ca..8f4ca09 100644 --- a/src/proclist.rs +++ b/src/proclist.rs @@ -3,12 +3,12 @@ use std::sync::mpsc::Sender; use std::process::{Child, Command}; use std::os::unix::process::{CommandExt, ExitStatusExt}; use std::io::{BufRead, BufReader}; -use std::ffi::{OsString, OsStr}; -use std::os::unix::ffi::{OsStringExt, OsStrExt}; +use std::ffi::OsString; +use std::os::unix::ffi::OsStrExt; use termion::event::Key; use unicode_width::UnicodeWidthStr; -use osstrtools::OsStrTools; +use osstrtools::{OsStringTools, OsStrTools, OsStrConcat}; use async_value::Stale; use crate::listview::{Listable, ListView}; @@ -46,21 +46,27 @@ pub struct Cmd { impl Cmd { fn process(&mut self) -> Vec<OsString> { - let cmd = self.cmd.clone().split(&OsString::from(" ")); + // Split the string now, so inserted files aren't screwed up by substitutions + let cmd = self.cmd.split(" ") + .into_iter() + .map(|s| s.to_os_string()) + .collect(); + let cmd = self.substitute_cwd_files(cmd); let cmd = self.substitute_tab_files(cmd); let cmd = self.substitute_tab_paths(cmd); + cmd } - fn substitute_cwd_files(&mut self, cmd: Vec<OsString>) -> Vec<OsString> { - if self.cwd_files.is_none() { return cmd; } + fn perform_substitution(&self, + cmd: Vec<OsString>, + pat: &str, + files: Vec<File>) -> Vec<OsString> { + if !self.cmd.contains(pat) { return cmd; } - let cwd_pat = OsString::from("$s"); - let cwd_files = self.cwd_files - .take() - .unwrap() // There always is a file, even if just place holder - .iter() + let files = files + .into_iter() .map(|file| // strip out the cwd part to make path shorter file.strip_prefix(&self.cwd) @@ -69,55 +75,46 @@ impl Cmd { .escape_single_quote()) .collect::<Vec<OsString>>(); - cmd.iter() - .map(|part| part.splice_quoted_single(&cwd_pat, - cwd_files.clone())) - .flatten().collect() + cmd.into_iter() + .map(|part| { + // If this part isn't the pattern, just return it as is + match part != pat { + true => part, + false => part.splice(pat, + &files) + .assemble_with_sep_and_wrap(" ", "'") + } + }) + .collect() + } + + fn substitute_cwd_files(&mut self, cmd: Vec<OsString>) -> Vec<OsString> { + if self.cwd_files.is_none() { return cmd; } + let files = self.cwd_files.take().unwrap(); + self.perform_substitution(cmd, "$s", files) } fn substitute_tab_files(&mut self, cmd: Vec<OsString>) -> Vec<OsString> { if self.tab_files.is_none() { return cmd; } - let tab_files = self.tab_files.take().unwrap(); tab_files.into_iter() .enumerate() .fold(cmd, |cmd, (i, tab_files)| { - let tab_files_pat = OsString::from(format!("${}s", i)); - let tab_file_paths = tab_files.iter() - .map(|file| - // strip out the cwd part to make path shorter - file.strip_prefix(&self.cwd) - .into_os_string() - // escape single quotes so file names with them work - .escape_single_quote()) - .collect::<Vec<OsString>>(); - - cmd.iter().map(|part| { - part.splice_quoted_single(&tab_files_pat, - tab_file_paths.clone()) - }).flatten().collect() + let tab_files_pat = String::from(format!("${}s", i)); + self.perform_substitution(cmd, &tab_files_pat, tab_files) }) } fn substitute_tab_paths(&mut self, cmd: Vec<OsString>) -> Vec<OsString> { if self.tab_paths.is_none() { return cmd; } - let tab_paths = self.tab_paths.take().unwrap(); tab_paths.into_iter() .enumerate() .fold(cmd, |cmd, (i, tab_path)| { - let tab_path_pat = OsString::from(format!("${}", i)); - let tab_path = tab_path.strip_prefix(&self.cwd) - .into_os_string() - // escape single quotes so file names with them work - .escape_single_quote(); - - cmd.iter().map(|part| { - part.splice_quoted_single(&tab_path_pat, - vec![tab_path.clone()]) - }).flatten().collect() + let tab_path_pat = String::from(format!("${}", i)); + self.perform_substitution(cmd, &tab_path_pat, vec![tab_path]) }) } } @@ -218,34 +215,29 @@ impl ListView<Vec<Process>> { fn run_proc_subshell(&mut self, mut cmd: Cmd) -> HResult<()> { let shell = std::env::var("SHELL").unwrap_or("sh".into()); let home = crate::paths::home_path()?.into_os_string(); - let fg = cmd.cmd.as_bytes().ends_with(b"! "); + let fg = cmd.cmd.as_bytes().ends_with(b"!"); if fg { - // remove that last ! - let real_len = cmd.cmd.as_bytes().len() - 2; - cmd.cmd = OsString::from_vec(cmd.cmd.as_bytes()[0..real_len].to_vec()); - // workaround until split is fixed - cmd.cmd.push(" "); + // Remove that last ! + cmd.cmd = cmd.cmd.trim_end("!"); } - let cmd_args = cmd.process(); + let cmd_args = cmd.process().concat(" "); - let short = OsStr::from_bytes("~".as_bytes()); - let short_cmd = cmd_args - .concat() - .replace(&home, &short) - .replace(OsStr::from_bytes("'\''".as_bytes()), - OsStr::from_bytes("'".as_bytes())) - .replace(OsStr::from_bytes("\"".as_bytes()), - OsStr::from_bytes("".as_bytes())) + // Nicer for display + let short = "~"; + let short_cmd = cmd_args.clone() + .replace(&home, short) + .replace("'\''", "'") + .replace("\"", "") .to_string_lossy() .to_string(); - let shell_args = cmd_args.concat(); + let shell_args = cmd_args; let shell_args = vec![OsString::from("-c"), shell_args.clone()]; cmd.cmd = OsString::from(shell.clone()); - cmd.args = Some(shell_args.clone()); + cmd.args = Some(shell_args); cmd.short_cmd = Some(short_cmd); if !fg { @@ -279,8 +271,19 @@ impl ListView<Vec<Process>> { .stdout(std::process::Stdio::piped()) // Without this stderr would be separate which is no good for procview .pre_exec(|| { libc::dup2(1, 2); Ok(()) }) - .spawn()? + .spawn() }; + + let handle = match handle { + Ok(handle) => handle, + Err(e) => { + let msg = format!("Error! Failed to start process: {}", + e); + self.core.show_status(&msg)?; + return Err(e)?; + } + }; + let mut proc = Process { cmd: short_cmd, handle: Arc::new(Mutex::new(handle)), @@ -672,51 +675,6 @@ impl Widget for ProcView { } -trait ConcatOsString { - fn concat(&self) -> OsString; - fn concat_quoted(&self) -> OsString; -} - -impl ConcatOsString for Vec<OsString> { - fn concat(&self) -> OsString { - let len = self.len(); - self.iter().enumerate().fold(OsString::new(), |string, (i, part)| { - let mut string = string.into_vec(); - let mut space = " ".as_bytes().to_vec(); - let mut part = part.clone().into_vec(); - - string.append(&mut part); - - if i != len { - string.append(&mut space); - } - - OsString::from_vec(string) - }) - } - - fn concat_quoted(&self) -> OsString { - let len = self.len(); - self.iter().enumerate().fold(OsString::new(), |string, (i, part)| { - let mut string = string.into_vec(); - let mut space = " ".as_bytes().to_vec(); - let mut quote = "\"".as_bytes().to_vec(); - let mut part = part.clone().into_vec(); - - - string.append(&mut quote.clone()); - string.append(&mut part); - string.append(&mut quote); - - - if i+1 != len { - string.append(&mut space); - } - - OsString::from_vec(string) - }) - } -} use crate::keybind::*; |