Skip to content

Commit 53eb62a

Browse files
committed
replace entire input with suggestion
1 parent 6902c54 commit 53eb62a

File tree

2 files changed

+57
-44
lines changed

2 files changed

+57
-44
lines changed

cli/src/state/atoms/__tests__/keyboard.test.ts

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,11 +354,63 @@ describe("keypress atoms", () => {
354354
}
355355
store.set(keyboardHandlerAtom, tabKey)
356356

357-
// Should append only 'de' to complete '/mode'
357+
// Should complete to '/mode'
358358
const text = store.get(textBufferStringAtom)
359359
expect(text).toBe("/mode")
360360
})
361361

362+
it("should complete command even when user types wrong letters", () => {
363+
// Type '/modl' - typo, but 'model' should still be suggested
364+
const chars = ["/", "m", "o", "d", "l"]
365+
for (const char of chars) {
366+
const key: Key = {
367+
name: char,
368+
sequence: char,
369+
ctrl: false,
370+
meta: false,
371+
shift: false,
372+
paste: false,
373+
}
374+
store.set(keyboardHandlerAtom, key)
375+
}
376+
377+
// Autocomplete should now be visible
378+
expect(store.get(showAutocompleteAtom)).toBe(true)
379+
380+
// Set up autocomplete suggestions
381+
const mockCommand: Command = {
382+
name: "model",
383+
description: "Manage models",
384+
aliases: [],
385+
usage: "/model <subcommand>",
386+
examples: ["/model info"],
387+
category: "settings",
388+
handler: vi.fn(),
389+
}
390+
const mockSuggestion: CommandSuggestion = {
391+
command: mockCommand,
392+
matchScore: 70,
393+
highlightedName: "model",
394+
}
395+
store.set(suggestionsAtom, [mockSuggestion])
396+
store.set(selectedIndexAtom, 0)
397+
398+
// Press Tab
399+
const tabKey: Key = {
400+
name: "tab",
401+
sequence: "\t",
402+
ctrl: false,
403+
meta: false,
404+
shift: false,
405+
paste: false,
406+
}
407+
store.set(keyboardHandlerAtom, tabKey)
408+
409+
// Should replace '/modl' with '/model' (not '/modlmodel')
410+
const text = store.get(textBufferStringAtom)
411+
expect(text).toBe("/model")
412+
})
413+
362414
it("should complete argument by replacing partial text", () => {
363415
// Type '/mode tes' - this will automatically trigger autocomplete
364416
const input = "/mode tes"

cli/src/state/atoms/keyboard.ts

Lines changed: 4 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -307,38 +307,6 @@ export const submitInputAtom = atom(null, (get, set, text: string | Buffer) => {
307307
// Keyboard Handler System
308308
// ============================================================================
309309

310-
/**
311-
* Helper function to get the completion text (only the missing part to append)
312-
*/
313-
function getCompletionText(currentInput: string, suggestion: CommandSuggestion | ArgumentSuggestion): string {
314-
if ("command" in suggestion) {
315-
// CommandSuggestion - complete the command name
316-
const commandName = suggestion.command.name
317-
const currentText = currentInput.startsWith("/") ? currentInput.slice(1) : currentInput
318-
319-
// If the command name starts with what user typed, return only the missing part
320-
if (commandName.toLowerCase().startsWith(currentText.toLowerCase())) {
321-
return commandName.slice(currentText.length)
322-
}
323-
324-
// Otherwise return the full command (shouldn't happen in normal flow)
325-
return commandName
326-
} else {
327-
// ArgumentSuggestion - complete the last argument
328-
const parts = currentInput.split(" ")
329-
const lastPart = parts[parts.length - 1] || ""
330-
const suggestionValue = suggestion.value
331-
332-
// If suggestion starts with what user typed, return only the missing part
333-
if (suggestionValue.toLowerCase().startsWith(lastPart.toLowerCase())) {
334-
return suggestionValue.slice(lastPart.length)
335-
}
336-
337-
// Otherwise return the full value
338-
return suggestionValue
339-
}
340-
}
341-
342310
/**
343311
* Helper function to format autocomplete suggestions for display/submission
344312
*/
@@ -487,17 +455,10 @@ function handleAutocompleteKeys(get: any, set: any, key: Key): void {
487455
const suggestion = allSuggestions[selectedIndex]
488456
const currentText = get(textBufferStringAtom)
489457

490-
// For argument suggestions, replace the entire input with formatted suggestion
491-
// For command suggestions, append the completion text
492-
if ("command" in suggestion) {
493-
// CommandSuggestion - append only the missing part
494-
const completionText = getCompletionText(currentText, suggestion)
495-
set(insertTextAtom, completionText)
496-
} else {
497-
// ArgumentSuggestion - replace entire input to avoid duplication
498-
const newText = formatSuggestion(suggestion, currentText)
499-
set(setTextAtom, newText)
500-
}
458+
// Always replace the entire input with formatted suggestion
459+
// This handles both commands and arguments correctly
460+
const newText = formatSuggestion(suggestion, currentText)
461+
set(setTextAtom, newText)
501462
}
502463
return
503464

0 commit comments

Comments
 (0)