Skip to content

refactor(peek): replace adapter registry with push-model peek sources#16

Merged
WilliamHsieh merged 1 commit into
masterfrom
feature/peek-cleanup
Jun 15, 2026
Merged

refactor(peek): replace adapter registry with push-model peek sources#16
WilliamHsieh merged 1 commit into
masterfrom
feature/peek-cleanup

Conversation

@WilliamHsieh

Copy link
Copy Markdown
Owner

Summary

Replaces the peek subsystem's name-keyed adapter registry with a "push" model: a peek source is just a function that builds OverlookPopupOptions and hands them to require("overlook.window").open_popup(opts). No dispatcher, no contract object, no .async flag, no string-keyed registry, no name lookup.

The old design dispatched through a table keyed by adapter name (default_adapters[name] / Config.adapters[name]), resolved at call time. That was stringly-typed, invisible to lua-ls, and existed mainly to support custom-adapters-by-name — an extension surface that isn't a goal pre-1.0. The built-in dispatch never needed it: the names are fixed at author time and the module is the handle.

Pre-1.0, internal cleanup, adapter contract free to break.

What changed

  • Deleted lua/overlook/peek.lua (the metatable __index dispatcher).
  • adapter/peek/: cursor, marks, definition are now plain functions. require("overlook.peek.cursor")() reads as the action and mirrors the peek_cursor API.
  • The sync/async split disappears. Sync sources call open_popup directly; async sources (LSP) call it later from their own callback. There's no .async flag or two-shape contract anymore.
  • window.lua: added module-level M.open_popup(opts) = M.current():open_popup(opts) — the single seam a source uses, so a source never has to know the Window/Stack/Popup layering. It lives where popups already live rather than in a separate peek layer.
  • api.lua: peek_* wrappers call the source modules directly; dropped the Peek require.
  • config.lua: removed the adapters option (and the your_custom_adapter stub that deep-merged into every user's config as a callable no-op). A custom source is now "write a function that calls Window.open_popup and bind it to a key" — no registration.
  • types.lua: dropped the OverlookAdapter contract; a peek source is documented as a plain function (OverlookPeekSource).

Bug fixes folded in

  • peek_mark no longer fires the stray pre-prompt marks() call that produced a double error on every invocation.
  • definition guards empty/nil LSP results and missing user_data (was an attempt to index a nil value crash on the common no-definition case).
  • cursor drops the dead file_path field (set but never read, not in OverlookPopupOptions).
  • A source with nothing to peek notifies and simply does not open; no generic "returned nil options" error stacked on top.

Test plan

  • Per-source specs (cursor_spec, marks_spec, definition_spec) assert each source calls Window.open_popup with the right options, or notifies and opens nothing.
  • api_spec covers peek_mark's prompt flow (no pre-prompt fire; one fire on a valid char; invalid/cancelled handling).
  • The dispatcher spec is removed (the dispatcher is gone).
  • 99 tests pass; stylua clean.

Breaking changes

  • Config.adapters is removed. Any custom adapter registered via config no longer resolves — register a custom source by binding a function that calls require("overlook.window").open_popup(opts) to a key instead. Acceptable pre-1.0.

🤖 Generated with Claude Code

The peek subsystem dispatched through a name-keyed adapter table
(default_adapters[name] / Config.adapters[name]) resolved at call time.
That registry was stringly-typed, invisible to lua-ls, and existed mainly
to serve a custom-adapter-by-name extension surface that isn't a goal
(pre-1.0, internal cleanup). The built-in dispatch never needed it -- the
names are fixed at author time and the module IS the handle.

New shape ("push"): a peek source is just a function that builds
OverlookPopupOptions and hands them to require("overlook.window").open_popup.
There is no dispatcher, no contract object, no .async flag, no registry, no
name lookup. Sync sources call open_popup directly; async sources (LSP) call
it later from their own callback -- the sync/async distinction disappears.

- Delete lua/overlook/peek.lua (the metatable dispatcher).
- lua/overlook/adapter/ -> lua/overlook/peek/ : cursor, marks, definition are
  now plain functions. require("overlook.peek.cursor")() reads as the action.
- window.lua: add module-level M.open_popup(opts) = M.current():open_popup(opts)
  so a source never has to know the Window/Stack/Popup layering. The seam
  lives where popups already live rather than in a separate peek layer.
- api.lua: peek_* wrappers call the source modules directly; drop the Peek
  require.
- config.lua: remove the `adapters` option (and the leaked your_custom_adapter
  stub) -- custom sources are now "write a function that calls
  Window.open_popup and bind it to a key", no registration.
- types.lua: drop the OverlookAdapter contract; document a peek source as a
  plain function (OverlookPeekSource alias).

Folds in the bug fixes from the earlier cleanup pass (unpushed, superseded):
- peek_mark no longer fires the stray pre-prompt marks() call (double error).
- definition guards empty/nil LSP results + missing user_data (was a crash).
- cursor drops the dead file_path field.
- a source that has nothing to peek notifies and simply does not open; no
  generic "returned nil options" error.

Tests: per-source specs (cursor/marks/definition) assert the source calls
Window.open_popup with the right options (or notifies and opens nothing);
api_spec covers peek_mark's prompt flow; the dispatcher spec is removed.
99 pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@WilliamHsieh WilliamHsieh merged commit 9a18d4b into master Jun 15, 2026
5 checks passed
@WilliamHsieh WilliamHsieh deleted the feature/peek-cleanup branch June 15, 2026 22:18
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.

1 participant