Cleaning 🧹

This commit is contained in:
Laurenz 2021-02-12 22:55:26 +01:00
parent a2fcc1bf28
commit 790dc9e667
20 changed files with 167 additions and 193 deletions

View File

@ -8,7 +8,6 @@ use super::*;
use crate::color::Color; use crate::color::Color;
use crate::exec::ExecContext; use crate::exec::ExecContext;
use crate::geom::{Angle, Length, Linear, Relative}; use crate::geom::{Angle, Length, Linear, Relative};
use crate::pretty::{Pretty, Printer};
use crate::syntax::Tree; use crate::syntax::Tree;
/// A computational value. /// A computational value.
@ -103,22 +102,6 @@ pub type ValueArray = Vec<Value>;
/// A dictionary value: `(color: #f79143, pattern: dashed)`. /// A dictionary value: `(color: #f79143, pattern: dashed)`.
pub type ValueDict = BTreeMap<String, Value>; pub type ValueDict = BTreeMap<String, Value>;
impl Pretty for ValueDict {
fn pretty(&self, p: &mut Printer) {
p.push('(');
if self.is_empty() {
p.push(':');
} else {
p.join(self, ", ", |(key, value), p| {
p.push_str(key);
p.push_str(": ");
value.pretty(p);
});
}
p.push(')');
}
}
/// A template value: `[*Hi* there]`. /// A template value: `[*Hi* there]`.
pub type ValueTemplate = Vec<TemplateNode>; pub type ValueTemplate = Vec<TemplateNode>;
@ -156,7 +139,6 @@ impl TemplateAny {
Self { name: name.into(), f: Rc::new(f) } Self { name: name.into(), f: Rc::new(f) }
} }
/// The name of the template node. /// The name of the template node.
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
&self.name &self.name
@ -358,13 +340,6 @@ impl ValueArgs {
} }
} }
// This is a workaround because `-> impl Trait + 'a + 'b` does not work.
//
// See also: https://github.com/rust-lang/rust/issues/49431
#[doc(hidden)]
pub trait Captures<'a> {}
impl<'a, T: ?Sized> Captures<'a> for T {}
/// An argument to a function call: `12` or `draw: false`. /// An argument to a function call: `12` or `draw: false`.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct ValueArg { pub struct ValueArg {
@ -681,80 +656,3 @@ macro_rules! typify {
} }
}; };
} }
#[cfg(test)]
mod tests {
use super::*;
use crate::color::RgbaColor;
use crate::pretty::pretty;
#[track_caller]
fn test_pretty(value: impl Into<Value>, exp: &str) {
assert_eq!(pretty(&value.into()), exp);
}
#[test]
fn test_pretty_print_value() {
// Simple values.
test_pretty(Value::None, "none");
test_pretty(false, "false");
test_pretty(12, "12");
test_pretty(3.14, "3.14");
test_pretty(Length::pt(5.5), "5.5pt");
test_pretty(Angle::deg(90.0), "90.0deg");
test_pretty(Relative::ONE / 2.0, "50.0%");
test_pretty(Relative::new(0.3) + Length::cm(2.0), "30.0% + 2.0cm");
test_pretty(Color::Rgba(RgbaColor::new(1, 1, 1, 0xff)), "#010101");
test_pretty("hello", r#""hello""#);
// Array.
test_pretty(Value::Array(vec![]), "()");
test_pretty(vec![Value::None], "(none,)");
test_pretty(vec![Value::Int(1), Value::Int(2)], "(1, 2)");
// Dictionary.
let mut dict = BTreeMap::new();
test_pretty(dict.clone(), "(:)");
dict.insert("one".into(), Value::Int(1));
test_pretty(dict.clone(), "(one: 1)");
dict.insert("two".into(), Value::Bool(false));
test_pretty(dict, "(one: 1, two: false)");
// Template.
test_pretty(
vec![
TemplateNode::Tree {
tree: Rc::new(vec![Node::Strong]),
map: HashMap::new(),
},
TemplateNode::Any(TemplateAny::new("example", |_| {})),
],
"[*<example>]",
);
// Function and arguments.
test_pretty(ValueFunc::new("nil", |_, _| Value::None), "<nil>");
test_pretty(
ValueArgs {
span: Span::ZERO,
items: vec![
ValueArg {
name: Some(Spanned::zero("a".into())),
value: Spanned::zero(Value::Int(1)),
},
ValueArg {
name: None,
value: Spanned::zero(Value::Int(2)),
},
],
},
"<a: 1, 2>",
);
// Any.
test_pretty(ValueAny::new(1), "1");
// Error.
test_pretty(Value::Error, "<error>");
}
}

View File

@ -145,8 +145,8 @@ impl Exec for Value {
impl Exec for ValueTemplate { impl Exec for ValueTemplate {
fn exec(&self, ctx: &mut ExecContext) { fn exec(&self, ctx: &mut ExecContext) {
for part in self { for node in self {
part.exec(ctx); node.exec(ctx);
} }
} }
} }

View File

@ -44,8 +44,8 @@ pub struct PageSettings {
pub size: Size, pub size: Size,
/// Whether the expand the pages to the `size` or to fit the content. /// Whether the expand the pages to the `size` or to fit the content.
pub expand: Spec<Expansion>, pub expand: Spec<Expansion>,
/// The amount of white space in the order [left, top, right, bottom]. If a /// The amount of white space on each side of the page. If a side is set to
/// side is set to `None`, the default for the paper class is used. /// `None`, the default for the paper class is used.
pub margins: Sides<Option<Linear>>, pub margins: Sides<Option<Linear>>,
} }

View File

@ -107,7 +107,7 @@ impl Display for Length {
use LengthUnit::*; use LengthUnit::*;
// Format with the unit that yields the shortest output, preferring // Format with the unit that yields the shortest output, preferring
// larger / metrics units when tied. // larger / metric units when tied.
let mut buf = ryu::Buffer::new(); let mut buf = ryu::Buffer::new();
let unit = [Cm, Mm, In, Pt] let unit = [Cm, Mm, In, Pt]
.iter() .iter()

View File

@ -1,11 +1,11 @@
use super::*; use super::*;
/// A node that represents a rectangular box. /// A node that places a rectangular filled background behind another node.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct NodeBackground { pub struct NodeBackground {
/// The background fill. /// The background fill.
pub fill: Fill, pub fill: Fill,
/// The child node to be filled in. /// The child node to be filled.
pub child: Node, pub child: Node,
} }
@ -13,17 +13,12 @@ impl Layout for NodeBackground {
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted { fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted {
let mut layouted = self.child.layout(ctx, areas); let mut layouted = self.child.layout(ctx, areas);
if let Some(first) = layouted.frames_mut().first_mut() { for frame in layouted.frames_mut() {
first.elements.insert( let element = Element::Geometry(Geometry {
0, shape: Shape::Rect(frame.size),
(
Point::ZERO,
Element::Geometry(Geometry {
shape: Shape::Rect(first.size),
fill: self.fill.clone(), fill: self.fill.clone(),
}), });
), frame.elements.insert(0, (Point::ZERO, element))
)
} }
layouted layouted

View File

@ -293,6 +293,7 @@ pub fn page(ctx: &mut EvalContext, args: &mut ValueArgs) -> Value {
None None
}) })
}); });
let width = args.get(ctx, "width"); let width = args.get(ctx, "width");
let height = args.get(ctx, "height"); let height = args.get(ctx, "height");
let margins = args.get(ctx, "margins"); let margins = args.get(ctx, "margins");
@ -352,7 +353,6 @@ pub fn page(ctx: &mut EvalContext, args: &mut ValueArgs) -> Value {
std::mem::swap(&mut page.expand.horizontal, &mut page.expand.vertical); std::mem::swap(&mut page.expand.horizontal, &mut page.expand.vertical);
} }
ctx.set_dirs(Gen::new(main, cross)); ctx.set_dirs(Gen::new(main, cross));
let mut softness = ctx.end_page_group(|_| false); let mut softness = ctx.end_page_group(|_| false);

View File

@ -508,6 +508,22 @@ impl Pretty for ValueArray {
} }
} }
impl Pretty for ValueDict {
fn pretty(&self, p: &mut Printer) {
p.push('(');
if self.is_empty() {
p.push(':');
} else {
p.join(self, ", ", |(key, value), p| {
p.push_str(key);
p.push_str(": ");
value.pretty(p);
});
}
p.push(')');
}
}
impl Pretty for ValueTemplate { impl Pretty for ValueTemplate {
fn pretty(&self, p: &mut Printer) { fn pretty(&self, p: &mut Printer) {
p.push('['); p.push('[');
@ -529,7 +545,7 @@ impl Pretty for TemplateNode {
impl Pretty for TemplateAny { impl Pretty for TemplateAny {
fn pretty(&self, p: &mut Printer) { fn pretty(&self, p: &mut Printer) {
p.push('<'); p.push_str("<node ");
p.push_str(self.name()); p.push_str(self.name());
p.push('>'); p.push('>');
} }
@ -537,7 +553,7 @@ impl Pretty for TemplateAny {
impl Pretty for ValueFunc { impl Pretty for ValueFunc {
fn pretty(&self, p: &mut Printer) { fn pretty(&self, p: &mut Printer) {
p.push('<'); p.push_str("<function ");
p.push_str(self.name()); p.push_str(self.name());
p.push('>'); p.push('>');
} }
@ -545,9 +561,9 @@ impl Pretty for ValueFunc {
impl Pretty for ValueArgs { impl Pretty for ValueArgs {
fn pretty(&self, p: &mut Printer) { fn pretty(&self, p: &mut Printer) {
p.push('<'); p.push('(');
p.join(&self.items, ", ", |item, p| item.pretty(p)); p.join(&self.items, ", ", |item, p| item.pretty(p));
p.push('>'); p.push(')');
} }
} }
@ -613,13 +629,22 @@ pretty_display! {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::collections::{BTreeMap, HashMap};
use std::rc::Rc;
use super::*; use super::*;
use crate::color::RgbaColor;
use crate::env::Env; use crate::env::Env;
use crate::eval::eval; use crate::eval::eval;
use crate::parse::parse; use crate::parse::parse;
#[track_caller] #[track_caller]
fn test(src: &str, exp: &str) { fn roundtrip(src: &str) {
test_parse(src, src);
}
#[track_caller]
fn test_parse(src: &str, exp: &str) {
let tree = parse(src).output; let tree = parse(src).output;
let found = pretty(&tree); let found = pretty(&tree);
if exp != found { if exp != found {
@ -631,8 +656,8 @@ mod tests {
} }
#[track_caller] #[track_caller]
fn roundtrip(src: &str) { fn test_value(value: impl Into<Value>, exp: &str) {
test(src, src); assert_eq!(pretty(&value.into()), exp);
} }
#[test] #[test]
@ -659,11 +684,11 @@ mod tests {
roundtrip("```\n`\n```"); roundtrip("```\n`\n```");
roundtrip("``` ` ```"); roundtrip("``` ` ```");
roundtrip("````\n```\n```\n````"); roundtrip("````\n```\n```\n````");
test("```lang```", "```lang ```"); test_parse("```lang```", "```lang ```");
test("```1 ```", "``"); test_parse("```1 ```", "``");
test("``` 1```", "`1`"); test_parse("``` 1```", "`1`");
test("``` 1 ```", "`1 `"); test_parse("``` 1 ```", "`1 `");
test("```` ` ````", "``` ` ```"); test_parse("```` ` ````", "``` ` ```");
} }
#[test] #[test]
@ -679,7 +704,7 @@ mod tests {
roundtrip("{20.0%}"); roundtrip("{20.0%}");
roundtrip("{#abcdef}"); roundtrip("{#abcdef}");
roundtrip(r#"{"hi"}"#); roundtrip(r#"{"hi"}"#);
test(r#"{"let's \" go"}"#, r#"{"let's \" go"}"#); test_parse(r#"{"let's \" go"}"#, r#"{"let's \" go"}"#);
// Arrays. // Arrays.
roundtrip("{()}"); roundtrip("{()}");
@ -720,8 +745,8 @@ 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]");
test("{#[v]}", "{v()}"); test_parse("{#[v]}", "{v()}");
test("#[v 1, #[f 2]]", "#[v 1 | f 2]"); test_parse("#[v 1, #[f 2]]", "#[v 1 | f 2]");
// Keywords. // Keywords.
roundtrip("#let x = 1 + 2"); roundtrip("#let x = 1 + 2");
@ -738,9 +763,70 @@ mod tests {
} }
#[test] #[test]
fn test_pretty_print_str() { fn test_pretty_print_value() {
assert_eq!(pretty("\n"), r#""\n""#); // Simple values.
assert_eq!(pretty("\\"), r#""\\""#); test_value(Value::None, "none");
assert_eq!(pretty("\""), r#""\"""#); test_value(false, "false");
test_value(12, "12");
test_value(3.14, "3.14");
test_value(Length::pt(5.5), "5.5pt");
test_value(Angle::deg(90.0), "90.0deg");
test_value(Relative::ONE / 2.0, "50.0%");
test_value(Relative::new(0.3) + Length::cm(2.0), "30.0% + 2.0cm");
test_value(Color::Rgba(RgbaColor::new(1, 1, 1, 0xff)), "#010101");
test_value("hello", r#""hello""#);
test_value("\n", r#""\n""#);
test_value("\\", r#""\\""#);
test_value("\"", r#""\"""#);
// Array.
test_value(Value::Array(vec![]), "()");
test_value(vec![Value::None], "(none,)");
test_value(vec![Value::Int(1), Value::Int(2)], "(1, 2)");
// Dictionary.
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(
vec![
TemplateNode::Tree {
tree: Rc::new(vec![Node::Strong]),
map: HashMap::new(),
},
TemplateNode::Any(TemplateAny::new("example", |_| {})),
],
"[*<node example>]",
);
// Function and arguments.
test_value(ValueFunc::new("nil", |_, _| Value::None), "<function nil>");
test_value(
ValueArgs {
span: Span::ZERO,
items: vec![
ValueArg {
name: Some(Spanned::zero("a".into())),
value: Spanned::zero(Value::Int(1)),
},
ValueArg {
name: None,
value: Spanned::zero(Value::Int(2)),
},
],
},
"(a: 1, 2)",
);
// Any.
test_value(ValueAny::new(1), "1");
// Error.
test_value(Value::Error, "<error>");
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 682 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@ -1,11 +1,11 @@
// Test bracketed function calls. // Test bracketed function calls.
--- ---
// Whitespace insignificant. // Whitespace is insignificant.
#[f], #[ f ] #[ f ]
// Body and no body. // Alternatives for embedding.
#[f][#[f]] #[f f()], #[f #[f]], #[f][#[f]],
// Tight functions. // Tight functions.
#[f]#[f] #[f]#[f]
@ -16,3 +16,33 @@
Second Second
] ]
---
// Chained once.
#[f | f]
// Chained twice.
#[f|f|f]
// With body.
// Error: 7-8 expected identifier, found integer
#[f | 1 | box][💕]
// With actual functions.
#[box width: 1cm | image "res/rhino.png"]
---
// Error: 8-8 expected identifier
#[f 1 |]
// Error: 4-4 expected identifier
#[ | f true]
// Error: 2:3-2:3 expected identifier
// Error: 1:4-1:4 expected identifier
#[|][Nope]
// Pipe wins over parens.
// Error: 2:6-2:6 expected closing paren
// Error: 1:9-1:10 expected expression, found closing paren
#[f (|f )]

View File

@ -1,31 +0,0 @@
// Test bracket call chaining.
---
// Chained once.
#[f | f]
// Chained twice.
#[f|f|f]
// With body.
// Error: 7-8 expected identifier, found integer
#[f | 1 | box][💕]
// With actual functions.
#[box width: 1cm | image "res/rhino.png"]
---
// Error: 8-8 expected identifier
#[f 1 |]
// Error: 4-4 expected identifier
#[ | f true]
// Error: 2:3-2:3 expected identifier
// Error: 1:4-1:4 expected identifier
#[|][Nope]
// Pipe wins over parens.
// Error: 2:6-2:6 expected closing paren
// Error: 1:9-1:10 expected expression, found closing paren
#[f (|f )]

View File

@ -11,8 +11,8 @@ C/*
*/D */D
// Works in code. // Works in code.
#[f /*1*/ a: "b" // #[test type /*1*/ (1) //
, 1] , "integer"]
--- ---
// End should not appear without start. // End should not appear without start.

View File

@ -54,7 +54,6 @@
} }
} }
// Make sure length, relative and linear // Make sure length, relative and linear
// - can all be added to / subtracted from each other, // - can all be added to / subtracted from each other,
// - multiplied with integers and floats, // - multiplied with integers and floats,

View File

@ -44,4 +44,4 @@
--- ---
// Templates. // Templates.
{[*{"Hi"} #[f 1]*]} {[*{"H" + "i"} there*]}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -1,23 +1,20 @@
#[page "a5", flip: true] #[page "a7", flip: true]
// Rectangle with width, should have paragraph height // Box with fixed width, should have text height.
#[box width: 2cm, color: #9650D6][aa] #[box width: 2cm, color: #9650D6][A]
Sometimes there is no box Sometimes there is no box.
// Rectangle with height, should span line // Box with fixed height, should span line.
#[box height: 2cm, width: 100%, color: #734CED][bb] #[box height: 2cm, width: 100%, color: #734CED][B]
// Empty rectangle with width and height // Empty box with fixed width and height.
#[box width: 6cm, height: 12pt, color: #CB4CED] #[box width: 6cm, height: 12pt, color: #CB4CED]
// This empty rectangle should not be displayed // Not visiblem, but creates a gap between the boxes above and below.
#[box width: 2in, color: #ff0000] #[box width: 2in, color: #ff0000]
// This one should be
#[box height: 15mm, width: 100%, color: #494DE3]
// These are in a row! // These are in a row!
#[box width: 2in, height: 10pt, color: #D6CD67] #[box width: 1in, height: 10pt, color: #D6CD67]
#[box width: 2in, height: 10pt, color: #EDD466] #[box width: 1in, height: 10pt, color: #EDD466]
#[box width: 2in, height: 10pt, color: #E3BE62] #[box width: 1in, height: 10pt, color: #E3BE62]