From ce85b9716df5e1ea804994202687f19cd711ae1b Mon Sep 17 00:00:00 2001 From: ath3 <45574139+ath3@users.noreply.github.com> Date: Tue, 21 Jun 2022 18:48:01 +0200 Subject: [PATCH] Enable shellwords for Windows (with escaping disabled) (#2767) --- helix-core/src/shellwords.rs | 52 ++++++++++++++++++++++++++------ helix-term/src/commands/typed.rs | 10 +----- 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/helix-core/src/shellwords.rs b/helix-core/src/shellwords.rs index 13f6f3e99..4323039ab 100644 --- a/helix-core/src/shellwords.rs +++ b/helix-core/src/shellwords.rs @@ -24,9 +24,13 @@ pub fn shellwords(input: &str) -> Vec> { state = match state { Normal => match c { '\\' => { - escaped.push_str(&input[start..i]); - start = i + 1; - NormalEscaped + if cfg!(unix) { + escaped.push_str(&input[start..i]); + start = i + 1; + NormalEscaped + } else { + Normal + } } '"' => { end = i; @@ -45,9 +49,13 @@ pub fn shellwords(input: &str) -> Vec> { NormalEscaped => Normal, Quoted => match c { '\\' => { - escaped.push_str(&input[start..i]); - start = i + 1; - QuoteEscaped + if cfg!(unix) { + escaped.push_str(&input[start..i]); + start = i + 1; + QuoteEscaped + } else { + Quoted + } } '\'' => { end = i; @@ -58,9 +66,13 @@ pub fn shellwords(input: &str) -> Vec> { QuoteEscaped => Quoted, Dquoted => match c { '\\' => { - escaped.push_str(&input[start..i]); - start = i + 1; - DquoteEscaped + if cfg!(unix) { + escaped.push_str(&input[start..i]); + start = i + 1; + DquoteEscaped + } else { + Dquoted + } } '"' => { end = i; @@ -99,6 +111,25 @@ mod test { use super::*; #[test] + #[cfg(windows)] + fn test_normal() { + let input = r#":o single_word twó wörds \three\ \"with\ escaping\\"#; + let result = shellwords(input); + let expected = vec![ + Cow::from(":o"), + Cow::from("single_word"), + Cow::from("twó"), + Cow::from("wörds"), + Cow::from("\\three\\"), + Cow::from("\\"), + Cow::from("with\\ escaping\\\\"), + ]; + // TODO test is_owned and is_borrowed, once they get stabilized. + assert_eq!(expected, result); + } + + #[test] + #[cfg(unix)] fn test_normal() { let input = r#":o single_word twó wörds \three\ \"with\ escaping\\"#; let result = shellwords(input); @@ -114,6 +145,7 @@ mod test { } #[test] + #[cfg(unix)] fn test_quoted() { let quoted = r#":o 'single_word' 'twó wörds' '' ' ''\three\' \"with\ escaping\\' 'quote incomplete"#; @@ -129,6 +161,7 @@ mod test { } #[test] + #[cfg(unix)] fn test_dquoted() { let dquoted = r#":o "single_word" "twó wörds" "" " ""\three\' \"with\ escaping\\" "dquote incomplete"#; let result = shellwords(dquoted); @@ -143,6 +176,7 @@ mod test { } #[test] + #[cfg(unix)] fn test_mixed() { let dquoted = r#":o single_word 'twó wörds' "\three\' \"with\ escaping\\""no space before"'and after' $#%^@ "%^&(%^" ')(*&^%''a\\\\\b' '"#; let result = shellwords(dquoted); diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs index ae3e63af9..58256c7d4 100644 --- a/helix-term/src/commands/typed.rs +++ b/helix-term/src/commands/typed.rs @@ -1802,15 +1802,7 @@ pub fn command_mode(cx: &mut Context) { // Handle typable commands if let Some(cmd) = typed::TYPABLE_COMMAND_MAP.get(parts[0]) { - let args = if cfg!(unix) { - shellwords::shellwords(input) - } else { - // Windows doesn't support POSIX, so fallback for now - parts - .into_iter() - .map(|part| part.into()) - .collect::>() - }; + let args = shellwords::shellwords(input); if let Err(e) = (cmd.fun)(cx, &args[1..], event) { cx.editor.set_error(format!("{}", e));