diff --git a/README.md b/README.md index f8e3f43..9e45d29 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,16 @@ the three commands — `ktext`, `kdesc`, `kdiag` (into `bin/`). See the source-install guide for prerequisites (TeX Live for PDF output, Python, and so on). +## Working with an AI assistant + +If you use a language model to help write Klammertext, give it +[`doc/klammertext_for_llm.md`](doc/klammertext_for_llm.md). It is a dense +reference written for a model rather than a person: the syntax, the things a +model is most likely to assume wrongly about it (Klammertext is not LaTeX, +Markdown, or Lisp, and reads oddly if you expect any of them), and how to ask +the `kdesc` and `kdiag` commands for the current state of the machine instead +of guessing. + ## Editor support Editing support for Emacs, Sublime Text, Vim, and Visual Studio Code — @@ -41,7 +51,7 @@ are regenerated on each release — patches cannot be merged directly. Report problems (or send patches) to the author; accepted changes are applied to the development tree and appear in a following snapshot. -This snapshot was assembled from development commit `6c8ee6c22fca`. +This snapshot was assembled from development commit `6c2ff7b8fce3`. ## License diff --git a/doc/klammertext_for_llm.md b/doc/klammertext_for_llm.md new file mode 100644 index 0000000..bde2da4 --- /dev/null +++ b/doc/klammertext_for_llm.md @@ -0,0 +1,236 @@ +# 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.