kate-deft/docs/PLUMBING.md

141 lines
5.1 KiB
Markdown

# Plumbing — configuring `~/lib/plumbing` for Kate
Kate is a full plan9port **plumb client**: it sends plumb messages (plumb a
token under the caret) and receives them on the `edit` port (open a file at a
line, or a directory as a folder). The *routing* — what a plumbed string means —
lives in the plumber's rules, not in Kate. This document covers the user-side
rules in `~/lib/plumbing` that make files and directories open in Kate.
The implementation (the native 9P client, the edit-port reader, and the
in-process handler) lives in `src/plumb/` — `plumb_lib` is the pure codec/9P
client and `plumbplugin.{h,cpp}` is the Kate glue.
## How plumbing reaches Kate
```
plumb <text> # or Kate's F2 on the caret token
│
▼
plumber ── applies ~/lib/plumbing rules ──► routes to a PORT
│
▼ (edit port)
Kate's reader thread ──► onPlumbEdit() ──► open file@line / open folder
```
- The plumber matches the message against rules **top to bottom; first match
wins**.
- A rule routes to a **port** (`plumb to edit`, `plumb to web`, …). The `edit`
port is where editors listen.
- `plumb client <prog>` / `plumb start <prog>` name what to run **if no
application currently holds that port**. A ruleset may contain **only one**
`client`/`start` action.
- `client` — the started program is expected to *open the port itself*; the
message is then delivered through the port. acme and Kate both work this
way (Kate via its edit-port reader).
- `start` — just runs the program with the given arguments.
## Make Kate the editor
Set the editor variable near the top of `~/lib/plumbing`:
```
editor = /usr/bin/kate
```
Every file rule ends with `plumb to edit` + `plumb client $editor`, so this
alone makes **files open in Kate**:
- If Kate is already running, its reader holds the `edit` port and receives the
message directly.
- If nothing holds `edit`, the plumber cold-starts `/usr/bin/kate`; once its
reader attaches, the message is delivered.
The **line/column** travels in the message as an `addr` attribute (e.g.
`addr=42`), *not* as a command-line argument. `plumb client` delivers it through
the port, and Kate's handler jumps to it — so `foo.c:42` opens `foo.c` at line
42.
> The `edit` port is single-consumer. If acme and Kate run at the same time,
> whichever holds `edit` wins; you cannot have both receive plumbed files. With
> `editor = /usr/bin/kate`, Kate is the one cold-started and holding the port.
## Open a directory as a folder
The stock `basic` rules only match **regular files** (`arg isfile`), so a bare
directory path fails with *"couldn't find destination for message."* Add a
directory rule. Place it **before** the generic file rules (those use `isfile`,
which fails on a directory, so ordering is not strictly required, but keeping it
with the other specific rules is clearest):
```
# any existing directory opens as a folder in Kate
type is text
data matches '[a-zA-Z¡-￿0-9_\-./@~]+'
arg isdir $0
data set $dir
plumb to edit
plumb start kate $dir
```
- `arg isdir $0` succeeds only for an existing directory and sets `$dir`.
- `data set $dir` makes the directory path the message payload.
- `plumb to edit` delivers to Kate's reader when it is running (the in-process
handler opens the folder; `start` does **not** fire).
- `plumb start kate $dir` cold-starts Kate on the directory when nothing holds
`edit`. Kate registers `inode/directory` in its desktop entry and opens a
directory as a folder.
Note the one-`client`/`start`-per-ruleset limit: this rule uses `start` (not
both `client` and `start`), which covers running and cold-start cases together.
## Apply changes to a running plumber
Rules reload without restarting the plumber:
```
cat ~/lib/plumbing | 9p write plumb/rules
```
A malformed ruleset is rejected whole (the write fails with an error such as
`ruleset has more than one client or start action`); the previous rules stay
in effect until a valid file is written.
## Quick verification
```
# a file (should route to the edit port, carrying addr=3)
plumb /path/to/file:3
# a directory (should route to the edit port, data = the dir)
plumb /path/to/dir
```
To watch what a plumb actually delivers, read the edit port in another shell:
```
9p read plumb/edit # prints the message: src/dst/wdir/type/attr/ndata/data
```
A successful file message looks like:
```
plumb
edit
<wdir>
text
addr=3
15
/path/to/file
```
and a directory message has an empty attr line and `data = /path/to/dir`.
## Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| `plumb: can't send message: couldn't find destination` | no rule matched (e.g. a directory with only `isfile` rules) | add the directory rule above |
| files open in **acme**, not Kate | `editor` still points at acme | set `editor = /usr/bin/kate` and reload |
| `9p write plumb/rules` fails | malformed rule, or two `client`/`start` actions in one ruleset | keep a single `client`/`start` per rule; fix the reported line |
| directory plumb starts Kate but no folder | Kate build without `inode/directory` handling | verify `kate /some/dir` opens the folder from a shell |