Completion engine with pluggable sources, layered candidate management, and support for AI-assisted secondary completions.
The engine maintains two completion layers:
Primary (layer 1): traditional candidates populated by the
provider's search() method (e.g. filesystem paths, commands).
Secondary (layer 2): auxiliary candidates populated by the
provider's search_secondary() method (e.g. CALM / AI ghost text).
All public methods without a secondary_ prefix operate on the
primary layer. Secondary-layer methods use the secondary_ prefix.
Each completion source must export a new() constructor that returns
a table implementing:
search(query, ...) — required; return array of candidate strings
update() — optional; refresh cached data (called on init and
via completion:update())
close() — optional; release resources (called on unregister
and via completion:close())
Metadata is a table indexed by candidate position (1-based). Common fields used by existing providers:
source (string) — identifies the completion source for TSS
styling (e.g. "bin", "fs", "lua_symbol")
Shell-specific fields (handled by the shell provider's promote()):
replace_prompt (string) — replace entire line with this prefix
plus the promoted candidate
exec_on_prom (bool) — execute immediately after promotion
trim_promotion (bool) — strip leading whitespace from candidate
reduce_spaces (bool) — collapse multiple spaces in candidate
| Name | Signature |
|---|---|
completion:flush | completion:flush() |
completion:available | completion:available() -> has_candidates |
completion:count | completion:count() -> n |
completion:chosen_index | completion:chosen_index() -> idx |
completion:set_chosen_index | completion:set_chosen_index(idx) |
completion:meta_at | completion:meta_at(idx) -> metadata |
completion:source | completion:source(name) -> src |
completion:get | completion:get(promoted) -> candidate |
completion:common_prefix | completion:common_prefix() -> prefix |
completion:update | completion:update() |
completion:register_source | completion:register_source(name, src) |
completion:unregister_source | completion:unregister_source(name) |
completion:close | completion:close() |
completion:provide | completion:provide(candidates) |
completion:set_meta | completion:set_meta(metadata) |
completion:secondary_set | completion:secondary_set(results) |
completion:secondary_set_ghost | completion:secondary_set_ghost(text) |
completion:secondary_text | completion:secondary_text() -> text |
completion:secondary_count | completion:secondary_count() -> n |
completion:secondary_scroll | completion:secondary_scroll(direction) -> scrolled |
completion:secondary_flush | completion:secondary_flush() |
completion:refresh_secondary | completion:refresh_secondary(input, history) |
new | new(config) -> completion, err |
completion:flush()
Clear all layers and reset selection
completion:available() ->
has_candidates
Check whether primary candidates are available
completion:count() ->
n
Return the number of primary candidates
completion:chosen_index() ->
idx
Return the index of the currently selected primary candidate
completion:set_chosen_index(
idx)
Set the index of the currently selected primary candidate
completion:meta_at(
idx) ->metadata
Return metadata for the primary candidate at the given index
completion:source(
name) ->src
Return a registered completion source by name
completion:get(
promoted) ->candidate
Get the currently selected primary candidate string
When promoted is true, returns the raw candidate string.
Otherwise returns the candidate styled for inline display.
When config.tss was provided at construction, styling uses the
theme-subscribed TSS keyed by the candidate's source metadata.
completion:common_prefix() ->
prefix
Compute the longest common prefix across all primary candidates
completion:update()
Trigger update on all registered completion sources
completion:register_source(
name,src)
Register a completion source at runtime
completion:unregister_source(
name)
Unregister a completion source, calling close() if available
completion:close()
Close all sources and clean up
completion:provide(
candidates)
Replace the primary candidate list
completion:set_meta(
metadata)
Replace the metadata table for primary candidates
completion:secondary_set(
results)
Set secondary layer candidates
results is an array of {text = ..., score = ...} tables, or nil
to clear the secondary layer.
completion:secondary_set_ghost(
text)
Set a single ghost text on the secondary layer
completion:secondary_text() ->
text
Get current secondary candidate text
completion:secondary_count() ->
n
Return the number of secondary candidates
completion:secondary_scroll(
direction) ->scrolled
Scroll through secondary candidates
Direction is "up" or "down". Wraps cyclically.
completion:secondary_flush()
Clear only the secondary layer
completion:refresh_secondary(
input,history)
Re-trigger secondary search if the provider supports it
new(
config) ->completion,err
Create a new completion instance from a config table
The config table must contain:
path — module path for the completion search provider
sources — optional list of module paths for completion sources
Each source module must export a new() constructor.
The module at config.path must return a table with at least search
and optionally the methods listed below. All provider methods are
injected directly onto the completion object, so inside them self
refers to the completion instance — giving access to self:source(),
self:provide(), self:set_meta(), etc.
Required:
search(self, input, history, cursor_pos) -> bool
Populate primary-layer candidates for the given input line. Call
self:provide() and self:set_meta() inside. When the input
object has eol_only = false, a numeric cursor_pos is passed
so the provider can complete at any position in the line.
Optional:
search_secondary(self, input, history) -> bool
Populate secondary-layer candidates (e.g. CALM / AI ghost text).
Call self:secondary_set() inside.
get(self, promoted) -> string
Return the current primary candidate. When promoted is true,
return raw text; otherwise return styled text for inline display.
If absent a default implementation using a built-in TSS rule is
used.
promote(self, candidate, metadata, line) -> {line=, action=}
Apply candidate to line and return the resulting line. Set
action = "execute" to trigger immediate execution. If absent, the
default behaviour is to append the candidate to the line.
should_promote_full(self) -> bool
Return true when the current candidate must skip common-prefix
narrowing and be promoted in full (e.g. line-replacement
completions).
should_auto_promote(self) -> bool
Return true when ENTER should auto-promote the current candidate
instead of submitting the line as-is.