Commit Graph

29 Commits

Author SHA1 Message Date
Levi Neely fd84f59f14 sloppyfocus: fold kate-sloppyfocus into the suite as deft_sloppyfocus
Bring the standalone kate-sloppyfocus plugin (focus-follows-mouse) into Deft as
the seventh plugin, [deft:util] sloppyfocus, under src/sloppyfocus/.

Ported to the suite's conventions:
- Wrapped SloppyFocusPlugin/View/ConfigPage in namespace deft.
- KF6-only CMake (dropped the KF5 fallback), target deft_sloppyfocus, installed
  to kf6/ktexteditor and guarded by KF6TextEditor_FOUND; links KF6::TextEditor/
  CoreAddons/I18n/ConfigCore + Qt6::Widgets.
- metadata.json -> sloppyfocusplugin.json with the [deft:util] sloppyfocus
  display name and author Levi Neely; factory JSON and .moc renamed to match.
- Config group renamed to deft_sloppyfocus.

Two port fixes required by the suite's stricter build:
- forward-declare QCheckBox/QSpinBox at global scope (the original's inline
  'class QSpinBox *' members became deft::QSpinBox once wrapped in the namespace).
- the KConfigGroup group name must be a QString (QT_NO_CAST_FROM_ASCII is on
  here), so the group is a QStringLiteral rather than a const char *.

README (plugin table, a new sloppyfocus section, layout tree) and AGENTS.md
updated. The plugin already removes its qApp event filter in its destructor, so
it is not subject to the reload crash fixed in 629a2da. 18/18 ctest green.
2026-10-09 11:31:30 +02:00
Levi Neely 67e8d53827 radial: add a conditional Ollie submenu to the right-button radial
When the sibling Ollie Kate plugin (ollie-kate) is loaded in the window, the
right-button radial grows an 'Ollie' branch: Ask, Explain, Fix, Refactor, Tests,
Doc, Verbatim, Start.

Ollie's context actions are not window/collection actions (they live on a
transient context menu, which the radial suppresses anyway), so findActionByName
cannot resolve them. Instead each slice carries an 'ollie:<verb>' id; triggerOllieVerb()
resolves the plugin view via pluginView("ollie-kate") and invokes its
Q_INVOKABLE action method by name (submitSelectionPrompt for fix/refactor/test/doc,
the zero-arg methods for the rest). The branch is built at show time and omitted
when the plugin is not loaded, mirroring the LSP branch. 18/18 ctest green.
2026-10-09 10:54:47 +02:00
Levi Neely 36e9890ec7 radial: add a conditional LSP submenu to the right-button radial
When Kate's LSP Client plugin is active, the right-button (editing) radial now
grows an 'LSP' branch: Go to Definition/Declaration/Type, Find References/
Implementations, Rename, Format, Code Action, Symbol Info, Hover.

The branch is built in showRadialAt() at open time, not in setupRadials(), so
it tracks the plugin being enabled/disabled without a restart. Each entry is
included only if its action currently resolves via findActionByName — the LSP
actions are referenced by their visible menu labels (the objectNames are not a
stable contract, the labels are) and the text-fallback resolver triggers them
like any other slice. When none resolve (LSP not loaded) the branch is empty and
the caller omits it, so nothing shows for non-LSP buffers.

Only the def with button == RightButton gets the branch (the editing radial),
not the middle-button window radial. 18/18 ctest green; deft_radial reinstalled.
2026-10-09 09:49:18 +02:00
Levi Neely efa1fe74c2 docs: credit eaburns's devdraw/acme as the source of the Wayland warp technique
Reword from 'following'/'taken from' to 'sourced from' — the pointer-constraints
warp technique was drawn from eaburns's Wayland devdraw/acme, not tracked or
lifted wholesale.
2026-10-08 21:04:01 +02:00
Levi Neely 4a785a8d46 docs: correct Wayland warp attribution to eaburns's devdraw/acme
The pointer-constraints warp technique follows eaburns's Wayland implementation
of devdraw/acme (github.com/eaburns/plan9port, wayland branch), not plan9port
proper. Fix the attribution in both the README radial section and the
waylandcursorwarp.h header comment, and link the source.
2026-10-08 21:02:50 +02:00
Levi Neely 6b8f66aabc docs(README): document radial's pointer-follows-focus warping
The radial menu warps the pointer to the centre of the newly active pane after
a split/close/focus-move slice (X11 QCursor::setPos; Wayland pointer-constraints,
as plan9port does), so the mouse follows keyboard/pane focus — acme-style.
2026-10-08 20:59:21 +02:00
Levi Neely e2a0338f40 docs(README): plug the plumb plugin 2026-10-08 20:58:15 +02:00
Levi Neely 5830340f1d docs(README): note plan9port as a runtime dep of the plumb plugin 2026-10-08 20:57:25 +02:00
Levi Neely 59e1178958 docs(README): remove 'Why not just use Kate's command bar?' section 2026-10-08 20:56:47 +02:00
Levi Neely d799603587 docs(README): link Kate's website on first mention 2026-10-08 20:54:53 +02:00
Levi Neely 94d609f3ab docs(README): credit the video-game radial lineage; foreground one-handed typing
- Name video games as the source for the radial/pie menu (weapon/emote wheel)
  alongside acme/sam/plumber, Emacs, and Sublime.
- Stop understating the one-handed-typing shift: state plainly that it is the
  driving ergonomic constraint — the reason the mouse carries the reaching and
  chords are off the table — in the intro, the design-constraints list, and the
  radial section.
2026-10-08 20:53:42 +02:00
Levi Neely e31fee664e docs(README): rewrite the intro to the honest motivation
Replace 'for people who despise menus' with the real story: an attempt to turn
Kate into a daily driver by pulling in ideas from the author's toolkit (acme,
sam, plumber; Emacs M-x; a Sublime-style palette), rather than claiming Kate is
already the author's editor.
2026-10-08 20:50:50 +02:00
Levi Neely 38f5468ce6 docs: remove PERF.md and its references
The performance notes documented one-off benchmarking of the switcher re-rank
and the fixes already applied; it is no longer useful as living documentation.
Drop docs/PERF.md and the references to it in README (layout tree), AGENTS.md
(reference-docs list and the build-type note), and the CMakeLists comment.
2026-10-08 20:46:31 +02:00
Levi Neely 33790043d8 docs: bring all docs up to date after the split/rename
- docs/radials.example.json: the config comments and the launcher-door action
  names were still Ollie-era — 'Copy to .../olliepalette/radials.json' ->
  'deft/radials.json', and ollie_goto_file/ollie_goto_symbol/ollie_command_palette
  -> deft_goto_file/deft_goto_symbol/deft_command_palette (the objectNames the
  radial plugin actually resolves; verified against radialconfig.cpp).
- docs/PLUMBING.md: replaced the dead 'See PLAN.md' pointer with the real
  implementation location (src/plumb/, plumb_lib + plumbplugin).
- README: link docs/radials.example.json from the radial Configure note.
- AGENTS.md: drop the environment-specific LSP-bridge remark (not universal
  contributor guidance); keep the plain 'read before you edit' rule.

PERF.md and SAM.md were already accurate and are unchanged.
2026-10-08 20:44:50 +02:00
Levi Neely 812ab782f8 docs: drop the roadmap, add AGENTS.md
Remove docs/PLAN.md (goal/constraints/milestone roadmap — stale planning prose)
and the README's Status/milestone section; the README already documents what
the plugins are and do. Refresh the layout tree's docs/ listing accordingly.

Add AGENTS.md: a working guide for contributors/agents — the one-.so-per-feature
architecture and shared libs, build/test/install commands, naming and style
conventions, the two load-bearing design decisions (eventFilter'd launcher keys
vs ambiguous shortcuts; cross-plugin calls by action objectName with no link
dependency), and the gotchas (osort collision, per-plugin frecency files,
live-Kate behaviour being unverifiable in CI).
2026-10-08 20:41:14 +02:00
Levi Neely d9829c9327 docs(README): add plugin screenshots
Add the docs/img/ screenshots and embed one in each plugin's subsection:
palette (deft-mx), radial (deft-radial), acme (deft-acme-select), sam
(deft-sam), and plumb (deft-ollie-plumb). The switch plugin has no screenshot
yet.
2026-10-08 20:36:53 +02:00
Levi Neely 4325513c47 build: auto-wire QT_PLUGIN_PATH for a user-local install
A home-prefix install puts the plugins outside Qt's default search path, so
Kate would not list them until QT_PLUGIN_PATH includes the install dir — the
step a bare 'cmake --install' silently left undone. Solve it the way the ollie
project does (a Plasma login env snippet), and automate the common case:

- Add 99-deft.sh.in, a Plasma env snippet that prepends the install's qt6
  plugin dir to QT_PLUGIN_PATH. configure_file() fills in the absolute path.
- On a user-local install (prefix inside $HOME), install(CODE) drops the
  configured 99-deft.sh into ~/.config/plasma-workspace/env/ so the lookup
  path is wired up with no manual step; Plasma sources it at next login. The
  installer also prints a one-line export to use the plugins immediately.
- On a system-prefix install it does not touch the user's config; it just
  prints where the plugins went and leaves the ready snippet in the build dir.

README: add a 'Making Kate find a user-local install' section explaining that
QT_PLUGIN_PATH must include ~/.local, that the installer handles it, and how to
activate it in the current session (or a non-Plasma shell).

Verified: cmake --install with the default prefix installs the six plugins and
writes ~/.config/plasma-workspace/env/99-deft.sh with the correct path.
2026-10-08 20:19:00 +02:00
Levi Neely 29136ac898 build: install to ~/.local and the Qt plugin dir by default
cmake --install previously defaulted to CMAKE_INSTALL_PREFIX=/usr/local (needs
root) and, via KDE_INSTALL_PLUGINDIR, to lib/<arch>/plugins/ — a directory Kate
does NOT scan (it scans lib/<arch>/qt6/plugins/, per QT_PLUGIN_PATH). So a plain
install both failed on permissions and would have put the plugins where they
can't be found.

Follow the sibling ollie project's approach instead of hand-rolling path logic:

- Default CMAKE_INSTALL_PREFIX to $HOME/.local when the user did not pass one.
  ECM's KDECMakeSettings resets an unspecified prefix back to /usr/local, so we
  capture CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT *before* including it and
  re-apply the user-local default *after*, where it is not clobbered.
- Point KDE_INSTALL_PLUGINDIR at QT6_INSTALL_PLUGINS (prefix-relative
  lib/<arch>/qt6/plugins) so kcoreaddons_add_plugin(INSTALL_NAMESPACE
  kf6/ktexteditor) lands where Kate looks. Set the *normal* variable (the macro
  reads it directly; a cache-only FORCE would be shadowed) as well as the cache.

Result: `cmake --install build` with no flags installs all six plugins to
~/.local/lib/<arch>/qt6/plugins/kf6/ktexteditor/ with no root.

README: replace the manual install -D loop with `cmake --install build`, state
clearly that it installs to the home dir by default, show the resulting path,
and document --prefix /usr for a system-wide install.
2026-10-08 20:16:09 +02:00
Levi Neely 2c41a430b6 docs(README): warn that the plugins are opinionated
Several plugins reshape or suppress Kate's defaults (radial takes the right
mouse button, acme rebinds Ctrl+A/E/H/U/W + double-click + mouse chords and
kills X11 primary paste, palette/switch/plumb claim Alt+X/P/G and F2). Add a
callout at the top of 'The plugins' so users enable them deliberately rather
than being surprised.
2026-10-08 20:06:54 +02:00
Levi Neely e9d86b35f8 docs(README): add per-plugin descriptions and usage guides
Add a 'The plugins' section with a short description and a defaults-based usage
guide for each of the six plugins: palette (M-x + the :-verb table + frecency),
switch (Go to File/Symbol, ctags, project scoping, cache), radial (open/choose
gestures + radials.json config), acme (line keys, pair select, mouse chords),
sam (tool view, Run, X/Y multi-file), and plumb (F2 send, edit port, fallback).
Trim the now-redundant usage prose from the install section and point it at the
new section.
2026-10-08 20:05:02 +02:00
Levi Neely 8d06c206bb rename: drop the last Ollie names; command pack -> DeftCommands
The transient core classes were already deleted in the split, but the shared
command library and a scattering of comments/ids still carried the old project
name. Finish de-Ollie-ing the tree so nothing but 'Deft' remains:

- src/commands: OllieCommands -> DeftCommands; files olliecommands.{h,cpp} ->
  deftcommands.{h,cpp}; lib target olliecommands_lib -> deftcommands_lib; tests
  test_olliecommands_live/test_ollieregistration -> test_deftcommands_live/
  test_deftregistration (ctest names deftcommands_live/deftregistration).
  palette plugin updated to match (include, fwd-decl, member type, ctor call,
  runVerb call, CMake link).
- Config paths: radial's user config moves olliepalette/radials.json ->
  deft/radials.json, matching the switch plugin's earlier olliepalette/ -> deft/
  move; comments updated.
- Stale ollie: id prefixes in the project benchmark (ollie:file:/ollie:sym: ->
  deft:file:/deft:sym:) and sample paths in test_palettemodel referencing the
  deleted src/plugin/ollieplugin.cpp.
- Comments still naming OllieView/OlliePlugin corrected to the real post-split
  classes (SamView, PlumbView) or to deft paths.
- README layout refreshed (deftcommands.{h,cpp}).

PLAN.md keeps the Ollie names inside its pre-split historical prose, as flagged
by the architecture note at its top.

Full clean rebuild + 18/18 ctest green; palette and radial reinstalled.
2026-10-08 20:03:17 +02:00
Levi Neely ed3bd4249b docs: describe the six-plugin layout after the split
README: replace the single-deft.so install instructions with the per-feature
plugin table (palette, switch, radial, acme, sam, plumb), a glob install loop,
and a note that the plugins cooperate by resolving each other's actions by
object name; refresh the layout tree (plugin/ gone, switch/ added, palette/ and
radial/ now hold their plugins) and mark milestones 5 and 6 DONE.

PLAN.md: add an architecture note at the top flagging the split and that the
design prose below refers to the former monolith as historical.
2026-10-08 19:56:11 +02:00
Levi Neely d96cb63baf rename suite to Deft (stage 1: namespace + artifact)
Rename the C++ namespace katecustom -> deft and include guards
KATECUSTOM_* -> DEFT_* across all sources. Rename the plugin artifact
olliepalette.so -> deft.so (CMake target 'deft') and set the plugin
display name to 'Deft'. Update README title/install paths.

File names, class names (Ollie*), and the src/ directory grouping are
left for the follow-up stages that split features into per-plugin .so's
([deft:nineify] / [deft:util]).
2026-10-08 18:49:35 +02:00
Levi Neely 217d042a1b M5: :-verb command pack (sort/case/base64/rot13/uuid/pipe)
Add src/commands/: texttransforms (pure, unit-tested string transforms) and
olliecommands (a KTextEditor::Command registering sort, rsort, case, b64enc,
b64dec, rot13, uuid, pipe). Verbs act on the selection in place, or the whole
document when nothing is selected. 'pipe <shell>' runs sh -c <shell> with the
selection on stdin and replaces it with stdout (the user types the command,
so shell execution is intended). The command object is created once by
OlliePlugin and auto-registers with the global editor.

15 transform unit tests; 6 ctest suites green overall. Verbs are reachable
from Kate's command line; surfacing them in the M-x palette is a follow-up
(they are Commands, not QActions).
2026-10-07 17:54:20 +02:00
Levi Neely 4be3ead30d Radial: add right-mouse-button gesture trigger
RMB is the natural radial trigger. The plugin now installs an application
event filter (gated to the active view) that, on an RMB press inside the
editor, pops the radial at the pointer and consumes the press plus the
following ContextMenu event, suppressing Kate's context menu (an
intentional, user-approved trade-off). The radial grabs the mouse on popup
so an in-progress RMB drag is tracked and the release selects the slice.

Config gains a per-radial "button" field (RightButton/MiddleButton)
alongside the key "trigger"; the built-in editing radial binds both Alt+R
and RightButton. All 5 ctest suites green.
2026-10-07 16:43:52 +02:00
Levi Neely a98db2913c M4: multi-level radial menu (mouse door), config-driven triggers
- RadialModel: pure tree + geometry (angle hit-test, dead zone, far-flick
  snap, descend/ascend). 14 tests.
- RadialMenu: frameless translucent widget painting the current ring with
  wedges, labels, branch markers and a central back/cancel hub; mouse hover
  highlights, release/click activates a leaf, descends a branch, or
  ascends/cancels from the hub; Esc ascends/cancels.
- RadialConfig: JSON -> radial tree parser with a built-in default, so
  multiple radials can bind to different triggers. 8 tests.
- Plugin wiring: one trigger action per configured radial (default Alt+R ->
  editing radial), popped at the caret via cursorPositionCoordinates().
  Slices reference Kate actions by objectName (resolved via findActionByName);
  the special ollie_command_palette slice opens the palette.

Honours the agreed model (keys/weapon-wheel triggers now; config carries a
per-radial trigger for mouse-button/gesture triggers later). All 5 ctest
suites green (36 tests).
2026-10-07 16:38:54 +02:00
Levi Neely 91a0e2d260 M3: loadable KTextEditor plugin with M-x command palette
- OlliePlugin (KTextEditor::Plugin) + OllieView, built as olliepalette.so
  via kcoreaddons_add_plugin, installed under kf6/ktexteditor.
- M-x bound to Alt+X (single modifier, adjacent keys on a compact layout,
  ApplicationShortcut so it is always live).
- On trigger, aggregates every enabled/visible QAction from the window's
  guiFactory()->clients() action collections (keyed by objectName) and
  shows them in PaletteWidget; the chosen row triggers the QAction. The
  action's current shortcut is surfaced in the group column.
- Enable position-independent code for linking the static palette lib into
  the shared plugin module.
- Plugin metadata verified valid via KPluginMetaData.

Frecency wiring deferred (model supports it; plugin passes 0). All three
ctest suites remain green.
2026-10-07 15:59:05 +02:00
Levi Neely 617b526e3f M2: command palette widget + ranked list model
- PaletteModel: QAbstractListModel ranking items via FuzzyRanker, with
  id/label/group/score and highlight-range roles plus a frecency bonus.
  Headless, unit-tested (10 cases).
- PaletteWidget: frameless popup with a filter line and results list.
  Live company-style updates, top hit preselected, custom delegate bolds
  matched characters. Keyboard (Up/Down/PageUp/PageDown/Enter/Esc, focus
  kept in the filter) and mouse (click to activate). No chords.
- Tighten FuzzyRanker typo tolerance: single adjacent transposition instead
  of deletion. Still recovers 'gti'->'git' but no longer false-matches
  'ren' against 'Open File'.

All tests green: fuzzyranker (14) + palettemodel (10).
2026-10-07 15:49:48 +02:00
Levi Neely 95bc9f7ed6 Initial commit: FuzzyRanker keystone + project plan
Kate plugin suite for menu-free, mouse-first, one-handed UX.

- FuzzyRanker: orderless + layered fuzzy matcher (exact/substring/
  initials/subsequence/bounded-typo) with merged highlight ranges.
  Fixes Kate's KFuzzyMatcher gaps (no orderless, 'gti' fails 'git').
- 14 QTest cases, all green.
- README + docs/PLAN.md: goal, design constraints, 5-milestone roadmap.
2026-10-07 15:45:58 +02:00