From 010ddc4795123987bdef3b5a60240203e7f11d01 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Tue, 26 Jan 2021 21:57:56 +0100 Subject: [PATCH] =?UTF-8?q?More=20straightforward=20pretty=20printing=20te?= =?UTF-8?q?sts=20=F0=9F=A7=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/syntax/expr.rs | 60 ++----------------------------- src/syntax/mod.rs | 89 +++++++++++++++++++++++++++++++++++++++++++++- src/syntax/node.rs | 36 ++----------------- 3 files changed, 93 insertions(+), 92 deletions(-) diff --git a/src/syntax/expr.rs b/src/syntax/expr.rs index 7e636d3d4..ea7625113 100644 --- a/src/syntax/expr.rs +++ b/src/syntax/expr.rs @@ -64,6 +64,8 @@ impl Pretty for Expr { Self::Angle(v, u) => write!(p, "{}{}", v, u).unwrap(), Self::Percent(v) => write!(p, "{}%", v).unwrap(), Self::Color(v) => write!(p, "{}", v).unwrap(), + // TODO: Debug escapes a bit more than we want (e.g. apostrophes). + // We probably need to do the escaping ourselves. Self::Str(v) => write!(p, "{:?}", &v).unwrap(), Self::Array(v) => v.pretty(p), Self::Dict(v) => v.pretty(p), @@ -543,61 +545,3 @@ impl Pretty for ExprFor { self.body.v.pretty(p); } } -#[cfg(test)] -mod tests { - use super::super::tests::test_pretty; - - #[test] - fn test_pretty_print_chaining() { - // All equivalent. - test_pretty("[v [[f]]]", "[v | f]"); - test_pretty("[v][[f]]", "[v | f]"); - test_pretty("[v | f]", "[v | f]"); - } - - #[test] - fn test_pretty_print_expressions() { - // Unary and binary operations. - test_pretty("{}", "{}"); - test_pretty("{1 +}", "{1}"); - test_pretty("{1++1}", "{1 + +1}"); - test_pretty("{+-1}", "{+-1}"); - test_pretty("{1 + func(-2)}", "{1 + func(-2)}"); - test_pretty("{1+2*3}", "{1 + 2 * 3}"); - test_pretty("{(1+2)*3}", "{(1 + 2) * 3}"); - - // Array. - test_pretty("(-5,)", "(-5,)"); - test_pretty("(1, 2, 3)", "(1, 2, 3)"); - - // Dictionary. - test_pretty("{(:)}", "{(:)}"); - test_pretty("{(percent: 5%)}", "{(percent: 5%)}"); - - // Content expression. - test_pretty("[v [[f]], 1]", "[v [[f]], 1]"); - - // Parens and blocks. - test_pretty("{(1)}", "{(1)}"); - test_pretty("{{1}}", "{{1}}"); - - // Control flow. - test_pretty("#let x = 1+2", "#let x = 1 + 2"); - test_pretty("#if x [y] #else [z]", "#if x [y] #else [z]"); - test_pretty("#for x #in y {z}", "#for x #in y {z}"); - } - - #[test] - fn test_pretty_print_literals() { - test_pretty("{none}", "{none}"); - test_pretty("{true}", "{true}"); - test_pretty("{25}", "{25}"); - test_pretty("{2.50}", "{2.5}"); - test_pretty("{1e2}", "{100.0}"); - test_pretty("{12pt}", "{12pt}"); - test_pretty("{90.0deg}", "{90deg}"); - test_pretty("{50%}", "{50%}"); - test_pretty("{#fff}", "{#ffffff}"); - test_pretty(r#"{"hi\n"}"#, r#"{"hi\n"}"#); - } -} diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index 22f51d826..fa1308ded 100644 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -31,7 +31,7 @@ mod tests { use crate::pretty::pretty; #[track_caller] - pub fn test_pretty(src: &str, exp: &str) { + fn test(src: &str, exp: &str) { let tree = parse(src).output; let found = pretty(&tree); if exp != found { @@ -41,4 +41,91 @@ mod tests { panic!("test failed"); } } + + #[track_caller] + fn roundtrip(src: &str) { + test(src, src); + } + + #[test] + fn test_pretty_print_node() { + // Basic text and markup. + roundtrip("*"); + roundtrip("_"); + roundtrip(" "); + roundtrip("\\ "); + roundtrip("\n\n"); + roundtrip("hi"); + + // Heading. + roundtrip("# *Ok*"); + + // Raw. + roundtrip("`lang 1`"); + test("`` hi``", "`hi`"); + test("`` ` ``", "```"); + } + + #[test] + fn test_pretty_print_expr() { + // Basic expressions. + roundtrip("{none}"); + roundtrip("{hi}"); + roundtrip("{true}"); + roundtrip("{10}"); + roundtrip("{3.14}"); + roundtrip("{10pt}"); + roundtrip("{14.1deg}"); + roundtrip("{20%}"); + roundtrip("{#abcdef}"); + roundtrip(r#"{"hi"}"#); + test(r#"{"let's go"}"#, r#"{"let\'s go"}"#); + + // Arrays. + roundtrip("{()}"); + roundtrip("{(1)}"); + roundtrip("{(1, 2, 3)}"); + + // Dictionaries. + roundtrip("{(:)}"); + roundtrip("{(key: value)}"); + roundtrip("{(a: 1, b: 2)}"); + + // Templates. + roundtrip("{[]}"); + roundtrip("{[*Ok*]}"); + roundtrip("{[[f]]}"); + + // Groups. + roundtrip("{(1)}"); + + // Blocks. + roundtrip("{}"); + roundtrip("{1}"); + roundtrip("{ #let x = 1; x += 2; x + 1 }"); + + // Operators. + roundtrip("{-x}"); + roundtrip("{not true}"); + roundtrip("{1 + 3}"); + + // Parenthesized calls. + roundtrip("{v()}"); + roundtrip("{v(1)}"); + roundtrip("{v(a: 1, b)}"); + + // Bracket calls. + roundtrip("[v]"); + roundtrip("[v 1]"); + roundtrip("[v 1, 2][*Ok*]"); + roundtrip("[v 1 | f 2]"); + roundtrip("{[[v]]}"); + test("[v 1, [[f 2]]]", "[v 1 | f 2]"); + test("[v 1, 2][[f 3]]", "[v 1, 2 | f 3]"); + + // Keywords. + roundtrip("#let x = 1 + 2"); + roundtrip("#if x [y] #else [z]"); + roundtrip("#for x #in y {z}"); + } } diff --git a/src/syntax/node.rs b/src/syntax/node.rs index 5c4c22b7d..db3b65108 100644 --- a/src/syntax/node.rs +++ b/src/syntax/node.rs @@ -150,40 +150,10 @@ impl Pretty for NodeRaw { p.push_str(&lang); p.push_str(" "); } - // TODO: Technically, we should handle backticks in the lines - // by wrapping with more backticks and possibly adding space - // before the first or after the last line. + // TODO: Technically, we should handle backticks in the lines by + // wrapping with more backticks, and we should add space before the + // first and/or after the last line if necessary. p.join(&self.lines, "\n", |line, p| p.push_str(line)); p.push_str("`"); } } - -#[cfg(test)] -mod tests { - use super::super::tests::test_pretty; - - #[test] - fn test_pretty_print_bracket_calls() { - // Top-level call expression formatted as bracket call. - test_pretty("[v]", "[v]"); - - // Blocks are preserved. - test_pretty("{v()}", "{v()}"); - test_pretty("{[[v]]}", "{[[v]]}"); - } - - #[test] - fn test_pretty_print_nodes() { - // Basic text and markup. - test_pretty(r"*Hi_\", r"*Hi_\"); - - // Whitespace. - test_pretty(" ", " "); - test_pretty("\n\n\n", "\n\n"); - - // Heading and raw. - test_pretty("# Ok", "# Ok"); - test_pretty("``\none\ntwo\n``", "`one\ntwo`"); - test_pretty("`lang one\ntwo`", "`lang one\ntwo`"); - } -}