From c97a01616abd3af6511ceac28a01ac6d3023ae83 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Sun, 19 Nov 2023 17:42:43 +0100 Subject: [PATCH] More useful `Debug` impls --- crates/typst-library/src/meta/bibliography.rs | 9 +- crates/typst/src/eval/args.rs | 52 +++-- crates/typst/src/eval/auto.rs | 10 +- crates/typst/src/eval/bytes.rs | 28 +-- crates/typst/src/eval/duration.rs | 10 +- crates/typst/src/eval/fields.rs | 4 +- crates/typst/src/eval/func.rs | 12 +- crates/typst/src/eval/module.rs | 14 +- crates/typst/src/eval/none.rs | 10 +- crates/typst/src/eval/str.rs | 186 +++++++++--------- crates/typst/src/eval/symbol.rs | 23 ++- crates/typst/src/eval/ty.rs | 8 +- crates/typst/src/eval/value.rs | 48 ++++- crates/typst/src/font/book.rs | 9 +- crates/typst/src/geom/abs.rs | 8 +- crates/typst/src/geom/angle.rs | 8 +- crates/typst/src/geom/color.rs | 181 +++++++++-------- crates/typst/src/geom/corners.rs | 121 +++++++----- crates/typst/src/geom/em.rs | 8 +- crates/typst/src/geom/fr.rs | 8 +- crates/typst/src/geom/gradient.rs | 12 +- crates/typst/src/geom/length.rs | 12 +- crates/typst/src/geom/paint.rs | 29 ++- crates/typst/src/geom/ratio.rs | 8 +- crates/typst/src/geom/rel.rs | 12 +- crates/typst/src/geom/scalar.rs | 26 ++- crates/typst/src/geom/sides.rs | 173 ++++++++-------- crates/typst/src/model/block.rs | 12 +- crates/typst/src/model/content.rs | 10 +- crates/typst/src/model/element.rs | 2 +- crates/typst/src/model/label.rs | 2 +- crates/typst/src/model/styles.rs | 34 ++-- crates/typst/src/util/deferred.rs | 1 - 33 files changed, 688 insertions(+), 402 deletions(-) diff --git a/crates/typst-library/src/meta/bibliography.rs b/crates/typst-library/src/meta/bibliography.rs index c258d19d8..b84c330a0 100644 --- a/crates/typst-library/src/meta/bibliography.rs +++ b/crates/typst-library/src/meta/bibliography.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; use std::ffi::OsStr; +use std::fmt::{self, Debug, Formatter}; use std::hash::{Hash, Hasher}; use std::path::Path; use std::sync::Arc; @@ -296,7 +297,7 @@ impl LocalName for BibliographyElem { /// A loaded bibliography. #[ty] -#[derive(Debug, Clone, PartialEq)] +#[derive(Clone, PartialEq)] pub struct Bibliography { map: Arc>, hash: u128, @@ -378,6 +379,12 @@ impl Bibliography { } } +impl Debug for Bibliography { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + f.debug_set().entries(self.map.keys()).finish() + } +} + impl Hash for Bibliography { fn hash(&self, state: &mut H) { self.hash.hash(state); diff --git a/crates/typst/src/eval/args.rs b/crates/typst/src/eval/args.rs index 72051bf72..1cb175e39 100644 --- a/crates/typst/src/eval/args.rs +++ b/crates/typst/src/eval/args.rs @@ -48,18 +48,6 @@ pub struct Args { pub items: EcoVec, } -/// An argument to a function call: `12` or `draw: false`. -#[derive(Debug, Clone, Hash)] -#[allow(clippy::derived_hash_with_manual_eq)] -pub struct Arg { - /// The span of the whole argument. - pub span: Span, - /// The name of the argument (`None` for positional arguments). - pub name: Option, - /// The value of the argument. - pub value: Spanned, -} - impl Args { /// Create positional arguments from a span and values. pub fn new(span: Span, values: impl IntoIterator) -> Self { @@ -274,12 +262,6 @@ impl Args { } } -impl PartialEq for Args { - fn eq(&self, other: &Self) -> bool { - self.to_pos() == other.to_pos() && self.to_named() == other.to_named() - } -} - impl Debug for Args { fn fmt(&self, f: &mut Formatter) -> fmt::Result { f.debug_list().entries(&self.items).finish() @@ -293,9 +275,33 @@ impl Repr for Args { } } -impl PartialEq for Arg { +impl PartialEq for Args { fn eq(&self, other: &Self) -> bool { - self.name == other.name && self.value.v == other.value.v + self.to_pos() == other.to_pos() && self.to_named() == other.to_named() + } +} + +/// An argument to a function call: `12` or `draw: false`. +#[derive(Clone, Hash)] +#[allow(clippy::derived_hash_with_manual_eq)] +pub struct Arg { + /// The span of the whole argument. + pub span: Span, + /// The name of the argument (`None` for positional arguments). + pub name: Option, + /// The value of the argument. + pub value: Spanned, +} + +impl Debug for Arg { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + if let Some(name) = &self.name { + name.fmt(f)?; + f.write_str(": ")?; + self.value.v.fmt(f) + } else { + self.value.v.fmt(f) + } } } @@ -308,3 +314,9 @@ impl Repr for Arg { } } } + +impl PartialEq for Arg { + fn eq(&self, other: &Self) -> bool { + self.name == other.name && self.value.v == other.value.v + } +} diff --git a/crates/typst/src/eval/auto.rs b/crates/typst/src/eval/auto.rs index 011bf6d0c..0dcf79c7d 100644 --- a/crates/typst/src/eval/auto.rs +++ b/crates/typst/src/eval/auto.rs @@ -1,5 +1,5 @@ use ecow::EcoString; -use std::fmt::Debug; +use std::fmt::{self, Debug, Formatter}; use crate::diag::StrResult; use crate::eval::{ty, CastInfo, FromValue, IntoValue, Reflect, Repr, Type, Value}; @@ -14,7 +14,7 @@ use crate::model::{Fold, Resolve, StyleChain}; /// parameter. Setting it to `{auto}` lets Typst automatically determine the /// direction from the [text language]($text.lang). #[ty(name = "auto")] -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct AutoValue; impl IntoValue for AutoValue { @@ -46,6 +46,12 @@ impl Reflect for AutoValue { } } +impl Debug for AutoValue { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + f.write_str("Auto") + } +} + impl Repr for AutoValue { fn repr(&self) -> EcoString { "auto".into() diff --git a/crates/typst/src/eval/bytes.rs b/crates/typst/src/eval/bytes.rs index 96415d200..0b074facb 100644 --- a/crates/typst/src/eval/bytes.rs +++ b/crates/typst/src/eval/bytes.rs @@ -1,5 +1,5 @@ use std::borrow::Cow; -use std::fmt::Debug; +use std::fmt::{self, Debug, Formatter}; use std::ops::{Add, AddAssign, Deref}; use std::sync::Arc; @@ -38,7 +38,7 @@ use crate::eval::{cast, func, scope, ty, Array, Reflect, Repr, Str, Value}; /// #str(data.slice(1, 4)) /// ``` #[ty(scope)] -#[derive(Debug, Clone, Hash, Eq, PartialEq)] +#[derive(Clone, Hash, Eq, PartialEq)] pub struct Bytes(Arc>>); impl Bytes { @@ -153,15 +153,15 @@ impl Bytes { } } -impl From<&[u8]> for Bytes { - fn from(slice: &[u8]) -> Self { - Self(Arc::new(Prehashed::new(slice.to_vec().into()))) +impl Debug for Bytes { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "Bytes({})", self.len()) } } -impl From> for Bytes { - fn from(vec: Vec) -> Self { - Self(Arc::new(Prehashed::new(vec.into()))) +impl Repr for Bytes { + fn repr(&self) -> EcoString { + eco_format!("bytes({})", self.len()) } } @@ -179,9 +179,15 @@ impl AsRef<[u8]> for Bytes { } } -impl Repr for Bytes { - fn repr(&self) -> EcoString { - eco_format!("bytes({})", self.len()) +impl From<&[u8]> for Bytes { + fn from(slice: &[u8]) -> Self { + Self(Arc::new(Prehashed::new(slice.to_vec().into()))) + } +} + +impl From> for Bytes { + fn from(vec: Vec) -> Self { + Self(Arc::new(Prehashed::new(vec.into()))) } } diff --git a/crates/typst/src/eval/duration.rs b/crates/typst/src/eval/duration.rs index 775cd5b26..35f41603a 100644 --- a/crates/typst/src/eval/duration.rs +++ b/crates/typst/src/eval/duration.rs @@ -1,6 +1,6 @@ use ecow::{eco_format, EcoString}; -use std::fmt::Debug; +use std::fmt::{self, Debug, Formatter}; use std::ops::{Add, Div, Mul, Neg, Sub}; use time::ext::NumericalDuration; @@ -8,7 +8,7 @@ use crate::eval::{func, repr, scope, ty, Repr}; /// Represents a positive or negative span of time. #[ty(scope)] -#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct Duration(time::Duration); impl Duration { @@ -110,6 +110,12 @@ impl Duration { } } +impl Debug for Duration { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + impl Repr for Duration { fn repr(&self) -> EcoString { let mut tmp = self.0; diff --git a/crates/typst/src/eval/fields.rs b/crates/typst/src/eval/fields.rs index f78339fba..a810d5430 100644 --- a/crates/typst/src/eval/fields.rs +++ b/crates/typst/src/eval/fields.rs @@ -1,11 +1,9 @@ use ecow::{eco_format, EcoString}; use crate::diag::StrResult; -use crate::eval::Version; +use crate::eval::{IntoValue, Type, Value, Version}; use crate::geom::{Align, Length, Rel, Stroke}; -use crate::eval::{IntoValue, Type, Value}; - /// Try to access a field on a value. /// /// This function is exclusively for types which have predefined fields, such as diff --git a/crates/typst/src/eval/func.rs b/crates/typst/src/eval/func.rs index 3633fc891..8bcb7e46c 100644 --- a/crates/typst/src/eval/func.rs +++ b/crates/typst/src/eval/func.rs @@ -1,4 +1,4 @@ -use std::fmt::Debug; +use std::fmt::{self, Debug, Formatter}; use std::sync::Arc; use comemo::{Prehashed, Tracked, TrackedMut}; @@ -128,7 +128,7 @@ pub use typst_macros::func; /// [`array.push(value)`]($array.push). These can modify the values they are /// called on. #[ty(scope, name = "function")] -#[derive(Debug, Clone, Hash)] +#[derive(Clone, Hash)] #[allow(clippy::derived_hash_with_manual_eq)] pub struct Func { /// The internal representation. @@ -138,7 +138,7 @@ pub struct Func { } /// The different kinds of function representations. -#[derive(Debug, Clone, PartialEq, Hash)] +#[derive(Clone, PartialEq, Hash)] enum Repr { /// A native Rust function. Native(Static), @@ -390,6 +390,12 @@ impl Func { } } +impl Debug for Func { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "Func({})", self.name().unwrap_or("..")) + } +} + impl super::Repr for Func { fn repr(&self) -> EcoString { match self.name() { diff --git a/crates/typst/src/eval/module.rs b/crates/typst/src/eval/module.rs index 9480f7978..26bf537d4 100644 --- a/crates/typst/src/eval/module.rs +++ b/crates/typst/src/eval/module.rs @@ -1,4 +1,4 @@ -use std::fmt::Debug; +use std::fmt::{self, Debug, Formatter}; use std::sync::Arc; use ecow::{eco_format, EcoString}; @@ -24,7 +24,7 @@ use crate::eval::{ty, Content, Scope, Value}; /// >>> #(-3) /// ``` #[ty] -#[derive(Debug, Clone, Hash)] +#[derive(Clone, Hash)] #[allow(clippy::derived_hash_with_manual_eq)] pub struct Module { /// The module's name. @@ -100,6 +100,16 @@ impl Module { } } +impl Debug for Module { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + f.debug_struct("Module") + .field("name", &self.name) + .field("scope", &self.inner.scope) + .field("content", &self.inner.content) + .finish() + } +} + impl super::Repr for Module { fn repr(&self) -> EcoString { eco_format!("", self.name()) diff --git a/crates/typst/src/eval/none.rs b/crates/typst/src/eval/none.rs index 896e2cebc..a022e578a 100644 --- a/crates/typst/src/eval/none.rs +++ b/crates/typst/src/eval/none.rs @@ -1,5 +1,5 @@ use ecow::EcoString; -use std::fmt::Debug; +use std::fmt::{self, Debug, Formatter}; use serde::{Serialize, Serializer}; @@ -19,7 +19,7 @@ use crate::eval::{cast, ty, CastInfo, FromValue, IntoValue, Reflect, Repr, Type, /// Not visible: #none /// ``` #[ty(name = "none")] -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct NoneValue; impl Reflect for NoneValue { @@ -51,6 +51,12 @@ impl FromValue for NoneValue { } } +impl Debug for NoneValue { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + f.pad("None") + } +} + impl Repr for NoneValue { fn repr(&self) -> EcoString { "none".into() diff --git a/crates/typst/src/eval/str.rs b/crates/typst/src/eval/str.rs index 123c408b0..70feae223 100644 --- a/crates/typst/src/eval/str.rs +++ b/crates/typst/src/eval/str.rs @@ -68,7 +68,7 @@ pub use ecow::eco_format; /// - `[\t]` for a tab /// - `[\u{1f600}]` for a hexadecimal Unicode escape sequence #[ty(scope, title = "String")] -#[derive(Debug, Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[derive(Serialize, Deserialize)] #[serde(transparent)] pub struct Str(EcoString); @@ -598,77 +598,6 @@ impl Str { } } -/// A value that can be cast to a string. -pub enum ToStr { - /// A string value ready to be used as-is. - Str(Str), - /// An integer about to be formatted in a given base. - Int(i64), -} - -cast! { - ToStr, - v: i64 => Self::Int(v), - v: f64 => Self::Str(repr::format_float(v, None, "").into()), - v: Version => Self::Str(format_str!("{}", v)), - v: Bytes => Self::Str( - std::str::from_utf8(&v) - .map_err(|_| "bytes are not valid utf-8")? - .into() - ), - v: Label => Self::Str(v.as_str().into()), - v: Type => Self::Str(v.long_name().into()), - v: Str => Self::Str(v), -} - -/// The out of bounds access error message. -#[cold] -fn out_of_bounds(index: i64, len: usize) -> EcoString { - eco_format!("string index out of bounds (index: {}, len: {})", index, len) -} - -/// The out of bounds access error message when no default value was given. -#[cold] -fn no_default_and_out_of_bounds(index: i64, len: usize) -> EcoString { - eco_format!("no default value was specified and string index out of bounds (index: {}, len: {})", index, len) -} - -/// The char boundary access error message. -#[cold] -fn not_a_char_boundary(index: i64) -> EcoString { - eco_format!("string index {} is not a character boundary", index) -} - -/// The error message when the string is empty. -#[cold] -fn string_is_empty() -> EcoString { - "string is empty".into() -} - -/// Convert an item of std's `match_indices` to a dictionary. -fn match_to_dict((start, text): (usize, &str)) -> Dict { - dict! { - "start" => start, - "end" => start + text.len(), - "text" => text, - "captures" => Array::new(), - } -} - -/// Convert regex captures to a dictionary. -fn captures_to_dict(cap: regex::Captures) -> Dict { - let m = cap.get(0).expect("missing first match"); - dict! { - "start" => m.start(), - "end" => m.end(), - "text" => m.as_str(), - "captures" => cap.iter() - .skip(1) - .map(|opt| opt.map_or(Value::None, |m| m.as_str().into_value())) - .collect::(), - } -} - impl Deref for Str { type Target = str; @@ -677,9 +606,15 @@ impl Deref for Str { } } +impl Debug for Str { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + Debug::fmt(self.as_str(), f) + } +} + impl Display for Str { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - f.pad(self) + Display::fmt(self.as_str(), f) } } @@ -689,6 +624,29 @@ impl Repr for Str { } } +impl Repr for EcoString { + fn repr(&self) -> EcoString { + self.as_ref().repr() + } +} + +impl Repr for &str { + fn repr(&self) -> EcoString { + let mut r = EcoString::with_capacity(self.len() + 2); + r.push('"'); + for c in self.chars() { + match c { + '\0' => r.push_str(r"\u{0}"), + '\'' => r.push('\''), + '"' => r.push_str(r#"\""#), + _ => c.escape_debug().for_each(|c| r.push(c)), + } + } + r.push('"'); + r + } +} + impl Add for Str { type Output = Self; @@ -793,29 +751,77 @@ cast! { v: Str => v.into(), } -impl Repr for &str { - fn repr(&self) -> EcoString { - let mut r = EcoString::with_capacity(self.len() + 2); - r.push('"'); - for c in self.chars() { - match c { - '\0' => r.push_str(r"\u{0}"), - '\'' => r.push('\''), - '"' => r.push_str(r#"\""#), - _ => c.escape_debug().for_each(|c| r.push(c)), - } - } - r.push('"'); - r +/// A value that can be cast to a string. +pub enum ToStr { + /// A string value ready to be used as-is. + Str(Str), + /// An integer about to be formatted in a given base. + Int(i64), +} + +cast! { + ToStr, + v: i64 => Self::Int(v), + v: f64 => Self::Str(repr::format_float(v, None, "").into()), + v: Version => Self::Str(format_str!("{}", v)), + v: Bytes => Self::Str( + std::str::from_utf8(&v) + .map_err(|_| "bytes are not valid utf-8")? + .into() + ), + v: Label => Self::Str(v.as_str().into()), + v: Type => Self::Str(v.long_name().into()), + v: Str => Self::Str(v), +} + +/// Convert an item of std's `match_indices` to a dictionary. +fn match_to_dict((start, text): (usize, &str)) -> Dict { + dict! { + "start" => start, + "end" => start + text.len(), + "text" => text, + "captures" => Array::new(), } } -impl Repr for EcoString { - fn repr(&self) -> EcoString { - self.as_ref().repr() +/// Convert regex captures to a dictionary. +fn captures_to_dict(cap: regex::Captures) -> Dict { + let m = cap.get(0).expect("missing first match"); + dict! { + "start" => m.start(), + "end" => m.end(), + "text" => m.as_str(), + "captures" => cap.iter() + .skip(1) + .map(|opt| opt.map_or(Value::None, |m| m.as_str().into_value())) + .collect::(), } } +/// The out of bounds access error message. +#[cold] +fn out_of_bounds(index: i64, len: usize) -> EcoString { + eco_format!("string index out of bounds (index: {}, len: {})", index, len) +} + +/// The out of bounds access error message when no default value was given. +#[cold] +fn no_default_and_out_of_bounds(index: i64, len: usize) -> EcoString { + eco_format!("no default value was specified and string index out of bounds (index: {}, len: {})", index, len) +} + +/// The char boundary access error message. +#[cold] +fn not_a_char_boundary(index: i64) -> EcoString { + eco_format!("string index {} is not a character boundary", index) +} + +/// The error message when the string is empty. +#[cold] +fn string_is_empty() -> EcoString { + "string is empty".into() +} + /// A regular expression. /// /// Can be used as a [show rule selector]($styling/#show-rules) and with diff --git a/crates/typst/src/eval/symbol.rs b/crates/typst/src/eval/symbol.rs index d15a89152..8219ec58d 100644 --- a/crates/typst/src/eval/symbol.rs +++ b/crates/typst/src/eval/symbol.rs @@ -47,7 +47,7 @@ pub use typst_macros::symbols; pub struct Symbol(Repr); /// The internal representation. -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Clone, Eq, PartialEq, Hash)] enum Repr { Single(char), Const(&'static [(&'static str, char)]), @@ -55,7 +55,7 @@ enum Repr { } /// A collection of symbols. -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Clone, Eq, PartialEq, Hash)] enum List { Static(&'static [(&'static str, char)]), Runtime(Box<[(EcoString, char)]>), @@ -214,6 +214,25 @@ impl Display for Symbol { } } +impl Debug for Repr { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Self::Single(c) => Debug::fmt(c, f), + Self::Const(list) => list.fmt(f), + Self::Multi(lists) => lists.fmt(f), + } + } +} + +impl Debug for List { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Self::Static(list) => list.fmt(f), + Self::Runtime(list) => list.fmt(f), + } + } +} + impl super::Repr for Symbol { fn repr(&self) -> EcoString { eco_format!("\"{}\"", self.get()) diff --git a/crates/typst/src/eval/ty.rs b/crates/typst/src/eval/ty.rs index 56cc7822a..3dc8f5558 100644 --- a/crates/typst/src/eval/ty.rs +++ b/crates/typst/src/eval/ty.rs @@ -53,7 +53,7 @@ pub use typst_macros::{scope, ty}; /// - The `{in}` operator on a type and a dictionary will evaluate to `{true}` /// if the dictionary has a string key matching the type's name #[ty(scope)] -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +#[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct Type(Static); impl Type { @@ -139,6 +139,12 @@ impl Type { } } +impl Debug for Type { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "Type({})", self.long_name()) + } +} + impl Repr for Type { fn repr(&self) -> EcoString { self.long_name().into() diff --git a/crates/typst/src/eval/value.rs b/crates/typst/src/eval/value.rs index 51006da00..baf18aa00 100644 --- a/crates/typst/src/eval/value.rs +++ b/crates/typst/src/eval/value.rs @@ -1,6 +1,6 @@ use std::any::Any; use std::cmp::Ordering; -use std::fmt::{self, Debug}; +use std::fmt::{self, Debug, Formatter}; use std::hash::{Hash, Hasher}; use std::sync::Arc; @@ -22,7 +22,7 @@ use crate::model::{Label, Styles}; use crate::syntax::{ast, Span}; /// A computational value. -#[derive(Debug, Default, Clone)] +#[derive(Default, Clone)] pub enum Value { /// The value that indicates the absence of a meaningful value. #[default] @@ -218,6 +218,42 @@ impl Value { } } +impl Debug for Value { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Self::None => Debug::fmt(&NoneValue, f), + Self::Auto => Debug::fmt(&AutoValue, f), + 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::Angle(v) => Debug::fmt(v, f), + Self::Ratio(v) => Debug::fmt(v, f), + Self::Relative(v) => Debug::fmt(v, f), + Self::Fraction(v) => Debug::fmt(v, f), + Self::Color(v) => Debug::fmt(v, f), + Self::Gradient(v) => Debug::fmt(v, f), + Self::Symbol(v) => Debug::fmt(v, f), + Self::Version(v) => Debug::fmt(v, f), + Self::Str(v) => Debug::fmt(v, f), + Self::Bytes(v) => Debug::fmt(v, f), + Self::Label(v) => Debug::fmt(v, f), + Self::Datetime(v) => Debug::fmt(v, f), + Self::Duration(v) => Debug::fmt(v, f), + Self::Content(v) => Debug::fmt(v, f), + Self::Styles(v) => Debug::fmt(v, f), + Self::Array(v) => Debug::fmt(v, f), + Self::Dict(v) => Debug::fmt(v, f), + Self::Func(v) => Debug::fmt(v, f), + Self::Args(v) => Debug::fmt(v, f), + Self::Type(v) => Debug::fmt(v, f), + Self::Module(v) => Debug::fmt(v, f), + Self::Plugin(v) => Debug::fmt(v, f), + Self::Dyn(v) => Debug::fmt(v, f), + } + } +} + impl Repr for Value { fn repr(&self) -> EcoString { match self { @@ -446,7 +482,7 @@ impl<'de> Visitor<'de> for ValueVisitor { } /// A value that is not part of the built-in enum. -#[derive(Debug, Clone, Hash)] +#[derive(Clone, Hash)] #[allow(clippy::derived_hash_with_manual_eq)] pub struct Dynamic(Arc); @@ -475,6 +511,12 @@ impl Dynamic { } } +impl Debug for Dynamic { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + impl Repr for Dynamic { fn repr(&self) -> EcoString { self.0.repr() diff --git a/crates/typst/src/font/book.rs b/crates/typst/src/font/book.rs index 6450c8821..dbdfab15a 100644 --- a/crates/typst/src/font/book.rs +++ b/crates/typst/src/font/book.rs @@ -1,5 +1,6 @@ use std::cmp::Reverse; use std::collections::BTreeMap; +use std::fmt::{self, Debug, Formatter}; use serde::{Deserialize, Serialize}; use ttf_parser::{name_id, PlatformId, Tag}; @@ -442,7 +443,7 @@ fn shared_prefix_words(left: &str, right: &str) -> usize { /// - 2 codepoints inside (18, 19) /// /// So the resulting encoding is `[2, 3, 4, 3, 3, 1, 2, 2]`. -#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] +#[derive(Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] #[serde(transparent)] pub struct Coverage(Vec); @@ -498,6 +499,12 @@ impl Coverage { } } +impl Debug for Coverage { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + f.pad("Coverage(..)") + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/typst/src/geom/abs.rs b/crates/typst/src/geom/abs.rs index 3b56f5f26..2a57e3687 100644 --- a/crates/typst/src/geom/abs.rs +++ b/crates/typst/src/geom/abs.rs @@ -1,7 +1,7 @@ use super::*; /// An absolute length. -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct Abs(Scalar); impl Abs { @@ -133,6 +133,12 @@ impl Numeric for Abs { } } +impl Debug for Abs { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{:?}pt", self.to_pt()) + } +} + impl Repr for Abs { fn repr(&self) -> EcoString { format_float(self.to_pt(), Some(2), "pt") diff --git a/crates/typst/src/geom/angle.rs b/crates/typst/src/geom/angle.rs index 2c379f262..b2f29b756 100644 --- a/crates/typst/src/geom/angle.rs +++ b/crates/typst/src/geom/angle.rs @@ -12,7 +12,7 @@ use super::*; /// #rotate(10deg)[Hello there!] /// ``` #[ty(scope)] -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct Angle(Scalar); impl Angle { @@ -119,6 +119,12 @@ impl Numeric for Angle { } } +impl Debug for Angle { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{:?}deg", self.to_deg()) + } +} + impl Repr for Angle { fn repr(&self) -> EcoString { format_float(self.to_deg(), Some(2), "deg") diff --git a/crates/typst/src/geom/color.rs b/crates/typst/src/geom/color.rs index e8413ada4..247b424bc 100644 --- a/crates/typst/src/geom/color.rs +++ b/crates/typst/src/geom/color.rs @@ -154,7 +154,7 @@ const ANGLE_EPSILON: f32 = 1e-5; /// })) /// ``` #[ty(scope)] -#[derive(Debug, Copy, Clone)] +#[derive(Copy, Clone)] pub enum Color { /// A 32-bit luma color. Luma(Luma), @@ -174,54 +174,6 @@ pub enum Color { Hsv(Hsv), } -impl From for Color { - fn from(c: Luma) -> Self { - Self::Luma(c) - } -} - -impl From for Color { - fn from(c: Oklab) -> Self { - Self::Oklab(c) - } -} - -impl From for Color { - fn from(c: Oklch) -> Self { - Self::Oklch(c) - } -} - -impl From for Color { - fn from(c: Rgb) -> Self { - Self::Rgb(c) - } -} - -impl From for Color { - fn from(c: LinearRgb) -> Self { - Self::LinearRgb(c) - } -} - -impl From for Color { - fn from(c: Cmyk) -> Self { - Self::Cmyk(c) - } -} - -impl From for Color { - fn from(c: Hsl) -> Self { - Self::Hsl(c) - } -} - -impl From for Color { - fn from(c: Hsv) -> Self { - Self::Hsv(c) - } -} - #[scope] impl Color { /// The module of preset color maps. @@ -1379,6 +1331,48 @@ impl Color { } } +impl Debug for Color { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Self::Luma(v) => write!(f, "Luma({})", v.luma), + Self::Oklab(v) => write!(f, "Oklab({}, {}, {}, {})", v.l, v.a, v.b, v.alpha), + Self::Oklch(v) => { + write!( + f, + "Oklch({}, {}, {:?}, {})", + v.l, + v.chroma, + hue_angle(v.hue.into_degrees()), + v.alpha + ) + } + Self::Rgb(v) => { + write!(f, "Rgb({}, {}, {}, {})", v.red, v.green, v.blue, v.alpha) + } + Self::LinearRgb(v) => { + write!(f, "LinearRgb({}, {}, {}, {})", v.red, v.green, v.blue, v.alpha) + } + Self::Cmyk(v) => write!(f, "Cmyk({}, {}, {}, {})", v.c, v.m, v.y, v.k), + Self::Hsl(v) => write!( + f, + "Hsl({:?}, {}, {}, {})", + hue_angle(v.hue.into_degrees()), + v.saturation, + v.lightness, + v.alpha + ), + Self::Hsv(v) => write!( + f, + "Hsv({:?}, {}, {}, {})", + hue_angle(v.hue.into_degrees()), + v.saturation, + v.value, + v.alpha + ), + } + } +} + impl Repr for Color { fn repr(&self) -> EcoString { match self { @@ -1435,20 +1429,14 @@ impl Repr for Color { "oklch({}, {}, {})", Ratio::new(c.l as _).repr(), format_float(c.chroma as _, Some(3), ""), - Angle::deg( - c.hue.into_degrees().rem_euclid(360.0 + ANGLE_EPSILON) as _ - ) - .repr() + hue_angle(c.hue.into_degrees()).repr(), ) } else { eco_format!( "oklch({}, {}, {}, {})", Ratio::new(c.l as _).repr(), format_float(c.chroma as _, Some(3), ""), - Angle::deg( - c.hue.into_degrees().rem_euclid(360.0 + ANGLE_EPSILON) as _ - ) - .repr(), + hue_angle(c.hue.into_degrees()).repr(), Ratio::new(c.alpha as _).repr(), ) } @@ -1457,20 +1445,14 @@ impl Repr for Color { if c.alpha == 1.0 { eco_format!( "color.hsl({}, {}, {})", - Angle::deg( - c.hue.into_degrees().rem_euclid(360.0 + ANGLE_EPSILON) as _ - ) - .repr(), + hue_angle(c.hue.into_degrees()).repr(), Ratio::new(c.saturation as _).repr(), Ratio::new(c.lightness as _).repr(), ) } else { eco_format!( "color.hsl({}, {}, {}, {})", - Angle::deg( - c.hue.into_degrees().rem_euclid(360.0 + ANGLE_EPSILON) as _ - ) - .repr(), + hue_angle(c.hue.into_degrees()).repr(), Ratio::new(c.saturation as _).repr(), Ratio::new(c.lightness as _).repr(), Ratio::new(c.alpha as _).repr(), @@ -1481,20 +1463,14 @@ impl Repr for Color { if c.alpha == 1.0 { eco_format!( "color.hsv({}, {}, {})", - Angle::deg( - c.hue.into_degrees().rem_euclid(360.0 + ANGLE_EPSILON) as _ - ) - .repr(), + hue_angle(c.hue.into_degrees()).repr(), Ratio::new(c.saturation as _).repr(), Ratio::new(c.value as _).repr(), ) } else { eco_format!( "color.hsv({}, {}, {}, {})", - Angle::deg( - c.hue.into_degrees().rem_euclid(360.0 + ANGLE_EPSILON) as _ - ) - .repr(), + hue_angle(c.hue.into_degrees()).repr(), Ratio::new(c.saturation as _).repr(), Ratio::new(c.value as _).repr(), Ratio::new(c.alpha as _).repr(), @@ -1505,6 +1481,10 @@ impl Repr for Color { } } +fn hue_angle(degrees: f32) -> Angle { + Angle::deg(degrees.rem_euclid(360.0 + ANGLE_EPSILON) as _) +} + impl PartialEq for Color { fn eq(&self, other: &Self) -> bool { match (self, other) { @@ -1579,6 +1559,54 @@ impl FromStr for Color { } } +impl From for Color { + fn from(c: Luma) -> Self { + Self::Luma(c) + } +} + +impl From for Color { + fn from(c: Oklab) -> Self { + Self::Oklab(c) + } +} + +impl From for Color { + fn from(c: Oklch) -> Self { + Self::Oklch(c) + } +} + +impl From for Color { + fn from(c: Rgb) -> Self { + Self::Rgb(c) + } +} + +impl From for Color { + fn from(c: LinearRgb) -> Self { + Self::LinearRgb(c) + } +} + +impl From for Color { + fn from(c: Cmyk) -> Self { + Self::Cmyk(c) + } +} + +impl From for Color { + fn from(c: Hsl) -> Self { + Self::Hsl(c) + } +} + +impl From for Color { + fn from(c: Hsv) -> Self { + Self::Hsv(c) + } +} + /// An 8-bit CMYK color. #[derive(Debug, Copy, Clone, PartialEq)] pub struct Cmyk { @@ -1681,25 +1709,18 @@ cast! { pub enum ColorSpace { /// The perceptual Oklab color space. Oklab, - /// The perceptual Oklch color space. Oklch, - /// The standard RGB color space. Srgb, - /// The D65-gray color space. D65Gray, - /// The linear RGB color space. LinearRgb, - /// The HSL color space. Hsl, - /// The HSV color space. Hsv, - /// The CMYK color space. Cmyk, } diff --git a/crates/typst/src/geom/corners.rs b/crates/typst/src/geom/corners.rs index bb8a4e4c5..e0b453147 100644 --- a/crates/typst/src/geom/corners.rs +++ b/crates/typst/src/geom/corners.rs @@ -2,7 +2,7 @@ use super::*; use crate::eval::{CastInfo, FromValue, IntoValue, Reflect}; /// A container with components for the four corners of a rectangle. -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)] +#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)] pub struct Corners { /// The value for the top left corner. pub top_left: T, @@ -96,57 +96,19 @@ impl Get for Corners { } } -/// The four corners of a rectangle. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum Corner { - /// The top left corner. - TopLeft, - /// The top right corner. - TopRight, - /// The bottom right corner. - BottomRight, - /// The bottom left corner. - BottomLeft, -} - -impl Corner { - /// The next corner, clockwise. - pub fn next_cw(self) -> Self { - match self { - Self::TopLeft => Self::TopRight, - Self::TopRight => Self::BottomRight, - Self::BottomRight => Self::BottomLeft, - Self::BottomLeft => Self::TopLeft, - } - } - - /// The next corner, counter-clockwise. - pub fn next_ccw(self) -> Self { - match self { - Self::TopLeft => Self::BottomLeft, - Self::TopRight => Self::TopLeft, - Self::BottomRight => Self::TopRight, - Self::BottomLeft => Self::BottomRight, - } - } - - /// The next side, clockwise. - pub fn side_cw(self) -> Side { - match self { - Self::TopLeft => Side::Top, - Self::TopRight => Side::Right, - Self::BottomRight => Side::Bottom, - Self::BottomLeft => Side::Left, - } - } - - /// The next side, counter-clockwise. - pub fn side_ccw(self) -> Side { - match self { - Self::TopLeft => Side::Left, - Self::TopRight => Side::Top, - Self::BottomRight => Side::Right, - Self::BottomLeft => Side::Bottom, +impl Debug for Corners { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + if self.is_uniform() { + f.write_str("Corners::splat(")?; + self.top_left.fmt(f)?; + f.write_str(")") + } else { + f.debug_struct("Corners") + .field("top_left", &self.top_left) + .field("top_right", &self.top_right) + .field("bottom_right", &self.bottom_right) + .field("bottom_left", &self.bottom_left) + .finish() } } } @@ -262,3 +224,58 @@ impl Fold for Corners> { }) } } + +/// The four corners of a rectangle. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum Corner { + /// The top left corner. + TopLeft, + /// The top right corner. + TopRight, + /// The bottom right corner. + BottomRight, + /// The bottom left corner. + BottomLeft, +} + +impl Corner { + /// The next corner, clockwise. + pub fn next_cw(self) -> Self { + match self { + Self::TopLeft => Self::TopRight, + Self::TopRight => Self::BottomRight, + Self::BottomRight => Self::BottomLeft, + Self::BottomLeft => Self::TopLeft, + } + } + + /// The next corner, counter-clockwise. + pub fn next_ccw(self) -> Self { + match self { + Self::TopLeft => Self::BottomLeft, + Self::TopRight => Self::TopLeft, + Self::BottomRight => Self::TopRight, + Self::BottomLeft => Self::BottomRight, + } + } + + /// The next side, clockwise. + pub fn side_cw(self) -> Side { + match self { + Self::TopLeft => Side::Top, + Self::TopRight => Side::Right, + Self::BottomRight => Side::Bottom, + Self::BottomLeft => Side::Left, + } + } + + /// The next side, counter-clockwise. + pub fn side_ccw(self) -> Side { + match self { + Self::TopLeft => Side::Left, + Self::TopRight => Side::Top, + Self::BottomRight => Side::Right, + Self::BottomLeft => Side::Bottom, + } + } +} diff --git a/crates/typst/src/geom/em.rs b/crates/typst/src/geom/em.rs index 9cb0c55a4..81c4a3508 100644 --- a/crates/typst/src/geom/em.rs +++ b/crates/typst/src/geom/em.rs @@ -3,7 +3,7 @@ use super::*; /// A length that is relative to the font size. /// /// `1em` is the same as the font size. -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct Em(Scalar); impl Em { @@ -68,6 +68,12 @@ impl Numeric for Em { } } +impl Debug for Em { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{:?}em", self.get()) + } +} + impl Repr for Em { fn repr(&self) -> EcoString { format_float(self.get(), None, "em") diff --git a/crates/typst/src/geom/fr.rs b/crates/typst/src/geom/fr.rs index f0cb42507..fe4fed497 100644 --- a/crates/typst/src/geom/fr.rs +++ b/crates/typst/src/geom/fr.rs @@ -13,7 +13,7 @@ use super::*; /// Left #h(1fr) Left-ish #h(2fr) Right /// ``` #[ty(name = "fraction")] -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct Fr(Scalar); impl Fr { @@ -63,6 +63,12 @@ impl Numeric for Fr { } } +impl Debug for Fr { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{:?}fr", self.get()) + } +} + impl Repr for Fr { fn repr(&self) -> EcoString { format_float(self.get(), Some(2), "fr") diff --git a/crates/typst/src/geom/gradient.rs b/crates/typst/src/geom/gradient.rs index 9f1ac30ba..f4a0c7e8d 100644 --- a/crates/typst/src/geom/gradient.rs +++ b/crates/typst/src/geom/gradient.rs @@ -159,7 +159,7 @@ use crate::syntax::{Span, Spanned}; /// Typst predefines color maps that you can use with your gradients. See the /// [`color`]($color/#predefined-color-maps) documentation for more details. #[ty(scope)] -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq, Eq, Hash)] pub enum Gradient { Linear(Arc), Radial(Arc), @@ -828,6 +828,16 @@ impl Gradient { } } +impl Debug for Gradient { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Self::Linear(v) => v.fmt(f), + Self::Radial(v) => v.fmt(f), + Self::Conic(v) => v.fmt(f), + } + } +} + impl Repr for Gradient { fn repr(&self) -> EcoString { match self { diff --git a/crates/typst/src/geom/length.rs b/crates/typst/src/geom/length.rs index b8db6e50b..3027fbea5 100644 --- a/crates/typst/src/geom/length.rs +++ b/crates/typst/src/geom/length.rs @@ -31,7 +31,7 @@ use crate::syntax::Span; /// (that is, excluding the `em` component). /// - `em`: The amount of `em` units in this length, as a [float]($float). #[ty(scope)] -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)] +#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)] pub struct Length { /// The absolute part. pub abs: Abs, @@ -126,6 +126,16 @@ impl Length { } } +impl Debug for Length { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match (self.abs.is_zero(), self.em.is_zero()) { + (false, false) => write!(f, "{:?} + {:?}", self.abs, self.em), + (true, false) => self.em.fmt(f), + (_, true) => self.abs.fmt(f), + } + } +} + impl Repr for Length { fn repr(&self) -> EcoString { match (self.abs.is_zero(), self.em.is_zero()) { diff --git a/crates/typst/src/geom/paint.rs b/crates/typst/src/geom/paint.rs index 1277107f9..2bedfe137 100644 --- a/crates/typst/src/geom/paint.rs +++ b/crates/typst/src/geom/paint.rs @@ -1,7 +1,7 @@ use super::*; /// How a fill or stroke should be painted. -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Clone, Eq, PartialEq, Hash)] pub enum Paint { /// A solid color. Solid(Color), @@ -32,15 +32,12 @@ impl Paint { } } -impl> From for Paint { - fn from(t: T) -> Self { - Self::Solid(t.into()) - } -} - -impl From for Paint { - fn from(gradient: Gradient) -> Self { - Self::Gradient(gradient) +impl Debug for Paint { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Self::Solid(v) => v.fmt(f), + Self::Gradient(v) => v.fmt(f), + } } } @@ -53,6 +50,18 @@ impl Repr for Paint { } } +impl> From for Paint { + fn from(t: T) -> Self { + Self::Solid(t.into()) + } +} + +impl From for Paint { + fn from(gradient: Gradient) -> Self { + Self::Gradient(gradient) + } +} + cast! { Paint, self => match self { diff --git a/crates/typst/src/geom/ratio.rs b/crates/typst/src/geom/ratio.rs index b0a092bac..670eeb755 100644 --- a/crates/typst/src/geom/ratio.rs +++ b/crates/typst/src/geom/ratio.rs @@ -12,7 +12,7 @@ use super::*; /// ] /// ``` #[ty] -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct Ratio(Scalar); impl Ratio { @@ -62,6 +62,12 @@ impl Ratio { } } +impl Debug for Ratio { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{:?}%", self.get()) + } +} + impl Repr for Ratio { fn repr(&self) -> EcoString { format_float(self.get() * 100.0, Some(2), "%") diff --git a/crates/typst/src/geom/rel.rs b/crates/typst/src/geom/rel.rs index 09a737e79..a2c8643e6 100644 --- a/crates/typst/src/geom/rel.rs +++ b/crates/typst/src/geom/rel.rs @@ -18,7 +18,7 @@ use super::*; /// - `length`: Its length component. /// - `ratio`: Its ratio component. #[ty(name = "relative", title = "Relative Length")] -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)] +#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)] pub struct Rel { /// The relative part. pub rel: Ratio, @@ -80,6 +80,16 @@ impl Rel { } } +impl Debug for Rel { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match (self.rel.is_zero(), self.abs.is_zero()) { + (false, false) => write!(f, "{:?} + {:?}", self.rel, self.abs), + (false, true) => self.rel.fmt(f), + (true, _) => self.abs.fmt(f), + } + } +} + impl Repr for Rel { fn repr(&self) -> EcoString { match (self.rel.is_zero(), self.abs.is_zero()) { diff --git a/crates/typst/src/geom/scalar.rs b/crates/typst/src/geom/scalar.rs index 45e00f5c8..a2b966da9 100644 --- a/crates/typst/src/geom/scalar.rs +++ b/crates/typst/src/geom/scalar.rs @@ -3,7 +3,7 @@ use super::*; /// A 64-bit float that implements `Eq`, `Ord` and `Hash`. /// /// Panics if it's `NaN` during any of those operations. -#[derive(Debug, Default, Copy, Clone)] +#[derive(Default, Copy, Clone)] pub struct Scalar(f64); // We have to detect NaNs this way since `f64::is_nan` isn’t const @@ -49,15 +49,9 @@ impl Numeric for Scalar { } } -impl From for Scalar { - fn from(float: f64) -> Self { - Self::new(float) - } -} - -impl From for f64 { - fn from(scalar: Scalar) -> Self { - scalar.0 +impl Debug for Scalar { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + self.0.fmt(f) } } @@ -101,6 +95,18 @@ impl Hash for Scalar { } } +impl From for Scalar { + fn from(float: f64) -> Self { + Self::new(float) + } +} + +impl From for f64 { + fn from(scalar: Scalar) -> Self { + scalar.0 + } +} + impl Neg for Scalar { type Output = Self; diff --git a/crates/typst/src/geom/sides.rs b/crates/typst/src/geom/sides.rs index 38477f36b..2ca7ca6a7 100644 --- a/crates/typst/src/geom/sides.rs +++ b/crates/typst/src/geom/sides.rs @@ -1,8 +1,10 @@ +use std::fmt::{self, Debug, Formatter}; + use super::*; use crate::eval::{CastInfo, FromValue, IntoValue, Reflect}; /// A container with left, top, right and bottom components. -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)] +#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)] pub struct Sides { /// The value for the left side. pub left: T, @@ -121,84 +123,21 @@ impl Get for Sides { } } -/// The four sides of objects. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum Side { - /// The left side. - Left, - /// The top side. - Top, - /// The right side. - Right, - /// The bottom side. - Bottom, -} - -impl Side { - /// The opposite side. - pub fn inv(self) -> Self { - match self { - Self::Left => Self::Right, - Self::Top => Self::Bottom, - Self::Right => Self::Left, - Self::Bottom => Self::Top, +impl Debug for Sides { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + if self.is_uniform() { + f.write_str("Sides::splat(")?; + self.left.fmt(f)?; + f.write_str(")") + } else { + f.debug_struct("Sides") + .field("left", &self.left) + .field("top", &self.top) + .field("right", &self.right) + .field("bottom", &self.bottom) + .finish() } } - - /// The next side, clockwise. - pub fn next_cw(self) -> Self { - match self { - Self::Left => Self::Top, - Self::Top => Self::Right, - Self::Right => Self::Bottom, - Self::Bottom => Self::Left, - } - } - - /// The next side, counter-clockwise. - pub fn next_ccw(self) -> Self { - match self { - Self::Left => Self::Bottom, - Self::Top => Self::Left, - Self::Right => Self::Top, - Self::Bottom => Self::Right, - } - } - - /// The first corner of the side in clockwise order. - pub fn start_corner(self) -> Corner { - match self { - Self::Left => Corner::BottomLeft, - Self::Top => Corner::TopLeft, - Self::Right => Corner::TopRight, - Self::Bottom => Corner::BottomRight, - } - } - - /// The second corner of the side in clockwise order. - pub fn end_corner(self) -> Corner { - self.next_cw().start_corner() - } - - /// Return the corresponding axis. - pub fn axis(self) -> Axis { - match self { - Self::Left | Self::Right => Axis::Y, - Self::Top | Self::Bottom => Axis::X, - } - } -} - -cast! { - Side, - self => Align::from(self).into_value(), - align: Align => match align { - Align::LEFT => Self::Left, - Align::RIGHT => Self::Right, - Align::TOP => Self::Top, - Align::BOTTOM => Self::Bottom, - _ => bail!("cannot convert this alignment to a side"), - }, } impl Reflect for Sides> { @@ -291,3 +230,83 @@ impl Fold for Sides> { }) } } + +/// The four sides of objects. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum Side { + /// The left side. + Left, + /// The top side. + Top, + /// The right side. + Right, + /// The bottom side. + Bottom, +} + +impl Side { + /// The opposite side. + pub fn inv(self) -> Self { + match self { + Self::Left => Self::Right, + Self::Top => Self::Bottom, + Self::Right => Self::Left, + Self::Bottom => Self::Top, + } + } + + /// The next side, clockwise. + pub fn next_cw(self) -> Self { + match self { + Self::Left => Self::Top, + Self::Top => Self::Right, + Self::Right => Self::Bottom, + Self::Bottom => Self::Left, + } + } + + /// The next side, counter-clockwise. + pub fn next_ccw(self) -> Self { + match self { + Self::Left => Self::Bottom, + Self::Top => Self::Left, + Self::Right => Self::Top, + Self::Bottom => Self::Right, + } + } + + /// The first corner of the side in clockwise order. + pub fn start_corner(self) -> Corner { + match self { + Self::Left => Corner::BottomLeft, + Self::Top => Corner::TopLeft, + Self::Right => Corner::TopRight, + Self::Bottom => Corner::BottomRight, + } + } + + /// The second corner of the side in clockwise order. + pub fn end_corner(self) -> Corner { + self.next_cw().start_corner() + } + + /// Return the corresponding axis. + pub fn axis(self) -> Axis { + match self { + Self::Left | Self::Right => Axis::Y, + Self::Top | Self::Bottom => Axis::X, + } + } +} + +cast! { + Side, + self => Align::from(self).into_value(), + align: Align => match align { + Align::LEFT => Self::Left, + Align::RIGHT => Self::Right, + Align::TOP => Self::Top, + Align::BOTTOM => Self::Bottom, + _ => bail!("cannot convert this alignment to a side"), + }, +} diff --git a/crates/typst/src/model/block.rs b/crates/typst/src/model/block.rs index 92e2a18e4..c1370c205 100644 --- a/crates/typst/src/model/block.rs +++ b/crates/typst/src/model/block.rs @@ -27,6 +27,12 @@ impl Block { } } +impl Debug for Block { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + impl Hash for Block { fn hash(&self, state: &mut H) { self.0.dyn_hash(state); @@ -39,12 +45,6 @@ impl Clone for Block { } } -impl Debug for Block { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - self.0.fmt(f) - } -} - /// A value that can be stored in a block. /// /// Auto derived for all types that implement [`Any`], [`Clone`], [`Hash`], diff --git a/crates/typst/src/model/content.rs b/crates/typst/src/model/content.rs index 4b9f11dec..48f84c357 100644 --- a/crates/typst/src/model/content.rs +++ b/crates/typst/src/model/content.rs @@ -1,5 +1,5 @@ use std::any::TypeId; -use std::fmt::Debug; +use std::fmt::{self, Debug, Formatter}; use std::iter::{self, Sum}; use std::ops::{Add, AddAssign}; use std::sync::Arc; @@ -65,7 +65,7 @@ use crate::syntax::Span; /// elements the content is composed of and what fields they have. /// Alternatively, you can inspect the output of the [`repr`]($repr) function. #[ty(scope)] -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct Content(Arc); impl Content { @@ -534,6 +534,12 @@ impl Default for Content { } } +impl Debug for Content { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + impl From for Content { fn from(value: T) -> Self { Self::new(value) diff --git a/crates/typst/src/model/element.rs b/crates/typst/src/model/element.rs index 7551f83b2..95e2befb5 100644 --- a/crates/typst/src/model/element.rs +++ b/crates/typst/src/model/element.rs @@ -117,7 +117,7 @@ impl Element { impl Debug for Element { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad(self.name()) + write!(f, "Element({})", self.name()) } } diff --git a/crates/typst/src/model/label.rs b/crates/typst/src/model/label.rs index 8886b3700..ae2a15c7e 100644 --- a/crates/typst/src/model/label.rs +++ b/crates/typst/src/model/label.rs @@ -66,7 +66,7 @@ impl Label { impl Repr for Label { fn repr(&self) -> EcoString { - eco_format!("<{}>", self.0.resolve()) + eco_format!("<{}>", self.as_str()) } } diff --git a/crates/typst/src/model/styles.rs b/crates/typst/src/model/styles.rs index dc65f1761..5566b8394 100644 --- a/crates/typst/src/model/styles.rs +++ b/crates/typst/src/model/styles.rs @@ -1,5 +1,5 @@ use std::borrow::Cow; -use std::fmt::{self, Debug, Formatter, Write}; +use std::fmt::{self, Debug, Formatter}; use std::iter; use std::mem; use std::ptr; @@ -16,7 +16,7 @@ use crate::syntax::Span; /// A list of style properties. #[ty] -#[derive(Debug, Default, PartialEq, Clone, Hash)] +#[derive(Default, PartialEq, Clone, Hash)] pub struct Styles(EcoVec>); impl Styles { @@ -89,6 +89,13 @@ impl From