From fd84d23ade16fea22e8f8413a5d29c95c2ee1d84 Mon Sep 17 00:00:00 2001 From: jassler Date: Fri, 12 May 2023 12:26:14 +0200 Subject: [PATCH] Support for align parameter in table to take an array (#1087) (#1149) --- library/src/layout/table.rs | 24 ++++++++++++++++++------ tests/ref/layout/table.png | Bin 5170 -> 7530 bytes tests/typ/layout/table.typ | 18 +++++++++++++++++- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/library/src/layout/table.rs b/library/src/layout/table.rs index 6e3e6330c..29e2edb88 100644 --- a/library/src/layout/table.rs +++ b/library/src/layout/table.rs @@ -87,9 +87,10 @@ pub struct TableElem { /// How to align the cell's content. /// - /// This can either be a single alignment or a function that returns an - /// alignment. The function is passed the cell's column and row index, - /// starting at zero. If set to `{auto}`, the outer alignment is used. + /// This can either be a single alignment, an array of alignments + /// (corresponding to each column) or a function that returns an alignment. + /// The function is passed the cell's column and row index, starting at zero. + /// If set to `{auto}`, the outer alignment is used. /// /// ```example /// #table( @@ -236,9 +237,11 @@ pub enum Celled { Value(T), /// A closure mapping from cell coordinates to a value. Func(Func), + /// An array of alignment values corresponding to each column. + Array(Vec), } -impl Celled { +impl Celled { /// Resolve the value based on the cell position. pub fn resolve(&self, vt: &mut Vt, x: usize, y: usize) -> SourceResult { Ok(match self { @@ -247,6 +250,11 @@ impl Celled { .call_vt(vt, [Value::Int(x as i64), Value::Int(y as i64)])? .cast() .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 Default for Celled { impl Cast for Celled { 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 { match value { Value::Func(v) => Ok(Self::Func(v)), + Value::Array(array) => { + Ok(Self::Array(array.into_iter().map(T::cast).collect::>()?)) + } v if T::is(&v) => Ok(Self::Value(T::cast(v)?)), v => ::error(v), } } fn describe() -> CastInfo { - T::describe() + CastInfo::Type("function") + T::describe() + CastInfo::Type("array") + CastInfo::Type("function") } } @@ -280,6 +291,7 @@ impl> From> for Value { match celled { Celled::Value(value) => value.into(), Celled::Func(func) => func.into(), + Celled::Array(arr) => arr.into(), } } } diff --git a/tests/ref/layout/table.png b/tests/ref/layout/table.png index 340d93a73d2f503f788b469e3e63c7e7607b96be..5c8dbf0e09bdba7c2a29c864027d41b6b613b9bc 100644 GIT binary patch literal 7530 zcmds6c|28X+a|)vE=1X7I)+G;Eiz=vQ0yWl$q=?V^N@KeZ8ixcl%Zsvwaqgb zLdZOBLzJn_cRS~N-`hFw>Ac_f@3;Q&+iQ8&TF<(l`@Zh$x}N)2E-UZfcXS^a8QFfc zijoEy895~x*`C)ld*DiRz3CPi8JjR#NnX>vpE&5Dt@-tRW#m0!WmVpg%td1r8o`T8ylXsjh_Pw!mBTfUZpPc0$BZ9L3o3LG5$P?B z(K+=JwU|=catX86b0}P7g(N#gw-GmWBz~;9?zZm~Ya5Nc(w~l1WGDU170j=DC>W4I zmFFm_xKQ+del!TBzrEDSfhY@#k@#asF*fN+zL}}%tpcvor!~so)z;Um5OJoaruA!V zh>pHH zB5b6hrbg_|PSDN#_U&6F8?LicgHy@LDaX}xqA@}tNL`MkX@KP7;?g|P{e5F)F8IZZ z7XlHDZo@vzh)@b_Ma3N_r!R@}Sors=>#xTHMk@U%6oNcfCM}h}&G&KpA3t>}k^yJd z6q&C1%8!Ct*4ehgmxRaTE8EABT3I*y(yzUMITZ|fUP`*6bm2lH8)3BOpCb^QdHEypy=)WeR-_TZE;BE z&bGI>ctK<1MGv(^eSQ67=*E_o37bwv!sCPldu!{h?XAV$ZRF9TC(xb4JKJu3Ml>`u z?xe51e5%o(iNwL=^AF)chDA>2FCa5AGh13(B=a_Tgn4**^KJT0OG|ry#BP3_dvWFX zg-1xvIYR2_sBy%_iTQc&vD*Dbm^TFl7Hv!Z!tUmuv<>g04M!r%-3F;(YIlld^prTJuNi5Vdl!X;bx19iesH)BNps~5vNbP$Sx2W&q)4^~K;9w=CRCV6{y-!HVZ?{afBk2A$dxy4I38jDnj^Yio1 zq`!zis1O|+s~#(MQc}`mwE8|fJ9}7ISkx(f{2&pjqoV^Emz$oR9u?KQG(w=JW1k-x z5%yf2o^)u7ZZ+0k*PEG{5zxwL51AStPfbgMA{5lkJgy0A8qw3x_x4mzI_m2lgMy$y^xc6B1G{ zUksWTu3zI(9jqX|d4t-B_fMDlDkvcEWKn9*PmzHf(L$>T-><5wYGX4W&VP+pEr#jP zp+k&}@7$M1A&O#wfqU+eBSPs2gC%aEY*IaCUT&O9#>S%sbSL=vf1#sWY)>M5BMwxN zQIXE7J_rszr0`7IBWD3~^=jC~w3sv2hmn9O>i3NpWd2K!{tR} zYn+sYsp%d-v|0>&a|tX&KBhYwAc*Ui?(_L3Id*`RNrxBz}g& ze~ZrbhY0r>`62~%@DUMt-`7s+7dsD^`@sCzjS8J68gcts=841rdMq`a!CT{+#t4CH z*RBzXL=$6U2vC`nY7ENg9{uR&Dr|pPXJ;p1Iy3>#Ku%d%1DfSQx8ZKKn?+8?ev38~ zSC)QBE#*-Jrf{czBqKu*LVibhePd%kt3>eZ_XL5+=##n>Z9j=%|gLpi3< zajZ68#_L&JTmXH_h2YKUl+b+JfqVdKe}75}3hedQTJXZndr76G--E@6qD3rP^(us* zXyIgiB#;9>(r(0j&;I{gP=9EI^}kSDz4k|=RT)AC#aR4pul<{jjOV6;9`wVJTzj8( zy_$%`{0h;4iS404(ja~~`TLH}qx|PCE?@p6GbiUXQOiFd;80^e)G84d9ud*-pSn2I z>On_MG&DrxhkVusU*E{~-65@U_^v0##_DNm zGQkkHK=cz{H9XHuSNgU7un#ZPsi~>4|D7oK)W!0xtOZON2PCggwZrmgO_|r)X+J9L zw(-lCFV`oc3{M%BKYRA96bk0IoIxN_zlw@>_4f95b*&N$hN&o!5~`gx{kiu`gXj?Pn80bpYL%=EOiqg@pNJI1#{{=*XB%tJ@!``*1XZ~5}=+kpcIfNvH+-v(~u zM(p1U*~N?lwyBk=o0gU~Sae(2+N3>EULgo@1s=S4ZzLsDR^vnj)JT@N@76b4H@7u) z*$qknFj_=!wxNCZtBCCEMaACowIQ#j$deS%clPYk!vOl4ni@KNuf?IV*;y;dPazZ~ zH8m|~2!~v29}j9;iVA=djkg;v2dIKGH#axV>bE9!v%!44ysmJUawxlgiL08L+FlBz zGY8>~5y77xnuvAb?7KEuMg>Yr$~P7O`f7=Wz8e#`*I5Q-C;X8j<_IWWW+XuIr@_JN zC%Tgq10lP8DyH-A?Dz@@yoT0$LrbfNt-^aFhkmrrA_1PhI_>)CA+ykdBd39Xn*u$D z1`nSSD|!2QXs9~yR$x1@V$*~AuM6x3PY4JMz+^($q(azb8q=?%9B9RRkNm8JaD4up z8u`Jjk{Tt4%FD}*a$0(OZC+Mt?y!;+)CUj;4#Z1)I1$&k7ArWIm_!{u zSN2~AhT7NH2QBB6i8kPdb#@sq8V?La#NzVh%OS4a(5N?8XSn^R2TRuA_eT*}!2?ga ztX#If5m`di8ppaAfEKGx&?Ny z&~Gd-ZGQoqk%H!y7F!#eqan)5%CwvY9utQkTh@eApFhV11pLCuw66xj4XxU$Zsp6D z=c-RT)35Py`eU(*Ha0fD<9QPj#LDQ{7$Z9q2S)-PuOSuxk#GULGFRxU(*e z;r!M;8NiAP14&hP%CvwIFct6vQhjQgZ>3b|Ddz=tJ*UK?@qJ{dS9rj1djX$ z074J|jTTwCd-_)#Qsg#q@O}~d_F>;OFVfNF+vYM^*z_0u8E%(Egz}z7^}ip!NV>@~ zP}sU4<;}82LF$?!^{YA*?mYA?5Oow6U$L}2)7k2XF38&Y4*aR&QPTMvw4DBm#mZy8 zs&QItObSS;r#-%>N^HK^b#yD3nT+R`shf}5-CUk>8m+;_AI?{#Y>9(#J+ zHu-GN@QwMeBCcY#Ypv_ z{0HBkRp<0qbFPzncFDWy89Cz4Uc~`)2=QQ?)lNpv88M<|-!xLyD_vh~)m8Vy2Rm10 zZfeHB0QEDC0t1(cg8tK}wzzj_%q>cUKHWNtE2<-Y=qY3to8jil8j$$O(B`*36hnLa#>W>IQG`)@pTk7mggTm9Hg!^|oz>ovK3X!?}-SKjh{+zn~< zudf;m7e0LY{+v<5xNc~!nL})#9UHuJD}9QRn((bw;b3Hy?QDFo<3NAi=EMQ2%>4m8 zs?yEG$wJvizU~FJ8zKpjYXwRNPbSz8xZ+c~RZ0#Io^0L{Ywb(jk>bp6%Wm0`P&pZX zvRF^M;!{$KJ2h=ZPo}{em%+|J0H5y`h*NtF@*b{usuvJ_c6Qp0)#aw7)uX(HqPT>n zyxUH3xXX14`#9Q9eT_dAK1PHV zUYu&XPVfw2Cm2DsM^U8m*R`@)kW2ye+uPet!}NFV+~KT-bC)p*>ipb25RK#L?C1IzFW7jbOujdxXfUVV;v9Yn0&PzgO zW@ez*45(bTcA@x|8Qm} z+-{SZnw)e6*Uoe7Qly}xi_2cD`TWPXhThBPZEP~$zFh{ckxGaBP9n`2zZ?|br7H!( z8HN=G_|#w)aj}~&Q>|>w%uzt8%4!`pzDyXDd0L9bfFFp)Yh`FB1tMWywnj#8oo6%# zYd=p-S(uotC|lbP7N;$G;ljhiYaTN9ZueDHRkgLLtE05FwOQqS!5Arh`Le#Q&SK$H zQL&6)xyxMS#Wc_GvV;(mmswe^uC6`o@|P22_0u)uWqouxP|?xRrQ4fx_wU~~GBS#c zjFjbIS$XmFD=cAptB#V4bIQczdhNE_H3W-NI8a%5x0*oXX6FE-Y`6D zh)@0W>85_o(pae6Mf~{O94#)88Htqe`ZoXmY!MtKC37Q`o8VDgOzZ6ExEeTxfQ8Z0 z(!#i_fWUEdcFq9*Nj%^&&&=!W@=kHY(O_`F(CM0>qi);~mfrckg69Ea#xKdYqoc#V ze8aq~%D#f6g--=eFe^qSCnuMut8f1XC?@cov!xa3)6V zD+8hLodrG5*TyilqxKR%u1jBdWeZMwGc)TDn_$I?z~3xlx|j-xLUd{0Or z&YwRIS@ncZJtR0d7|I|dB>s%G*5%8sEwSQe4@ST*YiMWy-)m)UEi@=7TFPw!pb9ie zl=2%u%Yc^Qs%zQg^XcU)YR+(V1ntuD&E6lT_|=1fQAPC z5lS^i6pc^46m?3*nK<*|g*~V{-18a-V*eS?jWIDtgD;4<%xVH?LYmey695`PPALZ; zJ;cD^_}gZJ1MF(#yO zSlb7dcGoZfZen6$uFlSs1V+Lev!=taEdiz3wvh>#ehIIsqr<-@N$54aa}uoq%5U5$ zx+_ypJWZodDbN+O-nRd!D7ZZ@ha~r-@#d}1_}z9vXlTgbcMv*^gdHLQbSD&d)eN z376+jC_+E<^ep!C z^P}fFdv+5`C#zlN>7t-;udK|+)6>(%CGQam%w|aNf&PBb=Q8~K>4k+70s;a6g~Gyb z`6mxz3Wp(XD=RDFHXmUtrvhf+X@7zE3LFc7PLSzoPfgZmUuXAZ8yb3v*^oBB0?q>{ zL_|cWi8I>HvV650D)snW=?5NXT52j26Vo#(w-8CfSoAr$R?uxl;8y%qWc+LMuAL9z zv}5(CpRZ`HvLNea_iVq#T$7KY=_9`&A%PB4S(OFD;H!|N06}qaC)f5jw6?Z3Hw!}F z^2-iwXl@QaLX~VTH9_{j+G*TF5mt(VJ+2=QQo}a$7}dIzGs3b0_E5>t=PxT|DPZpX E7t(AS3jhEB literal 5170 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 AF#rGn diff --git a/tests/typ/layout/table.typ b/tests/typ/layout/table.typ index 5d423e037..5526c4f66 100644 --- a/tests/typ/layout/table.typ +++ b/tests/typ/layout/table.typ @@ -13,10 +13,26 @@ --- #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 #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")