diff --git a/crates/typst/src/eval/array.rs b/crates/typst/src/eval/array.rs index 5d5fdcdbd..86c41ff6c 100644 --- a/crates/typst/src/eval/array.rs +++ b/crates/typst/src/eval/array.rs @@ -392,10 +392,18 @@ impl Array { } /// Enumerate all items in the array. - pub fn enumerate(&self) -> Self { + pub fn enumerate(&self, start: i64) -> StrResult { self.iter() .enumerate() - .map(|(i, value)| array![i, value.clone()].into_value()) + .map(|(i, value)| { + Ok(array![ + start + .checked_add_unsigned(i as u64) + .ok_or_else(|| "array index is too large".to_string())?, + value.clone() + ] + .into_value()) + }) .collect() } diff --git a/crates/typst/src/eval/methods.rs b/crates/typst/src/eval/methods.rs index bf47b7aa5..6a846f524 100644 --- a/crates/typst/src/eval/methods.rs +++ b/crates/typst/src/eval/methods.rs @@ -146,7 +146,10 @@ pub fn call( } "sorted" => array.sorted(vm, span, args.named("key")?)?.into_value(), "zip" => array.zip(args.expect("other")?).into_value(), - "enumerate" => array.enumerate().into_value(), + "enumerate" => array + .enumerate(args.named("start")?.unwrap_or(0)) + .at(span)? + .into_value(), "dedup" => array.dedup(vm, args.named("key")?)?.into_value(), _ => return missing(), }, diff --git a/docs/reference/types.md b/docs/reference/types.md index 4150cc9b1..d7cfaa653 100644 --- a/docs/reference/types.md +++ b/docs/reference/types.md @@ -892,6 +892,9 @@ The returned array consists of `(index, value)` pairs in the form of length-2 arrays. These can be [destructured]($scripting/#bindings) with a let binding or for loop. +- start: integer (named) + The index returned for the first pair of the returned list. + Defaults to `{0}`. - returns: array ### zip() diff --git a/tests/typ/compiler/array.typ b/tests/typ/compiler/array.typ index 4bc027efc..e2463cb0e 100644 --- a/tests/typ/compiler/array.typ +++ b/tests/typ/compiler/array.typ @@ -238,6 +238,15 @@ #test(((1, 2), 3).zip((4, 5)), (((1, 2), 4), (3, 5))) #test((1, "hi").zip((true, false)), ((1, true), ("hi", false))) +--- +// Test the `enumerate` method. +#test(().enumerate(), ()) +#test(().enumerate(start: 5), ()) +#test(("a", "b", "c").enumerate(), ((0, "a"), (1, "b"), (2, "c"))) +#test(("a", "b", "c").enumerate(start: 1), ((1, "a"), (2, "b"), (3, "c"))) +#test(("a", "b", "c").enumerate(start: 42), ((42, "a"), (43, "b"), (44, "c"))) +#test(("a", "b", "c").enumerate(start: -7), ((-7, "a"), (-6, "b"), (-5, "c"))) + --- // Test the `dedup` method. #test(().dedup(), ())