Commit Graph

10 Commits

Author SHA1 Message Date
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 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 eeee28a94a Radial: Wayland pointer warp via zwp_pointer_constraints_v1
QCursor::setPos is a no-op on Wayland, so cursor-follows-focus did
nothing there. Add WaylandCursorWarp (src/plugin/waylandcursorwarp.{h,
cpp}): on Wayland, lock the pointer to the top-level window's wl_surface,
set_cursor_position_hint to the target pane centre (surface-local), commit,
then release — the compositor warps to the hint on unlock (the mechanism
plan9port/acme use). Panes are children of one window = one surface, so
it is a warp within that surface. Handles come from QWaylandApplication +
QPlatformNativeInterface 'surface'. X11 keeps QCursor::setPos.

Build: pointer-constraints client glue generated via ECM and compiled as
a C static lib (kcoreaddons_add_plugin silently drops .c sources); enable
C language in project(); link Qt6::GuiPrivate + wayland-client. All
guarded + a stub when the Wayland bits are absent. 13 ctest suites pass.
2026-10-08 12:18:01 +02:00
Levi Neely a5b8d628b3 Perf: debounce palette filter + default to optimized build
Two fixes for the Alt+G typing lag:

1. Default CMAKE_BUILD_TYPE to RelWithDebInfo when unspecified — the
   shipped plugin was -O0. On mobydick (17k symbols) the worst
   type-forward keystroke drops ~340ms -> ~29ms (~12x).

2. Debounce the PaletteWidget filter with an 80ms single-shot timer so a
   fast typist's burst triggers one re-rank, not one per character.
   applyQueryNow() flushes the pending query on Enter so activation uses
   the latest text; activate() resets the debounce state.

The broad early-query keystrokes (1-2 chars matching most of N) are the
only ones still ~O(N); debounce ensures they are paid at most once per
pause. docs/PERF.md updated with measured numbers.
2026-10-08 11:13:37 +02:00
Levi Neely 2bf8d4a3c2 Perf: async + cached project indexing (fixes Alt+G open stall)
Add ProjectIndexer (project_lib, QtConcurrent + QFutureWatcher, 6 tests):
runs listFiles/listSymbols on the thread pool, delivers results on the UI
thread via filesReady/symbolsReady, caches per project root, and drops
stale results via a per-root generation counter.

Switchers now open the palette immediately — cache hit is instant, miss
shows a transient 'Indexing…' placeholder — and repopulate when the
background job finishes. The ~0.5-1s ctags stall on Alt+G no longer
blocks the UI thread. Cache invalidated on KateProjectBridge::
projectChanged. Register QList<Symbol> metatype; link Qt6::Concurrent.
Item building factored into buildFileItems/buildSymbolItems (shared by
the cache and async paths).
2026-10-08 11:02:52 +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 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