diff options
author | Jovansonlee Cesar <ivanceras@gmail.com> | 2020-11-04 16:23:14 +0800 |
---|---|---|
committer | Jovansonlee Cesar <ivanceras@gmail.com> | 2020-11-04 16:23:14 +0800 |
commit | 10fe6ee719747d9652aa56736e10d31d7ddce3c6 (patch) | |
tree | 591f8662eb7b39d6d8528d978940d09634e6b9af | |
parent | 146d1d5eb09e1d192a4a59b717bab82b2b204398 (diff) |
Add escape_line for escaping non-drawing characters with double quotes
-rw-r--r-- | svgbob/src/buffer/cell_buffer.rs | 42 | ||||
-rw-r--r-- | svgbob/src/util.rs | 37 |
2 files changed, 78 insertions, 1 deletions
diff --git a/svgbob/src/buffer/cell_buffer.rs b/svgbob/src/buffer/cell_buffer.rs index 4383cfc..fc1afd0 100644 --- a/svgbob/src/buffer/cell_buffer.rs +++ b/svgbob/src/buffer/cell_buffer.rs @@ -38,6 +38,7 @@ pub struct CellBuffer { /// .class { styles } /// ``` css_styles: Vec<(String, String)>, + escaped_text: Vec<(Cell, String)>, } impl Deref for CellBuffer { @@ -59,6 +60,7 @@ impl CellBuffer { CellBuffer { map: BTreeMap::new(), css_styles: vec![], + escaped_text: vec![], } } @@ -426,6 +428,28 @@ impl CellBuffer { )], ) } + + /// returns a (Cell, escaped string), and the strings that are not part of the escape string + fn escape_line(line: usize, raw: &str) -> (Vec<(Cell, String)>, String) { + let mut no_escaped_text = String::new(); + + let mut index = 0; + let mut escaped_text = vec![]; + let input_chars: Vec<char> = raw.chars().collect(); + let char_locs = parser::line_parse() + .parse(&input_chars) + .expect("should parse"); + for (start, end) in char_locs.iter() { + let escaped = raw[*start + 1..*end].to_string(); + let cell = Cell::new(*start as i32, line as i32); + escaped_text.push((cell, escaped)); + + no_escaped_text.push_str(&raw[index..*start]); + no_escaped_text.push_str(&" ".repeat(end + 1 - start)); + index = end + 1; + } + (escaped_text, no_escaped_text) + } } impl fmt::Display for CellBuffer { @@ -479,6 +503,24 @@ mod tests { use super::*; #[test] + fn test_escape_line() { + let raw = r#"The "qu/i/ck" brown "fox\"s" jumps over the lazy "do|g""#; + let ex2 = r#"The brown jumps over the lazy "#; + let (escaped, unescaped) = CellBuffer::escape_line(0, raw); + println!("escaped: {:#?}", escaped); + println!("unescaped: {}", unescaped); + assert_eq!( + vec![ + (Cell::new(4, 0), "qu/i/ck".to_string()), + (Cell::new(20, 0), r#"fox\"s"#.to_string()), + (Cell::new(49, 0), "do|g".to_string()) + ], + escaped + ); + assert_eq!(ex2, unescaped); + } + + #[test] fn test_simple_adjacents() { let art = r#" .. ._. diff --git a/svgbob/src/util.rs b/svgbob/src/util.rs index e05b038..2a50fab 100644 --- a/svgbob/src/util.rs +++ b/svgbob/src/util.rs @@ -72,12 +72,17 @@ pub fn is_collinear(a: &Point, b: &Point, c: &Point) -> bool { } pub fn pad(v: f32) -> f32 { - if v > 0.0 { v.ceil() } else { v.floor() } + if v > 0.0 { + v.ceil() + } else { + v.floor() + } } /// this is parser module which provides parsing for identifier for /// extracting the css tag of inside of a shape fragment pub mod parser { + use crate::Cell; use pom::parser::{call, end, is_a, list, none_of, one_of, sym, tag, Parser}; use std::iter::FromIterator; @@ -224,11 +229,41 @@ pub mod parser { css_legend_with_padding().parse(input) } + fn escape_string<'a>() -> pom::parser::Parser<'a, char, (usize, usize)> { + let escape_sequence = sym('\\') * sym('"'); //escape sequence \" + let char_string = escape_sequence | none_of("\""); + let escaped_string_end = sym('"') * char_string.repeat(0..).pos() - sym('"'); + none_of("\"").repeat(0..).pos() + escaped_string_end - none_of("\"").repeat(0..).discard() + } + + pub(crate) fn line_parse<'a>() -> pom::parser::Parser<'a, char, Vec<(usize, usize)>> { + escape_string().repeat(0..) + } + #[cfg(test)] mod tests { use super::*; #[test] + fn test_escaped_string() { + let raw = r#"The "qu/i/ck" brown "fox\"s" jumps over the lazy "do|g""#; + let input_chars: Vec<char> = raw.chars().collect(); + let char_locs = line_parse().parse(&input_chars).expect("should parse"); + println!("output3: {:?}", char_locs); + let mut escaped = vec![]; + let mut cleaned = vec![]; + for (start, end) in char_locs.iter() { + escaped.push(&raw[*start..=*end]); + cleaned.push(&raw[*start + 1..*end]); + } + println!("{:#?}", escaped); + let expected = vec![r#""qu/i/ck""#, r#""fox\"s""#, r#""do|g""#]; + assert_eq!(expected, escaped); + let expected_cleaned = vec![r#"qu/i/ck"#, r#"fox\"s"#, r#"do|g"#]; + assert_eq!(expected_cleaned, cleaned); + } + + #[test] fn test_css_styles() { let input = "{fill:blue; stroke:red;}"; let input_chars: Vec<char> = input.chars().collect(); |