-
Notifications
You must be signed in to change notification settings - Fork 426
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
317 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2024-2025 Mc-Zen | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
# Pillar | ||
|
||
_Shorthand notations for table column specifications in [Typst](https://typst.app/)._ | ||
|
||
|
||
[![Typst Package](https://img.shields.io/badge/dynamic/toml?url=https%3A%2F%2Fraw.githubusercontent.com%2FMc-Zen%2Fpillar%2Fv0.3.1%2Ftypst.toml&query=%24.package.version&prefix=v&logo=typst&label=package&color=239DAD)](https://typst.app/universe/package/pillar) | ||
[![Test Status](https://github.com/Mc-Zen/pillar/actions/workflows/run_tests.yml/badge.svg)](https://github.com/Mc-Zen/pillar/actions/workflows/run_tests.yml) | ||
[![MIT License](https://img.shields.io/badge/license-MIT-blue)](https://github.com/Mc-Zen/pillar/blob/main/LICENSE) | ||
|
||
|
||
|
||
- [Introduction](#introduction) | ||
- [Column specification](#column-specification) | ||
- [Number alignment](#number-alignment) | ||
- [`pillar.cols()`](#pillarcols) | ||
- [`pillar.table()`](#pillartable) | ||
- [`vline` customization](#vline-customization) | ||
|
||
## Introduction | ||
With **pillar**, you can significantly simplify the column setup of tables by unifying the specification of the number, alignment, and separation of columns. This package is in particular designed for scientific tables, which typically have simple styling: | ||
|
||
|
||
<p align="center"> | ||
<picture> | ||
<source media="(prefers-color-scheme: light)" srcset="https://github.com/user-attachments/assets/c0c60651-c682-4968-9ac9-0fa1e8d85dad"> | ||
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/user-attachments/assets/710ac89b-c03b-4975-8d46-90790ebcea9a"> | ||
<img alt="Table of some piano notes and their names and frequencies" src="https://github.com/user-attachments/assets/c0c60651-c682-4968-9ac9-0fa1e8d85dad"> | ||
</picture> | ||
</p> | ||
|
||
In order to prepare this table with just the built-in methods, some code like the following would be required. | ||
```typ | ||
#table( | ||
columns: 5, | ||
align: (center,) * 4 + (right,), | ||
stroke: none, | ||
[Piano Key], table.vline(), [MIDI Number], [Note Name], [Pitch Name], table.vline(), [$f$ in Hz], | ||
.. | ||
) | ||
``` | ||
Using **pillar**, the same can be achieved with | ||
```typ | ||
#import "@preview/pillar:0.3.1" | ||
#table( | ||
..pillar.cols("c|ccc|r"), | ||
[Piano Key], [MIDI Number], [Note Name], [Pitch Name], [$f$ in Hz], .. | ||
) | ||
``` | ||
or alternatively | ||
```typ | ||
#pillar.table( | ||
cols: "c|ccc|r", | ||
[Piano Key], [MIDI Number], [Note Name], [Pitch Name], [$f$ in Hz], .. | ||
) | ||
``` | ||
|
||
**Pillar** is designed for interoperability. It uses the powerful standard tables and provides generated arguments for `table`'s `columns`, `align`, `stroke`, and for the specified vertical lines. This means that all features of the built-in tables (and also `show` and `set` rules) can be applied as usual. | ||
|
||
|
||
|
||
|
||
## Column specification | ||
|
||
This package works with _column specification strings_. Each column is described by its alignment which can be `l` (left), `c` (center), `r` (right), or `a` (auto). | ||
|
||
The width of a column can optionally be specified by appending a (relative) length, or fraction in square brackets to the alignment specifier, e.g., `c[2cm]` or `r[1fr]`. | ||
|
||
Vertical lines can be added between columns with a `|` character. Double lines can be produced with `||` (see [`vline` customization](#vline-customization)). The stroke of the vertical line can be changed by appending anything that is usually allowed as a stroke argument in square brackets, e.g., `|[2pt]`, `|[red]` or `|[(dash: \"dashed\")]`. | ||
|
||
A column specification string may contain any number of spaces (e.g., to improve readability) — all spaces will be ignored. | ||
|
||
_If you find yourself writing highly complex column specifications, consider not using this package and resort to the parameters that the built-in tables provide. This package is intended for quick and relatively simple column specifications._ | ||
|
||
## Number alignment | ||
|
||
Choosing capital letters `L`, `C`, `R`, or `A` instead of lower-case letters activates number alignment at the decimal separator for a specific column (similar to the column type "S" of the LaTeX package [siunitx](https://github.com/josephwright/siunitx)). This feature is provided via the Typst package **Zero**. [Here](https://github.com/Mc-Zen/zero) you can read up on the configuration of number formatting. | ||
|
||
```typ | ||
#let percm = $"cm"^(-1)$ | ||
#pillar.table( | ||
cols: "l|CCCC", | ||
[], [$Δ ν_0$ in #percm], [$B'_ν$ in #percm], [$B''_ν$ in #percm], [$D'_ν$ in #percm], | ||
table.hline(), | ||
[Measurement], [14525.278], [1.41], [1.47], [1.5e-5], | ||
[Uncertainty], [2], [0.3], [0.3], [4e-6], | ||
[Ref. [2]], [14525,74856], [1.37316], [1.43777], [5.401e-6] | ||
) | ||
``` | ||
|
||
|
||
<p align="center"> | ||
<picture> | ||
<source media="(prefers-color-scheme: light)" srcset="https://github.com/user-attachments/assets/066cd34e-7043-48c7-b067-e3256e942f14"> | ||
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/user-attachments/assets/2f1cfd30-00e1-400b-968e-c6ae39939d28"> | ||
<img alt="Number alignment" src="https://github.com/user-attachments/assets/066cd34e-7043-48c7-b067-e3256e942f14"> | ||
</picture> | ||
</p> | ||
|
||
|
||
Non-number entries (e.g., in the header) are automatically recognized in some cases and will not be aligned. In ambiguous cases, adding a leading or trailing space tells Zero not to apply alignment to this cell, e.g., `[Voltage ]` instead of `[Voltage]`. | ||
|
||
|
||
## `pillar.cols()` | ||
|
||
This function produces an argument list that may contain arguments for `columns`, `align`, `stroke`, and `column-gutter` as well as instances of `table.vline()`. These arguments are intended to be expanded with the `..` syntax into the argument list of `table` as shown in the examples. | ||
|
||
## `pillar.table()` | ||
|
||
This is a thin wrapper that behaves just like the built-in `table`, except that it extracts the first positional argument if it is a string, and runs it through `pillar.cols()`. | ||
|
||
## `vline` customization | ||
|
||
In order to customize the default line setting, just use set rules on `table.vline`, e.g., | ||
```typ | ||
#set table.vline(stroke: .7pt) | ||
#table(..pillar.cols("c|cc"), ..) | ||
``` | ||
|
||
Double lines are currently experimental and are realized through column gutters. They could also be realized through patterns, but this can produce artifacts with some renderers. As it currently is, double lines are not supported before the first and after the last column. On the other hand, with the current method, double lines are styled with set rules on `table.vline` which is nice and not achievable in the same way with patterns. | ||
|
||
## Examples | ||
|
||
### Double lines | ||
The following example uses a double line for visually separating repeated table columns. | ||
```typ | ||
#pillar.table( | ||
cols: "ccc ||[.7pt] ccc", | ||
..([\#], [$α$ in °], [$β$ in °]) * 2, | ||
table.hline(), | ||
[1], [34.3], [11.1], [6], [34.0], [12.9], | ||
[2], [34.2], [11.2], [7], [34.3], [12.8], | ||
[3], [34.6], [11.4], [8], [33.9], [11.9], | ||
[4], [34.7], [10.3], [9], [34.4], [11.8], | ||
[5], [34.3], [11.1], [10], [34.4], [11.8], | ||
) | ||
``` | ||
|
||
|
||
<p align="center"> | ||
<picture> | ||
<source media="(prefers-color-scheme: light)" srcset="https://github.com/user-attachments/assets/e05e7bad-61b6-44f9-af34-5e558f338cdc"> | ||
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/user-attachments/assets/f1134ce3-dbd0-4a73-895d-544c3c9f2645"> | ||
<img alt="Demonstration example using double vertical lines" src="https://github.com/user-attachments/assets/e05e7bad-61b6-44f9-af34-5e558f338cdc"> | ||
</picture> | ||
</p> | ||
|
||
### Further customization | ||
|
||
This example shows the codes of the first ten printable ASCII characters, demonstrating stroke and column width customization. | ||
|
||
```typ | ||
#pillar.table( | ||
cols: "ccc|ccc|[1.8pt + blue] l[5cm]", | ||
[Dec],[Hex],[Bin],[Symbol], [HTML code], [HTML name], [Description], | ||
table.hline(), | ||
[32], [20], [00100000], [ ], [], [SP], [Space], | ||
[33], [21], [00100001], [!], [!], [!], [Exclamation mark], | ||
[34], [22], [00100010], ["], ["], ["], [Double quotes], | ||
[35], [23], [00100011], [#], [#], [\#], [Number sign], | ||
[36], [24], [00100100], [$], [$], [\$], [Dollar sign], | ||
[37], [25], [00100101], [%], [%], [%], [Percent sign], | ||
[38], [26], [00100110], [&], [&], [&], [Ampersand], | ||
[39], [27], [00100111], ['], ['], ['], [Single quote], | ||
[40], [28], [00101000], [(], [&lparen;], [(], [Opening parenthesis], | ||
[41], [29], [00101001], [)], [&rparen;], [)], [Closing parenthesis], | ||
) | ||
``` | ||
|
||
<p align="center"> | ||
<picture> | ||
<source media="(prefers-color-scheme: light)" srcset="https://github.com/user-attachments/assets/9fae998e-033d-4d7e-9344-fe3778bbd9e6"> | ||
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/user-attachments/assets/e6c82d82-aa5e-4ea7-9517-a644b9f9355e"> | ||
<img alt="Demonstration example using double vertical lines" src="https://github.com/user-attachments/assets/9fae998e-033d-4d7e-9344-fe3778bbd9e6"> | ||
</picture> | ||
</p> | ||
|
||
## Tests | ||
This package uses [typst-test](https://github.com/tingerrr/typst-test/) for running [tests](tests/). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
#import "@preview/zero:0.3.2": ztable | ||
|
||
#let stdstroke = stroke | ||
#let stdtable = table | ||
|
||
#let cols(spec, stroke: auto, line-distance: 1.6pt) = { | ||
assert(type(spec) == str, message: "expected a `str` argument, got `" + str(type(spec)) + "`") | ||
|
||
let aligns = (r: right, c: center, l: left, a: auto) | ||
let format = () | ||
|
||
let align = () | ||
let columns = () | ||
let vline-specs = () | ||
|
||
let i = 0 | ||
let col = 0 | ||
let count-vlines = 0 | ||
|
||
while i < spec.len() { | ||
let c = spec.at(i) | ||
if lower(c) in "lcra" { | ||
align.push(aligns.at(lower(c))) | ||
format.push(if lower(c) == c { none } else { auto }) | ||
columns.push(auto) | ||
col += 1 | ||
count-vlines = 0 | ||
} else if c == "|" { | ||
count-vlines += 1 | ||
vline-specs.push((col, count-vlines, stroke)) | ||
assert(count-vlines <= 2, message: "At most two consecutive `|` are supported. ") | ||
} else if c == "[" { | ||
let end = spec.slice(i).position("]") | ||
if end == none { | ||
assert(false, message: "Unmatched `[`") | ||
} | ||
let width = eval(spec.slice(i + 1, i + end)) | ||
if count-vlines == 0 { | ||
assert(columns.len() > 0, message: "Unexpected width specification `" + spec.slice(i, i + end + 1) + "` at the beginning") | ||
assert(width == auto or type(width) in (relative, length, fraction), message: "column width expects a relative length, fraction, or auto, found " + str(type(width))) | ||
columns.last() = width | ||
} else { | ||
assert(width == none or type(width) in (length, color, gradient, pattern, dictionary, stdstroke), message: "vline stroke expects a length, color, gradient, pattern, dictionary, stroke, or none, found " + str(type(width))) | ||
vline-specs.last().last() = width | ||
} | ||
i += end | ||
|
||
} else if c == " " { | ||
|
||
} else { | ||
if c == "]" { assert(false, message: "Unexpected `]`") } | ||
assert(false, message: "Unknown column type `" + c + "`") | ||
} | ||
i += 1 | ||
} | ||
let vlines = () | ||
let column-gutter = (auto,) * columns.len() | ||
for (col, num, stroke) in vline-specs { | ||
let vline = table.vline | ||
if stroke != auto { vline = vline.with(stroke: stroke) } | ||
if num == 2 { | ||
assert(col != 0 and col != columns.len(), message: "Double lines `||` are currently not supported before the first and after the last column. ") | ||
vlines.push(vline(x: col - 1, position: end)) | ||
column-gutter.at(col - 1) = line-distance | ||
} | ||
vlines.push(vline(x: col)) | ||
} | ||
|
||
if auto in format { format = (format: format) } | ||
else { format = (:) } | ||
|
||
arguments( | ||
columns: columns, | ||
align: align, | ||
stroke: none, | ||
column-gutter: column-gutter, | ||
..vlines, | ||
..format | ||
) | ||
} | ||
|
||
|
||
|
||
#let table(..children) = { | ||
let named = children.named() | ||
if "cols" in named { | ||
let colspec = named.cols | ||
named.remove("cols") | ||
return ztable( | ||
..cols(colspec), | ||
..named, | ||
..children.pos() | ||
) | ||
} else { return stdtable(..children) } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
#import "impl.typ": cols, table |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[package] | ||
name = "pillar" | ||
version = "0.3.1" | ||
entrypoint = "src/pillar.typ" | ||
authors = ["Mc-Zen <https://github.com/Mc-Zen>"] | ||
license = "MIT" | ||
description = "Faster column specifications for tables." | ||
compiler = "0.11.0" | ||
|
||
repository = "https://github.com/Mc-Zen/pillar" | ||
keywords = ["table", "tabular", "columns", "latex", "siunitx S column", "number alignment"] | ||
categories = ["visualization", "layout"] | ||
exclude = ["/docs/*"] |