summaryrefslogtreecommitdiff
path: root/library/src/compute
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-01-30 19:45:10 +0100
committerLaurenz <laurmaedje@gmail.com>2023-01-30 19:45:10 +0100
commit1ea0a933254d866e00acb9034bba39a5f4790682 (patch)
treed224b24f44d43795fabf2a35d0bb161b9d0d0938 /library/src/compute
parent3a4c5ae4b96ff5c2cd17a2f41a67398f21da0373 (diff)
User-defined symbols
Diffstat (limited to 'library/src/compute')
-rw-r--r--library/src/compute/construct.rs61
1 files changed, 61 insertions, 0 deletions
diff --git a/library/src/compute/construct.rs b/library/src/compute/construct.rs
index 784513f6..176409dd 100644
--- a/library/src/compute/construct.rs
+++ b/library/src/compute/construct.rs
@@ -240,6 +240,67 @@ castable! {
},
}
+/// # Symbol
+/// Create a custom symbol with modifiers.
+///
+/// ## Example
+/// ```
+/// #let envelope = symbol(
+/// "🖂",
+/// ("stamped", "🖃"),
+/// ("stamped.pen", "🖆"),
+/// ("lightning", "🖄"),
+/// ("fly", "🖅"),
+/// )
+///
+/// #envelope
+/// #envelope.stamped
+/// #envelope.stamped.pen
+/// #envelope.lightning
+/// #envelope.fly
+/// ```
+///
+/// ## Parameters
+/// - variants: Variant (positional, variadic)
+/// The variants of the symbol.
+///
+/// Can be a just a string consisting of a single character for the
+/// modifierless variant or an array with two strings specifying the modifiers
+/// and the symbol. Individual modifiers should be separated by dots. When
+/// displaying a symbol, Typst selects the first from the variants that have
+/// all attached modifiers and the minimum number of other modifiers.
+///
+/// - returns: symbol
+///
+/// ## Category
+/// construct
+#[func]
+pub fn symbol(args: &mut Args) -> SourceResult<Value> {
+ let mut list: Vec<(EcoString, char)> = vec![];
+ for Spanned { v, span } in args.all::<Spanned<Variant>>()? {
+ if list.iter().any(|(prev, _)| &v.0 == prev) {
+ bail!(span, "duplicate variant");
+ }
+ list.push((v.0, v.1));
+ }
+ Ok(Value::Symbol(Symbol::runtime(list)))
+}
+
+/// A value that can be cast to a symbol.
+struct Variant(EcoString, char);
+
+castable! {
+ Variant,
+ c: char => Self(EcoString::new(), c),
+ array: Array => {
+ let mut iter = array.into_iter();
+ match (iter.next(), iter.next(), iter.next()) {
+ (Some(a), Some(b), None) => Self(a.cast()?, b.cast()?),
+ _ => Err("point array must contain exactly two entries")?,
+ }
+ },
+}
+
/// # String
/// Convert a value to a string.
///