diff --git a/crates/typst-library/src/foundations/symbol.rs b/crates/typst-library/src/foundations/symbol.rs index fcb3a3ce5..880305284 100644 --- a/crates/typst-library/src/foundations/symbol.rs +++ b/crates/typst-library/src/foundations/symbol.rs @@ -246,10 +246,50 @@ impl Debug for List { impl crate::foundations::Repr for Symbol { fn repr(&self) -> EcoString { - eco_format!("\"{}\"", self.get()) + match &self.0 { + Repr::Single(c) => eco_format!("symbol(\"{}\")", *c), + Repr::Complex(variants) => { + eco_format!("symbol{}", repr_variants(variants.iter().copied(), "")) + } + Repr::Modified(arc) => { + let (list, modifiers) = arc.as_ref(); + if modifiers.is_empty() { + eco_format!("symbol{}", repr_variants(list.variants(), "")) + } else { + eco_format!("symbol{}", repr_variants(list.variants(), modifiers)) + } + } + } } } +fn repr_variants<'a>( + variants: impl Iterator, + applied_modifiers: &str, +) -> String { + crate::foundations::repr::pretty_array_like( + &variants + .filter(|(variant, _)| { + // Only keep variants that can still be accessed, i.e., variants + // that contain all applied modifiers. + parts(applied_modifiers).all(|am| variant.split('.').any(|m| m == am)) + }) + .map(|(variant, c)| { + let trimmed_variant = variant + .split('.') + .filter(|&m| parts(applied_modifiers).all(|am| m != am)); + if trimmed_variant.clone().all(|m| m.is_empty()) { + eco_format!("\"{c}\"") + } else { + let trimmed_modifiers = trimmed_variant.collect::>().join("."); + eco_format!("(\"{}\", \"{}\")", trimmed_modifiers, c) + } + }) + .collect::>(), + false, + ) +} + impl Serialize for Symbol { fn serialize(&self, serializer: S) -> Result where diff --git a/tests/suite/symbols/symbol.typ b/tests/suite/symbols/symbol.typ index 30d87e44f..f2f6abf85 100644 --- a/tests/suite/symbols/symbol.typ +++ b/tests/suite/symbols/symbol.typ @@ -49,3 +49,65 @@ --- symbol-unknown-modifier --- // Error: 13-20 unknown symbol modifier #emoji.face.garbage + +--- symbol-repr --- +#test( + repr(sym.amp), + `symbol("&", ("inv", "⅋"))`.text, +) +#test( + repr(sym.amp.inv), + `symbol("⅋")`.text, +) +#test( + repr(sym.arrow.double.r), + ``` + symbol( + "⇒", + ("bar", "⤇"), + ("long", "⟹"), + ("long.bar", "⟾"), + ("not", "⇏"), + ("l", "⇔"), + ("l.long", "⟺"), + ("l.not", "⇎"), + ) + ```.text, +) +#test(repr(sym.smash), "symbol(\"⨳\")") + +#let envelope = symbol( + "🖂", + ("stamped", "🖃"), + ("stamped.pen", "🖆"), + ("lightning", "🖄"), + ("fly", "🖅"), +) +#test( + repr(envelope), + ``` + symbol( + "🖂", + ("stamped", "🖃"), + ("stamped.pen", "🖆"), + ("lightning", "🖄"), + ("fly", "🖅"), + ) + ```.text, +) +#test( + repr(envelope.stamped), + `symbol("🖃", ("pen", "🖆"))`.text, +) +#test( + repr(envelope.stamped.pen), + `symbol("🖆")`.text, +) +#test( + repr(envelope.lightning), + `symbol("🖄")`.text, +) +#test( + repr(envelope.fly), + `symbol("🖅")`.text, +)