summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-08-21 16:38:51 +0200
committerLaurenz <laurmaedje@gmail.com>2021-08-21 17:30:21 +0200
commit0dd4ae0a7ac0c247078df492469ff20b8a90c886 (patch)
tree07a55343b9ccab3fe76b0f1b0de9d1be310d8b14 /src
parentf38eb10c2b54bd13ccef119454839f6a66448462 (diff)
Prune derives
Diffstat (limited to 'src')
-rw-r--r--src/color.rs34
-rw-r--r--src/diag.rs2
-rw-r--r--src/eval/array.rs12
-rw-r--r--src/eval/capture.rs1
-rw-r--r--src/eval/dict.rs24
-rw-r--r--src/eval/function.rs12
-rw-r--r--src/eval/mod.rs135
-rw-r--r--src/eval/scope.rs4
-rw-r--r--src/eval/state.rs6
-rw-r--r--src/eval/str.rs30
-rw-r--r--src/eval/template.rs14
-rw-r--r--src/eval/value.rs48
-rw-r--r--src/eval/walk.rs129
-rw-r--r--src/font.rs47
-rw-r--r--src/geom/angle.rs21
-rw-r--r--src/geom/fr.rs8
-rw-r--r--src/geom/length.rs16
-rw-r--r--src/geom/linear.rs8
-rw-r--r--src/geom/relative.rs8
-rw-r--r--src/geom/sides.rs16
-rw-r--r--src/image.rs3
-rw-r--r--src/layout/background.rs1
-rw-r--r--src/layout/constraints.rs10
-rw-r--r--src/layout/fixed.rs3
-rw-r--r--src/layout/grid.rs5
-rw-r--r--src/layout/image.rs1
-rw-r--r--src/layout/pad.rs1
-rw-r--r--src/layout/par.rs15
-rw-r--r--src/layout/shaping.rs87
-rw-r--r--src/layout/stack.rs2
-rw-r--r--src/layout/tree.rs60
-rw-r--r--src/loading/fs.rs2
-rw-r--r--src/loading/mem.rs2
-rw-r--r--src/loading/mod.rs5
-rw-r--r--src/paper.rs2
-rw-r--r--src/parse/mod.rs4
-rw-r--r--src/parse/parser.rs10
-rw-r--r--src/parse/scanner.rs7
-rw-r--r--src/parse/tokens.rs11
-rw-r--r--src/source.rs15
-rw-r--r--src/syntax/ident.rs2
-rw-r--r--src/syntax/node.rs8
-rw-r--r--src/syntax/pretty.rs16
-rw-r--r--src/syntax/span.rs42
-rw-r--r--src/syntax/token.rs8
-rw-r--r--src/syntax/visit.rs8
-rw-r--r--src/util/eco.rs36
47 files changed, 417 insertions, 524 deletions
diff --git a/src/color.rs b/src/color.rs
index 124c2042..bf4cf05a 100644
--- a/src/color.rs
+++ b/src/color.rs
@@ -12,18 +12,18 @@ pub enum Color {
Rgba(RgbaColor),
}
-impl Display for Color {
+impl Debug for Color {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
- Self::Rgba(c) => Display::fmt(c, f),
+ Self::Rgba(c) => Debug::fmt(c, f),
}
}
}
-impl Debug for Color {
+impl Display for Color {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
- Self::Rgba(c) => Debug::fmt(c, f),
+ Self::Rgba(c) => Display::fmt(c, f),
}
}
}
@@ -97,16 +97,6 @@ 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() {
@@ -121,18 +111,28 @@ impl Debug 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(())
+ }
+}
+
/// The error when parsing an [`RgbaColor`] from a string fails.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct ParseRgbaError;
-impl std::error::Error for ParseRgbaError {}
-
-impl fmt::Display for ParseRgbaError {
+impl Display for ParseRgbaError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.pad("invalid color")
}
}
+impl std::error::Error for ParseRgbaError {}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/src/diag.rs b/src/diag.rs
index 90f640f6..61432e93 100644
--- a/src/diag.rs
+++ b/src/diag.rs
@@ -22,7 +22,7 @@ pub type TypResult<T> = Result<T, Box<Vec<Error>>>;
pub type StrResult<T> = Result<T, String>;
/// An error in a source file.
-#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
+#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct Error {
/// The erroneous location in the source code.
pub span: Span,
diff --git a/src/eval/array.rs b/src/eval/array.rs
index e554b11e..acf44ab2 100644
--- a/src/eval/array.rs
+++ b/src/eval/array.rs
@@ -137,18 +137,18 @@ impl AddAssign for Array {
}
}
-impl FromIterator<Value> for Array {
- fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
- Self(Rc::new(iter.into_iter().collect()))
- }
-}
-
impl Extend<Value> for Array {
fn extend<T: IntoIterator<Item = Value>>(&mut self, iter: T) {
Rc::make_mut(&mut self.0).extend(iter);
}
}
+impl FromIterator<Value> for Array {
+ fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
+ Self(Rc::new(iter.into_iter().collect()))
+ }
+}
+
impl IntoIterator for Array {
type Item = Value;
type IntoIter = std::vec::IntoIter<Value>;
diff --git a/src/eval/capture.rs b/src/eval/capture.rs
index a6e543f9..f0a2b729 100644
--- a/src/eval/capture.rs
+++ b/src/eval/capture.rs
@@ -5,7 +5,6 @@ use crate::syntax::visit::{immutable::visit_expr, Visit};
use crate::syntax::{Expr, Ident};
/// A visitor that captures variable slots.
-#[derive(Debug)]
pub struct CapturesVisitor<'a> {
external: &'a Scopes<'a>,
internal: Scopes<'a>,
diff --git a/src/eval/dict.rs b/src/eval/dict.rs
index 66baaec0..dfac04ed 100644
--- a/src/eval/dict.rs
+++ b/src/eval/dict.rs
@@ -82,6 +82,12 @@ fn missing_key(key: &Str) -> String {
format!("dictionary does not contain key: {}", key)
}
+impl Debug for Dict {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ f.debug_map().entries(self.0.iter()).finish()
+ }
+}
+
impl Display for Dict {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.write_char('(')?;
@@ -100,12 +106,6 @@ impl Display for Dict {
}
}
-impl Debug for Dict {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- f.debug_map().entries(self.0.iter()).finish()
- }
-}
-
impl Add for Dict {
type Output = Self;
@@ -124,18 +124,18 @@ impl AddAssign for Dict {
}
}
-impl FromIterator<(Str, Value)> for Dict {
- fn from_iter<T: IntoIterator<Item = (Str, Value)>>(iter: T) -> Self {
- Self(Rc::new(iter.into_iter().collect()))
- }
-}
-
impl Extend<(Str, Value)> for Dict {
fn extend<T: IntoIterator<Item = (Str, Value)>>(&mut self, iter: T) {
Rc::make_mut(&mut self.0).extend(iter);
}
}
+impl FromIterator<(Str, Value)> for Dict {
+ fn from_iter<T: IntoIterator<Item = (Str, Value)>>(iter: T) -> Self {
+ Self(Rc::new(iter.into_iter().collect()))
+ }
+}
+
impl IntoIterator for Dict {
type Item = (Str, Value);
type IntoIter = std::collections::btree_map::IntoIter<Str, Value>;
diff --git a/src/eval/function.rs b/src/eval/function.rs
index 7967090b..57364d11 100644
--- a/src/eval/function.rs
+++ b/src/eval/function.rs
@@ -38,6 +38,12 @@ impl Function {
}
}
+impl Debug for Function {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ f.debug_struct("Function").field("name", &self.0.name).finish()
+ }
+}
+
impl Display for Function {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.write_str("<function")?;
@@ -49,12 +55,6 @@ impl Display for Function {
}
}
-impl Debug for Function {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- f.debug_struct("Function").field("name", &self.0.name).finish()
- }
-}
-
impl PartialEq for Function {
fn eq(&self, other: &Self) -> bool {
// We cast to thin pointers for comparison.
diff --git a/src/eval/mod.rs b/src/eval/mod.rs
index f7a32127..b8561a87 100644
--- a/src/eval/mod.rs
+++ b/src/eval/mod.rs
@@ -13,6 +13,7 @@ mod scope;
mod state;
mod str;
mod template;
+mod walk;
pub use self::str::*;
pub use array::*;
@@ -23,25 +24,24 @@ pub use scope::*;
pub use state::*;
pub use template::*;
pub use value::*;
+pub use walk::*;
use std::cell::RefMut;
use std::collections::HashMap;
-use std::fmt::Write;
use std::io;
use std::mem;
use std::path::PathBuf;
use std::rc::Rc;
use crate::diag::{At, Error, StrResult, Trace, Tracepoint, TypResult};
-use crate::geom::{Angle, Fractional, Gen, Length, Relative};
+use crate::geom::{Angle, Fractional, Length, Relative};
use crate::image::ImageStore;
-use crate::layout::{ParChild, ParNode, StackChild, StackNode};
use crate::loading::Loader;
use crate::parse::parse;
use crate::source::{SourceId, SourceStore};
use crate::syntax::visit::Visit;
use crate::syntax::*;
-use crate::util::{EcoString, RefMutExt};
+use crate::util::RefMutExt;
use crate::Context;
/// Evaluate a parsed source file into a module.
@@ -52,7 +52,7 @@ pub fn eval(ctx: &mut Context, source: SourceId, ast: &SyntaxTree) -> TypResult<
}
/// An evaluated module, ready for importing or instantiation.
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Default, Clone)]
pub struct Module {
/// The top-level definitions that were bound in this module.
pub scope: Scope,
@@ -717,128 +717,3 @@ impl Access for CallExpr {
})
}
}
-
-/// Walk a syntax node and fill the currently built template.
-pub trait Walk {
- /// Walk the node.
- fn walk(&self, ctx: &mut EvalContext) -> TypResult<()>;
-}
-
-impl Walk for SyntaxTree {
- fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> {
- for node in self.iter() {
- node.walk(ctx)?;
- }
- Ok(())
- }
-}
-
-impl Walk for SyntaxNode {
- fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> {
- match self {
- Self::Space => ctx.template.space(),
- Self::Linebreak(_) => ctx.template.linebreak(),
- Self::Parbreak(_) => ctx.template.parbreak(),
- Self::Strong(_) => {
- ctx.template.modify(|state| state.font_mut().strong ^= true);
- }
- Self::Emph(_) => {
- ctx.template.modify(|state| state.font_mut().emph ^= true);
- }
- Self::Text(text) => ctx.template.text(text),
- Self::Raw(raw) => raw.walk(ctx)?,
- Self::Heading(heading) => heading.walk(ctx)?,
- Self::List(list) => list.walk(ctx)?,
- Self::Enum(enum_) => enum_.walk(ctx)?,
- Self::Expr(expr) => match expr.eval(ctx)? {
- Value::None => {}
- Value::Int(v) => ctx.template.text(v.to_string()),
- Value::Float(v) => ctx.template.text(v.to_string()),
- Value::Str(v) => ctx.template.text(v),
- Value::Template(v) => ctx.template += v,
- // For values which can't be shown "naturally", we print the
- // representation in monospace.
- other => ctx.template.monospace(other.to_string()),
- },
- }
- Ok(())
- }
-}
-
-impl Walk for RawNode {
- fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> {
- if self.block {
- ctx.template.parbreak();
- }
-
- ctx.template.monospace(&self.text);
-
- if self.block {
- ctx.template.parbreak();
- }
-
- Ok(())
- }
-}
-
-impl Walk for HeadingNode {
- fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> {
- let level = self.level;
- let body = self.body.eval(ctx)?;
-
- ctx.template.parbreak();
- ctx.template.save();
- ctx.template.modify(move |state| {
- let font = state.font_mut();
- let upscale = 1.6 - 0.1 * level as f64;
- font.size *= upscale;
- font.strong = true;
- });
- ctx.template += body;
- ctx.template.restore();
- ctx.template.parbreak();
-
- Ok(())
- }
-}
-
-impl Walk for ListItem {
- fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> {
- let body = self.body.eval(ctx)?;
- walk_item(ctx, '•'.into(), body);
- Ok(())
- }
-}
-
-impl Walk for EnumItem {
- fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> {
- let body = self.body.eval(ctx)?;
- let mut label = EcoString::new();
- write!(&mut label, "{}.", self.number.unwrap_or(1)).unwrap();
- walk_item(ctx, label, body);
- Ok(())
- }
-}
-
-/// Walk a list or enum item, converting it into a stack.
-fn walk_item(ctx: &mut EvalContext, label: EcoString, body: Template) {
- ctx.template += Template::from_block(move |state| {
- let label = ParNode {
- dir: state.dirs.cross,
- line_spacing: state.line_spacing(),
- children: vec![ParChild::Text(
- label.clone(),
- state.aligns.cross,
- Rc::clone(&state.font),
- )],
- };
- StackNode {
- dirs: Gen::new(state.dirs.main, state.dirs.cross),
- children: vec![
- StackChild::Any(label.into(), Gen::default()),
- StackChild::Spacing((state.font.size / 2.0).into()),
- StackChild::Any(body.to_stack(&state).into(), Gen::default()),
- ],
- }
- });
-}
diff --git a/src/eval/scope.rs b/src/eval/scope.rs
index 2968ca20..0d701687 100644
--- a/src/eval/scope.rs
+++ b/src/eval/scope.rs
@@ -12,7 +12,7 @@ use crate::util::EcoString;
pub type Slot = Rc<RefCell<Value>>;
/// A stack of scopes.
-#[derive(Debug, Default, Clone, PartialEq)]
+#[derive(Debug, Default, Clone)]
pub struct Scopes<'a> {
/// The active scope.
pub top: Scope,
@@ -65,7 +65,7 @@ impl<'a> Scopes<'a> {
}
/// A map from variable names to variable slots.
-#[derive(Default, Clone, PartialEq)]
+#[derive(Default, Clone)]
pub struct Scope {
/// The mapping from names to slots.
values: HashMap<EcoString, Slot>,
diff --git a/src/eval/state.rs b/src/eval/state.rs
index 760a830a..05558915 100644
--- a/src/eval/state.rs
+++ b/src/eval/state.rs
@@ -63,7 +63,7 @@ impl Default for State {
}
/// Defines page properties.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct PageState {
/// The class of this page.
pub class: PaperClass,
@@ -220,7 +220,7 @@ impl Default for FontState {
}
/// Font family definitions.
-#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct FamilyState {
/// The user-defined list of font families.
pub list: Rc<Vec<FontFamily>>,
@@ -250,7 +250,7 @@ impl Default for FamilyState {
}
/// Defines a line that is positioned over, under or on top of text.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct LineState {
/// Stroke color of the line, defaults to the text color if `None`.
pub stroke: Option<Paint>,
diff --git a/src/eval/str.rs b/src/eval/str.rs
index 1a0e3e1f..a358cd9f 100644
--- a/src/eval/str.rs
+++ b/src/eval/str.rs
@@ -6,7 +6,7 @@ use crate::diag::StrResult;
use crate::util::EcoString;
/// A string value with inline storage and clone-on-write semantics.
-#[derive(Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
+#[derive(Default, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct Str(EcoString);
impl Str {
@@ -46,6 +46,20 @@ impl Str {
}
}
+impl Deref for Str {
+ type Target = str;
+
+ fn deref(&self) -> &str {
+ self.0.deref()
+ }
+}
+
+impl Debug for Str {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ Debug::fmt(&self.0, f)
+ }
+}
+
impl Display for Str {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.write_char('"')?;
@@ -63,20 +77,6 @@ impl Display for Str {
}
}
-impl Debug for Str {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- Debug::fmt(&self.0, f)
- }
-}
-
-impl Deref for Str {
- type Target = str;
-
- fn deref(&self) -> &str {
- self.0.deref()
- }
-}
-
impl Add for Str {
type Output = Self;
diff --git a/src/eval/template.rs b/src/eval/template.rs
index 2293796b..92b3eb86 100644
--- a/src/eval/template.rs
+++ b/src/eval/template.rs
@@ -160,15 +160,15 @@ impl Template {
}
}
-impl Display for Template {
+impl Debug for Template {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- f.pad("<template>")
+ f.pad("Template { .. }")
}
}
-impl Debug for Template {
+impl Display for Template {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- f.pad("Template { .. }")
+ f.pad("<template>")
}
}
@@ -465,11 +465,11 @@ impl ParBuilder {
}
fn push_inner(&mut self, child: ParChild) {
- if let ParChild::Text(curr_text, curr_props, curr_align) = &child {
- if let Some(ParChild::Text(prev_text, prev_props, prev_align)) =
+ if let ParChild::Text(curr_text, curr_align, curr_props) = &child {
+ if let Some(ParChild::Text(prev_text, prev_align, prev_props)) =
self.children.last_mut()
{
- if prev_align == curr_align && prev_props == curr_props {
+ if prev_align == curr_align && Rc::ptr_eq(prev_props, curr_props) {
prev_text.push_str(&curr_text);
return;
}
diff --git a/src/eval/value.rs b/src/eval/value.rs
index 99efc2e5..5edf0362 100644
--- a/src/eval/value.rs
+++ b/src/eval/value.rs
@@ -144,6 +144,12 @@ impl From<usize> for Value {
}
}
+impl From<RgbaColor> for Value {
+ fn from(v: RgbaColor) -> Self {
+ Self::Color(Color::Rgba(v))
+ }
+}
+
impl From<&str> for Value {
fn from(v: &str) -> Self {
Self::Str(v.into())
@@ -162,12 +168,6 @@ impl From<EcoString> for Value {
}
}
-impl From<RgbaColor> for Value {
- fn from(v: RgbaColor) -> Self {
- Self::Color(Color::Rgba(v))
- }
-}
-
impl From<Dynamic> for Value {
fn from(v: Dynamic) -> Self {
Self::Dyn(v)
@@ -181,7 +181,7 @@ impl Dynamic {
/// Create a new instance from any value that satisifies the required bounds.
pub fn new<T>(any: T) -> Self
where
- T: Type + Debug + Display + Clone + PartialEq + 'static,
+ T: Type + Debug + Display + PartialEq + 'static,
{
Self(Rc::new(any))
}
@@ -202,15 +202,15 @@ impl Dynamic {
}
}
-impl Display for Dynamic {
+impl Debug for Dynamic {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- Display::fmt(&self.0, f)
+ Debug::fmt(&self.0, f)
}
}
-impl Debug for Dynamic {
+impl Display for Dynamic {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- Debug::fmt(&self.0, f)
+ Display::fmt(&self.0, f)
}
}
@@ -228,7 +228,7 @@ trait Bounds: Debug + Display + 'static {
impl<T> Bounds for T
where
- T: Type + Debug + Display + Clone + PartialEq + 'static,
+ T: Type + Debug + Display + PartialEq + 'static,
{
fn as_any(&self) -> &dyn Any {
self
@@ -309,12 +309,6 @@ macro_rules! primitive {
const TYPE_NAME: &'static str = $name;
}
- impl From<$type> for Value {
- fn from(v: $type) -> Self {
- Value::$variant(v)
- }
- }
-
impl Cast<Value> for $type {
fn is(value: &Value) -> bool {
matches!(value, Value::$variant(_) $(| Value::$other(_))*)
@@ -332,6 +326,12 @@ macro_rules! primitive {
}
}
}
+
+ impl From<$type> for Value {
+ fn from(v: $type) -> Self {
+ Value::$variant(v)
+ }
+ }
};
}
@@ -342,17 +342,17 @@ macro_rules! dynamic {
const TYPE_NAME: &'static str = $name;
}
- impl From<$type> for $crate::eval::Value {
- fn from(v: $type) -> Self {
- $crate::eval::Value::Dyn($crate::eval::Dynamic::new(v))
- }
- }
-
castable! {
$type: <Self as $crate::eval::Type>::TYPE_NAME,
$($tts)*
@this: Self => this.clone(),
}
+
+ impl From<$type> for $crate::eval::Value {
+ fn from(v: $type) -> Self {
+ $crate::eval::Value::Dyn($crate::eval::Dynamic::new(v))
+ }
+ }
};
}
diff --git a/src/eval/walk.rs b/src/eval/walk.rs
new file mode 100644
index 00000000..4c6a1605
--- /dev/null
+++ b/src/eval/walk.rs
@@ -0,0 +1,129 @@
+use std::fmt::Write;
+use std::rc::Rc;
+
+use super::{Eval, EvalContext, Template, Value};
+use crate::diag::TypResult;
+use crate::geom::Gen;
+use crate::layout::{ParChild, ParNode, StackChild, StackNode};
+use crate::syntax::*;
+use crate::util::EcoString;
+
+/// Walk a syntax node and fill the currently built template.
+pub trait Walk {
+ /// Walk the node.
+ fn walk(&self, ctx: &mut EvalContext) -> TypResult<()>;
+}
+
+impl Walk for SyntaxTree {
+ fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> {
+ for node in self.iter() {
+ node.walk(ctx)?;
+ }
+ Ok(())
+ }
+}
+
+impl Walk for SyntaxNode {
+ fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> {
+ match self {
+ Self::Space => ctx.template.space(),
+ Self::Linebreak(_) => ctx.template.linebreak(),
+ Self::Parbreak(_) => ctx.template.parbreak(),
+ Self::Strong(_) => ctx.template.modify(|s| s.font_mut().strong ^= true),
+ Self::Emph(_) => ctx.template.modify(|s| s.font_mut().emph ^= true),
+ Self::Text(text) => ctx.template.text(text),
+ Self::Raw(raw) => raw.walk(ctx)?,
+ Self::Heading(heading) => heading.walk(ctx)?,
+ Self::List(list) => list.walk(ctx)?,
+ Self::Enum(enum_) => enum_.walk(ctx)?,
+ Self::Expr(expr) => match expr.eval(ctx)? {
+ Value::None => {}
+ Value::Int(v) => ctx.template.text(v.to_string()),
+ Value::Float(v) => ctx.template.text(v.to_string()),
+ Value::Str(v) => ctx.template.text(v),
+ Value::Template(v) => ctx.template += v,
+ // For values which can't be shown "naturally", we print the
+ // representation in monospace.
+ other => ctx.template.monospace(other.to_string()),
+ },
+ }
+ Ok(())
+ }
+}
+
+impl Walk for RawNode {
+ fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> {
+ if self.block {
+ ctx.template.parbreak();
+ }
+
+ ctx.template.monospace(&self.text);
+
+ if self.block {
+ ctx.template.parbreak();
+ }
+
+ Ok(())
+ }
+}
+
+impl Walk for HeadingNode {
+ fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> {
+ let level = self.level;
+ let body = self.body.eval(ctx)?;
+
+ ctx.template.parbreak();
+ ctx.template.save();
+ ctx.template.modify(move |state| {
+ let font = state.font_mut();
+ let upscale = 1.6 - 0.1 * level as f64;
+ font.size *= upscale;
+ font.strong = true;
+ });
+ ctx.template += body;
+ ctx.template.restore();
+ ctx.template.parbreak();
+
+ Ok(())
+ }
+}
+
+impl Walk for ListNode {
+ fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> {
+ let body = self.body.eval(ctx)?;
+ walk_item(ctx, '•'.into(), body);
+ Ok(())
+ }
+}
+
+impl Walk for EnumNode {
+ fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> {
+ let body = self.body.eval(ctx)?;
+ let mut label = EcoString::new();
+ write!(&mut label, "{}.", self.number.unwrap_or(1)).unwrap();
+ walk_item(ctx, label, body);
+ Ok(())
+ }
+}
+
+fn walk_item(ctx: &mut EvalContext, label: EcoString, body: Template) {
+ ctx.template += Template::from_block(move |state| {
+ let label = ParNode {
+ dir: state.dirs.cross,
+ line_spacing: state.line_spacing(),
+ children: vec![ParChild::Text(
+ label.clone(),
+ state.aligns.cross,
+ Rc::clone(&state.font),
+ )],
+ };
+ StackNode {
+ dirs: Gen::new(state.dirs.main, state.dirs.cross),
+ children: vec![
+ StackChild::Any(label.into(), Gen::default()),
+ StackChild::Spacing((state.font.size / 2.0).into()),
+ StackChild::Any(body.to_stack(&state).into(), Gen::default()),
+ ],
+ }
+ });
+}
diff --git a/src/font.rs b/src/font.rs
index 978fb601..dadf6830 100644
--- a/src/font.rs
+++ b/src/font.rs
@@ -14,8 +14,7 @@ use crate::geom::Length;
use crate::loading::{FileHash, Loader};
/// A unique identifier for a loaded font face.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
-#[derive(Serialize, Deserialize)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct FaceId(u32);
impl FaceId {
@@ -271,7 +270,7 @@ impl Face {
/// A length in em units.
///
/// `1em` is the same as the font size.
-#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, PartialOrd)]
+#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct Em(N64);
impl Em {
@@ -343,11 +342,15 @@ impl Display for VerticalFontMetric {
}
/// A generic or named font family.
-#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum FontFamily {
+ /// A family that has "serifs", small strokes attached to letters.
Serif,
+ /// A family in which glyphs do not have "serifs", small attached strokes.
SansSerif,
+ /// A family in which (almost) all glyphs are of equal width.
Monospace,
+ /// A specific family with a name.
Named(String),
}
@@ -575,15 +578,6 @@ impl Default for FontWeight {
}
}
-impl Display for FontWeight {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- match self.to_str() {
- Some(name) => f.pad(name),
- None => write!(f, "{}", self.0),
- }
- }
-}
-
impl Debug for FontWeight {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.pad(match *self {
@@ -601,6 +595,15 @@ impl Debug for FontWeight {
}
}
+impl Display for FontWeight {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ match self.to_str() {
+ Some(name) => f.pad(name),
+ None => write!(f, "{}", self.0),
+ }
+ }
+}
+
/// The width of a font face.
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[derive(Serialize, Deserialize)]
@@ -707,15 +710,6 @@ impl Default for FontStretch {
}
}
-impl Display for FontStretch {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- match self.to_str() {
- Some(name) => f.pad(name),
- None => write!(f, "{}", self.to_ratio()),
- }
- }
-}
-
impl Debug for FontStretch {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.pad(match *self {
@@ -733,6 +727,15 @@ impl Debug for FontStretch {
}
}
+impl Display for FontStretch {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ match self.to_str() {
+ Some(name) => f.pad(name),
+ None => write!(f, "{}", self.to_ratio()),
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/src/geom/angle.rs b/src/geom/angle.rs
index 8f18210c..cf3e49a0 100644
--- a/src/geom/angle.rs
+++ b/src/geom/angle.rs
@@ -1,8 +1,11 @@
-use super::*;
use decorum::N64;
+use serde::{Deserialize, Serialize};
+
+use super::*;
/// An angle.
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
+#[derive(Serialize, Deserialize)]
pub struct Angle(N64);
impl Angle {
@@ -52,6 +55,13 @@ impl Angle {
}
}
+impl Debug for Angle {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ let unit = AngularUnit::Deg;
+ write!(f, "{}{}", self.to_unit(unit), unit)
+ }
+}
+
impl Display for Angle {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
// Format with the unit that yields the shortest output, preferring
@@ -66,13 +76,6 @@ impl Display for Angle {
}
}
-impl Debug for Angle {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- let unit = AngularUnit::Deg;
- write!(f, "{}{}", self.to_unit(unit), unit)
- }
-}
-
impl Neg for Angle {
type Output = Self;
@@ -134,7 +137,7 @@ impl Sum for Angle {
}
}
/// Different units of angular measurement.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum AngularUnit {
/// Radians.
Rad,
diff --git a/src/geom/fr.rs b/src/geom/fr.rs
index 1768366a..eaf539d9 100644
--- a/src/geom/fr.rs
+++ b/src/geom/fr.rs
@@ -33,15 +33,15 @@ impl Fractional {
}
}
-impl Display for Fractional {
+impl Debug for Fractional {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "{}fr", self.get())
+ Display::fmt(self, f)
}
}
-impl Debug for Fractional {
+impl Display for Fractional {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- Display::fmt(self, f)
+ write!(f, "{}fr", self.get())
}
}
diff --git a/src/geom/length.rs b/src/geom/length.rs
index 343b523c..3510fa6f 100644
--- a/src/geom/length.rs
+++ b/src/geom/length.rs
@@ -126,6 +126,13 @@ impl Length {
}
}
+impl Debug for Length {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ let unit = LengthUnit::Pt;
+ write!(f, "{}{}", self.to_unit(unit), unit)
+ }
+}
+
impl Display for Length {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
use LengthUnit::*;
@@ -142,13 +149,6 @@ impl Display for Length {
}
}
-impl Debug for Length {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- let unit = LengthUnit::Pt;
- write!(f, "{}{}", self.to_unit(unit), unit)
- }
-}
-
impl Neg for Length {
type Output = Self;
@@ -217,7 +217,7 @@ impl<'a> Sum<&'a Length> for Length {
}
/// Different units of length measurement.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum LengthUnit {
/// Points.
Pt,
diff --git a/src/geom/linear.rs b/src/geom/linear.rs
index 38d19b13..6a20b826 100644
--- a/src/geom/linear.rs
+++ b/src/geom/linear.rs
@@ -47,15 +47,15 @@ impl Linear {
}
}
-impl Display for Linear {
+impl Debug for Linear {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "{} + {}", self.rel, self.abs)
+ write!(f, "{:?} + {:?}", self.rel, self.abs)
}
}
-impl Debug for Linear {
+impl Display for Linear {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "{:?} + {:?}", self.rel, self.abs)
+ write!(f, "{} + {}", self.rel, self.abs)
}
}
diff --git a/src/geom/relative.rs b/src/geom/relative.rs
index 149c0b9c..7785788c 100644
--- a/src/geom/relative.rs
+++ b/src/geom/relative.rs
@@ -46,15 +46,15 @@ impl Relative {
}
}
-impl Display for Relative {
+impl Debug for Relative {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "{}%", 100.0 * self.get())
+ Display::fmt(self, f)
}
}
-impl Debug for Relative {
+impl Display for Relative {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- Display::fmt(self, f)
+ write!(f, "{}%", 100.0 * self.get())
}
}
diff --git a/src/geom/sides.rs b/src/geom/sides.rs
index f9fdc01f..d4fdf247 100644
--- a/src/geom/sides.rs
+++ b/src/geom/sides.rs
@@ -33,6 +33,14 @@ impl<T> Sides<T> {
}
}
+impl Sides<Length> {
+ /// A size with `left` and `right` summed into `width`, and `top` and
+ /// `bottom` summed into `height`.
+ pub fn size(self) -> Size {
+ Size::new(self.left + self.right, self.top + self.bottom)
+ }
+}
+
impl Sides<Linear> {
/// Resolve the linear sides relative to the given `size`.
pub fn resolve(self, size: Size) -> Sides<Length> {
@@ -45,14 +53,6 @@ impl Sides<Linear> {
}
}
-impl Sides<Length> {
- /// A size with `left` and `right` summed into `width`, and `top` and
- /// `bottom` summed into `height`.
- pub fn size(self) -> Size {
- Size::new(self.left + self.right, self.top + self.bottom)
- }
-}
-
impl<T> Get<Side> for Sides<T> {
type Component = T;
diff --git a/src/image.rs b/src/image.rs
index 6ccfb11d..455f3105 100644
--- a/src/image.rs
+++ b/src/image.rs
@@ -13,8 +13,7 @@ use serde::{Deserialize, Serialize};
use crate::loading::{FileHash, Loader};
/// A unique identifier for a loaded image.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
-#[derive(Serialize, Deserialize)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct ImageId(u32);
impl ImageId {
diff --git a/src/layout/background.rs b/src/layout/background.rs
index 793782fd..306afd67 100644
--- a/src/layout/background.rs
+++ b/src/layout/background.rs
@@ -1,7 +1,6 @@
use super::*;
/// A node that places a rectangular filled background behind its child.
-#[derive(Debug, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "layout-cache", derive(Hash))]
pub struct BackgroundNode {
/// The kind of shape to use as a background.
diff --git a/src/layout/constraints.rs b/src/layout/constraints.rs
index 1a26daeb..d808abd9 100644
--- a/src/layout/constraints.rs
+++ b/src/layout/constraints.rs
@@ -1,5 +1,3 @@
-use std::ops::Deref;
-
use super::*;
/// Carries an item that is only valid in certain regions and the constraints
@@ -12,14 +10,6 @@ pub struct Constrained<T> {
pub constraints: Constraints,
}
-impl<T> Deref for Constrained<T> {
- type Target = T;
-
- fn deref(&self) -> &Self::Target {
- &self.item
- }
-}
-
/// Describe regions that match them.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct Constraints {
diff --git a/src/layout/fixed.rs b/src/layout/fixed.rs
index 7f292f14..02660d1d 100644
--- a/src/layout/fixed.rs
+++ b/src/layout/fixed.rs
@@ -3,7 +3,6 @@ use decorum::N64;
use super::*;
/// A node that can fix its child's width and height.
-#[derive(Debug, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "layout-cache", derive(Hash))]
pub struct FixedNode {
/// The fixed width, if any.
@@ -78,7 +77,7 @@ impl Layout for FixedNode {
// relayout with expansion.
if let Some(aspect) = aspect {
if width.is_none() && height.is_none() {
- let needed = frames[0].size.cap(size);
+ let needed = frames[0].item.size.cap(size);
let width = needed.width.max(aspect * needed.height);
regions.current = Size::new(width, width / aspect);
regions.expand = Spec::splat(true);
diff --git a/src/layout/grid.rs b/src/layout/grid.rs
index d9b56b48..b4a1fe79 100644
--- a/src/layout/grid.rs
+++ b/src/layout/grid.rs
@@ -1,7 +1,6 @@
use super::*;
/// A node that arranges its children in a grid.
-#[derive(Debug, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "layout-cache", derive(Hash))]
pub struct GridNode {
/// The `main` and `cross` directions of this grid.
@@ -256,7 +255,7 @@ impl<'a> GridLayouter<'a> {
for node in (0 .. self.rows.len()).filter_map(|y| self.cell(x, y)) {
let size = Gen::new(available, Length::inf()).to_size(self.main);
let regions = Regions::one(size, size, Spec::splat(false));
- let frame = node.layout(ctx, &regions).remove(0);
+ let frame = node.layout(ctx, &regions).remove(0).item;
resolved.set_max(frame.size.get(self.cross));
}
@@ -353,7 +352,7 @@ impl<'a> GridLayouter<'a> {
let mut sizes = node
.layout(ctx, &self.regions)
.into_iter()
- .map(|frame| frame.size.get(self.main));
+ .map(|frame| frame.item.size.get(self.main));
if let Some(size) = sizes.next() {
first.set_max(size);
diff --git a/src/layout/image.rs b/src/layout/image.rs
index 02a907f5..e3e5e741 100644
--- a/src/layout/image.rs
+++ b/src/layout/image.rs
@@ -4,7 +4,6 @@ use crate::image::ImageId;
use ::image::GenericImageView;
/// An image node.
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "layout-cache", derive(Hash))]
pub struct ImageNode {
/// The id of the image file.
diff --git a/src/layout/pad.rs b/src/layout/pad.rs
index 51025e3c..3075472b 100644
--- a/src/layout/pad.rs
+++ b/src/layout/pad.rs
@@ -1,7 +1,6 @@
use super::*;
/// A node that adds padding to its child.
-#[derive(Debug, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "layout-cache", derive(Hash))]
pub struct PadNode {
/// The amount of padding.
diff --git a/src/layout/par.rs b/src/layout/par.rs
index 317a91ad..84d784b0 100644
--- a/src/layout/par.rs
+++ b/src/layout/par.rs
@@ -1,4 +1,3 @@
-use std::fmt::{self, Debug, Formatter};
use std::rc::Rc;
use unicode_bidi::{BidiInfo, Level};
@@ -11,7 +10,6 @@ use crate::util::{EcoString, RangeExt, SliceExt};
type Range = std::ops::Range<usize>;
/// A node that arranges its children into a paragraph.
-#[derive(Debug, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "layout-cache", derive(Hash))]
pub struct ParNode {
/// The inline direction of this paragraph.
@@ -23,7 +21,6 @@ pub struct ParNode {
}
/// A child of a paragraph node.
-#[derive(Clone, Eq, PartialEq)]
#[cfg_attr(feature = "layout-cache", derive(Hash))]
pub enum ParChild {
/// Spacing between other nodes.
@@ -94,18 +91,6 @@ impl From<ParNode> for LayoutNode {
}
}
-impl Debug for ParChild {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- match self {
- Self::Spacing(amount) => write!(f, "Spacing({:?})", amount),
- Self::Text(text, align, _) => write!(f, "Text({:?}, {:?})", text, align),
- Self::Any(any, align) => {
- f.debug_tuple("Any").field(any).field(align).finish()
- }
- }
- }
-}
-
/// A paragraph representation in which children are already layouted and text
/// is separated into shapable runs.
struct ParLayouter<'a> {
diff --git a/src/layout/shaping.rs b/src/layout/shaping.rs
index ba8704ea..fad7f234 100644
--- a/src/layout/shaping.rs
+++ b/src/layout/shaping.rs
@@ -1,5 +1,4 @@
use std::borrow::Cow;
-use std::fmt::{self, Debug, Formatter};
use std::ops::Range;
use rustybuzz::UnicodeBuffer;
@@ -11,12 +10,45 @@ use crate::geom::{Dir, Length, Point, Size};
use crate::layout::Geometry;
use crate::util::SliceExt;
+/// Shape text into [`ShapedText`].
+pub fn shape<'a>(
+ ctx: &mut LayoutContext,
+ text: &'a str,
+ dir: Dir,
+ state: &'a FontState,
+) -> ShapedText<'a> {
+ let mut glyphs = vec![];
+ if !text.is_empty() {
+ shape_segment(
+ ctx,
+ &mut glyphs,
+ 0,
+ text,
+ dir,
+ state.size,
+ state.variant(),
+ state.families(),
+ None,
+ );
+ }
+
+ let (size, baseline) = measure(ctx, &glyphs, state);
+
+ ShapedText {
+ text,
+ dir,
+ state,
+ size,
+ baseline,
+ glyphs: Cow::Owned(glyphs),
+ }
+}
+
/// The result of shaping text.
///
/// This type contains owned or borrowed shaped text runs, which can be
/// measured, used to reshape substrings more quickly and converted into a
/// frame.
-#[derive(Clone)]
pub struct ShapedText<'a> {
/// The text that was shaped.
pub text: &'a str,
@@ -33,7 +65,7 @@ pub struct ShapedText<'a> {
}
/// A single glyph resulting from shaping.
-#[derive(Debug, Copy, Clone)]
+#[derive(Copy, Clone)]
pub struct ShapedGlyph {
/// The font face the glyph is contained in.
pub face_id: FaceId,
@@ -51,13 +83,6 @@ pub struct ShapedGlyph {
pub safe_to_break: bool,
}
-/// A visual side.
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
-enum Side {
- Left,
- Right,
-}
-
impl<'a> ShapedText<'a> {
/// Build the shaped text's frame.
pub fn build(&self, ctx: &LayoutContext) -> Frame {
@@ -174,44 +199,10 @@ impl<'a> ShapedText<'a> {
}
}
-impl Debug for ShapedText<'_> {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "Shaped({:?})", self.text)
- }
-}
-
-/// Shape text into [`ShapedText`].
-pub fn shape<'a>(
- ctx: &mut LayoutContext,
- text: &'a str,
- dir: Dir,
- state: &'a FontState,
-) -> ShapedText<'a> {
- let mut glyphs = vec![];
- if !text.is_empty() {
- shape_segment(
- ctx,
- &mut glyphs,
- 0,
- text,
- dir,
- state.size,
- state.variant(),
- state.families(),
- None,
- );
- }
-
- let (size, baseline) = measure(ctx, &glyphs, state);
-
- ShapedText {
- text,
- dir,
- state,
- size,
- baseline,
- glyphs: Cow::Owned(glyphs),
- }
+/// A visual side.
+enum Side {
+ Left,
+ Right,
}
/// Shape text with font fallback using the `families` iterator.
diff --git a/src/layout/stack.rs b/src/layout/stack.rs
index 51d17807..d07f68d7 100644
--- a/src/layout/stack.rs
+++ b/src/layout/stack.rs
@@ -1,7 +1,6 @@
use super::*;
/// A node that stacks its children.
-#[derive(Debug, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "layout-cache", derive(Hash))]
pub struct StackNode {
/// The `main` and `cross` directions of this stack.
@@ -14,7 +13,6 @@ pub struct StackNode {
}
/// A child of a stack node.
-#[derive(Debug, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "layout-cache", derive(Hash))]
pub enum StackChild {
/// Spacing between other nodes.
diff --git a/src/layout/tree.rs b/src/layout/tree.rs
index 1899a4d2..05f94c38 100644
--- a/src/layout/tree.rs
+++ b/src/layout/tree.rs
@@ -1,7 +1,6 @@
use super::*;
use std::any::Any;
-use std::fmt::{self, Debug, Formatter};
#[cfg(feature = "layout-cache")]
use std::hash::{Hash, Hasher};
@@ -10,7 +9,6 @@ use std::hash::{Hash, Hasher};
use fxhash::FxHasher64;
/// A tree of layout nodes.
-#[derive(Debug, Clone, Eq, PartialEq)]
pub struct LayoutTree {
/// Runs of pages with the same properties.
pub runs: Vec<PageRun>,
@@ -24,7 +22,6 @@ impl LayoutTree {
}
/// A run of pages that all have the same properties.
-#[derive(Debug, Clone, Eq, PartialEq)]
pub struct PageRun {
/// The size of each page.
pub size: Size,
@@ -47,7 +44,7 @@ impl PageRun {
/// A dynamic layouting node.
pub struct LayoutNode {
- node: Box<dyn Bounds>,
+ node: Box<dyn Layout>,
#[cfg(feature = "layout-cache")]
hash: u64,
}
@@ -57,7 +54,7 @@ impl LayoutNode {
#[cfg(not(feature = "layout-cache"))]
pub fn new<T>(node: T) -> Self
where
- T: Layout + Debug + Clone + Eq + PartialEq + 'static,
+ T: Layout + 'static,
{
Self { node: Box::new(node) }
}
@@ -66,7 +63,7 @@ impl LayoutNode {
#[cfg(feature = "layout-cache")]
pub fn new<T>(node: T) -> Self
where
- T: Layout + Debug + Clone + Eq + PartialEq + Hash + 'static,
+ T: Layout + Hash + 'static,
{
let hash = {
let mut state = FxHasher64::default();
@@ -99,60 +96,9 @@ impl Layout for LayoutNode {
}
}
-impl Debug for LayoutNode {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- self.node.fmt(f)
- }
-}
-
-impl Clone for LayoutNode {
- fn clone(&self) -> Self {
- Self {
- node: self.node.dyn_clone(),
- #[cfg(feature = "layout-cache")]
- hash: self.hash,
- }
- }
-}
-
-impl Eq for LayoutNode {}
-
-impl PartialEq for LayoutNode {
- fn eq(&self, other: &Self) -> bool {
- self.node.dyn_eq(other.node.as_ref())
- }
-}
-
#[cfg(feature = "layout-cache")]
impl Hash for LayoutNode {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_u64(self.hash);
}
}
-
-trait Bounds: Layout + Debug + 'static {
- fn as_any(&self) -> &dyn Any;
- fn dyn_eq(&self, other: &dyn Bounds) -> bool;
- fn dyn_clone(&self) -> Box<dyn Bounds>;
-}
-
-impl<T> Bounds for T
-where
- T: Layout + Debug + Eq + PartialEq + Clone + 'static,
-{
- fn as_any(&self) -> &dyn Any {
- self
- }
-
- fn dyn_eq(&self, other: &dyn Bounds) -> bool {
- if let Some(other) = other.as_any().downcast_ref::<Self>() {
- self == other
- } else {
- false
- }
- }
-
- fn dyn_clone(&self) -> Box<dyn Bounds> {
- Box::new(self.clone())
- }
-}
diff --git a/src/loading/fs.rs b/src/loading/fs.rs
index 46e3dba1..d03df3ba 100644
--- a/src/loading/fs.rs
+++ b/src/loading/fs.rs
@@ -13,7 +13,7 @@ use crate::font::FaceInfo;
/// Loads fonts and files from the local file system.
///
/// _This is only available when the `fs` feature is enabled._
-#[derive(Debug, Default, Clone)]
+#[derive(Default)]
pub struct FsLoader {
faces: Vec<FaceInfo>,
}
diff --git a/src/loading/mem.rs b/src/loading/mem.rs
index d7fb178f..9ff02d2d 100644
--- a/src/loading/mem.rs
+++ b/src/loading/mem.rs
@@ -9,7 +9,7 @@ use crate::font::FaceInfo;
use crate::util::PathExt;
/// Loads fonts and files from an in-memory storage.
-#[derive(Debug, Default, Clone)]
+#[derive(Default)]
pub struct MemLoader {
faces: Vec<FaceInfo>,
files: HashMap<PathBuf, Cow<'static, [u8]>>,
diff --git a/src/loading/mod.rs b/src/loading/mod.rs
index e6cca012..4841e752 100644
--- a/src/loading/mod.rs
+++ b/src/loading/mod.rs
@@ -11,15 +11,12 @@ pub use mem::*;
use std::io;
use std::path::Path;
-use serde::{Deserialize, Serialize};
-
use crate::font::FaceInfo;
/// A hash that identifies a file.
///
/// Such a hash can be [resolved](Loader::resolve) from a path.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
-#[derive(Serialize, Deserialize)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct FileHash(pub u64);
/// Loads resources from a local or remote source.
diff --git a/src/paper.rs b/src/paper.rs
index 1a3391a1..5c9775b8 100644
--- a/src/paper.rs
+++ b/src/paper.rs
@@ -3,7 +3,7 @@
use crate::geom::{Length, Linear, Relative, Sides, Size};
/// Specification of a paper.
-#[derive(Debug, Copy, Clone, PartialEq)]
+#[derive(Debug, Copy, Clone)]
pub struct Paper {
/// The broad class this paper belongs to.
class: PaperClass,
diff --git a/src/parse/mod.rs b/src/parse/mod.rs
index 37b65c04..649b4eb8 100644
--- a/src/parse/mod.rs
+++ b/src/parse/mod.rs
@@ -201,7 +201,7 @@ fn list_item(p: &mut Parser) -> SyntaxNode {
let column = p.column(start);
p.eat_assert(Token::Hyph);
let body = tree_indented(p, column);
- SyntaxNode::List(Box::new(ListItem { span: p.span_from(start), body }))
+ SyntaxNode::List(Box::new(ListNode { span: p.span_from(start), body }))
}
/// Parse a single enum item.
@@ -210,7 +210,7 @@ fn enum_item(p: &mut Parser, number: Option<usize>) -> SyntaxNode {
let column = p.column(start);
p.eat_assert(Token::Numbering(number));
let body = tree_indented(p, column);
- SyntaxNode::Enum(Box::new(EnumItem {
+ SyntaxNode::Enum(Box::new(EnumNode {
span: p.span_from(start),
number,
body,
diff --git a/src/parse/parser.rs b/src/parse/parser.rs
index 83e77a6a..c035319d 100644
--- a/src/parse/parser.rs
+++ b/src/parse/parser.rs
@@ -1,4 +1,3 @@
-use std::fmt::{self, Debug, Formatter};
use std::ops::Range;
use super::{TokenMode, Tokens};
@@ -28,7 +27,6 @@ pub struct Parser<'s> {
}
/// A logical group of tokens, e.g. `[...]`.
-#[derive(Debug, Copy, Clone)]
struct GroupEntry {
/// The start index of the group. Used by `Parser::end_group` to return the
/// group's full span.
@@ -391,11 +389,3 @@ impl<'s> Parser<'s> {
self.groups.iter().any(|g| g.kind == kind)
}
}
-
-impl Debug for Parser<'_> {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- let mut s = self.tokens.scanner();
- s.jump(self.next_start());
- write!(f, "Parser({}|{})", s.eaten(), s.rest())
- }
-}
diff --git a/src/parse/scanner.rs b/src/parse/scanner.rs
index f893c4d3..8e3e4278 100644
--- a/src/parse/scanner.rs
+++ b/src/parse/scanner.rs
@@ -1,4 +1,3 @@
-use std::fmt::{self, Debug, Formatter};
use std::slice::SliceIndex;
/// A featureful char-based scanner.
@@ -153,12 +152,6 @@ impl<'s> Scanner<'s> {
}
}
-impl Debug for Scanner<'_> {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "Scanner({}|{})", self.eaten(), self.rest())
- }
-}
-
/// Whether this character denotes a newline.
#[inline]
pub fn is_newline(character: char) -> bool {
diff --git a/src/parse/tokens.rs b/src/parse/tokens.rs
index 684e340e..91d3ab7f 100644
--- a/src/parse/tokens.rs
+++ b/src/parse/tokens.rs
@@ -1,11 +1,8 @@
-use std::fmt::{self, Debug, Formatter};
-
use super::{is_newline, Scanner};
use crate::geom::{AngularUnit, LengthUnit};
use crate::syntax::*;
/// An iterator over the tokens of a string of source code.
-#[derive(Clone)]
pub struct Tokens<'s> {
s: Scanner<'s>,
mode: TokenMode,
@@ -481,12 +478,6 @@ impl<'s> Tokens<'s> {
}
}
-impl Debug for Tokens<'_> {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "Tokens({}|{})", self.s.eaten(), self.s.rest())
- }
-}
-
fn keyword(ident: &str) -> Option<Token<'static>> {
Some(match ident {
"not" => Token::Not,
@@ -512,6 +503,8 @@ fn keyword(ident: &str) -> Option<Token<'static>> {
#[cfg(test)]
#[allow(non_snake_case)]
mod tests {
+ use std::fmt::Debug;
+
use super::*;
use Option::None;
diff --git a/src/source.rs b/src/source.rs
index 877fd729..b02af1b6 100644
--- a/src/source.rs
+++ b/src/source.rs
@@ -15,8 +15,7 @@ use crate::parse::{is_newline, Scanner};
use crate::util::PathExt;
/// A unique identifier for a loaded source file.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
-#[derive(Serialize, Deserialize)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct SourceId(u32);
impl SourceId {
@@ -252,12 +251,6 @@ impl SourceFile {
}
}
-impl AsRef<str> for SourceFile {
- fn as_ref(&self) -> &str {
- &self.src
- }
-}
-
/// The indices at which lines start (right behind newlines).
///
/// The beginning of the string (index 0) is not returned.
@@ -276,6 +269,12 @@ fn newlines(string: &str) -> impl Iterator<Item = usize> + '_ {
})
}
+impl AsRef<str> for SourceFile {
+ fn as_ref(&self) -> &str {
+ &self.src
+ }
+}
+
#[cfg(feature = "codespan-reporting")]
impl<'a> Files<'a> for SourceStore {
type FileId = SourceId;
diff --git a/src/syntax/ident.rs b/src/syntax/ident.rs
index 66ffb46d..c47e6fb1 100644
--- a/src/syntax/ident.rs
+++ b/src/syntax/ident.rs
@@ -12,7 +12,7 @@ use crate::util::EcoString;
/// - `_` and `-` as continuing characters.
///
/// [uax31]: http://www.unicode.org/reports/tr31/
-#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Debug, Clone, PartialEq)]
pub struct Ident {
/// The source code location.
pub span: Span,
diff --git a/src/syntax/node.rs b/src/syntax/node.rs
index 4ff69c17..875d32f5 100644
--- a/src/syntax/node.rs
+++ b/src/syntax/node.rs
@@ -20,9 +20,9 @@ pub enum SyntaxNode {
/// A section heading: `= Introduction`.
Heading(Box<HeadingNode>),
/// An item in an unordered list: `- ...`.
- List(Box<ListItem>),
+ List(Box<ListNode>),
/// An item in an enumeration (ordered list): `1. ...`.
- Enum(Box<EnumItem>),
+ Enum(Box<EnumNode>),
/// An expression.
Expr(Expr),
}
@@ -55,7 +55,7 @@ pub struct HeadingNode {
/// An item in an unordered list: `- ...`.
#[derive(Debug, Clone, PartialEq)]
-pub struct ListItem {
+pub struct ListNode {
/// The source code location.
pub span: Span,
/// The contents of the list item.
@@ -64,7 +64,7 @@ pub struct ListItem {
/// An item in an enumeration (ordered list): `1. ...`.
#[derive(Debug, Clone, PartialEq)]
-pub struct EnumItem {
+pub struct EnumNode {
/// The source code location.
pub span: Span,
/// The number, if any.
diff --git a/src/syntax/pretty.rs b/src/syntax/pretty.rs
index cf9ee69d..3c59914f 100644
--- a/src/syntax/pretty.rs
+++ b/src/syntax/pretty.rs
@@ -94,14 +94,14 @@ impl Pretty for SyntaxNode {
Self::Emph(_) => p.push('_'),
Self::Text(text) => p.push_str(text),
Self::Raw(raw) => raw.pretty(p),
- Self::Heading(n) => n.pretty(p),
- Self::List(n) => n.pretty(p),
- Self::Enum(n) => n.pretty(p),
- Self::Expr(n) => {
- if n.has_short_form() {
+ Self::Heading(heading) => heading.pretty(p),
+ Self::List(list) => list.pretty(p),
+ Self::Enum(enum_) => enum_.pretty(p),
+ Self::Expr(expr) => {
+ if expr.has_short_form() {
p.push('#');
}
- n.pretty(p);
+ expr.pretty(p);
}
}
}
@@ -173,14 +173,14 @@ impl Pretty for HeadingNode {
}
}
-impl Pretty for ListItem {
+impl Pretty for ListNode {
fn pretty(&self, p: &mut Printer) {
p.push_str("- ");
self.body.pretty(p);
}
}
-impl Pretty for EnumItem {
+impl Pretty for EnumNode {
fn pretty(&self, p: &mut Printer) {
if let Some(number) = self.number {
write!(p, "{}", number).unwrap();
diff --git a/src/syntax/span.rs b/src/syntax/span.rs
index e4a4fd32..bfb9e755 100644
--- a/src/syntax/span.rs
+++ b/src/syntax/span.rs
@@ -1,3 +1,4 @@
+use std::cmp::Ordering;
use std::fmt::{self, Debug, Formatter};
use std::ops::{Add, Range};
@@ -6,8 +7,7 @@ use serde::{Deserialize, Serialize};
use crate::source::SourceId;
/// A value with the span it corresponds to in the source code.
-#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
-#[derive(Serialize, Deserialize)]
+#[derive(Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct Spanned<T> {
/// The spanned value.
pub v: T,
@@ -48,8 +48,7 @@ impl<T: Debug> Debug for Spanned<T> {
}
/// Bounds of a slice of source code.
-#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
-#[derive(Serialize, Deserialize)]
+#[derive(Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct Span {
/// The id of the source file.
pub source: SourceId,
@@ -127,9 +126,18 @@ impl Debug for Span {
}
}
+impl PartialOrd for Span {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if self.source == other.source {
+ Some(self.start.cmp(&other.start).then(self.end.cmp(&other.end)))
+ } else {
+ None
+ }
+ }
+}
+
/// A byte position in source code.
-#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
-#[derive(Serialize, Deserialize)]
+#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
pub struct Pos(pub u32);
impl Pos {
@@ -148,17 +156,6 @@ impl Debug for Pos {
}
}
-impl<T> Add<T> for Pos
-where
- T: Into<Pos>,
-{
- type Output = Self;
-
- fn add(self, rhs: T) -> Self {
- Pos(self.0 + rhs.into().0)
- }
-}
-
impl From<u32> for Pos {
fn from(index: u32) -> Self {
Self(index)
@@ -171,6 +168,17 @@ impl From<usize> for Pos {
}
}
+impl<T> Add<T> for Pos
+where
+ T: Into<Pos>,
+{
+ type Output = Self;
+
+ fn add(self, rhs: T) -> Self {
+ Pos(self.0 + rhs.into().0)
+ }
+}
+
/// Convert a position or range into a span.
pub trait IntoSpan {
/// Convert into a span by providing the source id.
diff --git a/src/syntax/token.rs b/src/syntax/token.rs
index a4d1867a..219395cf 100644
--- a/src/syntax/token.rs
+++ b/src/syntax/token.rs
@@ -157,7 +157,7 @@ pub enum Token<'s> {
}
/// A quoted string token: `"..."`.
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+#[derive(Debug, Copy, Clone, PartialEq)]
pub struct StrToken<'s> {
/// The string inside the quotes.
///
@@ -170,7 +170,7 @@ pub struct StrToken<'s> {
}
/// A raw block token: `` `...` ``.
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+#[derive(Debug, Copy, Clone, PartialEq)]
pub struct RawToken<'s> {
/// The raw text between the backticks.
pub text: &'s str,
@@ -181,7 +181,7 @@ pub struct RawToken<'s> {
}
/// A math formula token: `$2pi + x$` or `$[f'(x) = x^2]$`.
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+#[derive(Debug, Copy, Clone, PartialEq)]
pub struct MathToken<'s> {
/// The formula between the dollars.
pub formula: &'s str,
@@ -193,7 +193,7 @@ pub struct MathToken<'s> {
}
/// A unicode escape sequence token: `\u{1F5FA}`.
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+#[derive(Debug, Copy, Clone, PartialEq)]
pub struct UnicodeEscapeToken<'s> {
/// The escape sequence between the braces.
pub sequence: &'s str,
diff --git a/src/syntax/visit.rs b/src/syntax/visit.rs
index 2b4649de..fe270ac5 100644
--- a/src/syntax/visit.rs
+++ b/src/syntax/visit.rs
@@ -104,12 +104,12 @@ impl_visitors! {
v.visit_tree(r!(heading.body));
}
- visit_list(v, item: ListItem) {
- v.visit_tree(r!(item.body));
+ visit_list(v, list: ListNode) {
+ v.visit_tree(r!(list.body));
}
- visit_enum(v, item: EnumItem) {
- v.visit_tree(r!(item.body));
+ visit_enum(v, enum_: EnumNode) {
+ v.visit_tree(r!(enum_.body));
}
visit_expr(v, expr: Expr) {
diff --git a/src/util/eco.rs b/src/util/eco.rs
index b44214bd..f1dfdfaf 100644
--- a/src/util/eco.rs
+++ b/src/util/eco.rs
@@ -163,24 +163,6 @@ impl EcoString {
}
}
-impl Default for EcoString {
- fn default() -> Self {
- Self::new()
- }
-}
-
-impl Display for EcoString {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- Display::fmt(self.as_str(), f)
- }
-}
-
-impl Debug for EcoString {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- Debug::fmt(self.as_str(), f)
- }
-}
-
impl Deref for EcoString {
type Target = str;
@@ -201,6 +183,24 @@ impl Deref for EcoString {
}
}
+impl Default for EcoString {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl Debug for EcoString {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ Debug::fmt(self.as_str(), f)
+ }
+}
+
+impl Display for EcoString {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ Display::fmt(self.as_str(), f)
+ }
+}
+
impl Eq for EcoString {}
impl PartialEq for EcoString {