Skip to content

Commit

Permalink
Add array.repeat
Browse files Browse the repository at this point in the history
  • Loading branch information
JustForFun88 committed Apr 26, 2024
1 parent 0bb45b3 commit 9855e68
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 4 deletions.
4 changes: 2 additions & 2 deletions crates/typst/src/eval/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,8 @@ pub fn mul(lhs: Value, rhs: Value) -> StrResult<Value> {

(Str(a), Int(b)) => Str(a.repeat(Value::Int(b).cast()?)?),
(Int(a), Str(b)) => Str(b.repeat(Value::Int(a).cast()?)?),
(Array(a), Int(b)) => Array(a.repeat(Value::Int(b).cast()?)?),
(Int(a), Array(b)) => Array(b.repeat(Value::Int(a).cast()?)?),
(Array(a), Int(b)) => Array(a.repeat_content(Value::Int(b).cast()?)?),
(Int(a), Array(b)) => Array(b.repeat_content(Value::Int(a).cast()?)?),
(Content(a), b @ Int(_)) => Content(a.repeat(b.cast()?)),
(a @ Int(_), Content(b)) => Content(b.repeat(a.cast()?)),

Expand Down
24 changes: 22 additions & 2 deletions crates/typst/src/foundations/array.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::cmp::Ordering;
use std::fmt::{Debug, Formatter};
use std::iter;
use std::num::{NonZeroI64, NonZeroUsize};
use std::ops::{Add, AddAssign};

Expand Down Expand Up @@ -135,8 +136,9 @@ impl Array {
.filter(|&v| v < self.0.len() + end_ok as usize)
}

/// Repeat this array `n` times.
pub fn repeat(&self, n: usize) -> StrResult<Self> {
/// Repeat the content of this array `n` times, that is, creates an
/// array that contains elements of the original array repeated n times.
pub fn repeat_content(&self, n: usize) -> StrResult<Self> {
let count = self
.len()
.checked_mul(n)
Expand Down Expand Up @@ -882,6 +884,24 @@ impl Array {
})
.collect()
}

/// Builds an array of a given value a given number of times.
///
/// ```example
/// array.repeat("apples", 2)
/// ```
#[func]
pub fn repeat(
/// The value that will be repeated to build the array.
value: Value,
/// Length of the array. Must be positive.
times: i64,
) -> StrResult<Array> {
match usize::try_from(times) {
Ok(times) => Ok(iter::repeat(value).take(times).collect()),
_ => Err(format!("Cannot create array with the length: {times}").into()),
}
}
}

/// A value that can be cast to bytes.
Expand Down
13 changes: 13 additions & 0 deletions tests/suite/foundations/array.typ
Original file line number Diff line number Diff line change
Expand Up @@ -492,3 +492,16 @@
--- array-unclosed ---
// Error: 3-4 unclosed delimiter
#{(}

--- array-repeat ---
// Test the `join` method.
#test(().repeat(2), ((), ()))
#test((1,).repeat(3), ((1,), (1,), (1,)))
#test(array.repeat("a", 4), ("a", "a", "a", "a"))
#test(array.repeat(5, 0), ())
#test((3,) * 2, (3, 3))
#test(2 * (3,), (3, 3))

--- array-repeat-negative-length ---
// Error: 2-21 Cannot create array with the length: -5
#array.repeat(1, -5)

0 comments on commit 9855e68

Please sign in to comment.