diff --git a/docs/PLAN.md b/docs/PLAN.md index 52dc56b..cd91bd0 100644 --- a/docs/PLAN.md +++ b/docs/PLAN.md @@ -178,21 +178,29 @@ Therefore the palette is replaced, not extended, and the replacement is built on consuming it — no registered shortcut, so no ambiguity, no per-view sweeping. ### M5 — Command vocabulary + project model + switchers — IN PROGRESS -- `:`-verb pack — DONE (palette path). `src/commands/`: `texttransforms.{h,cpp}` - (pure, unit-tested: sort/rsort, case upper|lower|title|snake|camel|kebab, - base64 enc/dec, rot13, uuid) + `olliecommands.{h,cpp}`. The verb logic lives in +- `:`-verb pack — DONE (palette **and** `:` command line). `src/commands/`: + `texttransforms.{h,cpp}` (pure, unit-tested: sort/rsort, case + upper|lower|title|snake|camel|kebab, base64 enc/dec, rot13, uuid) + + `olliecommands.{h,cpp}`. The verb logic lives in `OllieCommands::runVerb(view, cmd, msg)` and transforms the selection in place (or the whole document when nothing is selected); `pipe ` runs `sh -c ` with the selection on stdin. - Verbs are invoked from the **M-x palette** (entries prefixed `ollie:cmd:`, executed by calling `OllieCommands::runVerb` directly). `case` is expanded into one entry per style; `pipe` is palette-omitted (needs free text). + - They are **also reachable from Kate's `:` command line**. `OllieCommands` + is a `KTextEditor::Command`; its base constructor auto-registers its names + at the global `Editor::instance()`, and `exec()` forwards to `runVerb`. + - ROOT-CAUSE FIX of the earlier "not reachable from `:`" problem: the + KTextEditor registry **aborts registering a Command object entirely if any + one of its names collides** with an already-registered command. Our list + led with `sort`, which Kate ships as a built-in, so the collision silently + dropped **all** our verbs. The sort verb is now registered as **`osort`** + (runVerb still accepts the bare `sort`, so palette entries are unchanged). + `test_ollieregistration` asserts every verb resolves to our object via + `Editor::queryCommand`/`commandList` and guards against reclaiming `sort`. - A live test (`test_olliecommands_live`, headless KTextEditor doc/view) proves the transforms mutate a real buffer. - - KNOWN LIMITATION: `KTextEditor::Command` auto-registration via the base - constructor is NOT visible to `Editor::queryCommand()`/`commandList()` on - this build, so the verbs are not (yet) reachable from Kate's `:` command - line — only via the palette. Proper command-line registration is a follow-up. - Project = directory ("open folder == open project"): DONE (core + switcher). `src/project/projectindex.{h,cpp}` (`project_lib`, Qt::Core only, 12 unit tests): diff --git a/src/commands/CMakeLists.txt b/src/commands/CMakeLists.txt index 5352c59..06c36e1 100644 --- a/src/commands/CMakeLists.txt +++ b/src/commands/CMakeLists.txt @@ -20,4 +20,9 @@ if(Qt6Test_FOUND) target_link_libraries(test_olliecommands_live PRIVATE olliecommands_lib Qt6::Test KF6::TextEditor) add_test(NAME olliecommands_live COMMAND test_olliecommands_live) + + add_executable(test_ollieregistration test_ollieregistration.cpp) + target_link_libraries(test_ollieregistration PRIVATE + olliecommands_lib Qt6::Test Qt6::Widgets KF6::TextEditor) + add_test(NAME ollieregistration COMMAND test_ollieregistration) endif() diff --git a/src/commands/olliecommands.cpp b/src/commands/olliecommands.cpp index db2505b..e5be880 100644 --- a/src/commands/olliecommands.cpp +++ b/src/commands/olliecommands.cpp @@ -21,7 +21,13 @@ using namespace texttransforms; QStringList OllieCommands::supportedCmds() { return { - QStringLiteral("sort"), + // NOTE: "sort" is a built-in Kate command. The KTextEditor command + // registry aborts registering a Command object entirely if ANY of its + // names collides with an existing one, so claiming "sort" would silently + // drop ALL of our verbs from the ":" command line. We therefore register + // the sort verb as "osort" (runVerb still accepts the bare "sort" so the + // palette entries are unaffected). + QStringLiteral("osort"), QStringLiteral("rsort"), QStringLiteral("case"), QStringLiteral("b64enc"), @@ -88,7 +94,7 @@ bool OllieCommands::runVerb(KTextEditor::View *view, const QString &cmd, QString const Target t = currentTarget(view); - if (verb == QLatin1String("sort")) { + if (verb == QLatin1String("sort") || verb == QLatin1String("osort")) { const bool unique = args.contains(QLatin1String("u")); const bool ci = args.contains(QLatin1String("i")); applyResult(view, t, sortLines(t.text, unique, ci)); @@ -173,8 +179,8 @@ bool OllieCommands::runVerb(KTextEditor::View *view, const QString &cmd, QString bool OllieCommands::help(KTextEditor::View *, const QString &cmd, QString &msg) { const QString verb = cmd.section(QLatin1Char(' '), 0, 0); - if (verb == QLatin1String("sort")) { - msg = i18n("sort [u] [i] — sort selected lines; u=unique, i=case-insensitive"); + if (verb == QLatin1String("sort") || verb == QLatin1String("osort")) { + msg = i18n("osort [u] [i] — sort selected lines; u=unique, i=case-insensitive"); } else if (verb == QLatin1String("rsort")) { msg = i18n("rsort — reverse the order of selected lines"); } else if (verb == QLatin1String("case")) { diff --git a/src/commands/olliecommands.h b/src/commands/olliecommands.h index 8445d43..54bf9f4 100644 --- a/src/commands/olliecommands.h +++ b/src/commands/olliecommands.h @@ -5,7 +5,8 @@ * the editor. Each verb transforms the current selection in place (or the whole * document when nothing is selected). Verbs: * - * sort [u] [i] sort selected lines (u = unique, i = case-insensitive) + * osort [u] [i] sort selected lines (u = unique, i = case-insensitive) + * (registered as "osort" because Kate already ships "sort") * rsort reverse the order of selected lines * case