# 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 ` 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 ''` 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 ` — 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 :: *arg1* @@ @@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 ` to check the parameter list against what was written. Then `kdiag --type ''` if the question is how something is being parsed.