Support for align parameter in table to take an array (#1087) (#1149)

This commit is contained in:
jassler 2023-05-12 12:26:14 +02:00 committed by GitHub
parent a8728be9b0
commit fd84d23ade
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 7 deletions

View File

@ -87,9 +87,10 @@ pub struct TableElem {
/// How to align the cell's content. /// How to align the cell's content.
/// ///
/// This can either be a single alignment or a function that returns an /// This can either be a single alignment, an array of alignments
/// alignment. The function is passed the cell's column and row index, /// (corresponding to each column) or a function that returns an alignment.
/// starting at zero. If set to `{auto}`, the outer alignment is used. /// The function is passed the cell's column and row index, starting at zero.
/// If set to `{auto}`, the outer alignment is used.
/// ///
/// ```example /// ```example
/// #table( /// #table(
@ -236,9 +237,11 @@ pub enum Celled<T> {
Value(T), Value(T),
/// A closure mapping from cell coordinates to a value. /// A closure mapping from cell coordinates to a value.
Func(Func), Func(Func),
/// An array of alignment values corresponding to each column.
Array(Vec<T>),
} }
impl<T: Cast + Clone> Celled<T> { impl<T: Cast + Clone + Default> Celled<T> {
/// Resolve the value based on the cell position. /// Resolve the value based on the cell position.
pub fn resolve(&self, vt: &mut Vt, x: usize, y: usize) -> SourceResult<T> { pub fn resolve(&self, vt: &mut Vt, x: usize, y: usize) -> SourceResult<T> {
Ok(match self { Ok(match self {
@ -247,6 +250,11 @@ impl<T: Cast + Clone> Celled<T> {
.call_vt(vt, [Value::Int(x as i64), Value::Int(y as i64)])? .call_vt(vt, [Value::Int(x as i64), Value::Int(y as i64)])?
.cast() .cast()
.at(func.span())?, .at(func.span())?,
Self::Array(array) => x
.checked_rem(array.len())
.and_then(|i| array.get(i))
.cloned()
.unwrap_or_default(),
}) })
} }
} }
@ -259,19 +267,22 @@ impl<T: Default> Default for Celled<T> {
impl<T: Cast> Cast for Celled<T> { impl<T: Cast> Cast for Celled<T> {
fn is(value: &Value) -> bool { fn is(value: &Value) -> bool {
matches!(value, Value::Func(_)) || T::is(value) matches!(value, Value::Array(_) | Value::Func(_)) || T::is(value)
} }
fn cast(value: Value) -> StrResult<Self> { fn cast(value: Value) -> StrResult<Self> {
match value { match value {
Value::Func(v) => Ok(Self::Func(v)), Value::Func(v) => Ok(Self::Func(v)),
Value::Array(array) => {
Ok(Self::Array(array.into_iter().map(T::cast).collect::<StrResult<_>>()?))
}
v if T::is(&v) => Ok(Self::Value(T::cast(v)?)), v if T::is(&v) => Ok(Self::Value(T::cast(v)?)),
v => <Self as Cast>::error(v), v => <Self as Cast>::error(v),
} }
} }
fn describe() -> CastInfo { fn describe() -> CastInfo {
T::describe() + CastInfo::Type("function") T::describe() + CastInfo::Type("array") + CastInfo::Type("function")
} }
} }
@ -280,6 +291,7 @@ impl<T: Into<Value>> From<Celled<T>> for Value {
match celled { match celled {
Celled::Value(value) => value.into(), Celled::Value(value) => value.into(),
Celled::Func(func) => func.into(), Celled::Func(func) => func.into(),
Celled::Array(arr) => arr.into(),
} }
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@ -13,10 +13,26 @@
--- ---
#table(columns: 3, stroke: none, fill: green, [A], [B], [C]) #table(columns: 3, stroke: none, fill: green, [A], [B], [C])
---
// Test alignment with array.
#table(
columns: (1fr, 1fr, 1fr),
align: (left, center, right),
[A], [B], [C]
)
// Test empty array.
#set align(center)
#table(
columns: (1fr, 1fr, 1fr),
align: (),
[A], [B], [C]
)
--- ---
// Ref: false // Ref: false
#table() #table()
--- ---
// Error: 14-19 expected color, none, or function, found string // Error: 14-19 expected color, none, array, or function, found string
#table(fill: "hey") #table(fill: "hey")