237 lines
9.2 KiB
Markdown
237 lines
9.2 KiB
Markdown
|
|
# Klammertext — reference for an LLM assistant
|
||
|
|
|
||
|
|
For a language model helping someone author Klammertext documents. Dense and
|
||
|
|
example-led on purpose: it is not a tutorial, and it motivates nothing. A person
|
||
|
|
wanting to learn Klammertext should read the other documents in `doc/`.
|
||
|
|
|
||
|
|
**Read §1 and §2 before writing any Klammertext.** §2 exists because a model that
|
||
|
|
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.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 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.
|
||
|
|
|
||
|
|
| ask | command |
|
||
|
|
|---|---|
|
||
|
|
| every klammer, with parameters and description | `kdesc -k` |
|
||
|
|
| klammers whose name or description mentions X | `kdesc -k X` |
|
||
|
|
| the output targets | `kdesc -t` |
|
||
|
|
| 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 |
|
||
|
|
|
||
|
|
`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.
|
||
|
|
|
||
|
|
**Check a document without rendering it:**
|
||
|
|
|
||
|
|
```
|
||
|
|
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.
|
||
|
|
|
||
|
|
**Inspect how text is being parsed:** `kdiag --type '<text>'` shows the tokens
|
||
|
|
("katoms") and their types. This settles arguments about what a piece of syntax
|
||
|
|
actually means.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 2. What you will get wrong if you assume
|
||
|
|
|
||
|
|
| assumption | reality |
|
||
|
|
|---|---|
|
||
|
|
| It is a macro language like TeX | No catcodes. Token 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 @`. |
|
||
|
|
| 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. |
|
||
|
|
| 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. |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 3. Lexical core
|
||
|
|
|
||
|
|
Three prefix tiers, distinguished by how many `@`:
|
||
|
|
|
||
|
|
| written | tier | meaning |
|
||
|
|
|---|---|---|
|
||
|
|
| `@name` | application | use a klammer |
|
||
|
|
| `@@name` | definition | define a klammer |
|
||
|
|
| `@@@name` | system | modify the machine (targets, argument types, state, klammersets) |
|
||
|
|
|
||
|
|
**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@.
|
||
|
|
|
||
|
|
> **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.
|
||
|
|
|
||
|
|
```
|
||
|
|
@i just text i@ ← unnecessary; @i just text @ is better
|
||
|
|
@s1 A @c literal c@ heading s1@ ← name it: the body contains a klammer call
|
||
|
|
```
|
||
|
|
|
||
|
|
**Arguments.**
|
||
|
|
|
||
|
|
```
|
||
|
|
@name positional1 | positional2 :option value :flag @
|
||
|
|
```
|
||
|
|
|
||
|
|
- `|` separates positional arguments.
|
||
|
|
- `:name value` is an optional argument; it may appear anywhere in the list.
|
||
|
|
- `: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.
|
||
|
|
|
||
|
|
**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 (`@c`, `@code`). Their
|
||
|
|
content is not scanned for `@`, `|`, `#`, or `^`, so the machine cannot find the
|
||
|
|
end by counting — **these must be closed with the named form**:
|
||
|
|
|
||
|
|
```
|
||
|
|
@c ImfStandardAttributes.h c@
|
||
|
|
@code
|
||
|
|
int x = a[0]; // # and @ are safe in here
|
||
|
|
code@
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 4. A complete document
|
||
|
|
|
||
|
|
```
|
||
|
|
@document
|
||
|
|
:title Normalizing to OpenEXR Standard Attributes
|
||
|
|
:subtitle Predictability and provenance
|
||
|
|
:author Joseph Goldstone
|
||
|
|
:date @date@
|
||
|
|
: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 literal_text c@ for code.
|
||
|
|
|
||
|
|
@link https://openexr.com/ :text the OpenEXR site link@
|
||
|
|
|
||
|
|
@ul
|
||
|
|
first item
|
||
|
|
| second item
|
||
|
|
| third item
|
||
|
|
ul@
|
||
|
|
|
||
|
|
# A comment: removed, and never reaches the output.
|
||
|
|
|
||
|
|
@image figure_name :width .95w :caption A caption @
|
||
|
|
|
||
|
|
@
|
||
|
|
```
|
||
|
|
|
||
|
|
Render it:
|
||
|
|
|
||
|
|
```
|
||
|
|
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
|
||
|
|
```
|
||
|
|
|
||
|
|
Output goes **next to the input file** unless `-o` says otherwise.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 5. Klammers most used when authoring
|
||
|
|
|
||
|
|
Confirm parameters with `kdesc -k <name>` — this list is names and intent only.
|
||
|
|
|
||
|
|
| | |
|
||
|
|
|---|---|
|
||
|
|
| inline | `@i` italic, `@b` bold, `@t` typewriter, `@u` underline, `@c` inline literal, `@sup`, `@sub` |
|
||
|
|
| structure | `@s1`…`@s7` numbered headings, `@h1`…`@h7` unnumbered, `@part`, `@preface`, `@par` |
|
||
|
|
| blocks | `@code`, `@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` |
|
||
|
|
|
||
|
|
Bar depth is the dimension: one `|` separates items, two `||` separates rows.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 6. Defining a klammer (only if asked)
|
||
|
|
|
||
|
|
```
|
||
|
|
@@name.k arg1 | arg2 :opt default : Description of what it does @@
|
||
|
|
@@name.html :: <span>*arg1*</span> @@
|
||
|
|
@@name.tex :: \textbf{*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.
|
||
|
|
- Separators: `:` create, `::` create inheriting parameters, `:::` override an
|
||
|
|
existing definition, `::::` define a default that a later `:` may replace.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 7. 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*.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 8. Diagnostics
|
||
|
|
|
||
|
|
- **`-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.
|
||
|
|
|
||
|
|
**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.
|