The ansi target, txt table styles, kdesc reference from ref/, typeface and table-width fixes (from dev fcec5e2e77ac)
Since the previous release: Machine::read_string() (the fs::path/std::string overload pair split); kdesc -c and -u rendered from the ref/ reflection klammerset; a fit column's tex width measured in TeX over every entry; @typeface resolving to the family its css declares (a store directory name now works in html) and hieroglyphs in @unicode_examples set in their typeface; the ansi target -- plain text with the type styles a terminal can show, identical to txt once the escape sequences are stripped -- with the txt @table carrying :header_style, :style and :hline; @block anchoring, @table spacing and the Image_quality state variable; and the rewritten doc/klammertext_for_llm.md.
This commit is contained in:
1 parent
760fda5470
commit
9b0d0d7897
34 files changed
+895
-394
No files matched your search
+333
-96
@@ -8,18 +8,23 @@ wanting to learn Klammertext should read the other documents in `doc/`.
|
||||
has not seen this language will pattern-match it to LaTeX, Markdown, or Lisp and
|
||||
produce confidently wrong syntax.
|
||||
|
||||
The klammers named here are the **Standard Klammer Set**, which is what loads by
|
||||
default. A klammer set is user-extensible, so the authority for what exists in
|
||||
any particular setup is `kdesc`, not this file — see §1.
|
||||
The klammers named here are the **Standard Klammer Set** (SKS), which is what
|
||||
loads by default. A klammer set is user-extensible, so the authority for what
|
||||
exists in any particular setup is `kdesc`, not this file — see §1. Where this
|
||||
file and `kdesc` disagree, `kdesc` is right and this file is stale.
|
||||
|
||||
Vocabulary: text is **katomized** into **katoms** (the indivisible input units)
|
||||
by **katom rewrite rules**; a **klammer** is the function-like operator; a
|
||||
**target** is an output format; a **klammerset** is a named group of klammer
|
||||
definitions. The three user modes are **author** (`@`), **designer** (`@@`),
|
||||
**programmer** (`@@@`).
|
||||
|
||||
---
|
||||
|
||||
## 1. Do not guess — the machine will tell you
|
||||
|
||||
Klammertext is introspectable. `kdesc` **prints the live state of the machine's
|
||||
data structures in digested form**: what klammers exist, what arguments each
|
||||
takes, what the argument types accept, what targets exist. Query it instead of
|
||||
inferring from examples.
|
||||
data structures in digested form**. Query it instead of inferring from examples.
|
||||
|
||||
| ask | command |
|
||||
|---|---|
|
||||
@@ -29,12 +34,16 @@ inferring from examples.
|
||||
| argument types and what each accepts | `kdesc --argtypes` |
|
||||
| shared option groups and who uses them | `kdesc --optionsets` |
|
||||
| which targets each klammer can render to | `kdesc --coverage` |
|
||||
| what a user's own file defines | `kdesc -i FILE -k` |
|
||||
| the usage of any command | run it with no arguments |
|
||||
| what a user's own file defines (against the SKS) | `kdesc -i FILE -k` |
|
||||
| the klammersets available, with provenance | `kdesc --klammersets` |
|
||||
| how to write accented / non-English characters | `kdesc -c` |
|
||||
| how to write any Unicode character, with examples | `kdesc -u` |
|
||||
| installed typefaces; install or preview fonts | `kdesc --typeface`, `--typeface help` |
|
||||
| the usage of any command | run it with no arguments (exit 0) |
|
||||
|
||||
`kdesc -k <name>` before using an unfamiliar klammer costs one command and
|
||||
replaces a guess. The parameter list it prints is authoritative; this file is
|
||||
not.
|
||||
replaces a guess. The parameter list it prints is authoritative: a parameter
|
||||
shows as `name.type default`, an option as `:name.type default`.
|
||||
|
||||
**Check a document without rendering it:**
|
||||
|
||||
@@ -43,13 +52,15 @@ kdiag --process --check doc.kt
|
||||
```
|
||||
|
||||
reports every klammer application whose name, argument count, option names, or
|
||||
target coverage is wrong — including inside branches this render will not take.
|
||||
It applies nothing, so it is safe and fast. Use it before claiming a document is
|
||||
correct.
|
||||
target coverage is wrong — including inside `@cond` branches this render will
|
||||
not take and inside klammer bodies never applied. It applies nothing. Use it
|
||||
before claiming a document is correct.
|
||||
|
||||
**Inspect how text is being parsed:** `kdiag --type '<text>'` shows the katoms
|
||||
("katoms") and their types. This settles arguments about what a piece of syntax
|
||||
actually means.
|
||||
**Inspect how text is parsed:** `kdiag --type '<text>'` shows the katoms and
|
||||
their types; `kdiag --args '<text>'` shows how text splits into arguments;
|
||||
`kdiag --rewrite '<text>'` names the rewrite rule that fired. This settles
|
||||
arguments about what a piece of syntax means. `kdiag` deliberately loads no
|
||||
klammerset; give it `@read sks/sks.k @` in the input if it needs one.
|
||||
|
||||
---
|
||||
|
||||
@@ -57,15 +68,21 @@ actually means.
|
||||
|
||||
| assumption | reality |
|
||||
|---|---|
|
||||
| It is a macro language like TeX | No catcodes. Katom structure — the indivisible input units, which `kdiag` displays — is fixed when a file is read and cannot be changed by anything later. This is why static checking works. |
|
||||
| It is a macro language like TeX | No catcodes. Katom structure is fixed when a file is read and cannot be changed by anything later. This is why static checking works. |
|
||||
| `\command{arg}` | `@name arg @` — an `@` opens, and a **closing delimiter is required**. |
|
||||
| Arguments are `{a}{b}` | Positional arguments are separated by `|` — `@sup 2 \| 3 @`. |
|
||||
| Arguments are `{a}{b}` | Positional arguments are separated by `\|` — `@sup 2 \| 3 @`. |
|
||||
| Options are `[key=value]` | `:name value`, anywhere in the argument list — `@link URL :text Click @`. |
|
||||
| `%` starts a comment | `#` removes the rest of the line. `##` removes the rest of the file. `#[ … ]#` removes a block. |
|
||||
| `%` starts a comment | `#` removes the rest of the line. `##` removes the rest of the file. `#[ … ]#` removes a block (nestable). |
|
||||
| `*x*` is emphasis (Markdown) | `@i x @` is emphasis. `*name*` is **variable substitution** inside a klammer body; in prose write `^*` for a literal asterisk. |
|
||||
| `\\` escapes | `^` quotes: `^@ ^\| ^# ^^ ^: ^*` and **`^` before any ASCII punctuation** gives that character literally. |
|
||||
| `&`, `%`, `_`, `<`, `\` must be escaped for LaTeX/HTML | **Never.** The machine escapes the target's characters. An author quotes only Klammertext's own specials. Inside `@c`/`@code` nothing needs quoting. |
|
||||
| `--` is two hyphens | Under every target `--` is an en dash, `---` an em dash, `` `` `` / `''` curly double quotes, `` ` ``/`'` curly single quotes, `~` a non-breaking space (the LaTeX conventions). A literal `--flag` is `^-^-flag`; a literal tilde `^~`. Verbatim text (`@c`, `@code`, `^'…'^`) is exempt. |
|
||||
| Whitespace is insignificant | It is content, and it is preserved. Blank lines separate paragraphs. |
|
||||
| `\\` escapes | `^` quotes: `^@ ^\| ^# ^^ ^:` produce those characters literally. |
|
||||
| Text is nested in braces | Text lives between the opening and closing delimiter with no wrapper. |
|
||||
| The document body is the first argument | For `@document` the body goes in the **`:text` option** (or `:files`). A positional body is an error. |
|
||||
| `x@i` is "x, then italic" | A letter may not touch an opening `@`: `x@i` could be the close of a klammer named `x`. Write `x @i`. Brackets and sentence punctuation may abut: `(@i-x)`, `@i x @.` |
|
||||
| `:files ch1` names a file `ch1` | A bare word means **`kt/ch1.kt`** beside the root file. A name with a directory or extension is a pathname. |
|
||||
| `@font` sets the font | Retired. `@typeface name \| text @` is the temporary change; `@document :serif_typeface` etc. set the roles. |
|
||||
|
||||
---
|
||||
|
||||
@@ -81,17 +98,15 @@ Three prefix tiers, distinguished by how many `@`:
|
||||
|
||||
**Closing a klammer.** The close is `@` for the application tier, `@@` for
|
||||
definitions, `@@@` for system commands. A close may be *named* by putting the
|
||||
klammer's name immediately before it: `@i text i@.
|
||||
klammer's name immediately before it: `@i text i@`.
|
||||
|
||||
> **When to name the close.** Use a bare `@` by default. Use the named form
|
||||
> `name@` when the klammer's body **contains other klammer calls**. The reason is
|
||||
> diagnostic, not stylistic: if delimiters are unbalanced, a named close lets the
|
||||
> machine say exactly which klammer was left open. With bare closes everywhere it
|
||||
> can only report that the count did not work out. Do not name closes on short,
|
||||
> klammer-free bodies — it is noise.
|
||||
> `name@` when the body **contains other klammer calls**: if delimiters are
|
||||
> unbalanced, a named close lets the machine say which klammer was left open.
|
||||
> Do not name closes on short, klammer-free bodies — it is noise.
|
||||
|
||||
```
|
||||
@i just text i@ ← unnecessary; @i just text @ is better
|
||||
@i just text @ ← bare close
|
||||
@s1 A @c fragment c@ heading s1@ ← name it: the body contains a klammer call
|
||||
```
|
||||
|
||||
@@ -103,48 +118,59 @@ klammer's name immediately before it: `@i text i@.
|
||||
|
||||
- `|` separates positional arguments.
|
||||
- `:name value` is an optional argument; it may appear anywhere in the list.
|
||||
The value runs to the next `|` or `:option`.
|
||||
- `:name` written alone takes the argument type's "alone" value — for a boolean
|
||||
that is `true`, so `:number` means `:number true`.
|
||||
- An optional argument that is not written takes its default.
|
||||
that is `true`, so `:number` means `:number true`; `@table :hline` means
|
||||
`:hline all`.
|
||||
- An optional argument that is not written takes its default (kdesc shows it).
|
||||
|
||||
**Abbreviated form.** `@name-arg1-arg2` is `@name arg1 | arg2 @`, valid only
|
||||
while every argument is letters and digits: `@i-italic`, `@sup-2-3`, `@date@`.
|
||||
|
||||
**Literal klammers** take their content uninterpreted. It is not examined for
|
||||
`@`, `|`, `#`, or `^`, so the machine cannot find the end by counting and **the
|
||||
named close is required**:
|
||||
`@`, `|`, `#`, `^` or `*`, so the machine cannot find the end by counting and
|
||||
**the named close is required**:
|
||||
|
||||
```
|
||||
@code
|
||||
int x = a[0]; // # and @ are safe in here
|
||||
code@
|
||||
```
|
||||
|
||||
```
|
||||
@c a | b c@ ← inline: same rule, and the close must be "c@"
|
||||
```
|
||||
|
||||
`@c` and `@code` are the in-line and block forms of the same thing, and both are
|
||||
literal: **nothing inside either is interpreted**, so `#`, `@`, `|`, `^` and `*`
|
||||
all pass through as written and none of them needs quoting.
|
||||
|
||||
Code that lives in a **file** is `@source_listing`, never `@code` — `@code` is
|
||||
only for a block written out inline, and has no filename argument:
|
||||
`@c` and `@code` are the in-line and block forms of the same thing. Code that
|
||||
lives in a **file** is `@source_listing`, never `@code` (which has no filename
|
||||
argument):
|
||||
|
||||
```
|
||||
@source_listing src/derivations.cpp @ ← the whole file
|
||||
@source_listing src/derivations.cpp :marker fromRdd55 @ ← one region of it
|
||||
@source_listing src/derivations.cpp @ ← the whole file
|
||||
@source_listing src/derivations.cpp :marker fromRdd55 @ ← one region of it
|
||||
```
|
||||
|
||||
`:marker P` lists what lies between two lines that are exactly `//P`, each
|
||||
beginning in the first column. The source file thus declares its own extractable
|
||||
regions and the document asks for one by name, so editing the code cannot
|
||||
silently change what the document shows. A marker that is missing, or that does
|
||||
not appear exactly twice, is an **error** — never a silent fallback to the whole
|
||||
file.
|
||||
`:marker P` lists what lies between two lines that are exactly `//P` in column
|
||||
one. A marker missing or not appearing exactly twice is an **error**, never a
|
||||
fallback. `kdesc -k <name>` shows a literal parameter as `text.literal`.
|
||||
|
||||
`kdesc -k <name>` is how you tell: a parameter shown as `text.literal` is a
|
||||
literal parameter. Do not infer it from a klammer's purpose — check.
|
||||
**Whitespace and removal (`#`).** `#` rest of line, `##` rest of file, `#[ … ]#`
|
||||
block; `#-` removes surrounding whitespace, `#+N` inserts N spaces, `#/N` inserts
|
||||
N newlines (default 1).
|
||||
|
||||
**Characters (`^`).** One mechanism, four readings, in this order:
|
||||
|
||||
| form | gives | example |
|
||||
|---|---|---|
|
||||
| `^P` (P any ASCII punctuation) | that character literally | `^-^-flag`, `^~`, `^^`, `^@` |
|
||||
| `^'…'^` | a **literal span**: raw target markup passed through untouched | `^'$\cdot$'^` |
|
||||
| `^UUUU^` (4–6 hex digits) | the code point | `^0418^` И, `^263A^` ☺, `^13000^` 𓀀 |
|
||||
| `^UUUU UUUU …^` | a run of code points, one caret pair | `^9053 53EF 9053^` 道可道 |
|
||||
| `^` + base letter + mark | a diacritic | `^e'` é, `^u"` ü, `^n~` ñ, `^cc` ç, `^oh` ô |
|
||||
| `^xx^` mnemonic | an extended-Latin letter | `^s^` ß, `^ae^` æ, `^o^` ø |
|
||||
|
||||
`kdesc -c` prints the diacritic, extended-Latin and pinyin tables; `kdesc -u`
|
||||
the code-point notation with examples. The one `^` exception: `^'` opens a
|
||||
literal span, so a literal apostrophe is `^0027^`. A caret form that names
|
||||
nothing is an error, not silence.
|
||||
|
||||
---
|
||||
|
||||
@@ -156,15 +182,17 @@ literal parameter. Do not infer it from a klammer's purpose — check.
|
||||
:subtitle Predictability and provenance
|
||||
:author Joseph Goldstone
|
||||
:date @date@
|
||||
:structure article
|
||||
:point_size 12
|
||||
:text
|
||||
|
||||
@s1 Principles s1@
|
||||
|
||||
Ordinary paragraph text. A blank line starts a new paragraph.
|
||||
Use @i emphasis i@ and @b bold @ inline, and @c code_fragment c@ for code.
|
||||
Use @i emphasis @ and @b bold @ inline, and @c code_fragment c@ for code.
|
||||
A footnote @footnote Its text. @ is written inline.
|
||||
|
||||
@link https://openexr.com/ :text the OpenEXR site link@
|
||||
@link https://openexr.com/ :text the OpenEXR site @
|
||||
|
||||
@ul
|
||||
first item
|
||||
@@ -176,86 +204,295 @@ ul@
|
||||
|
||||
@image figure_name :width .95w :caption A caption @
|
||||
|
||||
@table :caption Sizes :column_width fit fill
|
||||
| Name | Description
|
||||
|| alpha | the first
|
||||
|| beta | the second
|
||||
table@
|
||||
|
||||
@
|
||||
```
|
||||
|
||||
Render it:
|
||||
A long document names its chapters instead of holding them:
|
||||
|
||||
```
|
||||
ktext doc.kt -t pdf # also: -t html, -t tex, -t txt
|
||||
ktext doc.kt -t html # writes a DIRECTORY doc/ containing index.html
|
||||
ktext -s '@i-x' -t html -d # -d displays instead of writing; -s takes a string
|
||||
@document :title The Book :structure book :files preface one two @
|
||||
```
|
||||
|
||||
Output goes **next to the input file** unless `-o` says otherwise.
|
||||
which reads `kt/preface.kt`, `kt/one.kt`, `kt/two.kt` beside the root file.
|
||||
|
||||
**Render it:**
|
||||
|
||||
```
|
||||
ktext doc.kt -t pdf # also: -t html, -t tex
|
||||
ktext doc.kt -t html # writes a DIRECTORY doc/ containing index.html (+css, fonts, js)
|
||||
ktext doc.kt -t txt -d # -d displays on stdout instead of writing -- but this
|
||||
# example errors under txt/ansi: @c and @image have no
|
||||
# txt definition (§5), and coverage is never silently degraded
|
||||
ktext -s '@i-x' -t html -d # -s takes a string; no file needed
|
||||
ktext doc.kt -s '@@version : 3.2.1 @@' -t pdf # -s is processed BEFORE the files:
|
||||
# define a klammer the document uses
|
||||
```
|
||||
|
||||
- Output goes **next to the input file** unless `-o` names a directory and/or
|
||||
basename. String-only input writes to the current directory.
|
||||
- `-s`, `-t`, `-o` take exactly one argument (quote spaces). `--klammersets`
|
||||
takes a list; end it with `--` if filenames follow.
|
||||
- Filenames may contain spaces: quote them on the command line; in a list
|
||||
(`:files`, several input files) separate names with a standalone ` / `.
|
||||
- `@document :structure` is `plain` (default; no TOC), `article` (in-page
|
||||
TOC), `book` (cover, navigation panel in html; chapters, recto/verso in
|
||||
pdf). Headings `@s1`… are `\chapter` in a book and `\section` otherwise.
|
||||
- Role typefaces: `:serif_typeface`, `:sans_typeface`, `:mono_typeface`
|
||||
(family name or store directory name, e.g. `EB Garamond` or `eb-garamond`);
|
||||
`:text_scale` scales all text; `:point_size`, `:leading`, `:paper_size`,
|
||||
`:landscape`, `:two_column`. `kdesc -k document` lists all forty.
|
||||
- **Outside a `@document`** nothing makes paragraphs: a fragment rendered on
|
||||
its own writes `@par text @` explicitly.
|
||||
|
||||
---
|
||||
|
||||
## 5. Klammers most used when authoring
|
||||
|
||||
Confirm parameters with `kdesc -k <name>` — this list is names and intent only.
|
||||
Confirm parameters with `kdesc -k <name>` — this is names and intent only.
|
||||
Not every klammer exists for every target (`kdesc --coverage`); txt and ansi
|
||||
are the limited ones.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| inline | `@i` italic, `@b` bold, `@t` typewriter, `@u` underline, `@c` inline code (literal; close with `c@`), `@sup`, `@sub` |
|
||||
| structure | `@s1`…`@s7` numbered headings, `@h1`…`@h7` unnumbered, `@part`, `@preface`, `@par` |
|
||||
| blocks | `@code` (a listing written inline), `@source_listing` (a listing read from a file), `@quote`, `@note`, `@indent`, `@block`, `@center`, `@right`, `@columns` |
|
||||
| lists | `@ul` unordered, `@ol` ordered, `@define` term/definition — items separated by `\|` |
|
||||
| tables | `@table` — cells by `\|`, rows by `\|\|`; `@tbl`, `@rowcolor` |
|
||||
| figures | `@image`, `@image_grid`, `@fig`, `@reference` |
|
||||
| other | `@link`, `@date`, `@datetime`, `@color`, `@font`, `@newpage`, `@vspace`, `@email` |
|
||||
| inline | `@i` italic, `@b` bold, `@t` typewriter, `@u` underline, `@s` sans, `@r` roman, `@ri` roman italic, `@c` inline code (literal; close `c@`), `@sup base \| script @`, `@sub`, `@ts scale \| text @` resize, `@color rgb :text`, `@typeface name \| text :scale @`, `@cjk` (needs an installed CJK typeface) |
|
||||
| structure | `@s1`…`@s7` numbered headings, `@h1`…`@h7` unnumbered, `@part`, `@preface`, `@par`, `@newpage`, `@vspace lines`, `@vfill`, `@nl` line break |
|
||||
| blocks | `@code` (inline listing), `@source_listing file :marker P`, `@quote text \| attribution @`, `@note`, `@indent :left :right`, `@center`, `@right`, `@block to \| content @` (absolute placement), `@columns items :n @`, `@multicolumn text :n :gap @`, `@lines` |
|
||||
| lists | `@ul :bullet`, `@ol :initial`, `@define :style` term/definition, `@qa question \| answer @` — items separated by `\|` |
|
||||
| tables | `@table` — cells by `\|`, rows by `\|\|` (§6); `@rowcolor` |
|
||||
| figures & references | `@image basename :width :caption`, `@image_grid`, `@fig id`, `@tbl id`, `@reference spec \| name @`, `@target id :text` |
|
||||
| footnotes & links | `@footnote text @`, `@link target :text :footnote`, `@email name \| domain @` |
|
||||
| dates | `@date`, `@datetime` (`:days N`, `:lang de`, `:number`), `@year`, `@timestamp` |
|
||||
| symbols | `@copyright`, `@registered`, `@trademark`, `@euro amount`, `@pi`, `@rightarrow`, `@dot`, `@sp` (space) |
|
||||
|
||||
Bar depth is the dimension: one `|` separates items, two `||` separates rows.
|
||||
Argument order is free for options, fixed for positionals.
|
||||
|
||||
**Coverage today** (`kdesc --coverage`; 89 klammers): html, tex and pdf cover
|
||||
nearly all. **txt and ansi cover 37**, among them `@b @i @t @u @s @r @ri @ts
|
||||
@typeface`, `@s1`–`@s7`, `@par @newpage @vspace @vfill @nl`, `@indent @right
|
||||
@lines @qa`, `@ul @ol`, `@table @tbl @reference`, `@footnote @link`, `@date
|
||||
@datetime`. Not for txt: `@c @code @source_listing @image @image_grid @quote
|
||||
@note @center @block @columns @multicolumn @define @sup @sub @color @h1`–`@h7`.
|
||||
`@u` has no html definition. A klammer applied under a target that lacks it is
|
||||
an **error**, never silently dropped.
|
||||
|
||||
---
|
||||
|
||||
## 6. Defining a klammer (only if asked)
|
||||
## 6. Tables
|
||||
|
||||
```
|
||||
@@name.k arg1 | arg2 :opt default : Description of what it does @@
|
||||
@table :caption Quarterly :column_width fit fit fill :cell_hpos l r r :calc 3(1-2) = + 1-2(1-2)
|
||||
| Item | Q1 | Q2
|
||||
|| Widgets | 10.5 | 12
|
||||
|| Gadgets | 3 | 4.25
|
||||
|| Total | |
|
||||
table@
|
||||
```
|
||||
|
||||
Cell indices are **zero-origin and count the header row**: `3(1-2)` is the
|
||||
fourth row, second and third columns; `1-2(1-2)` the two body rows above it;
|
||||
`-1` is the last row or column. A ranged target repeats the calculation across
|
||||
the range (here: one sum per column).
|
||||
|
||||
- First row is the header (`:header false` otherwise); header style
|
||||
`:header_style i` by default; `:style r i b` per column.
|
||||
- `:column_width` per column: `fit` (widest entry), `fill` (the remaining
|
||||
width, capped at the widest entry), a fraction of the text width (`.2`), or
|
||||
`*` (the remainder). `fill` may not combine with a fraction or `*`.
|
||||
- `:cell_hpos l c r` per column; `:justify <cells> <pos>; …` per cell.
|
||||
- Lines: default under the header and at the bottom; `:hline`/`:vline`
|
||||
replace them (`all`, `none`, or indexed ranges); `:grid` for all lines.
|
||||
- `:colspan`/`:rowspan` with the indexed-range syntax; `:allow_break true`
|
||||
makes a page-breaking table (pdf).
|
||||
- `:calc` — `;`-separated `<row>(<col>) = <op> <operands>`, prefix `+ - * /`
|
||||
folding left over the operands, which are cell ranges or numbers;
|
||||
**display-precision** (a printed total equals the sum of the printed lines);
|
||||
`notes/calc_notation.md` is the gallery. `:format <cells> module.function`
|
||||
formats cells with user Python. `:decimal comma` for comma decimals.
|
||||
- Placement: `:hpos left|center|right|none`, `:offset 2em` (inset from that
|
||||
margin); a caption goes **above** a table (`:caption_side top` default),
|
||||
below a figure. `:number false` for an unnumbered caption.
|
||||
|
||||
---
|
||||
|
||||
## 7. Targets
|
||||
|
||||
| target | output | notes |
|
||||
|---|---|---|
|
||||
| `html` | a directory `<name>/` with `index.html`, `css/`, `fonts/`, `js/` | self-contained, fonts localized; `book` structure adds navigation, search |
|
||||
| `tex` | `<name>.tex` | XeLaTeX source; fonts via fontspec from the font store |
|
||||
| `pdf` | `<name>.pdf` | `tex` plus a xelatex run (TeX Live required) |
|
||||
| `txt` | `<name>.txt` | plain text filled to `Target_txt_width` (72), blocks indented by `Target_txt_indent` (3); tables ruled and padded; captions numbered; **37 of 89 klammers** (§5) |
|
||||
| `ansi` | txt + SGR escape sequences | `@b`/`@i`/`@u` and table header styles shown by a terminal; **identical to txt once the escape sequences are stripped**; pick it with `-t ansi -d`; a terminal needs a font with an italic face (macOS Terminal: Menlo, not Monaco) |
|
||||
|
||||
`k`, `o`, `*` also appear in `kdesc -t`: they are declaration pseudo-targets
|
||||
(interface, option set, all targets), not outputs.
|
||||
|
||||
State variables an author may set (`@@@state Name :value V @@@` in the
|
||||
document, or `-s`): `Language` (`en`/`de`, for dates), `Image_quality` (JPEG
|
||||
quality of cached photographs, 85), `Target_txt_width`, `Target_txt_indent`,
|
||||
`Image_default_width`, `Image_search_path`.
|
||||
|
||||
Typefaces: the **font store** is closed-world (no network). The distribution
|
||||
ships eb-garamond, crimson-pro, open-sans, source-sans-3, inconsolata,
|
||||
source-code-pro, noto-sans-egyptian-hieroglyphs, noto-sans-cuneiform (see
|
||||
`kdesc --typeface`); more are installed with `kdesc --typeface install <dir>`
|
||||
into `KLAMMERTEXT_FONTS`. An unknown typeface is an error listing the available
|
||||
ones. CJK is deliberately not shipped.
|
||||
|
||||
---
|
||||
|
||||
## 8. Defining klammers (only if asked)
|
||||
|
||||
```
|
||||
@@name.k arg1 | arg2 :opt.type default : Description of what it does @@
|
||||
@@name.html :: <span>*arg1*</span> @@
|
||||
@@name.tex :: \textbf{*arg1*} @@
|
||||
@@name.txt :: *arg1* @@
|
||||
```
|
||||
|
||||
- `.k` declares the interface and documents it; per-target definitions inherit
|
||||
the parameter list with `::`.
|
||||
- `*arg*` substitutes an argument into the body.
|
||||
- A definition with no target suffix applies to every target.
|
||||
the parameter list with `::`. Every target's list must agree.
|
||||
- `*arg*` substitutes an argument into the body; `*Name*` also reads a state or
|
||||
environment variable.
|
||||
- Several targets may share a body: `@@name.html,tex :: … @@`. A definition
|
||||
with **no suffix** applies to every target (the writer's macro form; its body
|
||||
is escaped for the target, so `@@corp : Smith & Jones @@` is safe). `.*`
|
||||
written out is a *claim* of target independence.
|
||||
- Separators: `:` create, `::` create inheriting parameters, `:::` override an
|
||||
existing definition, `::::` define a default that a later `:` may replace.
|
||||
existing definition, `::::` define a default a later `:` may replace.
|
||||
- Argument types: `name.type` — `string` (default), `int`, `float`, `bool`,
|
||||
`list`, `length`, `literal` (raw content, named close required), `rest`
|
||||
(everything left, bars included; `rest(2)` = list of lists), and any
|
||||
`@@@argtype` the klammerset declares (`kdesc --argtypes`). An argtype may
|
||||
carry `:default` and `:alone`; a klammer may override the default, never the
|
||||
alone value.
|
||||
- **Option sets** (`.o`): a named group of optional parameters used by several
|
||||
klammers — `@@name.k arg @caption_args :caption_side top @ : … @@` splices
|
||||
the SKS's caption options with one default overridden. Usable only in a `.k`
|
||||
parameter list. A klammer *application* inside a parameter list is an error.
|
||||
- **`@eval`** is the primitive behind every non-trivial klammer:
|
||||
`@eval python_expr @` (module.function auto-imports; `K` holds the
|
||||
arguments), `@eval :cpp lib.function @`, `@eval :shell cmd @`,
|
||||
`@eval :haskell src @`; `:cwd DIR` runs it there (`:cwd *K_input_dir*`).
|
||||
A Python module is found next to the file that names it. **The result is
|
||||
re-read as Klammertext**: a result holding klammers is *generator* output and
|
||||
its text is escaped for the target; a result with none is *renderer* output
|
||||
and left alone. A literal `@` in a result must be emitted as `^@`.
|
||||
- A klammer whose tex body is target markup with a backslash must not be
|
||||
passed through a generator raw — the SKS carries such things as markers
|
||||
(`@nl`), resolved in an `:after_apply` phase.
|
||||
- **Klammersets**: `@@@klammerset sym | description :requires sks :files a.k b.k @@@`
|
||||
in `sym/sym.k`; loaded with `ktext --klammersets sym doc.kt` (symbols only,
|
||||
resolved in the document's directory, then `KLAMMERTEXT_KLAMMERSETS`, then
|
||||
the distribution; several combine in order, later definitions deciding
|
||||
collisions via the separators above). `kdesc -i file.k -k` shows what a file
|
||||
defines against the SKS. `--klammersets ref` adds the reflection klammers
|
||||
(`@diacritics_examples@`, `@unicode_examples@`, …) that generate the
|
||||
reference tables `kdesc -c`/`-u` print.
|
||||
|
||||
---
|
||||
|
||||
## 7. Behaviour worth knowing before you debug something
|
||||
## 9. Behaviour worth knowing before you debug something
|
||||
|
||||
- **`@cond` is strict about truth.** True: `true`, `True`, `1`. False: `false`,
|
||||
`False`, `0`, and empty. **Anything else is an error**, not "probably false".
|
||||
- **`@cond` evaluates only the branch it selects.** The branch not taken is not
|
||||
read, not evaluated, not expanded — a `@read` of a missing file in the unused
|
||||
branch is harmless.
|
||||
- **A state variable reaches a `@cond` predicate.** The document behaves like a
|
||||
function body whose arguments are its `@@@state` variables.
|
||||
- **`@eval :shell` and `:haskell`:** the command's standard output becomes
|
||||
document text; its standard error does not (it appears under `-v 1`); a nonzero
|
||||
exit is an error. Append `|| true` if a nonzero exit is expected.
|
||||
- **A definition inside a `@cond` branch does not register** — in either branch.
|
||||
Define outside and select between *applications*.
|
||||
`False`, `0`, empty. **Anything else is an error**, not "probably false".
|
||||
- **`@cond` is resolved at application time and evaluates only the branch it
|
||||
selects.** A `@read`/`@eval` in the other branch does not run. A top-level
|
||||
`@cond *Flag* | … @` sees the variable's value.
|
||||
- **A state variable is visible from the moment its declaration is read** —
|
||||
in every klammer body applied afterwards and in the top-level text of later
|
||||
input units, but not in the top-level text of the same unit that declares it.
|
||||
Declare early (`-s`, a first file, a klammerset).
|
||||
- **A definition inside a `@cond` branch does not register** — in either
|
||||
branch. Define outside and select between *applications*.
|
||||
- **`@eval :shell` and `:haskell`:** stdout becomes document text; stderr does
|
||||
not (shown under `-v 1`); a nonzero exit is an error. Append `|| true` if a
|
||||
nonzero exit is expected.
|
||||
- **Arguments arrive as written**, nested klammers already rendered; a macro
|
||||
escapes only its own body text. Never escape an output format's characters
|
||||
yourself, anywhere.
|
||||
- **Typographic transforms are per katom and skip verbatim text**: a `--` split
|
||||
by a klammer is two hyphens; inside `@c`/`@code` nothing is transformed.
|
||||
- **Recursion** is guarded: a klammer reaching itself 200 deep is a named
|
||||
`Recursion_error`; a document needing more than 100 top-level passes is an
|
||||
error.
|
||||
- **`@eval` results are trimmed**; a klammer that must emit leading space or
|
||||
pure vertical space uses the txt/tex markers the SKS provides
|
||||
(`phases.txt_nbsp_marker()`, `@vspace`).
|
||||
- The html **page cache** (`/dev/shm/_klammertext_cache/` on Linux) can serve
|
||||
a stale page after a change to a klammer's html; clear it when output looks
|
||||
old (`@document :cache false` disables it).
|
||||
|
||||
---
|
||||
|
||||
## 8. Diagnostics
|
||||
## 10. Diagnostics and what the commands print
|
||||
|
||||
- **`-v 1`** reports every decision the command made that the user could not have
|
||||
read off their own input: which klammerset was loaded and from where, which
|
||||
file a font or a `:files` name resolved to, how the output path was built.
|
||||
Higher levels are an implementation trace.
|
||||
- Logging and errors go to **standard error**; the rendered document goes to
|
||||
standard output, so `ktext doc.kt -d | …` is safe.
|
||||
- An error stops the run and names a file, line, and character. There is no
|
||||
warn-and-continue except in two documented cases.
|
||||
- A bare `ktext`, `kdesc`, or `kdiag` prints its usage and exits successfully.
|
||||
- Three cases only: **logging** (stderr, `-v` > 0), **an error** (stderr, then
|
||||
exit ≠ 0), **the requested output** (stdout). So `ktext doc.kt -t txt -d | …`
|
||||
is safe; nothing else lands in the document.
|
||||
- **`-v 1`** reports every decision the user could not read off their input:
|
||||
which klammerset loaded and from where, which file a typeface or `:files`
|
||||
name resolved to, how the output path was built, an override of another
|
||||
set's definition. `-v 2`+ is an implementation trace.
|
||||
- An error stops the run and names a file, line and character; messages are
|
||||
justified to 80 columns. There is **no warn-and-continue** except two
|
||||
aggregated heuristics: unknown target coverage, and a table wider than the
|
||||
page.
|
||||
- *"Word not parsed: …"* means a piece of text matched no katom type — usually
|
||||
a letter touching a delimiter (§2) or a punctuation run needing `^`.
|
||||
- Colour on stderr only when it is a terminal; `NO_COLOR` disables it. kdesc's
|
||||
`-c`/`-u` render through `ansi` on a terminal and `txt` in a pipe.
|
||||
|
||||
**When something is wrong:** run `kdiag --process --check doc.kt` first — it
|
||||
finds name, arity, option and coverage faults without rendering. Then `kdesc -k
|
||||
<klammer>` to check the parameter list against what was written. Then `kdiag
|
||||
--type '<fragment>'` if the question is how something is being parsed.
|
||||
**When something is wrong:** `kdiag --process --check doc.kt` first (name,
|
||||
arity, option and coverage faults without rendering); then `kdesc -k <klammer>`
|
||||
against what was written; then `kdiag --type '<fragment>'` if the question is
|
||||
how something is parsed; then `ktext … -v 1` if the question is which file or
|
||||
klammerset was used.
|
||||
|
||||
---
|
||||
|
||||
## 11. Klammertext from Python
|
||||
|
||||
```python
|
||||
import klammertext # kpy/ on PYTHONPATH (env/runtime.env)
|
||||
M = klammertext.Machine(target="html", files=["doc.kt"]) # as ktext sets itself up
|
||||
M.read("@@version : 3.2.1 @@") # what "ktext -s" does
|
||||
M.read_files() # the constructor's files, in order
|
||||
html = M.apply() # the rendered text
|
||||
```
|
||||
|
||||
`Machine(target='*', klammersets=None, files=None, output=None, display=False,
|
||||
verbose=0)`; `read(text)`, `read_file(name)`, `read_files()`,
|
||||
`apply(target=None, final_processing=True, escape_characters=True)`. **One
|
||||
Machine at a time** (a second raises `RuntimeError`); `apply()` reduces in
|
||||
place, so a second target needs a second Machine. Errors are `klammertext.Error`
|
||||
subclasses under the C++ names (`Parsing_error`, `Argument_error`,
|
||||
`Definition_error`, `Environment_error`, …) with `kind`, `description`,
|
||||
`filename`, `line`, `column`; `str(e)` is ktext's report; an `@eval`'s Python
|
||||
exception is chained as `__cause__`.
|
||||
|
||||
---
|
||||
|
||||
## 12. Adjacent tools
|
||||
|
||||
- **Markdown → Klammertext:** `sks/tns/md_to_sks.py` converts a `.md` file;
|
||||
what it cannot convert exactly is left in the output as `#[MD … ]#` markers,
|
||||
so the draft carries its own worklist (spec: `doc/markdown_to_klammertext.md`).
|
||||
`mdpdf file.md` renders Markdown straight to PDF through a headless Chromium,
|
||||
bypassing Klammertext.
|
||||
- **Editors:** `doc/edit/` holds Emacs, Sublime Text, Vim and VS Code support
|
||||
(highlighting, delimiter matching, reindent, table alignment, a language
|
||||
server); `doc/edit/README.md`.
|
||||
- **Containers:** `akopra/klammertext:latest` (and `:haskell`) hold the three
|
||||
commands, the SKS, TeX Live and the default fonts; `doc/linux_container_install.md`,
|
||||
`doc/macos_container_install.md`.
|
||||
- **Environment:** `KLAMMERTEXT_HOME` (the tree), `KLAMMERTEXT_FONTS`,
|
||||
`KLAMMERTEXT_KLAMMERSETS` (colon-separated search paths); `env/runtime.env`
|
||||
sets them when sourced.
|
||||
Reference in new issue
Block a user