2026-07-27 15:01:49 +02:00
# Klammertext editor support
Editing support for Klammertext files (`.kt` documents and `.k` klammer
2026-09-25 18:43:22 +02:00
definitions) in five editors, built around one shared implementation.
2026-07-27 15:01:49 +02:00
| Directory | Contents |
|---|---|
| `shared/` | **The shared editor core** (`klammertext_edit.py` ) and the **Klammertext language server** (`klammertext_ls.py` ). Everything structure-aware — indentation, table alignment, delimiter matching, delimiter diagnostics — implemented once, in dependency-free Python. |
| `emacs/` | Emacs major mode. An independent elisp implementation of the same algorithms (Emacs cannot call Python per keystroke), held byte-equal to the shared core by the test suite. |
| `sublime/` | Sublime Text package. Syntax file plus thin plugin wrappers that import the shared core directly (Sublime's plugin host is Python). |
| `vim/` | Vim plugin. Syntax/ftplugin files plus commands that run the shared core's CLI; with `+python3` , the core also runs in-process (`=` operator, live match highlighting). |
| `vscode/` | Visual Studio Code extension. TextMate grammar plus a dependency-free extension that spawns the language server and speaks LSP to it. |
2026-09-25 18:43:22 +02:00
| `notepadpp/` | Notepad++ (Windows). A User Defined Language for the highlighting, and two Run-menu commands that pass the current file through the shared core's CLI (delimiter check, reindent). No plugin host, so nothing structural runs in-process. |
2026-07-27 15:01:49 +02:00
## The architecture
Klammertext's *structural layer* — @-run tiers, bar-run dimension,
`^` -escapes, `#` removal, literal spans, nesting depth — is independent of
both the Klammermachine and any klammer set, and every editor needs the
same operations on it. Those operations live in
** `shared/klammertext_edit.py` **:
- **Indentation** — 2 spaces per nesting level; bar runs and closing
delimiters sit at their opener's column; `@document` is transparent;
verbatim/`@eval` /removed content is never touched. Explicit-only in
every editor: whitespace is content in Klammertext.
- **Table alignment** — pad a `@table` 's rows so the depth-0 `|`
separators line up (rows end with `||` ; cells over 30 characters or
spanning lines opt their row out; over 100 columns the command declines;
never a space inside a bar run).
- **Delimiter matching** — open ↔ close for klammer applications, literal
klammers matched by name with opaque content, everything else by depth.
- **Diagnostics** — whole-buffer balance check over all three `@` -tiers:
unclosed openings, extra closes, name and tier mismatches, unclosed
literal spans and `#[` blocks.
- **A CLI** (`indent | align | match | check` over stdin/stdout) for
editors that shell out (Vim), and for scripts.
** `shared/klammertext_ls.py` ** puts a language server in front of the same
core: JSON-RPC over stdio, no dependencies. It serves publishDiagnostics,
document/range formatting (reindentation), documentHighlight and
definition (the matcher), and a `klammertext.alignTable` command. The
VS Code extension is its first client; any LSP client works — Neovim's
built-in LSP, Emacs eglot, Sublime's LSP package — with a one-line
2026-09-25 18:43:22 +02:00
configuration pointing at `python3 klammertext_ls.py` (on Windows
`python klammertext_ls.py` ).
2026-07-27 15:01:49 +02:00
Syntax highlighting and cursor-latency features stay native in each editor
(a tokenizer or a per-keystroke matcher cannot round-trip to Python), so
each editor directory carries its own syntax artifact and, where relevant,
its own thin glue.
## Locating the shared core
The Sublime, Vim, and VS Code integrations find `klammertext_edit.py` (and
VS Code additionally `klammertext_ls.py` ) in this order: a copy at the
integration's own root (the **editing zip** vendors one there, so each
unpacked folder is self-contained), `../shared/` relative to the
integration (this repository's layout — using an editor directory straight
from a checkout just works), then `$KLAMMERTEXT_HOME/doc/edit/shared/` .
## Keeping things in sync
`klammertext_edit.py` is the source of truth for the policy lists
(`LITERAL_KLAMMERS` , `TRANSPARENT_KLAMMERS` , `CODE_KLAMMERS` ,
`ALIGN_KLAMMERS` ) and limits (`INDENT_OFFSET` , `CELL_MAX` , `ROW_MAX` ).
Two kinds of artifact cannot read it and restate parts of it by hand:
1. **The Emacs mode** — a full independent implementation with its own
defcustoms, checked byte-for-byte against the shared core by
`tst/editor_test.sh` .
2. **The static syntax files** — the literal-klammer set (`@code` ) appears
2026-09-25 18:43:22 +02:00
in the Sublime `.sublime-syntax` , the Vim `syntax/klammertext.vim` , the
VS Code `tmLanguage.json` grammar, and the Notepad++ `Klammertext.udl.xml`
(and the Emacs defcustom). When you add a literal klammer, change them
together; each file's header carries the same SYNC note. The UDL can
hold only names that are not prefixes of other klammer names (it has
no word boundary), so it carries `code` and not `c` .
2026-07-27 15:01:49 +02:00
## Testing
2026-09-22 22:53:13 +02:00
`tst/editor_test.sh` (run by `dev/rebuild.sh` and `make -C tst test` )
2026-07-27 15:01:49 +02:00
drives the fixture pairs in `tst/editor/` through the shared core's API
and CLI, checks idempotence, checks the Emacs implementation for
byte-equality, runs the language server through a scripted LSP client
(`ls_test.py` ), exercises the VS Code extension against the real server
under a stubbed VS Code API (`vscode_ext_test.js` ), and runs the Vim
plugin's commands headlessly. Emacs, Vim, and Node/VS Code halves skip
gracefully where not installed.