summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-01-04 21:29:15 +0100
committerLaurenz <laurmaedje@gmail.com>2021-01-04 21:29:15 +0100
commit2e77b1c836220766398e379ae0157736fb448874 (patch)
tree70fc7d28f44193f26d880b5315ce55ed951af73c
parent77c06ebc24ab3a43dc2268763ff8f10963f875b4 (diff)
Better value representations, type function 🌐
-rw-r--r--src/color.rs30
-rw-r--r--src/eval/context.rs10
-rw-r--r--src/eval/state.rs36
-rw-r--r--src/eval/value.rs130
-rw-r--r--src/geom/length.rs6
-rw-r--r--src/geom/relative.rs2
-rw-r--r--src/layout/fixed.rs4
-rw-r--r--src/layout/node.rs19
-rw-r--r--src/layout/pad.rs4
-rw-r--r--src/layout/par.rs4
-rw-r--r--src/layout/stack.rs4
-rw-r--r--src/library/extend.rs16
-rw-r--r--src/library/insert.rs4
-rw-r--r--src/library/layout.rs20
-rw-r--r--src/library/mod.rs97
-rw-r--r--src/syntax/span.rs8
16 files changed, 224 insertions, 170 deletions
diff --git a/src/color.rs b/src/color.rs
index f349fdb4..d74584ae 100644
--- a/src/color.rs
+++ b/src/color.rs
@@ -1,6 +1,6 @@
//! Color handling.
-use std::fmt::{self, Debug, Formatter};
+use std::fmt::{self, Debug, Display, Formatter};
use std::str::FromStr;
/// A color in a dynamic format.
@@ -10,10 +10,18 @@ pub enum Color {
Rgba(RgbaColor),
}
+impl Display for Color {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ match self {
+ Self::Rgba(c) => Display::fmt(c, f),
+ }
+ }
+}
+
impl Debug for Color {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
- Self::Rgba(c) => c.fmt(f),
+ Self::Rgba(c) => Debug::fmt(c, f),
}
}
}
@@ -76,6 +84,16 @@ impl FromStr for RgbaColor {
}
}
+impl Display for RgbaColor {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ write!(f, "#{:02x}{:02x}{:02x}", self.r, self.g, self.b)?;
+ if self.a != 255 {
+ write!(f, "{:02x}", self.a)?;
+ }
+ Ok(())
+ }
+}
+
impl Debug for RgbaColor {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
if f.alternate() {
@@ -83,14 +101,10 @@ impl Debug for RgbaColor {
f,
"rgba({:02}, {:02}, {:02}, {:02})",
self.r, self.g, self.b, self.a,
- )?;
+ )
} else {
- write!(f, "#{:02x}{:02x}{:02x}", self.r, self.g, self.b)?;
- if self.a != 255 {
- write!(f, "{:02x}", self.a)?;
- }
+ Display::fmt(self, f)
}
- Ok(())
}
}
diff --git a/src/eval/context.rs b/src/eval/context.rs
index ece33146..64a8fbbe 100644
--- a/src/eval/context.rs
+++ b/src/eval/context.rs
@@ -119,15 +119,17 @@ impl EvalContext {
if !children.is_empty() || keep_empty(group.softness) {
self.runs.push(NodePages {
size: group.size,
- child: Node::any(NodePad {
+ child: NodePad {
padding: group.padding,
- child: Node::any(NodeStack {
+ child: NodeStack {
dirs: group.dirs,
align: group.align,
expansion: Gen::uniform(Expansion::Fill),
children,
- }),
- }),
+ }
+ .into(),
+ }
+ .into(),
})
}
group.softness
diff --git a/src/eval/state.rs b/src/eval/state.rs
index 7860c004..2a8ee2f0 100644
--- a/src/eval/state.rs
+++ b/src/eval/state.rs
@@ -128,7 +128,22 @@ impl StateFont {
impl Default for StateFont {
fn default() -> Self {
Self {
- families: Rc::new(default_font_families()),
+ /// The default tree of font fallbacks.
+ families: Rc::new(fallback! {
+ list: ["sans-serif"],
+ classes: {
+ "serif" => ["source serif pro", "noto serif"],
+ "sans-serif" => ["source sans pro", "noto sans"],
+ "monospace" => ["source code pro", "noto sans mono"],
+ },
+ base: [
+ "source sans pro",
+ "noto sans",
+ "segoe ui emoji",
+ "noto emoji",
+ "latin modern math",
+ ],
+ }),
variant: FontVariant {
style: FontStyle::Normal,
weight: FontWeight::REGULAR,
@@ -141,22 +156,3 @@ impl Default for StateFont {
}
}
}
-
-/// The default tree of font fallbacks.
-fn default_font_families() -> FallbackTree {
- fallback! {
- list: ["sans-serif"],
- classes: {
- "serif" => ["source serif pro", "noto serif"],
- "sans-serif" => ["source sans pro", "noto sans"],
- "monospace" => ["source code pro", "noto sans mono"],
- },
- base: [
- "source sans pro",
- "noto sans",
- "segoe ui emoji",
- "noto emoji",
- "latin modern math",
- ],
- }
-}
diff --git a/src/eval/value.rs b/src/eval/value.rs
index a91ff137..80c6b820 100644
--- a/src/eval/value.rs
+++ b/src/eval/value.rs
@@ -1,6 +1,6 @@
use std::any::Any;
use std::collections::HashMap;
-use std::fmt::{self, Debug, Formatter};
+use std::fmt::{self, Debug, Display, Formatter};
use std::ops::Deref;
use std::rc::Rc;
@@ -45,14 +45,6 @@ pub enum Value {
}
impl Value {
- /// Create a new dynamic value.
- pub fn any<T>(any: T) -> Self
- where
- T: Type + Debug + Clone + PartialEq + 'static,
- {
- Self::Any(ValueAny::new(any))
- }
-
/// Try to cast the value into a specific type.
pub fn cast<T>(self) -> CastResult<T, Self>
where
@@ -68,8 +60,8 @@ impl Value {
Self::Bool(_) => bool::TYPE_NAME,
Self::Int(_) => i64::TYPE_NAME,
Self::Float(_) => f64::TYPE_NAME,
- Self::Relative(_) => Relative::TYPE_NAME,
Self::Length(_) => Length::TYPE_NAME,
+ Self::Relative(_) => Relative::TYPE_NAME,
Self::Linear(_) => Linear::TYPE_NAME,
Self::Color(_) => Color::TYPE_NAME,
Self::Str(_) => String::TYPE_NAME,
@@ -88,16 +80,24 @@ impl Eval for &Value {
/// Evaluate everything contained in this value.
fn eval(self, ctx: &mut EvalContext) -> Self::Output {
- match self {
- // Don't print out none values.
- Value::None => {}
-
- // Pass through.
- Value::Content(tree) => tree.eval(ctx),
-
- // Format with debug.
- val => ctx.push(ctx.make_text_node(format!("{:?}", val))),
- }
+ ctx.push(ctx.make_text_node(match self {
+ Value::None => return,
+ Value::Bool(v) => v.to_string(),
+ Value::Int(v) => v.to_string(),
+ Value::Float(v) => v.to_string(),
+ Value::Length(v) => v.to_string(),
+ Value::Relative(v) => v.to_string(),
+ Value::Linear(v) => v.to_string(),
+ Value::Color(v) => v.to_string(),
+ Value::Str(v) => v.clone(),
+ // TODO: Find good representation for composite types.
+ Value::Array(_v) => "(array)".into(),
+ Value::Dict(_v) => "(dictionary)".into(),
+ Value::Content(tree) => return tree.eval(ctx),
+ Value::Func(v) => v.to_string(),
+ Value::Any(v) => v.to_string(),
+ Value::Error => "(error)".into(),
+ }));
}
}
@@ -110,21 +110,21 @@ impl Default for Value {
impl Debug for Value {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
- Self::None => f.pad("none"),
- Self::Bool(v) => v.fmt(f),
- Self::Int(v) => v.fmt(f),
- Self::Float(v) => v.fmt(f),
- Self::Length(v) => v.fmt(f),
- Self::Relative(v) => v.fmt(f),
- Self::Linear(v) => v.fmt(f),
- Self::Color(v) => v.fmt(f),
- Self::Str(v) => v.fmt(f),
- Self::Array(v) => v.fmt(f),
- Self::Dict(v) => v.fmt(f),
- Self::Content(v) => v.fmt(f),
- Self::Func(v) => v.fmt(f),
- Self::Any(v) => v.fmt(f),
- Self::Error => f.pad("<error>"),
+ Self::None => f.pad("None"),
+ Self::Bool(v) => Debug::fmt(v, f),
+ Self::Int(v) => Debug::fmt(v, f),
+ Self::Float(v) => Debug::fmt(v, f),
+ Self::Length(v) => Debug::fmt(v, f),
+ Self::Relative(v) => Debug::fmt(v, f),
+ Self::Linear(v) => Debug::fmt(v, f),
+ Self::Color(v) => Debug::fmt(v, f),
+ Self::Str(v) => Debug::fmt(v, f),
+ Self::Array(v) => Debug::fmt(v, f),
+ Self::Dict(v) => Debug::fmt(v, f),
+ Self::Content(v) => Debug::fmt(v, f),
+ Self::Func(v) => Debug::fmt(v, f),
+ Self::Any(v) => Debug::fmt(v, f),
+ Self::Error => f.pad("Error"),
}
}
}
@@ -140,15 +140,18 @@ pub type ValueContent = Tree;
/// A wrapper around a reference-counted executable function.
#[derive(Clone)]
-pub struct ValueFunc(Rc<dyn Fn(&mut EvalContext, &mut Args) -> Value>);
+pub struct ValueFunc {
+ name: String,
+ f: Rc<dyn Fn(&mut EvalContext, &mut Args) -> Value>,
+}
impl ValueFunc {
/// Create a new function value from a rust function or closure.
- pub fn new<F>(func: F) -> Self
+ pub fn new<F>(name: impl Into<String>, f: F) -> Self
where
F: Fn(&mut EvalContext, &mut Args) -> Value + 'static,
{
- Self(Rc::new(func))
+ Self { name: name.into(), f: Rc::new(f) }
}
}
@@ -162,13 +165,18 @@ impl Deref for ValueFunc {
type Target = dyn Fn(&mut EvalContext, &mut Args) -> Value;
fn deref(&self) -> &Self::Target {
- self.0.as_ref()
+ self.f.as_ref()
}
}
+impl Display for ValueFunc {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ write!(f, "<function {}>", self.name)
+ }
+}
impl Debug for ValueFunc {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- f.pad("<function>")
+ Display::fmt(self, f)
}
}
@@ -179,7 +187,7 @@ impl ValueAny {
/// Create a new instance from any value that satisifies the required bounds.
pub fn new<T>(any: T) -> Self
where
- T: Type + Debug + Clone + PartialEq + 'static,
+ T: Type + Debug + Display + Clone + PartialEq + 'static,
{
Self(Box::new(any))
}
@@ -221,13 +229,19 @@ impl PartialEq for ValueAny {
}
}
+impl Display for ValueAny {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ Display::fmt(&self.0, f)
+ }
+}
+
impl Debug for ValueAny {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- self.0.fmt(f)
+ Debug::fmt(&self.0, f)
}
}
-trait Bounds: Debug + 'static {
+trait Bounds: Debug + Display + 'static {
fn as_any(&self) -> &dyn Any;
fn into_any(self: Box<Self>) -> Box<dyn Any>;
fn dyn_eq(&self, other: &ValueAny) -> bool;
@@ -237,7 +251,7 @@ trait Bounds: Debug + 'static {
impl<T> Bounds for T
where
- T: Type + Debug + Clone + PartialEq + 'static,
+ T: Type + Debug + Display + Clone + PartialEq + 'static,
{
fn as_any(&self) -> &dyn Any {
self
@@ -304,6 +318,16 @@ impl<T, V> CastResult<T, V> {
}
}
+impl Type for Value {
+ const TYPE_NAME: &'static str = "value";
+}
+
+impl Cast<Value> for Value {
+ fn cast(value: Value) -> CastResult<Self, Value> {
+ CastResult::Ok(value)
+ }
+}
+
impl<T> Cast<Spanned<Value>> for T
where
T: Cast<Value>,
@@ -390,15 +414,6 @@ impl From<&str> for Value {
}
}
-impl<F> From<F> for Value
-where
- F: Fn(&mut EvalContext, &mut Args) -> Value + 'static,
-{
- fn from(func: F) -> Self {
- Self::Func(ValueFunc::new(func))
- }
-}
-
impl From<ValueAny> for Value {
fn from(v: ValueAny) -> Self {
Self::Any(v)
@@ -407,9 +422,8 @@ impl From<ValueAny> for Value {
/// Make a type usable as a [`Value`].
///
-/// Given a type `T`, this implements the following traits:
+/// Given a type `T`, this always implements the following traits:
/// - [`Type`] for `T`,
-/// - [`From<T>`](From) for [`Value`],
/// - [`Cast<Value>`](Cast) for `T`.
#[macro_export]
macro_rules! impl_type {
@@ -423,12 +437,6 @@ macro_rules! impl_type {
const TYPE_NAME: &'static str = $type_name;
}
- impl From<$type> for $crate::eval::Value {
- fn from(any: $type) -> Self {
- $crate::eval::Value::any(any)
- }
- }
-
impl $crate::eval::Cast<$crate::eval::Value> for $type {
fn cast(
value: $crate::eval::Value,
diff --git a/src/geom/length.rs b/src/geom/length.rs
index 0e445153..23650e89 100644
--- a/src/geom/length.rs
+++ b/src/geom/length.rs
@@ -90,7 +90,7 @@ impl Display for Length {
} else {
(self.to_cm(), Unit::Cm)
};
- write!(f, "{:.2}{}", val, unit)
+ write!(f, "{}{}", (val * 100.0).round() / 100.0, unit)
}
}
@@ -214,8 +214,8 @@ mod tests {
#[test]
fn test_length_formatting() {
- assert_eq!(Length::pt(-28.34).to_string(), "-1.00cm".to_string());
- assert_eq!(Length::pt(23.0).to_string(), "23.00pt".to_string());
+ 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());
}
}
diff --git a/src/geom/relative.rs b/src/geom/relative.rs
index ce473e3d..fdd1f9bb 100644
--- a/src/geom/relative.rs
+++ b/src/geom/relative.rs
@@ -32,7 +32,7 @@ impl Relative {
impl Display for Relative {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "{:.2}%", self.0)
+ write!(f, "{}%", (self.0 * 10000.0).round() / 100.0)
}
}
diff --git a/src/layout/fixed.rs b/src/layout/fixed.rs
index 2ec46df3..cb69b178 100644
--- a/src/layout/fixed.rs
+++ b/src/layout/fixed.rs
@@ -25,8 +25,8 @@ impl Layout for NodeFixed {
}
}
-impl From<NodeFixed> for Node {
+impl From<NodeFixed> for NodeAny {
fn from(fixed: NodeFixed) -> Self {
- Self::any(fixed)
+ Self::new(fixed)
}
}
diff --git a/src/layout/node.rs b/src/layout/node.rs
index c945ee19..fa7fe010 100644
--- a/src/layout/node.rs
+++ b/src/layout/node.rs
@@ -14,16 +14,6 @@ pub enum Node {
Any(NodeAny),
}
-impl Node {
- /// Create a new dynamic node.
- pub fn any<T>(any: T) -> Self
- where
- T: Layout + Debug + Clone + PartialEq + 'static,
- {
- Self::Any(NodeAny::new(any))
- }
-}
-
impl Layout for Node {
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted {
match self {
@@ -81,9 +71,12 @@ impl Debug for NodeAny {
}
}
-impl From<NodeAny> for Node {
- fn from(dynamic: NodeAny) -> Self {
- Self::Any(dynamic)
+impl<T> From<T> for Node
+where
+ T: Into<NodeAny>,
+{
+ fn from(t: T) -> Self {
+ Self::Any(t.into())
}
}
diff --git a/src/layout/pad.rs b/src/layout/pad.rs
index f947a7f5..9e2718c3 100644
--- a/src/layout/pad.rs
+++ b/src/layout/pad.rs
@@ -29,9 +29,9 @@ impl Layout for NodePad {
}
}
-impl From<NodePad> for Node {
+impl From<NodePad> for NodeAny {
fn from(pad: NodePad) -> Self {
- Self::any(pad)
+ Self::new(pad)
}
}
diff --git a/src/layout/par.rs b/src/layout/par.rs
index 3a8e3969..7b2e4e92 100644
--- a/src/layout/par.rs
+++ b/src/layout/par.rs
@@ -36,9 +36,9 @@ impl Layout for NodePar {
}
}
-impl From<NodePar> for Node {
+impl From<NodePar> for NodeAny {
fn from(par: NodePar) -> Self {
- Self::any(par)
+ Self::new(par)
}
}
diff --git a/src/layout/stack.rs b/src/layout/stack.rs
index e98be7ed..eac631d9 100644
--- a/src/layout/stack.rs
+++ b/src/layout/stack.rs
@@ -34,9 +34,9 @@ impl Layout for NodeStack {
}
}
-impl From<NodeStack> for Node {
+impl From<NodeStack> for NodeAny {
fn from(stack: NodeStack) -> Self {
- Self::any(stack)
+ Self::new(stack)
}
}
diff --git a/src/library/extend.rs b/src/library/extend.rs
new file mode 100644
index 00000000..e388c9c8
--- /dev/null
+++ b/src/library/extend.rs
@@ -0,0 +1,16 @@
+use crate::prelude::*;
+
+/// `type`: Find out the name of a value's type.
+///
+/// # Positional arguments
+/// - Any value.
+///
+/// # Return value
+/// The name of the value's type as a string.
+pub fn type_(ctx: &mut EvalContext, args: &mut Args) -> Value {
+ if let Some(value) = args.require::<Value>(ctx, "value") {
+ value.type_name().into()
+ } else {
+ Value::Error
+ }
+}
diff --git a/src/library/insert.rs b/src/library/insert.rs
index 7d95afe3..8d60927a 100644
--- a/src/library/insert.rs
+++ b/src/library/insert.rs
@@ -83,8 +83,8 @@ impl Layout for NodeImage {
}
}
-impl From<NodeImage> for Node {
+impl From<NodeImage> for NodeAny {
fn from(image: NodeImage) -> Self {
- Self::any(image)
+ Self::new(image)
}
}
diff --git a/src/library/layout.rs b/src/library/layout.rs
index e469c9be..774e6781 100644
--- a/src/library/layout.rs
+++ b/src/library/layout.rs
@@ -1,3 +1,5 @@
+use std::fmt::{self, Display, Formatter};
+
use crate::eval::Softness;
use crate::layout::{Expansion, NodeFixed, NodeSpacing, NodeStack};
use crate::paper::{Paper, PaperClass};
@@ -153,7 +155,19 @@ impl Switch for Alignment {
}
impl_type! {
- Alignment: "alignment"
+ Alignment: "alignment",
+}
+
+impl Display for Alignment {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ f.pad(match self {
+ Self::Left => "left",
+ Self::Center => "center",
+ Self::Right => "right",
+ Self::Top => "top",
+ Self::Bottom => "bottom",
+ })
+ }
}
/// `box`: Layout content into a box.
@@ -161,7 +175,7 @@ impl_type! {
/// # Named arguments
/// - Width of the box: `width`, of type `linear` relative to parent width.
/// - Height of the box: `height`, of type `linear` relative to parent height.
-pub fn boxed(ctx: &mut EvalContext, args: &mut Args) -> Value {
+pub fn box_(ctx: &mut EvalContext, args: &mut Args) -> Value {
let snapshot = ctx.state.clone();
let width = args.get(ctx, "width");
@@ -189,7 +203,7 @@ pub fn boxed(ctx: &mut EvalContext, args: &mut Args) -> Value {
ctx.push(NodeFixed {
width,
height,
- child: Node::any(NodeStack { dirs, align, expansion, children }),
+ child: NodeStack { dirs, align, expansion, children }.into(),
});
ctx.state = snapshot;
diff --git a/src/library/mod.rs b/src/library/mod.rs
index 1cc7b9e9..f9047fc6 100644
--- a/src/library/mod.rs
+++ b/src/library/mod.rs
@@ -1,67 +1,78 @@
//! The standard library.
+mod extend;
mod insert;
mod layout;
mod style;
+pub use extend::*;
pub use insert::*;
pub use layout::*;
pub use style::*;
use fontdock::{FontStretch, FontStyle, FontWeight};
-use crate::eval::Scope;
+use crate::eval::{Scope, ValueAny, ValueFunc};
use crate::geom::Dir;
/// The scope containing the standard library.
pub fn _std() -> Scope {
let mut std = Scope::new();
+ macro_rules! set {
+ (func: $name:expr, $func:expr) => {
+ std.set($name, ValueFunc::new($name, $func))
+ };
+ (any: $var:expr, $any:expr) => {
+ std.set($var, ValueAny::new($any))
+ };
+ }
// Functions.
- std.set("align", align);
- std.set("box", boxed);
- std.set("font", font);
- std.set("h", h);
- std.set("image", image);
- std.set("page", page);
- std.set("pagebreak", pagebreak);
- std.set("rgb", rgb);
- std.set("v", v);
+ set!(func: "align", align);
+ set!(func: "box", box_);
+ set!(func: "font", font);
+ set!(func: "h", h);
+ set!(func: "image", image);
+ set!(func: "page", page);
+ set!(func: "pagebreak", pagebreak);
+ set!(func: "rgb", rgb);
+ set!(func: "type", type_);
+ set!(func: "v", v);
// Constants.
- std.set("left", Alignment::Left);
- std.set("center", Alignment::Center);
- std.set("right", Alignment::Right);
- std.set("top", Alignment::Top);
- std.set("bottom", Alignment::Bottom);
- std.set("ltr", Dir::LTR);
- std.set("rtl", Dir::RTL);
- std.set("ttb", Dir::TTB);
- std.set("btt", Dir::BTT);
- std.set("serif", FontFamily::Serif);
- std.set("sans-serif", FontFamily::SansSerif);
- std.set("monospace", FontFamily::Monospace);
- std.set("normal", FontStyle::Normal);
- std.set("italic", FontStyle::Italic);
- std.set("oblique", FontStyle::Oblique);
- std.set("thin", FontWeight::THIN);
- std.set("extralight", FontWeight::EXTRALIGHT);
- std.set("light", FontWeight::LIGHT);
- std.set("regular", FontWeight::REGULAR);
- std.set("medium", FontWeight::MEDIUM);
- std.set("semibold", FontWeight::SEMIBOLD);
- std.set("bold", FontWeight::BOLD);
- std.set("extrabold", FontWeight::EXTRABOLD);
- std.set("black", FontWeight::BLACK);
- std.set("ultra-condensed", FontStretch::UltraCondensed);
- std.set("extra-condensed", FontStretch::ExtraCondensed);
- std.set("condensed", FontStretch::Condensed);
- std.set("semi-condensed", FontStretch::SemiCondensed);
- std.set("normal", FontStretch::Normal);
- std.set("semi-expanded", FontStretch::SemiExpanded);
- std.set("expanded", FontStretch::Expanded);
- std.set("extra-expanded", FontStretch::ExtraExpanded);
- std.set("ultra-expanded", FontStretch::UltraExpanded);
+ set!(any: "left", Alignment::Left);
+ set!(any: "center", Alignment::Center);
+ set!(any: "right", Alignment::Right);
+ set!(any: "top", Alignment::Top);
+ set!(any: "bottom", Alignment::Bottom);
+ set!(any: "ltr", Dir::LTR);
+ set!(any: "rtl", Dir::RTL);
+ set!(any: "ttb", Dir::TTB);
+ set!(any: "btt", Dir::BTT);
+ set!(any: "serif", FontFamily::Serif);
+ set!(any: "sans-serif", FontFamily::SansSerif);
+ set!(any: "monospace", FontFamily::Monospace);
+ set!(any: "normal", FontStyle::Normal);
+ set!(any: "italic", FontStyle::Italic);
+ set!(any: "oblique", FontStyle::Oblique);
+ set!(any: "thin", FontWeight::THIN);
+ set!(any: "extralight", FontWeight::EXTRALIGHT);
+ set!(any: "light", FontWeight::LIGHT);
+ set!(any: "regular", FontWeight::REGULAR);
+ set!(any: "medium", FontWeight::MEDIUM);
+ set!(any: "semibold", FontWeight::SEMIBOLD);
+ set!(any: "bold", FontWeight::BOLD);
+ set!(any: "extrabold", FontWeight::EXTRABOLD);
+ set!(any: "black", FontWeight::BLACK);
+ set!(any: "ultra-condensed", FontStretch::UltraCondensed);
+ set!(any: "extra-condensed", FontStretch::ExtraCondensed);
+ set!(any: "condensed", FontStretch::Condensed);
+ set!(any: "semi-condensed", FontStretch::SemiCondensed);
+ set!(any: "normal", FontStretch::Normal);
+ set!(any: "semi-expanded", FontStretch::SemiExpanded);
+ set!(any: "expanded", FontStretch::Expanded);
+ set!(any: "extra-expanded", FontStretch::ExtraExpanded);
+ set!(any: "ultra-expanded", FontStretch::UltraExpanded);
std
}
diff --git a/src/syntax/span.rs b/src/syntax/span.rs
index 3be770b8..e924b03b 100644
--- a/src/syntax/span.rs
+++ b/src/syntax/span.rs
@@ -269,14 +269,14 @@ impl Location {
}
}
-impl Debug for Location {
+impl Display for Location {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- Display::fmt(self, f)
+ write!(f, "{}:{}", self.line, self.column)
}
}
-impl Display for Location {
+impl Debug for Location {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "{}:{}", self.line, self.column)
+ Display::fmt(self, f)
}
}