mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Remove template pretty printing
Was buggy and pretty useless anyway since it couldn't peek into function templates.
This commit is contained in:
parent
5afb42ad89
commit
edff2ae680
163
src/pretty.rs
163
src/pretty.rs
@ -17,37 +17,12 @@ where
|
|||||||
p.finish()
|
p.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pretty print an item with a expression map and return the resulting string.
|
|
||||||
pub fn pretty_with_map<T>(item: &T, map: &ExprMap) -> String
|
|
||||||
where
|
|
||||||
T: PrettyWithMap + ?Sized,
|
|
||||||
{
|
|
||||||
let mut p = Printer::new();
|
|
||||||
item.pretty_with_map(&mut p, Some(map));
|
|
||||||
p.finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Pretty print an item.
|
/// Pretty print an item.
|
||||||
pub trait Pretty {
|
pub trait Pretty {
|
||||||
/// Pretty print this item into the given printer.
|
/// Pretty print this item into the given printer.
|
||||||
fn pretty(&self, p: &mut Printer);
|
fn pretty(&self, p: &mut Printer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pretty print an item with an expression map that applies to it.
|
|
||||||
pub trait PrettyWithMap {
|
|
||||||
/// Pretty print this item into the given printer.
|
|
||||||
fn pretty_with_map(&self, p: &mut Printer, map: Option<&ExprMap>);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Pretty for T
|
|
||||||
where
|
|
||||||
T: PrettyWithMap,
|
|
||||||
{
|
|
||||||
fn pretty(&self, p: &mut Printer) {
|
|
||||||
self.pretty_with_map(p, None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A buffer into which items are printed.
|
/// A buffer into which items are printed.
|
||||||
pub struct Printer {
|
pub struct Printer {
|
||||||
buf: String,
|
buf: String,
|
||||||
@ -103,16 +78,16 @@ impl Write for Printer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrettyWithMap for Tree {
|
impl Pretty for Tree {
|
||||||
fn pretty_with_map(&self, p: &mut Printer, map: Option<&ExprMap>) {
|
fn pretty(&self, p: &mut Printer) {
|
||||||
for node in self {
|
for node in self {
|
||||||
node.pretty_with_map(p, map);
|
node.pretty(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrettyWithMap for Node {
|
impl Pretty for Node {
|
||||||
fn pretty_with_map(&self, p: &mut Printer, map: Option<&ExprMap>) {
|
fn pretty(&self, p: &mut Printer) {
|
||||||
match self {
|
match self {
|
||||||
// TODO: Handle escaping.
|
// TODO: Handle escaping.
|
||||||
Self::Text(text) => p.push_str(text),
|
Self::Text(text) => p.push_str(text),
|
||||||
@ -122,18 +97,13 @@ impl PrettyWithMap for Node {
|
|||||||
Self::Strong(_) => p.push('*'),
|
Self::Strong(_) => p.push('*'),
|
||||||
Self::Emph(_) => p.push('_'),
|
Self::Emph(_) => p.push('_'),
|
||||||
Self::Raw(raw) => raw.pretty(p),
|
Self::Raw(raw) => raw.pretty(p),
|
||||||
Self::Heading(heading) => heading.pretty_with_map(p, map),
|
Self::Heading(heading) => heading.pretty(p),
|
||||||
Self::List(list) => list.pretty_with_map(p, map),
|
Self::List(list) => list.pretty(p),
|
||||||
Self::Expr(expr) => {
|
Self::Expr(expr) => {
|
||||||
if let Some(map) = map {
|
if expr.has_short_form() {
|
||||||
let value = &map[&(expr as *const _)];
|
p.push('#');
|
||||||
value.pretty(p);
|
|
||||||
} else {
|
|
||||||
if expr.has_short_form() {
|
|
||||||
p.push('#');
|
|
||||||
}
|
|
||||||
expr.pretty(p);
|
|
||||||
}
|
}
|
||||||
|
expr.pretty(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,20 +165,20 @@ impl Pretty for RawNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrettyWithMap for HeadingNode {
|
impl Pretty for HeadingNode {
|
||||||
fn pretty_with_map(&self, p: &mut Printer, map: Option<&ExprMap>) {
|
fn pretty(&self, p: &mut Printer) {
|
||||||
for _ in 0 .. self.level {
|
for _ in 0 .. self.level {
|
||||||
p.push('#');
|
p.push('#');
|
||||||
}
|
}
|
||||||
p.push(' ');
|
p.push(' ');
|
||||||
self.body.pretty_with_map(p, map);
|
self.body.pretty(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrettyWithMap for ListNode {
|
impl Pretty for ListNode {
|
||||||
fn pretty_with_map(&self, p: &mut Printer, map: Option<&ExprMap>) {
|
fn pretty(&self, p: &mut Printer) {
|
||||||
p.push_str("- ");
|
p.push_str("- ");
|
||||||
self.body.pretty_with_map(p, map);
|
self.body.pretty(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,7 +248,7 @@ impl Pretty for Named {
|
|||||||
impl Pretty for TemplateExpr {
|
impl Pretty for TemplateExpr {
|
||||||
fn pretty(&self, p: &mut Printer) {
|
fn pretty(&self, p: &mut Printer) {
|
||||||
p.push('[');
|
p.push('[');
|
||||||
self.tree.pretty_with_map(p, None);
|
self.tree.pretty(p);
|
||||||
p.push(']');
|
p.push(']');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -488,7 +458,6 @@ impl Pretty for Value {
|
|||||||
Value::Relative(v) => v.pretty(p),
|
Value::Relative(v) => v.pretty(p),
|
||||||
Value::Linear(v) => v.pretty(p),
|
Value::Linear(v) => v.pretty(p),
|
||||||
Value::Color(v) => v.pretty(p),
|
Value::Color(v) => v.pretty(p),
|
||||||
// TODO: Handle like text when directly in template.
|
|
||||||
Value::Str(v) => v.pretty(p),
|
Value::Str(v) => v.pretty(p),
|
||||||
Value::Array(v) => v.pretty(p),
|
Value::Array(v) => v.pretty(p),
|
||||||
Value::Dict(v) => v.pretty(p),
|
Value::Dict(v) => v.pretty(p),
|
||||||
@ -529,29 +498,7 @@ impl Pretty for DictValue {
|
|||||||
|
|
||||||
impl Pretty for TemplateValue {
|
impl Pretty for TemplateValue {
|
||||||
fn pretty(&self, p: &mut Printer) {
|
fn pretty(&self, p: &mut Printer) {
|
||||||
p.push('[');
|
p.push_str("<template>");
|
||||||
for part in self {
|
|
||||||
part.pretty(p);
|
|
||||||
}
|
|
||||||
p.push(']');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Pretty for TemplateNode {
|
|
||||||
fn pretty(&self, p: &mut Printer) {
|
|
||||||
match self {
|
|
||||||
Self::Tree { tree, map } => tree.pretty_with_map(p, Some(map)),
|
|
||||||
Self::Str(s) => p.push_str(s),
|
|
||||||
Self::Func(func) => func.pretty(p),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Pretty for TemplateFunc {
|
|
||||||
fn pretty(&self, p: &mut Printer) {
|
|
||||||
p.push_str("<node ");
|
|
||||||
p.push_str(self.name());
|
|
||||||
p.push('>');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,12 +583,20 @@ pretty_display! {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::BTreeMap;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::parse::parse;
|
use crate::parse::parse;
|
||||||
|
|
||||||
|
macro_rules! map {
|
||||||
|
($($k:ident: $v:expr),* $(,)?) => {{
|
||||||
|
#[allow(unused_mut)]
|
||||||
|
let mut m = BTreeMap::new();
|
||||||
|
$(m.insert(stringify!($k).to_string(), $v);)*
|
||||||
|
m
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn roundtrip(src: &str) {
|
fn roundtrip(src: &str) {
|
||||||
test_parse(src, src);
|
test_parse(src, src);
|
||||||
@ -698,7 +653,6 @@ mod tests {
|
|||||||
fn test_pretty_print_expr() {
|
fn test_pretty_print_expr() {
|
||||||
// Basic expressions.
|
// Basic expressions.
|
||||||
roundtrip("{none}");
|
roundtrip("{none}");
|
||||||
roundtrip("{hi}");
|
|
||||||
roundtrip("{true}");
|
roundtrip("{true}");
|
||||||
roundtrip("{10}");
|
roundtrip("{10}");
|
||||||
roundtrip("{3.14}");
|
roundtrip("{3.14}");
|
||||||
@ -708,6 +662,7 @@ mod tests {
|
|||||||
roundtrip("{#abcdef}");
|
roundtrip("{#abcdef}");
|
||||||
roundtrip(r#"{"hi"}"#);
|
roundtrip(r#"{"hi"}"#);
|
||||||
test_parse(r#"{"let's \" go"}"#, r#"{"let's \" go"}"#);
|
test_parse(r#"{"let's \" go"}"#, r#"{"let's \" go"}"#);
|
||||||
|
roundtrip("{hi}");
|
||||||
|
|
||||||
// Arrays.
|
// Arrays.
|
||||||
roundtrip("{()}");
|
roundtrip("{()}");
|
||||||
@ -738,7 +693,7 @@ mod tests {
|
|||||||
roundtrip("{not true}");
|
roundtrip("{not true}");
|
||||||
roundtrip("{1 + 3}");
|
roundtrip("{1 + 3}");
|
||||||
|
|
||||||
// Function calls.
|
// Functions.
|
||||||
roundtrip("{v()}");
|
roundtrip("{v()}");
|
||||||
roundtrip("{v()()}");
|
roundtrip("{v()()}");
|
||||||
roundtrip("{v(1)}");
|
roundtrip("{v(1)}");
|
||||||
@ -747,22 +702,21 @@ mod tests {
|
|||||||
roundtrip("#v(1)");
|
roundtrip("#v(1)");
|
||||||
roundtrip("#v(1, 2)[*Ok*]");
|
roundtrip("#v(1, 2)[*Ok*]");
|
||||||
roundtrip("#v(1, f[2])");
|
roundtrip("#v(1, f[2])");
|
||||||
|
|
||||||
// Closures.
|
|
||||||
roundtrip("{(a, b) => a + b}");
|
roundtrip("{(a, b) => a + b}");
|
||||||
|
|
||||||
// Keywords.
|
// Control flow.
|
||||||
roundtrip("#let x = 1 + 2");
|
roundtrip("#let x = 1 + 2");
|
||||||
test_parse("#let f(x) = y", "#let f = (x) => y");
|
test_parse("#let f(x) = y", "#let f = (x) => y");
|
||||||
test_parse("#if x [y] #else [z]", "#if x [y] else [z]");
|
test_parse("#if x [y] #else [z]", "#if x [y] else [z]");
|
||||||
roundtrip("#while x {y}");
|
roundtrip("#while x {y}");
|
||||||
roundtrip("#for x in y {z}");
|
roundtrip("#for x in y {z}");
|
||||||
roundtrip("#for k, x in y {z}");
|
roundtrip("#for k, x in y {z}");
|
||||||
|
roundtrip("#import \"file.typ\" using *");
|
||||||
|
roundtrip("#include \"chapter1.typ\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pretty_print_value() {
|
fn test_pretty_print_value() {
|
||||||
// Simple values.
|
|
||||||
test_value(Value::None, "none");
|
test_value(Value::None, "none");
|
||||||
test_value(false, "false");
|
test_value(false, "false");
|
||||||
test_value(12i64, "12");
|
test_value(12i64, "12");
|
||||||
@ -776,64 +730,21 @@ mod tests {
|
|||||||
test_value("\n", r#""\n""#);
|
test_value("\n", r#""\n""#);
|
||||||
test_value("\\", r#""\\""#);
|
test_value("\\", r#""\\""#);
|
||||||
test_value("\"", r#""\"""#);
|
test_value("\"", r#""\"""#);
|
||||||
|
|
||||||
// Array.
|
|
||||||
test_value(Value::Array(vec![]), "()");
|
test_value(Value::Array(vec![]), "()");
|
||||||
test_value(vec![Value::None], "(none,)");
|
test_value(vec![Value::None], "(none,)");
|
||||||
test_value(vec![Value::Int(1), Value::Int(2)], "(1, 2)");
|
test_value(vec![Value::Int(1), Value::Int(2)], "(1, 2)");
|
||||||
|
test_value(map![], "(:)");
|
||||||
// Dictionary.
|
test_value(map![one: Value::Int(1)], "(one: 1)");
|
||||||
let mut dict = BTreeMap::new();
|
|
||||||
test_value(dict.clone(), "(:)");
|
|
||||||
dict.insert("one".into(), Value::Int(1));
|
|
||||||
test_value(dict.clone(), "(one: 1)");
|
|
||||||
dict.insert("two".into(), Value::Bool(false));
|
|
||||||
test_value(dict, "(one: 1, two: false)");
|
|
||||||
|
|
||||||
// Template.
|
|
||||||
test_value(
|
test_value(
|
||||||
vec![
|
map![two: Value::Bool(false), one: Value::Int(1)],
|
||||||
TemplateNode::Tree {
|
"(one: 1, two: false)",
|
||||||
tree: Rc::new(vec![Node::Strong(Span::ZERO)]),
|
|
||||||
map: HashMap::new(),
|
|
||||||
},
|
|
||||||
TemplateNode::Func(TemplateFunc::new("example", |_| {})),
|
|
||||||
],
|
|
||||||
"[*<node example>]",
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Function.
|
|
||||||
test_value(FuncValue::new(None, |_, _| Value::None), "<function>");
|
test_value(FuncValue::new(None, |_, _| Value::None), "<function>");
|
||||||
test_value(
|
test_value(
|
||||||
FuncValue::new(Some("nil".into()), |_, _| Value::None),
|
FuncValue::new(Some("nil".into()), |_, _| Value::None),
|
||||||
"<function nil>",
|
"<function nil>",
|
||||||
);
|
);
|
||||||
|
|
||||||
// Any.
|
|
||||||
test_value(AnyValue::new(1), "1");
|
test_value(AnyValue::new(1), "1");
|
||||||
|
|
||||||
// Error.
|
|
||||||
test_value(Value::Error, "<error>");
|
test_value(Value::Error, "<error>");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_pretty_print_args() {
|
|
||||||
// Arguments.
|
|
||||||
assert_eq!(
|
|
||||||
pretty(&FuncArgs {
|
|
||||||
span: Span::ZERO,
|
|
||||||
items: vec![
|
|
||||||
FuncArg {
|
|
||||||
name: Some(Spanned::zero("a".into())),
|
|
||||||
value: Spanned::zero(Value::Int(1)),
|
|
||||||
},
|
|
||||||
FuncArg {
|
|
||||||
name: None,
|
|
||||||
value: Spanned::zero(Value::Int(2)),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
"(a: 1, 2)",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -97,12 +97,14 @@ impl Expr {
|
|||||||
/// Whether the expression can be shortened in markup with a hashtag.
|
/// Whether the expression can be shortened in markup with a hashtag.
|
||||||
pub fn has_short_form(&self) -> bool {
|
pub fn has_short_form(&self) -> bool {
|
||||||
matches!(self,
|
matches!(self,
|
||||||
Expr::Ident(_)
|
Self::Ident(_)
|
||||||
| Expr::Call(_)
|
| Self::Call(_)
|
||||||
| Expr::Let(_)
|
| Self::Let(_)
|
||||||
| Expr::If(_)
|
| Self::If(_)
|
||||||
| Expr::While(_)
|
| Self::While(_)
|
||||||
| Expr::For(_)
|
| Self::For(_)
|
||||||
|
| Self::Import(_)
|
||||||
|
| Self::Include(_)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 6.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
@ -26,7 +26,6 @@
|
|||||||
// Error: 1-3 expected function, found string
|
// Error: 1-3 expected function, found string
|
||||||
#x()
|
#x()
|
||||||
|
|
||||||
---
|
|
||||||
// Error: 3:1 expected closing bracket
|
// Error: 3:1 expected closing bracket
|
||||||
#args[`a]`
|
#args[`a]`
|
||||||
|
|
||||||
|
@ -57,10 +57,9 @@
|
|||||||
|
|
||||||
#let a = "a"
|
#let a = "a"
|
||||||
|
|
||||||
#args[a] \
|
|
||||||
#args(a) \
|
#args(a) \
|
||||||
#args(a, [b]) \
|
#args[a] \
|
||||||
#args(a)[b]
|
#args(a, [b])
|
||||||
|
|
||||||
// Template can be argument or body depending on whitespace.
|
// Template can be argument or body depending on whitespace.
|
||||||
#if "template" == type[b] [Sure ]
|
#if "template" == type[b] [Sure ]
|
||||||
|
@ -17,4 +17,4 @@
|
|||||||
// Error: 3:5 expected comma
|
// Error: 3:5 expected comma
|
||||||
// Error: 2:12-2:16 expected identifier
|
// Error: 2:12-2:16 expected identifier
|
||||||
// Error: 1:17-1:18 expected expression, found colon
|
// Error: 1:17-1:18 expected expression, found colon
|
||||||
{(:1 b:[], true::)}
|
{(:1 b:"", true::)}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
#test(type("hi"), "string")
|
#test(type("hi"), "string")
|
||||||
#test(repr([Hi #rect[there]]), "[Hi [<node rect>]]")
|
#test(repr((1, 2, false, )), "(1, 2, false)")
|
||||||
|
|
||||||
---
|
---
|
||||||
// Check the output.
|
// Check the output.
|
||||||
|
@ -86,6 +86,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "punctuation.definition.list.numbered.typst",
|
"name": "punctuation.definition.list.numbered.typst",
|
||||||
|
"match": "^\\s*[0-9]*\\.\\s+"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "string.other.math.block.typst",
|
"name": "string.other.math.block.typst",
|
||||||
@ -110,7 +111,6 @@
|
|||||||
"begin": "`",
|
"begin": "`",
|
||||||
"end": "`",
|
"end": "`",
|
||||||
"captures": { "0": { "name": "punctuation.definition.raw.typst" } }
|
"captures": { "0": { "name": "punctuation.definition.raw.typst" } }
|
||||||
"match": "^\\s*[0-9]*\\.\\s+"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "keyword.control.typst",
|
"name": "keyword.control.typst",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user