Plugin Capability Matrix
Audit of the plugin protocol (v2) as of 0.12.x: what the protocol declares, what the host actually implements, and what the bundled plugins use. This is the “take stock” pass after the 0.8 plugin work (issue #296). For the protocol itself — message formats, examples, contribution/teardown rules — see Plugin Development.
Capabilities
Capabilities are declared by a plugin in its register_language_provider
action and stored as Capability variants (src/plugin/types.rs). The host
routes them via PluginManager::provider_for (src/plugin/manager.rs).
| Capability | Declared in protocol | Handled by host | Used by a bundled plugin |
|---|---|---|---|
fold | yes | yes — gates set_fold_regions in handle_plugin_set_fold_regions (src/app/refresh.rs) | yes — used by the bundled rust, go, python, json, sh, and yaml language provider plugins |
status_facts | yes (0.18.x) | yes — gates set_status_facts in handle_plugin_set_status_facts (src/app/refresh.rs) | yes — used by the bundled k8s plugin, coexisting with yaml’s fold registration on the same .yaml/.yml extensions |
highlight | yes | no — accepted at registration, never checked anywhere | no |
hover | yes (reserved) | no — unimplementable in v2 (no request/response correlation) | no |
diagnostics | yes (reserved) | no — same as hover | no |
definition | yes (reserved) | no — same as hover | no |
Note on highlight: real syntax highlighting flows through syntax plugins
(kind = "syntax", a .sublime-syntax file fed to syntect — see the bundled
terraform plugin), not through language-provider capabilities. The
highlight capability is documented as reserved for future provider-driven
highlighting; today registering it has no effect.
Actions
Every action the host accepts, dispatched in App::handle_plugin_action
(src/app/refresh.rs). Unknown actions are silently ignored.
| Action | Handled by host | Contribution tracked | Torn down | Used by a bundled plugin |
|---|---|---|---|---|
show_message | yes | no (transient status text) | n/a — plugin_message may briefly outlive the plugin; harmless | no |
open_file | yes | no (one-shot navigation) | n/a | no |
set_icon_map | yes | has_icon_map | yes — icon map/fields cleared | yes — iconize |
set_content | yes | content_paths | yes — content removed, current file re-rendered | yes — markdown |
register_language_provider | yes | provider registration in PluginManager | yes — remove_provider_registrations | yes — rust, python, json, yaml, k8s |
set_fold_regions | yes | fold_region_paths | yes — regions removed, fold state reset | yes — rust, python, json, yaml |
set_status_facts | yes | status_fact_paths | yes — facts removed for contributed paths | yes — k8s |
Teardown status: every stateful set_* action stamps PluginContributions
and is cleared by App::teardown_plugin_contributions (src/app/mod.rs).
No teardown gaps were found in this audit.
Protocol v1 git actions (set_file_statuses, set_blame_data,
set_status_bar_git_info) were removed in 0.11.22 along with the retired
shell-script git plugins; git features are built in. They are listed in the
version history in Plugin Development only.
Bundled plugins
| Plugin | Kind | Actions sent | Capabilities registered |
|---|---|---|---|
iconize | process | set_icon_map | none |
markdown | process | set_content | none |
python | process | register_language_provider, set_fold_regions | fold |
rust | process | register_language_provider, set_fold_regions | fold |
go | process | register_language_provider, set_fold_regions | fold |
json | process | register_language_provider, set_fold_regions | fold |
sh | process | register_language_provider, set_fold_regions | fold |
yaml | process | register_language_provider, set_fold_regions | fold |
k8s | process | register_language_provider, set_status_facts | status_facts |
terraform | syntax | none (no subprocess) | n/a — extends syntect directly |
Gaps and follow-ups
- Reserved capabilities (
hover,diagnostics,definition) are unimplementable in protocol v2 — they need id-correlated request/response. Tracked in the protocol v3 proposal (issue #481), which names this audit as its precursor. - The language-provider fold pipeline has bundled consumers —
register_language_provider+Capability::Fold+set_fold_regionsare used by the bundledrust(issue #599),go(issue #600),python(issue #601),json(issue #604),sh(issue #605), andyaml(issue #603) language provider plugins. Therustandgoplugins register thefoldcapability for.rsand.gofiles via the sharedbrace_folddetector (#598); thepythonplugin uses the sharedindent_folddetector; thejsonplugin usesbrace_fold_with_brackets, abrace_foldvariant that also folds[…]arrays; theshplugin usesshell_brace_fold, a shell-specific variant that handles#line comments, single/double quoted strings, and heredocs; theyamlplugin uses the sharedyaml_folddetector — the same algorithm the built-incrate::yaml_fold::detect_fold_regionsre-exports, so plugin-enabled and built-in YAML folding agree. Built-in YAML folding (compute_file_loadinsrc/app/loader.rs) is unchanged in this phase — it still dispatches toyaml_fold::detect_fold_regionsdirectly, and the plugin’s regions only take over when the plugin is enabled (existing override precedence inhandle_plugin_set_fold_regions). Retiring the built-in dispatch is a separate follow-up (issue #603 phase 2), deferred until bundled plugins have a default-enabled mechanism. Known limitation: provider routing is extension-based; extensionless scripts with a#!/bin/bashshebang won’t route to the plugin. Shebang routing is a host/protocol gap (see #605). Capability::Highlightis declared but routes to nothing. Either implement provider-driven highlighting in v3 or re-document it as reserved alongsidehover/diagnostics/definition. Not yet tracked in a dedicated issue; candidate checklist item for #481.status_facts/set_status_facts(0.18.x) resolves the protocol gap that blocked issue #606 (k8s manifest awareness): the epic’s “per-language statusbar facts” item (originally #482, merged into #602) had no protocol surface, and #606 was filed as a proposal rather than a build order for exactly that reason. The new capability is deliberately generic free text, not a structured breadcrumb — the bundledk8splugin uses it for both candidate features from #606 (resource identity and multi-doc per-kind counts) combined into one string, rather than adding a secondbreadcrumbcapability. Not yet solved: per-cursor “which resource is the viewport in right now” needs the host to send line/cursor position onon_selection_change, which the protocol still doesn’t carry — thek8splugin reports the first resource in the file instead of the one under the cursor. That’s a separate, still-open protocol gap.