diff --git a/crates/typst-macros/src/elem.rs b/crates/typst-macros/src/elem.rs index 6ab437cd3..441cb4add 100644 --- a/crates/typst-macros/src/elem.rs +++ b/crates/typst-macros/src/elem.rs @@ -322,10 +322,12 @@ fn create(element: &Elem) -> Result { let partial_eq_impl = element.unless_capability("PartialEq", || create_partial_eq_impl(element)); let repr_impl = element.unless_capability("Repr", || create_repr_impl(element)); + let derive_debug = element.unless_capability("Debug", || quote! { #[derive(Debug)] }); Ok(quote! { #[doc = #docs] - #[derive(Debug, Clone, Hash)] + #derive_debug + #[derive(Clone, Hash)] #[allow(clippy::derived_hash_with_manual_eq)] #vis struct #ident { #(#fields,)* @@ -974,7 +976,8 @@ fn create_repr_impl(element: &Elem) -> TokenStream { /// Creates the element's casting vtable. fn create_capable_impl(element: &Elem) -> TokenStream { // Forbidden capabilities (i.e capabilities that are not object safe). - const FORBIDDEN: &[&str] = &["Construct", "PartialEq", "Hash", "LocalName", "Repr"]; + const FORBIDDEN: &[&str] = + &["Construct", "PartialEq", "Hash", "LocalName", "Repr", "Debug"]; let ident = &element.ident; let relevant = element diff --git a/crates/typst/src/foundations/content.rs b/crates/typst/src/foundations/content.rs index 52198642b..f7667b2d0 100644 --- a/crates/typst/src/foundations/content.rs +++ b/crates/typst/src/foundations/content.rs @@ -879,12 +879,19 @@ impl Debug for Packed { } /// Defines the element for sequences. -#[elem(Repr, PartialEq)] +#[elem(Debug, Repr, PartialEq)] struct SequenceElem { #[required] children: Vec>, } +impl Debug for SequenceElem { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "Sequence ")?; + f.debug_list().entries(&self.children).finish() + } +} + // Derive is currently incompatible with `elem` macro. #[allow(clippy::derivable_impls)] impl Default for SequenceElem { @@ -923,7 +930,7 @@ impl Repr for SequenceElem { } /// Defines the `ElemFunc` for styled elements. -#[elem(Repr, PartialEq)] +#[elem(Debug, Repr, PartialEq)] struct StyledElem { #[required] child: Prehashed, @@ -931,6 +938,15 @@ struct StyledElem { styles: Styles, } +impl Debug for StyledElem { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + for style in self.styles.iter() { + writeln!(f, "#{style:?}")?; + } + self.child.fmt(f) + } +} + impl PartialEq for StyledElem { fn eq(&self, other: &Self) -> bool { *self.child == *other.child diff --git a/crates/typst/src/foundations/styles.rs b/crates/typst/src/foundations/styles.rs index b2287c2db..da8447c3a 100644 --- a/crates/typst/src/foundations/styles.rs +++ b/crates/typst/src/foundations/styles.rs @@ -80,6 +80,11 @@ impl Styles { self.0.is_empty() } + /// Iterate over the contained styles. + pub fn iter(&self) -> impl Iterator { + self.0.iter().map(|style| &**style) + } + /// Set an inner value for a style property. /// /// If the property needs folding and the value is already contained in the diff --git a/crates/typst/src/layout/flow.rs b/crates/typst/src/layout/flow.rs index f5d44d9bf..d7b9880fe 100644 --- a/crates/typst/src/layout/flow.rs +++ b/crates/typst/src/layout/flow.rs @@ -1,3 +1,5 @@ +use std::fmt::{self, Debug, Formatter}; + use comemo::Prehashed; use crate::diag::{bail, SourceResult}; @@ -22,7 +24,7 @@ use crate::visualize::{ /// /// This element is responsible for layouting both the top-level content flow /// and the contents of boxes. -#[elem(Layout)] +#[elem(Debug, Layout)] pub struct FlowElem { /// The children that will be arranges into a flow. #[variadic] @@ -95,6 +97,13 @@ impl Layout for Packed { } } +impl Debug for FlowElem { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "Flow ")?; + f.debug_list().entries(&self.children).finish() + } +} + /// Performs flow layout. struct FlowLayouter<'a> { /// Whether this is the root flow. diff --git a/crates/typst/src/model/par.rs b/crates/typst/src/model/par.rs index 690b7276b..4594e7fd7 100644 --- a/crates/typst/src/model/par.rs +++ b/crates/typst/src/model/par.rs @@ -1,3 +1,5 @@ +use std::fmt::{self, Debug, Formatter}; + use comemo::Prehashed; use crate::diag::SourceResult; @@ -33,7 +35,7 @@ use crate::layout::{Em, Fragment, Length, Size}; /// let $a$ be the smallest of the /// three integers. Then, we ... /// ``` -#[elem(title = "Paragraph", Construct)] +#[elem(title = "Paragraph", Debug, Construct)] pub struct ParElem { /// The spacing between lines. #[resolve] @@ -144,6 +146,13 @@ impl Packed { } } +impl Debug for ParElem { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "Par ")?; + f.debug_list().entries(&self.children).finish() + } +} + /// How to determine line breaks in a paragraph. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Cast)] pub enum Linebreaks { diff --git a/crates/typst/src/text/mod.rs b/crates/typst/src/text/mod.rs index 01d93febe..23a685d84 100644 --- a/crates/typst/src/text/mod.rs +++ b/crates/typst/src/text/mod.rs @@ -86,7 +86,7 @@ pub(super) fn define(global: &mut Scope) { /// With a function call. /// ]) /// ``` -#[elem(Construct, PlainText, Repr)] +#[elem(Debug, Construct, PlainText, Repr)] pub struct TextElem { /// A font family name or priority list of font family names. /// @@ -657,6 +657,12 @@ impl TextElem { } } +impl Debug for TextElem { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "Text({})", self.text) + } +} + impl Repr for TextElem { fn repr(&self) -> EcoString { eco_format!("[{}]", self.text)