summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml1
-rw-r--r--src/eval/value.rs10
-rw-r--r--src/geom/angle.rs11
-rw-r--r--src/geom/length.rs24
-rw-r--r--src/geom/relative.rs2
-rw-r--r--src/parse/tests.rs45
-rw-r--r--src/syntax/expr.rs6
-rw-r--r--tests/ref/lang/values.pngbin0 -> 24313 bytes
-rw-r--r--tests/typ/lang/values.typ33
9 files changed, 69 insertions, 63 deletions
diff --git a/Cargo.toml b/Cargo.toml
index dba398a5..1b6989cc 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -18,6 +18,7 @@ image = { version = "0.23", default-features = false, features = ["jpeg", "png"]
itoa = "0.4"
miniz_oxide = "0.3"
pdf-writer = { path = "../pdf-writer" }
+ryu = "1.0"
ttf-parser = "0.8.2"
unicode-xid = "0.2"
anyhow = { version = "1", optional = true }
diff --git a/src/eval/value.rs b/src/eval/value.rs
index 13548c87..20cc457c 100644
--- a/src/eval/value.rs
+++ b/src/eval/value.rs
@@ -116,8 +116,8 @@ impl Pretty for Value {
match self {
Value::None => p.push_str("none"),
Value::Bool(v) => write!(p, "{}", v).unwrap(),
- Value::Int(v) => write!(p, "{}", v).unwrap(),
- Value::Float(v) => write!(p, "{}", v).unwrap(),
+ Value::Int(v) => p.push_str(itoa::Buffer::new().format(*v)),
+ Value::Float(v) => p.push_str(ryu::Buffer::new().format(*v)),
Value::Length(v) => write!(p, "{}", v).unwrap(),
Value::Angle(v) => write!(p, "{}", v).unwrap(),
Value::Relative(v) => write!(p, "{}", v).unwrap(),
@@ -521,9 +521,9 @@ mod tests {
test_pretty(false, "false");
test_pretty(12.4, "12.4");
test_pretty(Length::pt(5.5), "5.5pt");
- test_pretty(Angle::deg(90.0), "90deg");
- test_pretty(Relative::ONE / 2.0, "50%");
- test_pretty(Relative::new(0.3) + Length::cm(2.0), "30% + 2cm");
+ 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""#);
test_pretty(vec![Spanned::zero(Node::Strong)], "[*]");
diff --git a/src/geom/angle.rs b/src/geom/angle.rs
index 47541cb8..07471a02 100644
--- a/src/geom/angle.rs
+++ b/src/geom/angle.rs
@@ -56,7 +56,16 @@ impl Angle {
impl Display for Angle {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "{}{}", self.to_deg(), AngularUnit::Deg)
+ // Format with the unit that yields the shortest output, preferring
+ // degrees when tied.
+ let mut buf = ryu::Buffer::new();
+ let unit = [AngularUnit::Deg, AngularUnit::Rad]
+ .iter()
+ .copied()
+ .min_by_key(|&unit| buf.format(self.to_unit(unit)).len())
+ .unwrap();
+
+ write!(f, "{}{}", buf.format(self.to_unit(unit)), unit)
}
}
diff --git a/src/geom/length.rs b/src/geom/length.rs
index bfb1d668..00803e13 100644
--- a/src/geom/length.rs
+++ b/src/geom/length.rs
@@ -99,13 +99,16 @@ impl Length {
impl Display for Length {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- // Format small lengths as points and large ones as centimeters.
- let (val, unit) = if self.to_pt().abs() < 25.0 {
- (self.to_pt(), LengthUnit::Pt)
- } else {
- (self.to_cm(), LengthUnit::Cm)
- };
- write!(f, "{}{}", (val * 100.0).round() / 100.0, unit)
+ // Format with the unit that yields the shortest output, preferring
+ // larger units when tied.
+ let mut buf = ryu::Buffer::new();
+ let unit = [LengthUnit::Cm, LengthUnit::Mm, LengthUnit::Pt]
+ .iter()
+ .copied()
+ .min_by_key(|&unit| buf.format(self.to_unit(unit)).len())
+ .unwrap();
+
+ write!(f, "{}{}", buf.format(self.to_unit(unit)), unit)
}
}
@@ -229,8 +232,9 @@ mod tests {
#[test]
fn test_length_formatting() {
- assert_eq!(Length::pt(-28.34).to_string(), "-1cm".to_string());
- assert_eq!(Length::pt(23.0).to_string(), "23pt".to_string());
- assert_eq!(Length::cm(12.728).to_string(), "12.73cm".to_string());
+ assert_eq!(Length::pt(23.0).to_string(), "23.0pt");
+ assert_eq!(Length::pt(-28.3465).to_string(), "-1.0cm");
+ assert_eq!(Length::cm(12.728).to_string(), "12.728cm");
+ assert_eq!(Length::cm(4.5).to_string(), "4.5cm");
}
}
diff --git a/src/geom/relative.rs b/src/geom/relative.rs
index d39ead3a..e91ea672 100644
--- a/src/geom/relative.rs
+++ b/src/geom/relative.rs
@@ -37,7 +37,7 @@ impl Relative {
impl Display for Relative {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "{}%", (self.0 * 10000.0).round() / 100.0)
+ write!(f, "{}%", ryu::Buffer::new().format(100.0 * self.0))
}
}
diff --git a/src/parse/tests.rs b/src/parse/tests.rs
index 8d52c24b..9a35f552 100644
--- a/src/parse/tests.rs
+++ b/src/parse/tests.rs
@@ -3,13 +3,12 @@
use std::fmt::Debug;
use super::parse;
-use crate::color::RgbaColor;
use crate::diag::{Diag, Level, Pass};
-use crate::geom::{AngularUnit, LengthUnit};
+use crate::geom::LengthUnit;
use crate::syntax::*;
use BinOp::*;
-use Expr::{Angle, Bool, Color, Float, Int, Length, Percent};
+use Expr::{Float, Int, Length};
use Node::{Space, Strong};
use UnOp::{Neg, Pos};
@@ -290,43 +289,3 @@ fn test_parse_expressions() {
S(6..6, "expected expression"),
S(10..10, "expected expression")]);
}
-
-#[test]
-fn test_parse_values() {
- // Basics.
- t!("{_}" Block!(Id("_")));
- t!("{name}" Block!(Id("name")));
- t!("{ke-bab}" Block!(Id("ke-bab")));
- t!("{α}" Block!(Id("α")));
- t!("{none}" Block!(Expr::None));
- t!("{true}" Block!(Bool(true)));
- t!("{false}" Block!(Bool(false)));
- t!("{1.0e-4}" Block!(Float(1e-4)));
- t!("{3.15}" Block!(Float(3.15)));
- t!("{50%}" Block!(Percent(50.0)));
- t!("{4.5cm}" Block!(Length(4.5, LengthUnit::Cm)));
- t!("{12e1pt}" Block!(Length(12e1, LengthUnit::Pt)));
- t!("{13rad}" Block!(Angle(13.0, AngularUnit::Rad)));
- t!("{45deg}" Block!(Angle(45.0, AngularUnit::Deg)));
-
- // Strings.
- t!(r#"{"hi"}"# Block!(Str("hi")));
- t!(r#"{"a\n[]\"\u{1F680}string"}"# Block!(Str("a\n[]\"🚀string")));
-
- // Colors.
- t!("{#f7a20500}" Block!(Color(RgbaColor::new(0xf7, 0xa2, 0x05, 0))));
- t!("{#a5}"
- nodes: [Block!(Color(RgbaColor::new(0, 0, 0, 0xff)))],
- errors: [S(1..4, "invalid color")]);
-
- // Content.
- t!("{[*Hi*]}" Block!(Template![Strong, Text("Hi"), Strong]));
-
- // Nested blocks.
- t!("{{1}}" Block!(Block!(@Int(1))));
-
- // Invalid tokens.
- t!("{1u}"
- nodes: [],
- errors: [S(1..3, "expected expression, found invalid token")]);
-}
diff --git a/src/syntax/expr.rs b/src/syntax/expr.rs
index b758a849..79533918 100644
--- a/src/syntax/expr.rs
+++ b/src/syntax/expr.rs
@@ -54,8 +54,8 @@ impl Pretty for Expr {
Self::None => p.push_str("none"),
Self::Ident(v) => p.push_str(&v),
Self::Bool(v) => write!(p, "{}", v).unwrap(),
- Self::Int(v) => write!(p, "{}", v).unwrap(),
- Self::Float(v) => write!(p, "{}", v).unwrap(),
+ Self::Int(v) => p.push_str(itoa::Buffer::new().format(*v)),
+ Self::Float(v) => p.push_str(ryu::Buffer::new().format(*v)),
Self::Length(v, u) => write!(p, "{}{}", v, u).unwrap(),
Self::Angle(v, u) => write!(p, "{}{}", v, u).unwrap(),
Self::Percent(v) => write!(p, "{}%", v).unwrap(),
@@ -370,7 +370,7 @@ mod tests {
test_pretty("{true}", "{true}");
test_pretty("{25}", "{25}");
test_pretty("{2.50}", "{2.5}");
- test_pretty("{1e2}", "{100}");
+ test_pretty("{1e2}", "{100.0}");
test_pretty("{12pt}", "{12pt}");
test_pretty("{90.0deg}", "{90deg}");
test_pretty("{50%}", "{50%}");
diff --git a/tests/ref/lang/values.png b/tests/ref/lang/values.png
new file mode 100644
index 00000000..4205221b
--- /dev/null
+++ b/tests/ref/lang/values.png
Binary files differ
diff --git a/tests/typ/lang/values.typ b/tests/typ/lang/values.typ
new file mode 100644
index 00000000..ce41fc43
--- /dev/null
+++ b/tests/typ/lang/values.typ
@@ -0,0 +1,33 @@
+#let name = "Typst";
+#let ke-bab = "Kebab!";
+#let α = "Alpha";
+
+{name} \
+{ke-bab} \
+{α} \
+{none} (empty) \
+{true} \
+{false} \
+{1.0e-4} \
+{3.15} \
+{1e-10} \
+{50.368%} \
+{0.0000012345pt} \
+{4.5cm} \
+{12e1pt} \
+{2.5rad} \
+{45deg} \
+{"hi"} \
+{"a\n[]\"\u{1F680}string"} \
+{#f7a20500} \
+{[*{"Hi"} [f 1]*]} \
+{{1}}
+
+// Error: 1:1-1:4 unknown variable
+{_} \
+
+// Error: 1:2-1:5 invalid color
+{#a5}
+
+// Error: 1:2-1:4 expected expression, found invalid token
+{1u}