# Deft Deft is my attempt to turn [Kate](https://kate-editor.org/) into a daily driver I actually want to use. I live in Plan 9's [acme](http://acme.cat-v.org/) most of the time, but I like a lot of what Kate offers — and I don't like menu-driven workflows. So this is a suite of Kate / KTextEditor plugins that pulls in ideas from the tools I reach for — acme, sam, and the plumber from Plan 9; `M-x` from Emacs; a Sublime-style fuzzy palette; and the radial/pie menus that video games have used for years to put actions a flick away from the cursor — and bends Kate toward them. The deeper reason is ergonomic: I've moved to typing one-handed, and that reshapes everything. A workflow built on two-handed chords and reaching across the keyboard simply doesn't work anymore. The mouse does the reaching, the keyboard stays under one hand, and no action is allowed to require a chord or an F-key. This isn't a preference knob — it's the constraint the whole design is built around. The aim is a text editor driven by the mouse at the cursor and by plain-letter keyboard input — never by hunting through nested menubars or memorizing complex chords. ## Design constraints These are hard constraints that shape every decision: - **Mouse-heavy.** The fastest input is the mouse, used *locally* at the caret (radial / floating surfaces, in the spirit of a game's weapon wheel), not a trek to the menubar. - **One-handed typing (the driving constraint).** Input must work comfortably with a single hand. This is not a convenience toggle; it is why the mouse carries the reaching and why chords are off the table. - **No complex chords.** Single modifier at most (`Ctrl`+letter). No leader-key chord trees, no multi-cursor keybinds. - **Compact keyboard.** F-keys and nav clusters live on a layer toggle, so they carry extra cognitive cost and are avoided as primary triggers. - **Emacs/Sublime fluency.** `M-x` (`Alt+x`) is comfortable and welcome as a primary keyboard entry point, as is a Sublime-style type-to-filter palette. ### Unifying principle > **One action registry. Three doors onto it:** > **`M-x` (keyboard), a radial caret menu (mouse), and the `:` command line (optional).** > **No action requires an F-key or a chord.** ## Environment - Kate 25.12.3, KDE Frameworks 6, Qt 6 - C++20, CMake, extra-cmake-modules - C++ is the only first-class plugin path on this install (no Python/Pâté binding present) - [plan9port](https://9fans.github.io/plan9port/) — the `plumb` plugin is a plumb client and talks to plan9port's plumber at runtime (see [docs/PLUMBING.md](docs/PLUMBING.md)). Only needed if you enable `plumb` (highly recommended!). ## Build ```sh cmake -B build -S . cmake --build build QT_QPA_PLATFORM=offscreen ./build/bin/test_fuzzyranker # run the matcher tests ctest --test-dir build # or via ctest ``` ## Install the plugins into Kate Deft is **one `.so` per feature**, not a monolith. The build produces six KTextEditor plugins under `build/bin/kf6/ktexteditor/`: | Plugin file | Display name | Feature | |------------------|-----------------------|---------| | `deft_palette.so`| `[deft:util] palette` | Command palette (`Alt+X` / M-x) over every window action + the `:`-verbs + the switchers, frecency-ranked | | `deft_switch.so` | `[deft:util] switch` | Project **Go to File** (`Alt+P`) and **Go to Symbol** (`Alt+G`) | | `deft_radial.so` | `[deft:util] radial` | Radial caret menu (`Alt+R` / right-mouse) | | `deft_acme.so` | `[deft:nineify] acme` | Acme editing gestures (line keys, pair selection, mouse chords) | | `deft_sam.so` | `[deft:nineify] sam` | `sam`-style structural regular expressions | | `deft_plumb.so` | `[deft:nineify] plumb`| Plan 9 plumber (open under cursor) | Drop whichever features you want where Kate scans for KTextEditor plugins. The simplest way is `cmake --install`, which already targets the right place: ```sh cmake --install build ``` **By default this installs into your home directory, not system-wide.** The build sets `CMAKE_INSTALL_PREFIX` to `~/.local` when you don't pass one (these are personal plugins, so installing them under `/usr/local` — the stock CMake default — would need `root` and is the wrong place), and it points the plugin install dir at Qt's own plugin path. So the plugins land at: ``` ~/.local/lib//qt6/plugins/kf6/ktexteditor/deft_*.so ``` which is exactly the directory Kate scans (`QT_PLUGIN_PATH`). To install system-wide instead, pass an explicit prefix (and expect to need `root`): ```sh cmake --install build --prefix /usr ``` ### Making Kate find a user-local install Qt only loads plugins from directories on **`QT_PLUGIN_PATH`**, and that does *not* include `~/.local` by default — so after a home-directory install Kate will not list the plugins until that path is on the search list. This is a one-time, per-user setup step. The install **automates it for you**: when the prefix is inside your home, it writes a login snippet to `~/.config/plasma-workspace/env/99-deft.sh` that adds the plugin directory to `QT_PLUGIN_PATH`. Plasma sources it at login, so after the next **log out / log in** Kate finds the plugins. To use them in the *current* session without logging out, run the export the installer prints, e.g.: ```sh export QT_PLUGIN_PATH="$HOME/.local/lib/x86_64-linux-gnu/qt6/plugins:$QT_PLUGIN_PATH" ``` (For a non-Plasma session, put that same line in your shell profile. For a system-prefix install this step is unnecessary; the installer prints the ready snippet under the build dir if you still want it.) Then in Kate: Settings → Configure Kate → Plugins → enable each **`[deft:…]`** plugin you installed. See [The plugins](#the-plugins) below for what each one does and how to drive it. The plugins cooperate but do not depend on one another: palette's "Go to File/Symbol" entries and radial's launcher slices resolve `switch`'s actions by object name at runtime, so each `.so` works on its own and simply gains those entry points when its sibling is also enabled. ## The plugins Each plugin is independent — enable only what you want. Keys shown below are the defaults. > ⚠️ **These plugins are opinionated.** They are built around one person's > workflow (mouse-at-the-caret, one-handed typing, no chords, Plan 9 / Emacs > habits), and several *reshape or suppress Kate's defaults* rather than just > adding features: > > - `radial` hijacks the **right mouse button** in the editor, suppressing the > normal context menu while enabled. > - `acme` rebinds `Ctrl+A/E/H/U/W`, repurposes **double-click**, turns > left-button **mouse chords** into Cut/Paste, and kills X11 middle-click > primary paste. > - `palette` and `switch` claim `Alt+X/P/G`; `plumb` claims `F2`. > > This is deliberate, not a bug. If you want a conventional Kate, don't enable > the ones whose gestures you aren't ready for — try them one at a time. ### `[deft:util] palette` — command palette (M-x) ![The Deft command palette open over a Kate window](docs/img/deft-mx.png) A Sublime/Emacs-style launcher over **every action currently offered by the window**, matched with the orderless `FuzzyRanker` (space-separated tokens in any order, with typo tolerance) and ranked by *frecency* (frequency + recency of your past choices). - **Open:** `Alt+X`. Type to filter, `Enter` or click to run, `Esc` to dismiss. - Entries include all live menu/toolbar actions, the `:`-verbs below, and — when `switch` is enabled — **Go to File** and **Go to Symbol**. - Usage is remembered in `~/.config/deft/palette.frecency.json`. It also registers a small pack of **`:` command-line verbs** (type `:` in Kate, or pick them from the palette). Each transforms the selection in place, or the whole document when nothing is selected: | Verb | Effect | |------|--------| | `osort [u] [i]` | sort selected lines (`u` = unique, `i` = case-insensitive) | | `rsort` | reverse the order of selected lines | | `case