kate-deft/AGENTS.md

113 lines
5.6 KiB
Markdown

# AGENTS.md
Working notes for anyone (human or agent) hacking on **Deft**, a suite of Kate /
KTextEditor plugins. Read this before changing code.
## What this repo is
Six independent KTextEditor plugins, one `.so` per feature, plus a few shared
static libraries. Each plugin is a `KTextEditor::Plugin` with its own
`K_PLUGIN_FACTORY_WITH_JSON` factory and `.json` metadata. Kate loads one plugin
per `.so`.
| `.so` | display name | source dir | links |
|-------|--------------|------------|-------|
| `deft_palette` | `[deft:util] palette` | `src/palette/` | `palette`, `deftcommands_lib` |
| `deft_switch` | `[deft:util] switch` | `src/switch/` | `palette`, `project_lib` |
| `deft_radial` | `[deft:util] radial` | `src/radial/` | `radial` |
| `deft_sloppyfocus` | `[deft:util] sloppyfocus` | `src/sloppyfocus/` | self-contained |
| `deft_acme` | `[deft:nineify] acme` | `src/acme/` | self-contained |
| `deft_sam` | `[deft:nineify] sam` | `src/sam/` | `sam_lib` |
| `deft_plumb` | `[deft:nineify] plumb`| `src/plumb/` | `plumb_lib` |
Shared static libs (headless, unit-tested in isolation):
`fuzzyranker`, `palette` (model + widget + `FrecencyStore`), `deftcommands_lib`
(text transforms + the `:`-verb `KTextEditor::Command`), `project_lib`
(project/symbol index, `ProjectIndexer`, `KateProjectBridge`), `sam_lib`,
`plumb_lib`.
## Build / test / install
```sh
cmake -B build -S . # configure (defaults: RelWithDebInfo, prefix ~/.local)
cmake --build build -j # build everything
QT_QPA_PLATFORM=offscreen ctest --test-dir build # 18 tests, must stay green
cmake --install build # installs the 6 .so to ~/.local/.../qt6/plugins/kf6/ktexteditor
```
- **Always build and run the full `ctest` after a change.** Tests need
`QT_QPA_PLATFORM=offscreen` (they create real `KTextEditor` docs/views).
- The symbol-switcher path and its tests need **`ctags`** on `PATH`; those tests
skip gracefully when it is absent.
- Installing is wired for a user-local prefix: see `CMakeLists.txt`. It also
drops `~/.config/plasma-workspace/env/99-deft.sh` to put the install dir on
`QT_PLUGIN_PATH` (generated from `99-deft.sh.in`). Don't hand-roll install
paths — `KDE_INSTALL_PLUGINDIR` is pointed at `QT6_INSTALL_PLUGINS` so plugins
land where Kate scans.
- An unqualified `cmake -B build` produces an **optimized** build on purpose
(`CMAKE_BUILD_TYPE=RelWithDebInfo`); the palette re-rank and indexing are
several times slower at `-O0`.
## Conventions that matter
- **Namespace `deft`, `Deft`-prefixed names in all code.** The project was once
called Ollie; nothing should reintroduce `Ollie`/`ollie` in identifiers,
config paths (`~/.config/deft/…`), or id prefixes (`deft:cmd:`, `deft:file:`,
`deft:sym:`).
- **Match the existing style.** No pointless indirection; file-local helpers
duplicated across plugins are preferred over a shared lib for a few trivial
functions.
- **Never rewrite a file from memory.** Read it first, then make targeted edits.
## Two load-bearing design decisions
Changing either of these will break the suite in non-obvious ways.
### 1. Launcher keys are intercepted in an `eventFilter`, not registered shortcuts
The door keys — palette `Alt+X`, switch `Alt+P`/`Alt+G` — are **not** registered
as `QAction` shortcuts. Kate already binds many `Alt+<letter>` combos; a
registered duplicate makes Qt refuse to fire *either* and report an "ambiguous
shortcut". So each view installs an application `eventFilter`, matches the key
itself (scoped to its own window via `isAncestorOf`), and consumes it. The
`QAction`s still exist for their `objectName`/label and discoverability, just
without a shortcut. `plumb`'s `F2` is the exception — it has no Kate collision,
so it is a normal registered shortcut.
### 2. Cross-plugin calls go through action `objectName`, never direct calls
The plugins are separate `.so`s with no link dependency on each other. When
`palette` offers "Go to File/Symbol", or `radial` has a launcher slice, it
resolves the target by `objectName` at runtime and triggers it:
- `switch` registers window actions `deft_goto_file` and `deft_goto_symbol`.
- `palette` registers `deft_command_palette`.
- `findActionByName` searches the window's GUI-factory client action collections
**and** `window()->actions()` (sibling doors are added with
`QWidget::addAction`, not via an XMLGUI client — so the window-actions search
is required, not optional).
If you add a new cross-plugin entry point, register the action under a stable
`deft_*` objectName and resolve it the same way. Never `#include` another
plugin's header or add a link dependency between plugins.
## Gotchas
- The `:`-verb sort is registered as **`osort`**, not `sort`: the KTextEditor
command registry drops an entire `Command` object if any one of its names
collides with a built-in, and Kate ships `sort`. `test_deftregistration`
guards against reintroducing a colliding name. `runVerb` still accepts bare
`sort` for palette entries.
- Each plugin keeps its **own** `FrecencyStore` file (`deft/palette.frecency.json`,
`deft/switch.frecency.json`) — separate files, so two independent rankings
can't clobber one another through a shared file.
- Live Kate behaviour (plugin discovery, the Plasma env snippet pickup, actual
gesture handling) can only be verified in a real KDE session. CI/sandbox runs
cannot confirm it — flag anything that depends on it as unverified.
## Reference docs
- `docs/PLUMBING.md` — configuring the Plan 9 plumber to route into Kate.
- `docs/SAM.md` — the sam structural-regexp dialect and semantics.
- `docs/radials.example.json` — example radial-menu config.