Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

let width specifications in niceTables be numbers from (0,1] #1088

Merged
merged 2 commits into from
Aug 6, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
218 changes: 116 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,39 @@ 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 if (substr($width, -1) eq '%');
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