Typed arguments, calculated tables, spans, closed-world fonts, top-level fnt/ and env/

Sync with klammertext-dev through b90b0e09:

- Argument types end to end: :python_cast values are applied (Python
  @eval receives real bools/numbers/lists), argument values are
  validated against their argtype patterns with the argtype's
  description as the error message, argtypes can declare :default
  (overridable per declaration), and parameterized type families are
  supported: rest(N) casts a rest argument to an N-dimensional list
  (bar-count = dimension).
- Unified indexed_range syntax (selector with parenthesized subsets,
  composable mnemonic names) for table lines and spans.
- Table klammer: caption fonts fixed in both targets, :column_width /
  :leading / :colsep wired, :colspan and :rowspan render (HTML
  attributes; \multicolumn / \multirow), calculated cell values (:calc)
  with prefix operators, display-precision semantics, :calc_format and
  :decimal period|comma.
- Fonts: closed-world resolution on the Klammertext font store
  (infrastructure in mac/font_store; no Google Fonts links or fetch).
  Default fonts live in the top-level fnt/; additional fonts install
  into KLAMMERTEXT_FONTS directories via kdesc --font (list, samples,
  preview, install — classification by font metadata).  CSS font family
  names are quoted (digit-initial families were silently lost).
- Environment files moved from mac/env/ to the top-level env/; shell
  profiles source env/runtime.env.  Dead per-host variants removed.
- Container: fnt/ ships in the image; curl removed (no network use).
This commit is contained in:
2026-07-22 18:17:43 +02:00
parent 6b75aa0c54
commit 8a2699a253
100 changed files with 1726 additions and 1152 deletions

View File

@@ -1,63 +1,165 @@
#[ f: 0->1; n: 1.. (integer)
l, c, r
[<numeric-size>] <width> <justification>
width is widest line in a cell f [default]
width is fraction of table <f>t
width is specific length <n>pt|px|in|cm [...not portable?]
width width is remaining (evenly divided) *
]#
# Table argument types and klammer declaration
@@@argtype table_hpos |
@@@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). 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. 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
: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), a fraction 0.0->1.0 (that fraction of the total table
width), or '*' (use the remaining width of the table; there can only be one
column with '*'). If there are fewer positions than columns in the table, the
last value is repeated. Extra positions generate a warning.
:pattern (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. Default is 'l'
# :pattern ((f^|(0?\.'uint't^|\\*))[lcr]?^|\s)+
# :pattern ((f^|'float't^|\\*)[lcr]?^|\s)+
:pattern ([.\w]+^|\*^|\s+)+
#:pattern (l^|c^|r^|\s)+
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 line description; one or more of 'top',
'head', 'inner', 'bottom', or a row number for a line at the bottom
of that row
#:pattern (top^|head^|inner^|bottom^|\d+^|\d+:\(\d+\-\d+\)^|\s+)*
#:python_cast (lambda s : s.split())
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),
and 'all' (every boundary). A name or index may be followed by
parenthesized subsets to draw only part of a line, given as zero-origin
column ranges. 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
:pattern ((?^:top^|head^|inner^|bottom^|all)(?^:'index_subsets')?^|'indexed_range'^|\s+)+
:python_cast (lambda s : s.split())
@@@
@@@argtype table_vline |
a table's vertical line description; one or more of 'outer', 'inner,
or a column number for a line at the right of that column
# :pattern (outer^|inner^|\d+^|\d+^|\d+:\(\d+\-\d+\)^|\s+)*
# :python_cast (lambda s : s.split())
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), and 'all' (every boundary). 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)(?^:'index_subsets')?^|'indexed_range'^|\s+)+
:python_cast (lambda s : s.split())
@@@
@@@argtype table_span |
a list of spans in a table in the form (X,Y):N (no spaces), where
(X,Y) is the position in the table (zero origin in the top left
corner) and N is the number of columns or rows in the span
#:pattern (\(\d+(?:-\d+)?,\d+(?:-\d+)?\):\d+\s*)*
#:python_cast (lambda s : s.split())
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 target is a single cell written <row>(<column>) with zero-origin
indices, the operator is one of + - * /, and each operand is either 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. 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.
Example:
1(3) = * 1(1-2) ;
2(3) = * 2(1-2) ;
3(3) = + 1-2(3)
:pattern \s*(\d+\(\d+\)\s*=\s*[-+*/](\s+(\d+(?^:-\d*)?'index_subsets'^|'float'))+\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
@@@
@@@argtype format_spec |
a Python format specification applied to calculated cell values, for
example ",.2f" for two decimal places with grouped thousands.
:pattern \S+
@@@
@@rowcolor.tex s : \colorrow{*s*} @@
@@table rows.rest
@@table rows.rest(2)
:id
@caption_arguments@
:center.bool true
:indent.length 1em
:header.bool true
:allow_break.bool false
:hline.table_hline
:column_width.column_width
:hline.table_hline
:vline.table_vline
:grid.bool false
:cell_hpos.table_hpos c
:cell_hpos.cell_hpos
:header_font.font i
:font.font_list r
:font.font_list
:colspan.table_span
:rowspan.table_span
:calc.table_calc
:calc_format.format_spec
:decimal.decimal_mark
:leading.float 1.3
:colsep 4pt
: