ADR-0022 stage 8 follow-up r2: completion UX fixes from real testing
Two concrete behaviour changes from the user's second testing
round:
1. **Single vs multi commit paths.** Previously every Tab,
even single-candidate, created a memo so Esc/Backspace could
undo. The downside: with one candidate, repeated Tab "cycled"
through the same item invisibly — looked stuck. Now:
- Single candidate → insert with trailing space, no memo.
The user can keep typing or hit Tab again to fresh-complete
at the new cursor. (Trade-off: Esc/Backspace no longer
whole-span undo for unique completions; the user accepted
this for the chained-Tab fluency.)
- Multi candidate → insert WITHOUT trailing space, create
memo for cycling. The natural commit gesture is space —
pressing it clears the memo and inserts the space normally,
producing "<chosen> " ready for the next position.
The "stuck on unique" symptom goes away, and the missing
trailing space on multi-Tab signals "you're picking; press
space when you're done" without needing modal affordances.
2. **Keyword candidates in grammar order.** Dropped the
alphabetical sort in `describe_expected` in favour of
chumsky's native source-order traversal of `or_not`/`choice`
chains — empirically this matches the canonical command
shape. Result: `add column ` now offers `to` before
`table` (as `add column [to] [table] <Table>:…` reads),
not `table` before `to` which previously suggested the
nonsensical `add column table to ...`. Identifiers still
alphabetised within their group; entry-keyword fallback
for the no-prefix case stays alphabetical (no source order
when 10 separate command branches).
Tests: 750 passing, 0 failing, 1 ignored (747 baseline →
+3 net: replaced single-candidate Esc/Backspace tests with
new multi-candidate variants; added the unique-Tab-chains-
naturally case that drove the round-2 fix; kept the
keywords-in-grammar-order test updated to assert
`to`/`table`/identifiers ordering).
This commit is contained in:
+8
-2
@@ -765,8 +765,14 @@ fn describe_expected(expected: &[RichPattern<'_, Token>]) -> Vec<String> {
|
||||
})
|
||||
.map(describe_pattern)
|
||||
.collect();
|
||||
items.sort();
|
||||
items.dedup();
|
||||
// Dedup preserving first occurrence (which reflects
|
||||
// chumsky's traversal order — typically source order for
|
||||
// `or_not` / `choice` chains). Empirically this gives a
|
||||
// grammar-natural ordering: `to` before `table` in
|
||||
// `add column [to] [table] …`, which alphabetical
|
||||
// (table, to) would invert.
|
||||
let mut seen = std::collections::HashSet::new();
|
||||
items.retain(|s| seen.insert(s.clone()));
|
||||
items
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user