kdesc gains --coverage, which reports for every klammer the set of targets it can render to, and — the point of it — which klammers' coverage cannot be derived and must therefore be declared. Three rules: coverage is DERIVED where the definitions determine it (a general body of klammer calls covers the intersection of what those klammers cover, by a greatest fixpoint after loading), DECLARED where the engine cannot interpret what decides it (an @eval body, whose targets are undecidable), and UNKNOWN where nothing is written — which never means "deliberately unavailable". Two new spellings in a definition's name. A comma-separated target list, "@@table.html,tex :: ...", gives one body several targets; it is surface syntax, expanded at registration, and each member goes through the redefinition rules on its own. And "@@date.* :: ..." writes the general target out, asserting that the klammer works for EVERY target including ones not yet defined — a stronger claim than a list of the targets defined today, and the one target declaration that could be mechanically falsified. The Standard Klammer Set was swept accordingly: it now has no general definitions at all, every klammer names the targets it serves, six use ".*", and tex and pdf are at zero undecided. kdesc's flags are reorganised on two rules: a flag reached for often gets a single letter (-k klammers, -t targets, -c characters, -i input), a more specialised topic a multi-letter name (--argtypes, --katoms, --rewrite, --optionsets, --coverage, --klammerset, --font); and -v says how much to show about PROCESSING, never what the RESULT contains — so the katom regex column is "--katoms full" and the coverage detail "--coverage all". NOTE: "-k" now lists klammers (optionally filtered by a name/description search); the katom table moved to "--katoms". Fixes carried along: an option written with no value crashed the command with SIGSEGV instead of reporting the mistake; two required positional arguments never parsed; kdesc and kdiag printed an error and exited 0; and definition diagnostics counted registrations rather than what was written, so one line could be reported as two definitions and then printed twice. Four new test suites: target_list, coverage, command_option, kdesc. (from dev 46f54080bd9a)
235 lines
10 KiB
Plaintext
235 lines
10 KiB
Plaintext
# Table argument types and klammer declaration
|
|
|
|
@@@argtype index_subsets |
|
|
one or more subsets in parentheses, attached to an index. Each subset is a
|
|
single index <n>, a closed range <n>-<m>, or an open range <n>- (from <n> to
|
|
the end). A negative index counts from the end (-1 is the last). Several
|
|
subsets are separated by commas, with no spaces.
|
|
Example: (1-4,6-9)
|
|
:pattern \((?^:-?\d+(?^:-(?^:-?\d+)?)?)(?^:,-?\d+(?^:-(?^:-?\d+)?)?)*\)
|
|
@@@
|
|
|
|
@@@argtype indexed_range |
|
|
an index with optional subsets, written with no spaces. The index part is a
|
|
single index <i>, a closed index range <i>-<j>, or an open index range <i>-
|
|
(from <i> to the last index). It may be followed by parenthesized subsets
|
|
(see the index_subsets type) restricting the extent in the other dimension.
|
|
All indices are zero-origin. A negative index counts from the end, as in
|
|
Python: -1 is the last index, -2 the second to last. Ranges are inclusive,
|
|
so "1--2" is index 1 through the second-to-last index. Examples:
|
|
|
|
3 index 3, full extent
|
|
2-5 indices 2 through 5, full extent
|
|
3(1-4,6-9) index 3, restricted to 1 through 4 and 6 through 9
|
|
2-5(0-2) indices 2 through 5, each restricted to 0 through 2
|
|
-1 the last index
|
|
1--2 index 1 through the second-to-last index
|
|
|
|
:pattern -?\d+(?^:-(?^:-?\d+)?)?(?^:'index_subsets')?
|
|
@@@
|
|
|
|
@@@argtype column_width |
|
|
width of the table columns. Each column is one of 'fit' (widest line of the
|
|
cells in that column), 'fill' (the remaining width of the table after the
|
|
other columns, but no more than the column's widest line -- the table stops
|
|
growing once nothing needs a line break), a fraction 0.0->1.0 (that
|
|
fraction of the total table width), or '*' (the remaining width,
|
|
unconditionally -- the table always spans the full width). Several 'fill'
|
|
columns divide the remaining width in proportion to their widest lines;
|
|
'fill' cannot be combined with a fraction or '*'. If there are fewer
|
|
positions than columns in the table, the last value is repeated. Extra
|
|
positions generate a warning.
|
|
:pattern (fill^|fit^|f^|0?\.\d+^|\*^|\s+)+
|
|
:python_cast (lambda s : s.split())
|
|
:default fit
|
|
@@@
|
|
|
|
@@@argtype cell_hpos |
|
|
horizontal formatting in a table cell. One of 'l', 'c' or 'r' for each
|
|
cell in a row. If there are fewer positions than cells in a row, the
|
|
last value is repeated. Extra positions generate a warning.
|
|
:pattern (l^|c^|r^|\s+)+
|
|
:python_cast (lambda s : s.split())
|
|
:default l
|
|
@@@
|
|
|
|
@@@argtype table_hline |
|
|
|
|
a table's horizontal lines, as one or more whitespace-separated items.
|
|
With N rows there are N+1 horizontal boundaries, numbered 0 to N from the
|
|
top; boundary i lies above row i, and boundary N is the bottom. An item
|
|
is either a boundary name or an indexed_range of boundary indices. The
|
|
names are 'top' (boundary 0), 'head' (boundary 1, under a header row),
|
|
'bottom' (boundary N), 'inner' (all boundaries between top and bottom),
|
|
'all' (every boundary), and 'none' (no lines). A name or index may be
|
|
followed by parenthesized subsets to draw only part of a line, given as
|
|
zero-origin column ranges. When ^:hline is given it replaces the default
|
|
lines (with a header, 'head' and 'bottom'); ^:hline none removes them.
|
|
Examples:
|
|
|
|
top bottom lines above and below the table
|
|
head(1-) a line under the header, from column 1 to the last
|
|
3(1-4,6-9) two partial lines at boundary 3
|
|
all every line
|
|
none no lines
|
|
|
|
:pattern ((?^:top^|head^|inner^|bottom^|all^|none)(?^:'index_subsets')?^|'indexed_range'^|\s+)+
|
|
:python_cast (lambda s : s.split())
|
|
:alone all
|
|
@@@
|
|
|
|
@@@argtype table_vline |
|
|
|
|
a table's vertical lines, as one or more whitespace-separated items.
|
|
With M columns there are M+1 vertical boundaries, numbered 0 to M from
|
|
the left; boundary i lies to the left of column i, and boundary M is the
|
|
right edge. An item is either a boundary name or an indexed_range of
|
|
boundary indices. The names are 'outer' (boundaries 0 and M), 'inner'
|
|
(all boundaries between them), 'all' (every boundary), and 'none' (no
|
|
lines). A name or index may be followed by parenthesized subsets to
|
|
draw only part of a line, given as zero-origin row ranges. Examples:
|
|
|
|
outer lines at the left and right edges
|
|
2(0-3) a line left of column 2, spanning rows 0 through 3
|
|
all every line
|
|
|
|
:pattern ((?^:outer^|inner^|all^|none)(?^:'index_subsets')?^|'indexed_range'^|\s+)+
|
|
:python_cast (lambda s : s.split())
|
|
:alone all
|
|
@@@
|
|
|
|
@@@argtype table_span |
|
|
|
|
a list of cell spans, each an indexed_range whose index selects the row
|
|
(for colspan) or the column (for rowspan), and whose parenthesized subset
|
|
gives the zero-origin range of cells to merge. An index range repeats
|
|
the same span; several subsets make several spans. Examples for colspan:
|
|
|
|
1(2-4) in row 1, merge columns 2 through 4
|
|
1(0-1,3-5) two merges in row 1
|
|
2-4(0-1) the same merge in rows 2 through 4
|
|
|
|
:pattern ('indexed_range'^|\s+)+
|
|
:python_cast (lambda s : s.split())
|
|
@@@
|
|
|
|
@@@argtype table_calc |
|
|
|
|
calculations that fill table cells with computed values, separated by
|
|
semicolons. Each calculation has the form
|
|
|
|
<target> = <operator> <operand> <operand> ...
|
|
|
|
where the operator is one of + - * / and each operand is a cell selection
|
|
or a number. A cell selection is an indexed_range read as <rows>(<columns>);
|
|
a range expands to all of its cells in row order, so "+ 1-2(3)" sums column 3
|
|
of rows 1 and 2. The SHAPE of the target chooses the operation: a single
|
|
cell <row>(<column>) folds the operands to one value, while a target that
|
|
ranges over rows (0-(2)) or columns (-1(0-)) runs the calculation once per
|
|
row or column (a "map"). See notes/calc_notation.md for the map forms,
|
|
relative operands, and broadcasting. A plain number is a constant
|
|
and always uses a period as its decimal mark. Operators fold from the
|
|
left ("- 1(0-2)" is a minus b minus c); with a single operand, - negates
|
|
and / gives the reciprocal. Calculations run in the order given, and each
|
|
reads the values earlier calculations have written, as displayed.
|
|
Negative indices count from the end (see indexed_range), which is handy
|
|
when a total sits in the last row: "-1(5) = + 1--2(5)" writes into the
|
|
last row of column 5 the sum of that column from row 1 through the row
|
|
above it. Example:
|
|
|
|
1(3) = * 1(1-2) ;
|
|
2(3) = * 2(1-2) ;
|
|
3(3) = + 1-2(3)
|
|
|
|
# Coarse structural check only -- "<target> = <op> <operand>..." groups
|
|
# separated by ";" -- so that a malformed target or operand reaches
|
|
# run_calc() in table.py, whose per-token validation gives a precise message
|
|
# (e.g. an infix "* a * b" reports that "*" is not a number or a cell
|
|
# selection) instead of this whole description being dumped. A token is any
|
|
# run of characters other than space, ";", or "=" ("^^" escapes the regex
|
|
# class negation "[^...]" so the Klammertext "^" is not consumed).
|
|
:pattern \s*([^^\s;=]+\s*=\s*[-+*/](\s+[^^\s;=]+)+\s*(;\s*^|\s*$))+
|
|
|
|
@@@
|
|
|
|
@@@argtype decimal_mark |
|
|
the character used as the decimal mark in numeric cell values, either
|
|
'period' (1,234.56) or 'comma' (1.234,56). Governs both the reading of
|
|
numbers from cells in table calculations and the formatting of
|
|
calculated values.
|
|
:pattern period^|comma
|
|
:default period
|
|
:alone comma
|
|
@@@
|
|
|
|
@@@argtype table_justify |
|
|
cell justification overrides, as one or more <cells> <position> pairs
|
|
separated by semicolons (the same list style as ^:calc). <cells> is an
|
|
indexed_range selecting cells; <position> is l, c, or r and overrides
|
|
the column justification given by ^:cell_hpos for those cells. A colspan
|
|
anchor's override justifies the whole merged cell. For example,
|
|
"-3--1(3) r" right-justifies the cells in column 3 of the last three
|
|
rows.
|
|
# Coarse check ("<cells> <position>" pairs); justify_overrides() in
|
|
# table.py validates the range and position.
|
|
:pattern \s*([^^\s;]+\s+[lcr]\s*(;\s*^|\s*$))+
|
|
@@@
|
|
|
|
@@@argtype table_format |
|
|
cell formatting, as one or more <cells> <function> pairs separated by
|
|
semicolons (the same list style as :calc). <cells> is an indexed_range
|
|
selecting the cells to format; <function> is a <module>.<function> Python
|
|
reference (the same form the eval klammer uses) to a function that takes the
|
|
cell's value and the target and returns the formatted text. The function
|
|
lives in a module the writer supplies (a currency style is specific to a
|
|
document, so the SKS ships none): for example, with a euro() function in
|
|
your own module, "0-(5) myformats.euro" formats every cell of column 5 as a
|
|
Euro amount. Runs after :calc, so it formats computed values; a cell whose
|
|
value is not a number is left unchanged, with a warning.
|
|
# Coarse check ("<cells> <function>" pairs); apply_formats() in table.py
|
|
# validates the range and calls the function.
|
|
:pattern \s*([^^\s;]+\s+[^^\s;]+\s*(;\s*^|\s*$))+
|
|
@@@
|
|
|
|
@@rowcolor.k c : Change the color of a table row to color *c* @@
|
|
@@rowcolor.tex :: \colorrow{*s*} @@
|
|
|
|
@@table.k rows.rest(2)
|
|
:id
|
|
@caption_args@
|
|
@hpos_args@
|
|
:header.bool true
|
|
:allow_break.bool false
|
|
:column_width.column_width
|
|
:hline.table_hline
|
|
:vline.table_vline
|
|
:grid.bool false
|
|
:cell_hpos.cell_hpos
|
|
:justify.table_justify
|
|
:header_font.font i
|
|
:font.font_list
|
|
:colspan.table_span
|
|
:rowspan.table_span
|
|
:calc.table_calc
|
|
:format.table_format
|
|
:decimal.decimal_mark
|
|
:leading.float 1.3
|
|
:colsep 4pt
|
|
:
|
|
A table of rows of cells. The cells of a row are separated by "|" and the
|
|
rows by "||", so the argument is two-dimensional; the first row is the
|
|
header unless ^:header is false.
|
|
|
|
Everything else is optional, and a table written with no options is a plain
|
|
grid of its cells. ^:column_width lays the columns out, ^:hline and ^:vline
|
|
draw lines, ^:colspan and ^:rowspan merge cells, ^:justify and ^:cell_hpos
|
|
place text within them, ^:calc computes cells from other cells and ^:format
|
|
formats them, and ^:hpos and ^:offset place the whole table in the text
|
|
column.
|
|
@@
|
|
|
|
@@table.html,tex :: @eval table.Table(K) eval@ @@
|
|
|
|
@@tbl.k spec.figure_id : The caption title for a table @@
|
|
@@tbl.html,tex,txt :: @reference *spec* | Table @ @@
|