Files
klammertext/doc/edit/emacs/README.md
T
ack e4f1307aa9 Characters that killed a render, what may sit next to a klammer, and ref/
A character written in the ^...^ mnemonic form -- ^oe^, ^zz^, ^hello^ --
used to kill ktext outright: no message, no output, and an exit status
that looked like a crash because it was one.  Only the forms that happen
to spell hexadecimal digits escaped, and they were right by luck rather
than by reading.  Any caret form that names no character is now a located
error that quotes what was written.

A klammer may now sit inside square brackets and braces as it already
could inside parentheses, and may be followed by the punctuation that
ends a sentence: [@i word@], {@b word@}, @i word@'s.  The rule is a fixed
list of characters, because none of them can occur inside a klammer name
and so none of them is ambiguous next to a delimiter.  A letter still
cannot: "x@" is the named closing delimiter, so a letter before "@" has
two readings and no rule can separate them.

The abbreviations an author writes -- the hyphen form @i-word, a klammer
glued to its neighbouring punctuation -- are now recognised as author
conveniences only.  They are not applied to @@ definitions or @@@ system
commands, which are written by someone who needs no such shorthand and
whose forms are already whole.

Also fixed, each of them silent: an exported shell function in the
environment broke every @eval in the document; a line break written with
@nl was destroyed when it passed through a klammer that generates a
table, printing as \textbackslash{}newline in the finished PDF; and
"kdesc --coverage" shortened its file column by comparing the spelling of
a path rather than the path, so a klammer set reached by a symbolic link
showed a full path where its neighbours showed a short one.

New in the distribution: ref/, a small klammerset that describes the
Klammermachine's own tables in Klammertext.  It currently provides the
character tables -- the diacritics and the extended Latin letters -- as
klammers that render to any target, so the documentation of what can be
written cannot drift from what the machine accepts.  It is early, and
will grow.

The Klammertext taxonomy now has a section on targets, describes the
@@@klammerset system command alongside the other three, and states the
precedence of "^" -- what a caret means before a letter, a digit, a
punctuation character, and a quote, in one ordered list.

(from dev 6594c7ff8c1f)
2026-09-07 22:37:05 +02:00

262 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Emacs mode for Klammertext
`klammertext-mode.el` is an Emacs major mode for editing Klammertext files. It
helps Klammertext authors see the structure of klammer application through
syntax highlighting.
Requires **Emacs 27.1 or newer** — the version Ubuntu 22.04 and Pop!_OS
22.04 ship, so it is the practical floor. Tested on 27.1 and 30.2.
## Install
Put the `emacs` directory somewhere on your system, then tell Emacs where it is
and load the mode. Add to `~/.emacs.d/init.el`:
```elisp
(add-to-list 'load-path "full-pathname-of-the-emacs-directory")
(require 'klammertext-mode)
(require 'klammertext-indent) ; optional, experimental: TAB indentation
(require 'klammertext-align) ; optional, experimental: table alignment
```
Replace `full-pathname-of-the-emacs-directory` with the full path to the
directory that contains `klammertext-mode.el`. The last two requires load
the experimental indentation and table-alignment support (see their sections
below); each is a separate unit — comment its line out to disable it
entirely.
The mode auto-activates for `.kt` and `.k` files. (The `.k` / `.kt` distinction
is a filing convention, not a lexical one — the same mode serves both.) You can
also switch to it manually with `M-x klammertext-mode`.
## What it highlights
**Text-removal ("ignore") constructs** — in two independently chosen colors,
one for the *removed content*, one for the *marker characters*:
| Construct | Meaning |
|--------------|----------------------------------|
| `#` ... | remove to end of line |
| `##` ... | remove to end of buffer |
| `#[ ... ]#` | remove enclosed text (nestable) |
**Klammer applications** — in two independent colors: one for *opening* a
klammer, one for *closing* it. The `@` and the name of an opening are one
syntactic unit and share the opening color; the close (named or bare) gets the
closing color, so you always have visual confirmation of where a klammer ends:
| Form | Color | Meaning |
|-----------|---------|----------------------------------|
| `@name` | opening | opening `@` + name (one unit) |
| `name@` | closing | named closing delimiter |
| `@` | closing | bare closing delimiter |
In the abbreviated form `@name-arg1-arg2` (equivalent to `@name arg1 | arg2 @`)
only the name is colored — the name ends at the first hyphen, and the
hyphen-separated arguments stay plain, just as `arg1`/`arg2` would be plain in
the long form.
Because a named closing carries the closing color across its name too, long
klammers that name their closing delimiter (`@document ... document@`) stand
out — which is exactly where naming the closing delimiter earns its keep
(accurate unmatched-delimiter error messages). Short bodies (`@i word @`) are
conventionally left with a bare `@` to keep the text uncluttered.
**Klammer definitions** (`@@`) are highlighted the same way, in their own pair
of colors — so definitions read as distinct from applications at a glance:
| Form | Color | Meaning |
|------------|---------|-----------------------------------|
| `@@name` | opening | opening `@@` + name (one unit) |
| `name@@` | closing | named closing delimiter |
| `@@` | closing | bare closing delimiter |
The name ends at the first non-name character, so a target suffix like
`@@name.html` colors only `@@name` and leaves `.html` plain. A definition's
body (between `@@name` and the closing `@@`) is highlighted like ordinary
Klammertext — e.g. an `@i … @` inside it shows as a normal application.
**System/target commands** (`@@@`) — `@@@target`, `@@@argtype`, `@@@state`,
`@@@klammerset` — get
a third pair of colors, so the three `@`-levels (application, definition, system)
are visually distinct:
| Form | Color | Meaning |
|------------|---------|-----------------------------------|
| `@@@name` | opening | opening `@@@` + name (one unit) |
| `name@@@` | closing | named closing delimiter |
| `@@@` | closing | bare closing delimiter |
`@@@` commands do not nest, so each delimiter is colored independently; their
bodies (`| … |` option lists) are highlighted as ordinary Klammertext.
## The eight faces
All eight faces are defined by the `defconst klammertext--palette` at the
beginning of `klammertext-mode.el`.
| Face | Applies to |
|-----------------------------------|-------------------------------------|
| `klammertext-ignored-face` | removed content |
| `klammertext-marker-face` | `#`, `##`, `#[`, `]#` |
| `klammertext-klammer-open-face` | an application opening `@name` |
| `klammertext-klammer-close-face` | an application close `name@` or `@` |
| `klammertext-def-open-face` | a definition opening `@@name` |
| `klammertext-def-close-face` | a definition close `name@@` or `@@` |
| `klammertext-system-open-face` | a system opening `@@@name` |
| `klammertext-system-close-face` | a system close `name@@@` or `@@@` |
To experiment with a color (evaluate in `*scratch*`, or add to your init):
```elisp
(set-face-foreground 'klammertext-marker-face "cyan")
(set-face-foreground 'klammertext-system-close-face "chocolate4")
```
or `M-x customize-face RET klammertext-marker-face RET`.
## Matching delimiters (show-paren)
With `show-paren-mode` on (the default in Emacs 28+), placing point on a klammer
**application** delimiter highlights its partner, in both directions: on an
opening `@name` it highlights the closing `@`/`name@`, and on a close it
highlights the opening `@name`. Nesting is respected — in `@a @b x @ @`, the
outer `@a` matches the last `@`, not the first.
Matching covers applications only (`@`), not `@@`/`@@@`, since that is where
paired delimiters matter most. The matcher steps over `@@`/`@@@`, removed text,
other literal spans and escaped `^@`; the abbreviated `@name-arg` form has no
closing delimiter, so nothing is highlighted on it.
**Literal klammers** (those in `klammertext-literal-klammers`, e.g. `@code`) are
closed with the full `NAME@` form because their content is verbatim. These are
matched *by name* — `@code` ↔ `code@` — with the content treated as opaque, so a
stray `@` inside (`@code x @ y code@`) doesn't confuse the match, in either
direction. Register any klammer that declares a `literal` argument with
`(klammertext-add-literal-klammer "name")` in your init file so both its
highlighting and its delimiter matching work.
If a **named** close disagrees with its opening — e.g. `@doc … foo@` (should be
`doc@`) — the mismatched delimiter is shown in **bright red** (bold), and a
message describing the mismatch appears in the minibuffer, e.g.
> `Klammertext: closing foo@ does not match opening @doc`
An unbalanced delimiter (an opening with no close, or vice versa) is flagged the
same way. This turns the naming convention into a live check: name a long
klammer's closing delimiter and a typo'd or unbalanced name lights up
immediately. The red comes from `klammertext-mismatch-face`, which is remapped
over `show-paren-mismatch` **only in Klammertext buffers** (your global
`show-paren-mismatch` face is left untouched); customize it to taste.
This is wired in automatically (`show-paren-data-function`); you only need
`show-paren-mode` enabled. It relies on nothing in the syntax table — Klammertext
delimiters can't be expressed there — so it does not interfere with other
`@`/`#` characters.
### Jumping between matches
`klammertext-jump-to-match`, bound to **`C-c C-j`**, moves point to the matching
delimiter: from an opening `@name` to its close, and from a close back to its
opening `@name`. It uses the same matcher as the highlighting. The starting
position is pushed to the mark ring, so `C-u C-SPC` jumps back. (Also available
as `M-x klammertext-jump-to-match`.)
## Indentation (experimental)
With `klammertext-indent.el` loaded (the optional require above), **TAB**
indents the current line — and `indent-region` a selection — to reflect the
klammer nesting, two spaces per level:
```
@ol
Item one
| Item two
@ol
Embedded item one
| Embedded item two
@
| Item three
@
```
The rule: a line indents to 2 × depth; a line *beginning* with a bar run
(`|`, `||`, …) or a closing delimiter sits one level less — at its owner's
opening column. So the bars and the close line up under the `@` of the list
they belong to, and `| ` (bar + space) puts item text exactly at the content
column. The bar rule is dimension-independent: `||` table rows drop to the
opener's column the same way. All three `@`-tiers indent uniformly.
Exceptions, all deliberate:
- Klammers in `klammertext-transparent-klammers` (default: `document`)
contribute no level, so a document's ordinary paragraphs stay at the left
margin.
- Lines inside a literal klammer's verbatim content (`@code ... code@`), and
inside the argument span of a klammer in `klammertext-code-klammers`
(default: `eval` — inline Python is indentation-sensitive), are never
touched. Neither are removed regions (`#[ ... ]#`, after `##`).
Nothing reformats automatically — whitespace is content in Klammertext, so
indentation happens only when you ask for it (TAB, `indent-region`). The
offset is `klammertext-indent-offset` (default 2); all three variables are
customizable in the `klammertext-indent` group.
## Table alignment (experimental)
With `klammertext-align.el` loaded (the optional require above), **`C-c C-a`**
with point anywhere inside a `@table` span pads the cells of its rows so the
`|` separators line up:
```
@table
First item | Second | A third item that's longer ||
Row 2 | Text | Not as long ||
@
```
A row is one line ending with the row delimiter `||` (the customary trailing
delimiter — the parser strips one trailing delimiter, and it keeps every row
uniform, which also suits program-generated tables); the last row may omit
it. Alignment is for small data items, so a row is left untouched — and
contributes nothing to the column widths — when any of its cells is longer
than `klammertext-align-cell-max` (30) characters or the row spans lines.
If the aligned rows would exceed `klammertext-align-row-max` (100) columns,
nothing changes and the reason is reported.
The padding is semantically free: the SKS strips cell content, and no
whitespace is ever inserted inside a bar run (which would turn a `||` row
separator into an empty `| |` cell). Bars inside a nested klammer in a cell
(`@frac 1 | 2 @`) belong to that klammer, not the table, and are left alone.
Aligned rows adopt the leading whitespace of the first aligned row — run TAB
first if the rows disagree.
## Literal klammers
Inside a `literal` argument — for example the body of `@code ... code@` — `#`
and `@` are literal text, not Klammertext syntax. The mode highlights the
opening `@code` and closing `code@` but leaves the interior as normal text,
for any klammer registered in `klammertext-literal-klammers`. `@code` is
registered by default.
If you define your own klammer with a `literal` parameter (a relatively
advanced action — see the `literal` argument type in the project
documentation), register it in your init file:
```elisp
(klammertext-add-literal-klammer "myverbatim")
```
Because the list is consulted at fontification time, registering a klammer
while a buffer is already open takes effect after `M-x font-lock-update` (or
re-visiting the file).
## Known limitations (deliberate, for now)
- Unescaped `@` is always treated as a delimiter (as the Klammermachine does),
so an `@` in prose that is *not* meant as a klammer — e.g. an email address
written `foo@bar` instead of `foo^@bar` — will be highlighted. This reflects
what the machine actually sees.
- Very large multiline blocks or literal spans edited far from their opening
may occasionally need `M-x font-lock-update` to re-highlight correctly.