From 0766964a90bef03df35de35d672995a385fc7172 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Fri, 7 Jan 2022 18:29:10 -0500 Subject: implement escaping characters --- src/parse.rs | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 103 insertions(+), 6 deletions(-) (limited to 'src/parse.rs') diff --git a/src/parse.rs b/src/parse.rs index 9d0d230..72de364 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -125,19 +125,35 @@ impl WordOrRedirect { word.as_rule(), Rule::bareword | Rule::single_string | Rule::double_string )); + let interpolate = matches!( + word.as_rule(), + Rule::bareword | Rule::double_string + ); word_str.push_str(word.as_str()); - Self::Redirect(Redirect::parse(&word_str)) + if interpolate { + word_str = strip_escape(&word_str); + } else { + word_str = strip_basic_escape(&word_str); + } + Self::Redirect(Redirect::parse(&strip_escape(&word_str))) } else { assert!(matches!( word.as_rule(), Rule::bareword | Rule::single_string | Rule::double_string )); + let interpolate = matches!( + word.as_rule(), + Rule::bareword | Rule::double_string + ); + let mut word_str = word.as_str().to_string(); + if interpolate { + word_str = strip_escape(&word_str); + } else { + word_str = strip_basic_escape(&word_str); + } Self::Word(Word { - word: word.as_str().to_string(), - interpolate: matches!( - word.as_rule(), - Rule::bareword | Rule::double_string - ), + word: word_str, + interpolate, quoted: matches!( word.as_rule(), Rule::single_string | Rule::double_string @@ -277,6 +293,44 @@ impl Commands { } } +fn strip_escape(s: &str) -> String { + let mut new = String::new(); + let mut escape = false; + for c in s.chars() { + if escape { + new.push(c); + escape = false; + } else { + match c { + '\\' => escape = true, + _ => new.push(c), + } + } + } + new +} + +fn strip_basic_escape(s: &str) -> String { + let mut new = String::new(); + let mut escape = false; + for c in s.chars() { + if escape { + match c { + '\\' | '\'' => {} + _ => new.push('\\'), + } + new.push(c); + escape = false; + } else { + match c { + '\\' => escape = true, + _ => new.push(c), + } + } + } + new +} + #[derive(Debug)] pub struct Error { input: String, @@ -557,4 +611,47 @@ mod test { ) ); } + + #[test] + fn test_escape() { + parse_eq!( + "foo\\ bar", + c!("foo\\ bar", p!("foo\\ bar", e!(w!("foo bar")))) + ); + parse_eq!( + "'foo\\ bar'", + c!( + "'foo\\ bar'", + p!("'foo\\ bar'", e!(w!("foo\\ bar", false, true))) + ) + ); + parse_eq!( + "\"foo\\ bar\"", + c!( + "\"foo\\ bar\"", + p!("\"foo\\ bar\"", e!(w!("foo bar", true, true))) + ) + ); + parse_eq!( + "\"foo\\\"bar\"", + c!( + "\"foo\\\"bar\"", + p!("\"foo\\\"bar\"", e!(w!("foo\"bar", true, true))) + ) + ); + parse_eq!( + "'foo\\'bar\\\\'", + c!( + "'foo\\'bar\\\\'", + p!("'foo\\'bar\\\\'", e!(w!("foo'bar\\", false, true))) + ) + ); + parse_eq!( + "foo > bar\\ baz", + c!( + "foo > bar\\ baz", + p!("foo > bar\\ baz", e!(w!("foo") ; r!(1, "bar baz", Out))) + ) + ); + } } -- cgit v1.2.3-54-g00ecf