From 8e0bead3be84687520405d97613fdc369c233b67 Mon Sep 17 00:00:00 2001 From: Andrew Frantz Date: Wed, 4 Sep 2024 20:22:00 -0400 Subject: [PATCH 1/6] feat: whitespace stripping --- src/lib.rs | 1 + src/wdl_util.rs | 121 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 src/wdl_util.rs diff --git a/src/lib.rs b/src/lib.rs index 9c992f1..eb24341 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ //! Crankshaft. pub mod engine; +pub mod wdl_util; /// Generates the `as_`, `into_`, and `unwrap_` methods commonly found on enum /// wrappers.o diff --git a/src/wdl_util.rs b/src/wdl_util.rs new file mode 100644 index 0000000..60b1448 --- /dev/null +++ b/src/wdl_util.rs @@ -0,0 +1,121 @@ +//! Module for utility functions. +//! +//! Currently that is whitespace stripping. + +fn remove_line_continuations(s: &str) -> String { + let mut result = String::new(); + let mut chars = s.chars(); + while let Some(c) = chars.next() { + if c == '\\' { + if let Some(next) = chars.next() { + if next == '\n' { + while let Some(ws) = chars.next() { + if ws == ' ' || ws == '\t' { + continue; + } else { + result.push(ws); + break; + } + } + } + } + } + result.push(c); + } + result +} + +fn calculate_leading_whitespace(s: &str) -> usize { + let mut min_leading_whitespace = usize::MAX; + let mut parsing_leading_whitespace = true; + let mut cur_char_index = 0; + let mut cur_line_index = 0; + s.chars().for_each(|c| match c { + ' ' | '\t' if parsing_leading_whitespace => cur_char_index += 1, + '\n' => { + parsing_leading_whitespace = true; + cur_line_index += 1; + cur_char_index = 0; + } + _ => { + parsing_leading_whitespace = false; + if cur_char_index < min_leading_whitespace { + min_leading_whitespace = cur_char_index; + } + cur_char_index += 1; + } + }); + if min_leading_whitespace == usize::MAX { + 0 + } else { + min_leading_whitespace + } +} + +/// Strips leading whitespace from a string. +pub fn strip_leading_whitespace(s: &str, command: bool) -> String { + let s = if command { + remove_line_continuations(s) + } else { + s.to_string() + }; + let leading_whitespace = calculate_leading_whitespace(&s); + let result = s + .lines() + .map(|line| { + if line.len() >= leading_whitespace { + &line[leading_whitespace..] + } else { + "" + } + }) + .collect::>() + .join("\n"); + result +} + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_remove_line_continuations() { + let input = "first line \ + still first line +second line"; + let expected = "first line still first line\nsecond line"; + assert_eq!(remove_line_continuations(input), expected); + } + + #[test] + fn test_calculate_leading_whitespace() { + let input = " first line is indented 4 spaces + second line is indented 8 spaces + third line is indented 4 spaces"; + assert_eq!(calculate_leading_whitespace(input), 4); + let input = " first line is indented 4 spaces + \t \t second line is indented with a mix of 8 spaces and tabs +\t\t\t\tfourth line is indented 4 tabs"; + assert_eq!(calculate_leading_whitespace(input), 4); + } + + #[test] + fn test_strip_leading_whitespace() { + let input = " first line is indented 4 spaces + second line is indented 8 spaces + third line is indented 4 spaces"; + let expected = "first line is indented 4 spaces\n second line is indented 8 spaces\nthird line is indented 4 spaces"; + assert_eq!(strip_leading_whitespace(input, false), expected); + } + + #[test] + fn test_strip_leading_whitespace_with_line_continuations() { + let input = " first line is indented 4 spaces \ + still first line + second line is indented 8 spaces + third line is indented 4 spaces"; + let expected = "first line is indented 4 spaces still first line\n second line is indented 8 spaces\nthird line is indented 4 spaces"; + assert_eq!(strip_leading_whitespace(input, true), expected); + } +} \ No newline at end of file From 54e864e9b74538c9da5e6129b3591da11afc8045 Mon Sep 17 00:00:00 2001 From: Andrew Frantz Date: Wed, 4 Sep 2024 20:24:05 -0400 Subject: [PATCH 2/6] fix: bool negation --- src/wdl_util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wdl_util.rs b/src/wdl_util.rs index 60b1448..65f18a0 100644 --- a/src/wdl_util.rs +++ b/src/wdl_util.rs @@ -54,7 +54,7 @@ fn calculate_leading_whitespace(s: &str) -> usize { /// Strips leading whitespace from a string. pub fn strip_leading_whitespace(s: &str, command: bool) -> String { - let s = if command { + let s = if !command { remove_line_continuations(s) } else { s.to_string() From d5c4337f46f01efb10a084d2395bb9249f288ffe Mon Sep 17 00:00:00 2001 From: Andrew Frantz Date: Wed, 4 Sep 2024 20:27:07 -0400 Subject: [PATCH 3/6] chore: cargo fmt --- src/wdl_util.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/wdl_util.rs b/src/wdl_util.rs index 65f18a0..fe1e066 100644 --- a/src/wdl_util.rs +++ b/src/wdl_util.rs @@ -74,7 +74,6 @@ pub fn strip_leading_whitespace(s: &str, command: bool) -> String { result } - #[cfg(test)] mod tests { use super::*; @@ -118,4 +117,4 @@ second line"; let expected = "first line is indented 4 spaces still first line\n second line is indented 8 spaces\nthird line is indented 4 spaces"; assert_eq!(strip_leading_whitespace(input, true), expected); } -} \ No newline at end of file +} From 8f43cdb8dbe39cc025541d30de39a4bee82df9ca Mon Sep 17 00:00:00 2001 From: Andrew Frantz Date: Thu, 5 Sep 2024 10:50:03 -0400 Subject: [PATCH 4/6] Update wdl_util.rs --- src/wdl_util.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/wdl_util.rs b/src/wdl_util.rs index fe1e066..d5b9cc3 100644 --- a/src/wdl_util.rs +++ b/src/wdl_util.rs @@ -54,13 +54,13 @@ fn calculate_leading_whitespace(s: &str) -> usize { /// Strips leading whitespace from a string. pub fn strip_leading_whitespace(s: &str, command: bool) -> String { - let s = if !command { - remove_line_continuations(s) - } else { + let s_owned = if command { s.to_string() + } else { + remove_line_continuations(s) }; - let leading_whitespace = calculate_leading_whitespace(&s); - let result = s + let leading_whitespace = calculate_leading_whitespace(&s_owned); + let result = s_owned .lines() .map(|line| { if line.len() >= leading_whitespace { @@ -100,21 +100,21 @@ second line"; } #[test] - fn test_strip_leading_whitespace() { - let input = " first line is indented 4 spaces + fn test_strip_leading_whitespace_not_in_command() { + let input = " first line is indented 4 spaces \ + still first line second line is indented 8 spaces third line is indented 4 spaces"; - let expected = "first line is indented 4 spaces\n second line is indented 8 spaces\nthird line is indented 4 spaces"; + let expected = "first line is indented 4 spaces still first line\n second line is indented 8 spaces\nthird line is indented 4 spaces"; assert_eq!(strip_leading_whitespace(input, false), expected); } #[test] - fn test_strip_leading_whitespace_with_line_continuations() { - let input = " first line is indented 4 spaces \ - still first line + fn test_strip_leading_whitespace_in_command() { + let input = " first line is indented 4 spaces and trails a backslash \\ second line is indented 8 spaces third line is indented 4 spaces"; - let expected = "first line is indented 4 spaces still first line\n second line is indented 8 spaces\nthird line is indented 4 spaces"; + let expected = "first line is indented 4 spaces and trails a backslash \\\n second line is indented 8 spaces\nthird line is indented 4 spaces"; assert_eq!(strip_leading_whitespace(input, true), expected); } } From 10211413ef4d0ff33b931edcb9857c1d11d668e4 Mon Sep 17 00:00:00 2001 From: Andrew Frantz Date: Thu, 5 Sep 2024 10:58:53 -0400 Subject: [PATCH 5/6] Update wdl_util.rs --- src/wdl_util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wdl_util.rs b/src/wdl_util.rs index d5b9cc3..aac6054 100644 --- a/src/wdl_util.rs +++ b/src/wdl_util.rs @@ -9,7 +9,7 @@ fn remove_line_continuations(s: &str) -> String { if c == '\\' { if let Some(next) = chars.next() { if next == '\n' { - while let Some(ws) = chars.next() { + for ws in chars.by_ref() { if ws == ' ' || ws == '\t' { continue; } else { From c94b8aa42685f54647bd43a2bf4c158d7d201905 Mon Sep 17 00:00:00 2001 From: Andrew Frantz Date: Thu, 5 Sep 2024 12:41:05 -0400 Subject: [PATCH 6/6] Update wdl_util.rs --- src/wdl_util.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/wdl_util.rs b/src/wdl_util.rs index aac6054..04a9644 100644 --- a/src/wdl_util.rs +++ b/src/wdl_util.rs @@ -2,6 +2,7 @@ //! //! Currently that is whitespace stripping. +/// Removes line continuations from a string. fn remove_line_continuations(s: &str) -> String { let mut result = String::new(); let mut chars = s.chars(); @@ -25,6 +26,7 @@ fn remove_line_continuations(s: &str) -> String { result } +/// Calculates the leading whitespace of a string. fn calculate_leading_whitespace(s: &str) -> usize { let mut min_leading_whitespace = usize::MAX; let mut parsing_leading_whitespace = true;