Here's an implementation with xparse
and expl3
.
The idea is to first sum the items in the “multiratio” so as to establish the modulus. Then a suitable preamble is built, multiplying each item by the modulus and subtracting twice the \tabcolsep
.
I set up things so you don't need to type \hline
.
The optional argument defaults to \columnwidth
, but you can try
\quicktable[10cm]{1:2:1}{&&\\&&}
and see the result.
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\quicktable}{ O{\columnwidth} m m }
{
\zenoshuai_quicktable:nnn { #1 } { #2 } { #3 }
}
\seq_new:N \l__zenoshuai_quicktable_header_seq
\seq_new:N \l__zenoshuai_quicktable_body_seq
\tl_new:N \l__zenoshuai_quicktable_header_tl
\dim_new:N \l__zenoshuai_quicktable_modulus_dim
\cs_generate_variant:Nn \seq_set_split:Nnn { NV }
\cs_new_protected:Nn \zenoshuai_quicktable:nnn
{
\seq_set_split:NVn \l__zenoshuai_quicktable_header_seq \c_colon_str { #2 }
\dim_set:Nn \l__zenoshuai_quicktable_modulus_dim
{
#1/(\seq_use:Nn \l__zenoshuai_quicktable_header_seq { + })
}
\tl_set:Nx \l__zenoshuai_quicktable_header_tl
{
|\seq_map_function:NN \l__zenoshuai_quicktable_header_seq \__zenoshuai_quicktable_col:n
}
\__zenoshuai_quicktable_body:Vn \l__zenoshuai_quicktable_header_tl { #3 }
}
\cs_new:Nn \__zenoshuai_quicktable_col:n
{
p { \dim_eval:n { #1\l__zenoshuai_quicktable_modulus_dim - 2\tabcolsep } }|
}
\cs_new_protected:Nn \__zenoshuai_quicktable_body:nn
{
\seq_set_split:Nnn \l__zenoshuai_quicktable_body_seq { \\ } { #2 }
\begin{tabular}{#1}
\hline
\seq_use:Nn \l__zenoshuai_quicktable_body_seq { \\ \hline } \\
\hline
\end{tabular}
}
\cs_generate_variant:Nn \__zenoshuai_quicktable_body:nn { V }
\ExplSyntaxOff
\begin{document}
\noindent X\hrulefill X
\bigskip
\noindent
\quicktable{1:1:2}{
&&\\
&&
}
\bigskip
\noindent
\quicktable{2:2:6}{
&&\\
&&
}
\bigskip
\noindent
\quicktable{1:1:1:1}{
&&&\\
&&&
}
\end{document}

A slightly more complicated version that also works when array
is loaded.
\documentclass{article}
\usepackage{xparse,array}
% important: code should go after \usepackage{array} or any package that loads it
\ExplSyntaxOn
\bool_new:N \g_zenoshuai_quicktable_array_bool
\use:c { @ifpackageloaded } { array }
{
\bool_gset_true:N \g_zenoshuai_quicktable_array_bool
}
{
\bool_gset_false:N \g_zenoshuai_quicktable_array_bool
}
\NewDocumentCommand{\quicktable}{ O{\columnwidth} m m }
{
\zenoshuai_quicktable:nnn { #1 } { #2 } { #3 }
}
\seq_new:N \l__zenoshuai_quicktable_header_seq
\seq_new:N \l__zenoshuai_quicktable_body_seq
\tl_new:N \l__zenoshuai_quicktable_header_tl
\dim_new:N \l__zenoshuai_quicktable_modulus_dim
\cs_generate_variant:Nn \seq_set_split:Nnn { NV }
\cs_new_protected:Nn \zenoshuai_quicktable:nnn
{
\seq_set_split:NVn \l__zenoshuai_quicktable_header_seq \c_colon_str { #2 }
\dim_set:Nn \l__zenoshuai_quicktable_modulus_dim
{
\bool_if:NTF \g_zenoshuai_quicktable_array_bool
{(#1 - \int_eval:n { \seq_count:N \l__zenoshuai_quicktable_header_seq +1 }\arrayrulewidth) }
{ #1 }
/(\seq_use:Nn \l__zenoshuai_quicktable_header_seq { + })
}
\tl_set:Nx \l__zenoshuai_quicktable_header_tl
{
|\seq_map_function:NN \l__zenoshuai_quicktable_header_seq \__zenoshuai_quicktable_col:n
}
\__zenoshuai_quicktable_body:Vn \l__zenoshuai_quicktable_header_tl { #3 }
}
\cs_new:Nn \__zenoshuai_quicktable_col:n
{
p { \dim_eval:n { #1\l__zenoshuai_quicktable_modulus_dim - 2\tabcolsep } }|
}
\cs_new_protected:Nn \__zenoshuai_quicktable_body:nn
{
\seq_set_split:Nnn \l__zenoshuai_quicktable_body_seq { \\ } { #2 }
\begin{tabular}{#1}
\hline
\seq_use:Nn \l__zenoshuai_quicktable_body_seq { \\ \hline } \\
\hline
\end{tabular}
}
\cs_generate_variant:Nn \__zenoshuai_quicktable_body:nn { V }
\ExplSyntaxOff
\begin{document}
\noindent X\hrulefill X
\bigskip
\noindent
\quicktable{1:1:2}{
&&\\
&&
}
\bigskip
\noindent
\quicktable{2:2:6}{
&&\\
&&
}
\bigskip
\noindent
\quicktable{1:1:1:1}{
&&&\\
&&&
}
\end{document}
\tabcolsep
and the\arrayrulewidth
.array
isn't loaded, so\arrayrulewidth
won't contribute to the overall width.\begin{tabularx}{\linewidth}{|*2{>{\hsize=.75\hsize\linewidth=\hsize}X|}>{\hsize=1.5\hsize\linewidth=\hsize}X|}
.1:1:2
represent?