Skip to content

Commit

Permalink
let width specifications in niceTables be numbers from the interval (…
Browse files Browse the repository at this point in the history
…0,1]
  • Loading branch information
Alex-Jordan committed Jul 25, 2024
1 parent 91a4419 commit 1e4afb0
Showing 1 changed file with 115 additions and 102 deletions.
217 changes: 115 additions & 102 deletions macros/ui/niceTables.pl
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,9 @@ =head3 All output formats
C<r> for right-aligned column
C<p{width}> for a column with left-aligned paragraphs of fixed width.
The width needs to be absolute to work in all output formats.
C<p{width}> for a column with left-aligned paragraphs of the given width.
The width can be an absolute width or (unlike in LaTeX) a positive decimal number at most 1.
If it is a decimal, it will be interpreted as a portion of the available width.
C<X> for a column that expands to fill (see C<Xratio> below),
and will have left-aligned paragraphs
Expand Down Expand Up @@ -536,7 +537,8 @@ sub TableEnvironment {
if ($main::displayMode eq 'TeX') {
my $tabulartype = $hasX ? 'tabularx' : 'tabular';
my $tabularwidth = $hasX ? "$tableOpts->{Xratio}\\linewidth" : '';
$rows = latexEnvironment($rows, $tabulartype, [ $tabularwidth, '[t]', $tableOpts->{texalignment} ], ' ');
my $texalignment = $tableOpts->{texalignment} =~ s/p\{0*(0(\.\d*)?|1(\.0*)?)\}/p\{$1\\linewidth\}/gr;
$rows = latexEnvironment($rows, $tabulartype, [ $tabularwidth, '[t]', $texalignment ], ' ');
$rows = prefix($rows, '\centering%') if $tableOpts->{center};
$rows = prefix($rows, '\renewcommand{\arraystretch}{' . ($tableOpts->{padding}[0] + 1) . '}', '');
$rows = prefix($rows, '\setlength{\tabcolsep}{' . ($tableOpts->{padding}[1] * 10) . 'pt}', '');
Expand Down Expand Up @@ -566,16 +568,15 @@ sub TableEnvironment {
$ptxmargins = "${leftmargin}% ${rightmargin}%";
$ptxwidth .= '%';
} elsif (!$tableOpts->{center}) {
$ptxwidth = '100%';
$ptxmargins = '0% 0%';
}
if ($tableOpts->{LaYoUt}) {
$rows = tag(
$rows,
'sbsgroup',
{
width => $ptxwidth,
margins => $ptxmargins,
widths => $cols
}
);
} elsif (!$tableOpts->{LaYoUt}) {
Expand All @@ -584,13 +585,12 @@ sub TableEnvironment {
$rows,
'tabular',
{
valign => ($tableOpts->{valign} ne 'middle') ? $tableOpts->{valign} : '',
bottom => $tableOpts->{horizontalrules} ? 'minor' : '',
rowheaders => $tableOpts->{rowheaders} ? 'yes' : '',
margins => $ptxmargins,
width => $ptxwidth,
left => $ptxleft,
top => $ptxtop,
valign => ($tableOpts->{valign} ne 'middle') ? $tableOpts->{valign} : '',
bottom => $tableOpts->{horizontalrules} ? 'minor' : '',
'row-headers' => $tableOpts->{rowheaders} ? 'yes' : '',
width => $ptxwidth,
left => $ptxleft,
top => $ptxtop,
}
);
}
Expand Down Expand Up @@ -674,49 +674,87 @@ sub Cols {
}

if ($main::displayMode eq 'PTX') {
my $ptxhalign = '';
$ptxhalign = 'center' if ($align->{halign} eq 'c');
$ptxhalign = 'right' if ($align->{halign} eq 'r');
my $ptxright = '';
$ptxright = getPTXthickness($align->{right});
my $ptxtop = '';
$ptxtop = getPTXthickness($top);
my $ptxwidth = '';
$ptxwidth = getWidthPercent($align->{width}) if $align->{width};
$ptxwidth = ($tableOpts->{Xratio} / $#$alignment * 100) . '%'
if ($align->{halign} eq 'X');
$ptxwidth = getWidthPercent($width) if $width;
push(
@cols,
tag(
'', 'col',
{
halign => $ptxhalign,
right => $ptxright,
top => $ptxtop,
width => $ptxwidth
}
)
);
if ($tableOpts->{LaYoUt}) {
push @cols, ($align->{width} ? getWidthPercent($align->{width}) : '%');
} else {
my $ptxhalign = '';
$ptxhalign = 'center' if ($align->{halign} eq 'c');
$ptxhalign = 'right' if ($align->{halign} eq 'r');
my $ptxright = '';
$ptxright = getPTXthickness($align->{right});
my $ptxtop = '';
$ptxtop = getPTXthickness($top);
my $ptxwidth = '';
$ptxwidth = getWidthPercent($align->{width}) if $align->{width};
$ptxwidth = ($tableOpts->{Xratio} / $#$alignment * 100) . '%'
if ($align->{halign} eq 'X');
$ptxwidth = getWidthPercent($width) if $width;
push(
@cols,
tag(
'', 'col',
{
halign => $ptxhalign,
right => $ptxright,
top => $ptxtop,
width => $ptxwidth
}
)
);
}
} else {
my $htmlright = '';
$htmlright .= css('border-right', 'solid 2px')
if ($i == 1 && $tableOpts->{rowheaders} && $tableOpts->{headerrules});
$htmlright .= css('border-right', getRuleCSS($align->{right}));
my $htmltop = '';
$htmltop .= css('border-top', getRuleCSS($top));
my $htmlwidth = '';
if ($align->{width}) {
$htmlwidth = css('width', $align->{width});
$htmlwidth = css('width', getWidthPercent($align->{width}))
if ($align->{width} =~ /^0*(0(\.\d*)?|1(\.0*)?)$/);
}

# $i starts at 1, but columncss indexing starts at 0
my $htmlcolcss = css($columnscss->[ $i - 1 ]);
if ($align->{tex} =~ /\\columncolor(\[HTML\])?\{(.*?)[}!]/) {
$htmlcolcss .= css('background-color', ($1 ? '#' : '') . $2);
}

push(@cols, tag('', 'col', { style => "${htmlright}${htmltop}${htmlcolcss}" }));
push(@cols, tag('', 'col', { style => "${htmlright}${htmltop}${htmlcolcss}${htmlwidth}" }));
}

}

if ($main::displayMode eq 'PTX' && $tableOpts->{LaYoUt}) {
my @decimalcols = map { substr $_, 0, -1 } @cols;
my $total = 0;
my $count = 0;
for (@decimalcols) {
if ($_ eq '') {
$count++;
} else {
$total += $_;
}
}
# determine if somewhere in the alignment there are X columns
my $hasX = 0;
for my $align (@$alignment) {
if ($align->{halign} eq 'X') {
$hasX = 1;
last;
}
}
my $width = ($hasX ? $tableOpts->{Xratio} * 100 : 100);
my $fill = ($count != 0) ? int(($width - $total) / $count * 10**4) / 10**4 : 0;
for (@decimalcols) {
$_ = $fill if ($_ eq '');
}
@cols = map { $_ . '%' } @decimalcols;
return join(' ', @cols);
}

return join("\n", @cols);

}
Expand Down Expand Up @@ -805,52 +843,11 @@ sub Rows {
if (!$ptxleft && $rowArray->[0]{halign} && $alignment->[0]{left});

if ($tableOpts->{LaYoUt}) {
my $ptxwidthsum = 0;
my $ptxautocols = $#alignment;
for my $j (1 .. $#alignment) {
if ($rowArray->[ $j - 1 ]{width}) {
$ptxwidthsum +=
substr getWidthPercent($tableArray->[ $j - 1 ]{width}),
0, -1;
$ptxautocols -= 1;
} elsif ($alignment->[$j]{width}) {
$ptxwidthsum += substr getWidthPercent($alignment->[$j]{width}), 0, -1;
$ptxautocols -= 1;
}
}

# determine if somewhere in the overall alignment, there are X columns
my $hasX = 0;
for my $align (@$alignment) {
if ($align->{halign} eq 'X') {
$hasX = 1;
last;
}
}
my $leftoverspace =
(($hasX) ? $tableOpts->{Xratio} * 100 : 100) - $ptxwidthsum;
my $divvyuptherest = 0;
$divvyuptherest = int($leftoverspace / $ptxautocols * 10000) / 10000
unless ($ptxautocols == 0);
my @ptxwidths;
for my $j (1 .. $#alignment) {
if ($rowOpts->[ $j - 1 ]{width}) {
push(@ptxwidths, getWidthPercent($rowOpts->[ $j - 1 ]{width}));
} elsif ($alignment->[$j]{width}) {
push(@ptxwidths, getWidthPercent($alignment->[$j]{width}));
} else {
push(@ptxwidths, $divvyuptherest . '%');
}
}

my $ptxwidths = join(" ", @ptxwidths);
$row = tag(
$row,
'sidebyside',
{
valign => ($valign) ? $valign : $tableOpts->{valign},
margins => '0% 0%',
widths => $ptxwidths,
valign => ($valign) ? $valign : $tableOpts->{valign},
}
);
} else {
Expand Down Expand Up @@ -954,6 +951,7 @@ sub Row {
|| ($tableOpts->{rowheaders} && $tableOpts->{headerrules} && $i == 0))
{
my $columntype = $cellOpts->{halign};
$columntype = $columntype =~ s/p\{0*(0(\.\d*)?|1(\.0*)?)\}/p\{$1\\linewidth\}/gr;
$columntype = $cellAlign->{halign} // 'l' unless $columntype;
$columntype = 'p{' . $tableOpts->{Xratio} / ($#$rowArray + 1) . "\\linewidth}"
if ($columntype eq 'X');
Expand Down Expand Up @@ -1038,8 +1036,11 @@ sub Row {
if ($cellAlign->{halign} eq 'c');
$css .= css('text-align', 'right')
if ($cellAlign->{halign} eq 'r');
$css .= css('width', $cellAlign->{width})
if ($cellAlign->{width});
if ($cellAlign->{width} =~ /^0*(0(\.\d*)?|1(\.0*)?)$/) {
$css .= css('width', getWidthPercent($1));
} elsif ($cellAlign->{width}) {
$css .= css('width', $cellAlign->{width});
}
$css .= css('font-weight', 'bold')
if ($cellAlign->{tex} =~ /\\bfseries/);
$css .= css('font-style', 'italic')
Expand Down Expand Up @@ -1075,8 +1076,11 @@ sub Row {
if ($cellOpts->{halign} =~ /^c/);
$css .= css('text-align', 'right') if ($cellOpts->{halign} =~ /^r/);
$css .= css('text-align', 'left') if ($cellOpts->{halign} =~ /^p/);
$css .= css('width', $1)
if ($cellOpts->{halign} =~ /^p\{([^}]*?)}/);
if ($cellOpts->{halign} =~ /^p\{0*(0(\.\d*)?|1(\.0*)?)}/) {
$css .= css('width', getWidthPercent($1));
} elsif ($cellOpts->{halign} =~ /^p\{([^}]*?)}/) {
$css .= css('width', $1);
}
$css .= css('font-weight', 'bold')
if ($cellOpts->{tex} =~ /\\bfseries/);
$css .= css('font-style', 'italic')
Expand Down Expand Up @@ -1581,29 +1585,38 @@ sub getPTXthickness {
}

sub getWidthPercent {
my $absWidth = shift;
my $x = 0;
my $unit = 'cm';
if ($absWidth =~ /^(\.\d+|\d+\.?\d*)\s*(\w+)/) {
my $width = shift;
return $width * 100 . '%' if ($width =~ /^0*(0(\.\d*)?|1(\.0*)?)$/);
my $x = 0;
my $unit = 'cm';
if ($width =~ /^(\.\d+|\d+\.?\d*)\s*(\w+)$/) {
$x = $1;
$unit = $2;
}
my %convert_to_cm = (
'pt' => 1 / 864 * 249 / 250 * 12 * 2.54,
'mm' => 1 / 10,
'cm' => 1,
'in' => 2.54,
'ex' => 0.15132,
'em' => 0.35146,
'mu' => 0.35146 / 8,
'sp' => 1 / 864 * 249 / 250 * 12 * 2.54 / 65536,
'bp' => 2.54 / 72,
'dd' => 1 / 864 * 249 / 250 * 12 * 2.54 * 1238 / 1157,
'pc' => 1 / 864 * 249 / 250 * 12 * 2.54 * 12,
'cc' => 1 / 864 * 249 / 250 * 12 * 2.54 * 1238 / 1157 * 12,
'px' => 2.54 / 72,
my %convert_to_pt = (
# units with related absolute defintions
# the following are as TeX defines them
pt => 1,
pc => 12,
in => 72.27,
mm => 72.27 / 25.4,
cm => 72.27 / 2.54,
sp => 1 / 65536,
dd => 1238 / 1157,
cc => 12 * 1238 / 1157,
bp => 72.27 / 72,
# CSS defines 1 px to be 1/96 of an inch
# note that px is not a legal unit in TeX
px => 72 / 96,
# units relative to font
# the following are based on TeX default font
# (10pt Computer Modern)
em => 10.00002,
ex => 4.30554,
);
return (int($x * $convert_to_cm{$unit} / (6.25 * 2.54) * 10000) / 100) . '%';
# This is only used for PTX output, and a PTX document's default width is 340pt.
# We offer a percent with up to six significant digits
return (int($x * $convert_to_pt{$unit} / 340 * 10**6) / 10**4) . '%';
}

sub hrule {
Expand Down

0 comments on commit 1e4afb0

Please sign in to comment.