Adding our Ctrl+A/E/H/U/W actions alongside Kate's own (Select All, Close, lowercase, …) left both claiming the same sequence, so Qt reported ambiguous shortcuts. clearConflictingShortcuts() now walks every GUI-client action collection and removes our sequences from any foreign action, also clearing their KActionCollection default shortcuts so they are not restored. The sweep runs at setup, once more deferred to the event loop (after the GUI factory merges all clients), and on every viewCreated so new documents don't re-introduce the conflict. Also implements the five Acme motions against the View/Document API with semantics ported from plan9port acme text.c. All 5 ctest suites green. |
||
|---|---|---|
| docs | ||
| src | ||
| .gitignore | ||
| CMakeLists.txt | ||
| README.md | ||
README.md
kate-custom
A suite of Kate plugins for people who despise menus. The aim is a text editor that is 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), not a trek to the menubar.
- One-handed typing. Keyboard input must work comfortably with one hand.
- 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.
Why not just use Kate's command bar?
Kate's KCommandBar is a sealed widget: it accepts a list of actions via
setActions() and exposes no hook to customize its matcher. Its matcher,
KFuzzyMatcher, is single-needle, strictly in-order subsequence, with no typo
tolerance — by KDE's own documentation, "gti" will not match "git". There
is no "orderless" (space-separated tokens in any order) and no company-style
live completion.
So the project replaces the palette rather than extending it, built on a custom
matcher (FuzzyRanker).
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)
Build
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 plugin into Kate
The plugin builds to build/bin/kf6/ktexteditor/olliepalette.so. Drop it where
Kate scans for KTextEditor plugins (a user path on QT_PLUGIN_PATH):
install -D build/bin/kf6/ktexteditor/olliepalette.so \
~/.local/lib/x86_64-linux-gnu/qt6/plugins/kf6/ktexteditor/olliepalette.so
Then in Kate: Settings → Configure Kate → Plugins → enable Ollie Command Palette. Press Alt+X (M-x) to open the command palette; type to filter, Enter or click to run. Open the editing radial menu either by pressing Alt+R (opens at the caret) or by pressing the right mouse button in the editor (opens at the pointer; the normal context menu is suppressed while this is enabled). Move toward a slice and release — or click; a branch slice (marked ▸) opens a submenu, the centre hub goes back/cancels.
Status
See docs/PLAN.md for the full roadmap.
- Milestone 1 — FuzzyRanker (keystone): DONE. Orderless, layered scoring (exact / substring / word-initials / subsequence / bounded typo), merged highlight ranges. 14 unit tests, all green.
- Milestone 2 — custom palette widget: DONE.
PaletteModel+PaletteWidget(frameless popup, live filtering, highlighted matches, keyboard + mouse activation). 10 model unit tests, all green. - Milestone 3 — KTextEditor plugin + M-x: DONE. Loadable
olliepalette.so;Alt+Xopens the palette over every action in the window's GUI clients. - Milestone 4 — radial caret menu: DONE (first increment). Multi-level
radial menu at the caret (
Alt+R) or at the pointer via a right-mouse gesture, mouse-driven selection, config tree with per-radial key + mouse triggers. Free-form stroke gestures next. - Milestone 5 — command vocabulary + project-as-directory + switchers: next.
Layout
CMakeLists.txt top-level KF6/Qt6/ECM project
src/
fuzzy/
fuzzyranker.{h,cpp} orderless + layered fuzzy matcher
test_fuzzyranker.cpp QTest suite
palette/
palettemodel.{h,cpp} ranked, filterable list model (headless)
palettewidget.{h,cpp} frameless command-palette popup
test_palettemodel.cpp QTest suite
radial/
radialmodel.{h,cpp} radial tree + hit-test geometry (headless)
radialmenu.{h,cpp} frameless multi-level radial widget
radialconfig.{h,cpp} JSON → radial tree + built-in default
test_radialmodel.cpp QTest suite
test_radialconfig.cpp QTest suite
plugin/
ollieplugin.{h,cpp} KTextEditor::Plugin + M-x + radial wiring
ollieplugin.json plugin metadata
docs/
PLAN.md goal, constraints, roadmap