# 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. ## 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) ``` Replace `full-pathname-of-the-emacs-directory` with the full path to the directory that contains `klammertext-mode.el`. 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` — 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`.) ## 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.