From e09b55f00f4213a76285e90825dfab570a051359 Mon Sep 17 00:00:00 2001 From: Malo <57839069+MDLC01@users.noreply.github.com> Date: Mon, 6 Jan 2025 16:41:58 +0100 Subject: [PATCH] Allow adding and joining `arguments` (#5651) --- crates/typst-library/src/foundations/args.rs | 16 ++++++++++++++++ crates/typst-library/src/foundations/ops.rs | 2 ++ .../{scripting => foundations}/arguments.typ | 9 +++++++++ 3 files changed, 27 insertions(+) rename tests/suite/{scripting => foundations}/arguments.typ (60%) diff --git a/crates/typst-library/src/foundations/args.rs b/crates/typst-library/src/foundations/args.rs index a4cbcb28b..44aa9dd6d 100644 --- a/crates/typst-library/src/foundations/args.rs +++ b/crates/typst-library/src/foundations/args.rs @@ -1,4 +1,5 @@ use std::fmt::{self, Debug, Formatter}; +use std::ops::Add; use ecow::{eco_format, eco_vec, EcoString, EcoVec}; use typst_syntax::{Span, Spanned}; @@ -376,6 +377,21 @@ impl PartialEq for Args { } } +impl Add for Args { + type Output = Self; + + fn add(mut self, rhs: Self) -> Self::Output { + self.items.retain(|item| { + !item.name.as_ref().is_some_and(|name| { + rhs.items.iter().any(|a| a.name.as_ref() == Some(name)) + }) + }); + self.items.extend(rhs.items); + self.span = Span::detached(); + self + } +} + /// An argument to a function call: `12` or `draw: false`. #[derive(Clone, Hash)] #[allow(clippy::derived_hash_with_manual_eq)] diff --git a/crates/typst-library/src/foundations/ops.rs b/crates/typst-library/src/foundations/ops.rs index 8d12966bf..85a041b6c 100644 --- a/crates/typst-library/src/foundations/ops.rs +++ b/crates/typst-library/src/foundations/ops.rs @@ -36,6 +36,7 @@ pub fn join(lhs: Value, rhs: Value) -> StrResult { (Symbol(a), Content(b)) => Content(TextElem::packed(a.get()) + b), (Array(a), Array(b)) => Array(a + b), (Dict(a), Dict(b)) => Dict(a + b), + (Args(a), Args(b)) => Args(a + b), (a, b) => mismatch!("cannot join {} with {}", a, b), }) } @@ -136,6 +137,7 @@ pub fn add(lhs: Value, rhs: Value) -> HintedStrResult { (Array(a), Array(b)) => Array(a + b), (Dict(a), Dict(b)) => Dict(a + b), + (Args(a), Args(b)) => Args(a + b), (Color(color), Length(thickness)) | (Length(thickness), Color(color)) => { Stroke::from_pair(color, thickness).into_value() diff --git a/tests/suite/scripting/arguments.typ b/tests/suite/foundations/arguments.typ similarity index 60% rename from tests/suite/scripting/arguments.typ rename to tests/suite/foundations/arguments.typ index e82f49624..1439b6be5 100644 --- a/tests/suite/scripting/arguments.typ +++ b/tests/suite/foundations/arguments.typ @@ -16,3 +16,12 @@ #let args = arguments(0, 1, a: 2, 3) // Error: 2-14 arguments do not contain key "b" and no default value was specified #args.at("b") + +--- arguments-plus-sum-join --- +#let lhs = arguments(0, "1", key: "value", 3) +#let rhs = arguments(other-key: 4, key: "other value", 3) +#let result = arguments(0, "1", 3, other-key: 4, key: "other value", 3) +#test(lhs + rhs, result) +#test({lhs; rhs}, result) +#test((lhs, rhs).sum(), result) +#test((lhs, rhs).join(), result)