pub struct PartialParse<'a> {
pub completed: Vec<&'a str>,
pub partial: &'a str,
pub tree_path: Vec<&'a str>,
pub raw_line: &'a str,
pub cursor_offset: usize,
pub tap_count: u32,
}Expand description
Structured snapshot of the partial command-line state at the
cursor position. Passed to subtree providers so they can offer
context-aware completions without re-tokenising COMP_LINE.
Carries both the whitespace-tokenised view (completed,
partial, tree_path — the same shape every veks-completion
flow uses) AND the raw line + cursor offset that grammar-aware
providers (e.g. for embedded query DSLs like MetricsQL or PromQL)
need to resolve quote / bracket / operator state. Callers that
don’t have raw context populate raw_line with an empty string
and cursor_offset with 0 — grammar helpers fall back to the
tokenised view in that case.
Fields§
§completed: Vec<&'a str>Words the user has already completed (whitespace-separated, program name excluded).
partial: &'a strThe partial word currently under the cursor (may be empty).
tree_path: Vec<&'a str>Path through the command tree that resolved against
completed. Same shape as completed but only the prefix
that maps to actual nodes.
raw_line: &'a strRaw COMP_LINE (or equivalent) — the full command line as
the user typed it, before any tokenisation. Empty when the
caller didn’t have it.
cursor_offset: usizeByte offset of the cursor within raw_line. 0 when
raw_line is empty.
tap_count: u32Tap count for this completion invocation. The engine sets
this from the rotating-tier counter (1 on the first tap,
2 on a rapid follow-up, etc.). Providers may use it to
layer their output — e.g., tap 1 = primary candidates
(metric names inside a function-arg position), tap 2 = +
secondary candidates (inner functions to stack). Defaults
to 1 for callers that don’t drive rotation.
Implementations§
Source§impl<'a> PartialParse<'a>
impl<'a> PartialParse<'a>
Sourcepub const DEFAULT_BASH_WORDBREAKS: &'static str = " \t\n<>;|&"
pub const DEFAULT_BASH_WORDBREAKS: &'static str = " \t\n<>;|&"
COMP_WORDBREAKS value that the engine’s bash hook
installs locally — a deliberately minimal set that keeps
shell metacharacters as word separators (< > ; | &) but
drops everything bash would otherwise use to “helpfully”
split inside a grammar token: ' " (shell wrapper quotes),
= (key=value), ( (function-call open), : (label
values, subquery step). With these out of the way:
'metricsql expris one word → readline doesn’t auto-close the wrapper quote when our candidate ends mid-context (e.g.delta().up{job=is one word → label-value candidates splice cleanly without prefix gymnastics.delta(rate(is one word → nested function-call completions work without the shell mid-quoting.
This is the bash-side “raw mode” the engine relies on so
shell-quoting heuristics don’t fight grammar-aware splicing.
The hook sets it locally per call so the user’s interactive
COMP_WORDBREAKS is untouched outside completion.
{, [, ], }, , were already not in bash’s default
set — they don’t split the word in bash, which is what makes
PartialParse::splice_candidate necessary in the first
place. We additionally strip ' " = ( : to extend the same
“splicer owns this” treatment to those grammar contexts.
Sourcepub fn before_cursor(&self) -> &'a str
pub fn before_cursor(&self) -> &'a str
Slice of raw_line strictly before the cursor. Empty when
raw_line is empty.
Sourcepub fn after_cursor(&self) -> &'a str
pub fn after_cursor(&self) -> &'a str
Slice of raw_line from the cursor to the end.
Sourcepub fn bracket_state(&self) -> BracketState
pub fn bracket_state(&self) -> BracketState
Compute the bracket / quote state at the cursor by linearly
scanning before_cursor. Honors quotes (everything inside
"…" or '…' is counted as string content, brackets within
don’t shift the depth) and supports backslash-escapes inside
quotes.
When raw_line is empty (caller didn’t supply it), returns
the default zero-depth state.
Sourcepub fn trigger_char(&self) -> Option<char>
pub fn trigger_char(&self) -> Option<char>
Last non-whitespace, non-identifier character before the
cursor, scanning back over identifier characters first.
Useful for “what symbol triggered this completion?” — e.g.,
= after label means we’re in a label-value position.
Returns None if the only thing before the cursor is
identifier characters or whitespace.
Sourcepub fn shell_word_start(&self) -> usize
pub fn shell_word_start(&self) -> usize
Byte offset in Self::raw_line where the shell will
consider the “current word” to begin — the byte after the
last word-separator character before the cursor, or 0 if
none. Falls back to 0 when raw_line is empty.
Today this assumes bash semantics
(Self::DEFAULT_BASH_WORDBREAKS). When other shells gain
first-class support, this method may take a per-shell
wordbreak set.
Sourcepub fn shell_current_word(&self) -> &'a str
pub fn shell_current_word(&self) -> &'a str
What the shell sees as the “current word” — the slice
between Self::shell_word_start and the cursor. This is
the segment the shell will replace when the user accepts
a candidate the engine returns.
Sourcepub fn splice_candidate(&self, target_start: usize, suggestion: &str) -> String
pub fn splice_candidate(&self, target_start: usize, suggestion: &str) -> String
Splice a logical suggestion into the shell-correct form
for a COMPREPLY candidate. Providers compute suggestions in
their own grammar terms (e.g. “the label key is job”);
this helper produces the substitution string the shell
needs so that whatever the user already typed in the
shell-perceived current word, before the suggestion’s
insertion point, is preserved.
target_start is the byte offset in Self::raw_line
where the suggestion logically begins. For an inside-{
label-key suggestion in up{job, target_start is the
position right after the {. The helper returns
raw_line[shell_word_start..target_start] + suggestion —
i.e., the part of the shell’s current word that’s BEFORE
the completion target, plus the new content.
When target_start <= shell_word_start, the suggestion
replaces the entire shell word (or starts before it), so
the helper returns the suggestion unchanged.
§Example
use veks_completion::PartialParse;
let pp = PartialParse {
completed: vec![],
partial: "",
tree_path: vec![],
raw_line: "myapp query up{",
cursor_offset: 15,
tap_count: 1,
};
assert_eq!(pp.shell_word_start(), 12); // after the last space
assert_eq!(pp.shell_current_word(), "up{"); // shell will replace this
// Suggestion: the label key `job`. Logically it starts
// right after the `{` (byte 15).
let candidate = pp.splice_candidate(15, "job");
assert_eq!(candidate, "up{job");
// → shell replaces "up{" with "up{job" ⇒ final word "up{job"Sourcepub fn ident_before_cursor(&self) -> &'a str
pub fn ident_before_cursor(&self) -> &'a str
Identifier (or partial identifier) immediately to the left
of the cursor. For input up{job=, returns "" (cursor is
right after =, so the partial-ident before the cursor is
empty). For input up{jo, returns "jo".
Trait Implementations§
Source§impl<'a> Clone for PartialParse<'a>
impl<'a> Clone for PartialParse<'a>
Source§fn clone(&self) -> PartialParse<'a>
fn clone(&self) -> PartialParse<'a>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more