Skip to content

feat(search): add fuzzy subsequence matching - #348

Open
xcha wants to merge 1 commit into
floatboatai:mainfrom
xcha:feat/search-fuzzy
Open

xcha wants to merge 1 commit into
floatboatai:mainfrom
xcha:feat/search-fuzzy

Conversation

@xcha

@xcha xcha commented Sep 18, 2026

Copy link
Copy Markdown

Summary / 摘要

Adds an opt-in fuzzy mode to @floatboat/nexus-plugin-search. Queries match as an ordered subsequence within a single line and carry an fzf-inspired relevance score; navigation, select-all, viewport highlighting and rendered table-cell highlights all follow fuzzy matches through the existing CodeMirror search pipeline.

Motivation / 背景与动机

Roadmap #17. Today a query like fbb cannot find foo bar baz — only literal, whole-word and regex modes exist. Implemented in-package (~130 lines) rather than adding a fuzzy library dependency, per GOVERNANCE §6.3.

Changes / 变更内容

  • packages/plugin-search:
    • SearchOptions.fuzzy, SearchMatch.score?, SearchPluginLabels.fuzzy? (additive only); new exported FuzzySearchQuery
    • Line-scoped subsequence matcher with a minimal-span alignment (forward pass + backward tighten), scored with match / word-boundary / camelCase / consecutive / gap-penalty / exact-case terms
    • FuzzyQueryHandler implements the CodeMirror search query-type protocol (nextMatch, prevMatch, matchAll, highlight, getReplacement), so fuzzy rides the standard search state field instead of a parallel UI
    • Panel: fuzzy toggle (localizable), mutual exclusion with regexp / wholeWord, replace toggle + row hidden while active
    • Fuzzy replace is find-only; getReplacement returns the matched text so a programmatically invoked replace is an identity transform rather than destructive
    • No new dependency: @codemirror/state is not declared here, editor state types are derived from @codemirror/view
  • packages/plugin-search/test: 24 new tests (matcher scoring, line scope, CRLF, panel wiring, CM navigation, select-all, replace hiding, history recall, table highlights)
  • docs/ROADMAP.md, docs/ROADMAP.zh.md: feat(core,react,vue,search,slash,toolbar): editor API, search, slash commands and toolbar enhancements #17done
  • openspec/: proposal, plugin spec delta, tasks

Known trade-off: the fuzzy query-type protocol is not exported by @codemirror/search — only the runtime method names are stable. The handler is implemented against that shape and covered by integration tests that exercise the real commands. See the proposal's Design Notes for why subclassing SearchQuery was chosen over a parallel UI.

Testing / 测试

  • Targeted suite: plugin-search 58/58 passing
  • Typecheck clean: plugin-search, reference-plugins, electron-demo
  • Full suite: 921 passed / 1 failed — the failure is pre-existing on main (apps/electron-demo/test/plugin-host-broker.test.ts:667, O_NONBLOCK is 0 on Windows); CI runs ubuntu-latest
  • Build: ESM + d.ts clean; dist/ stays gitignored
  • OpenSpec: openspec validate --strict not run — CLI is not installed locally
  • Manual UI check in electron-demo: ✅ done, screenshots below — fuzzy toggle renders, fbb matches foo bar baz, camelCase boundaries score above mid-word matches, table cell highlights follow fuzzy spans, replace controls hide while fuzzy is active
  • Repo CI: pending maintainer approval to run (fork PR from a first-time contributor)

Compliance / 合规自检

  • CLA signed — signed when the bot prompted
  • AI disclosure: the functional code in this PR was drafted with Claude Code. I reviewed it line by line and can walk through every decision in the proposal's Design Notes section.
  • New dependencies: none (packages/plugin-search/package.json unchanged)
  • No build artifacts committed
  • No secrets / .env / personal vault data committed

Checklist / 自检清单

  • Title follows Conventional Commits
  • Public API changes update package README / types — no README exists for packages/plugin-search; types updated in-place, check:api does not cover this package
  • Touched live-preview-table.ts — no, not touched
  • New capability → OpenSpec proposal linked (add-search-fuzzy)
  • Change aligns with project scope (GOVERNANCE.md §4)

Screenshots / Recordings

4199037b35a6acb3a41869036bbba943 b436d442a61cd49a2c6df2a0705a8142

@CLAassistant

CLAassistant commented Sep 18, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants