Skip to content

Commit 3e0dc95

Browse files
committed
fix(cli): make @-menu show anywhere in the user input
1 parent 6454604 commit 3e0dc95

File tree

2 files changed

+19
-8
lines changed

2 files changed

+19
-8
lines changed

cli/src/chat.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ export const Chat = ({
370370
fileSuggestionItems,
371371
} = useSuggestionEngine({
372372
inputValue,
373+
cursorPosition,
373374
slashCommands: SLASH_COMMANDS,
374375
localAgents,
375376
fileTree,

cli/src/hooks/use-suggestion-engine.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,27 +34,35 @@ const parseSlashContext = (input: string): TriggerContext => {
3434
return { active: true, query: commandSegment, startIndex }
3535
}
3636

37-
const parseMentionContext = (input: string): TriggerContext => {
37+
const parseMentionContext = (input: string, cursorPosition: number): TriggerContext => {
3838
if (!input) {
3939
return { active: false, query: '', startIndex: -1 }
4040
}
4141

4242
const lastNewline = input.lastIndexOf('\n')
4343
const lineStart = lastNewline === -1 ? 0 : lastNewline + 1
44-
const line = input.slice(lineStart)
44+
45+
// Only look at text up to cursor position to find the relevant @
46+
const textUpToCursor = input.slice(0, cursorPosition)
47+
const lineUpToCursor = textUpToCursor.slice(lineStart)
4548

46-
const atIndex = line.lastIndexOf('@')
49+
const atIndex = lineUpToCursor.lastIndexOf('@')
4750
if (atIndex === -1) {
4851
return { active: false, query: '', startIndex: -1 }
4952
}
5053

51-
const beforeChar = atIndex > 0 ? line[atIndex - 1] : ''
54+
const beforeChar = atIndex > 0 ? lineUpToCursor[atIndex - 1] : ''
5255
if (beforeChar && !/\s/.test(beforeChar)) {
5356
return { active: false, query: '', startIndex: -1 }
5457
}
5558

56-
const query = line.slice(atIndex + 1)
57-
if (query.includes(' ') || query.includes('\t')) {
59+
// Extract query from @ until the next whitespace or cursor position
60+
const afterAt = lineUpToCursor.slice(atIndex + 1)
61+
const firstSpaceIndex = afterAt.search(/\s/)
62+
const query = firstSpaceIndex === -1 ? afterAt : afterAt.slice(0, firstSpaceIndex)
63+
64+
// If we found a space in the query, the mention is complete - don't show menu
65+
if (firstSpaceIndex !== -1) {
5866
return { active: false, query: '', startIndex: -1 }
5967
}
6068

@@ -372,13 +380,15 @@ export interface SuggestionEngineResult {
372380

373381
interface SuggestionEngineOptions {
374382
inputValue: string
383+
cursorPosition: number
375384
slashCommands: SlashCommand[]
376385
localAgents: LocalAgentInfo[]
377386
fileTree: FileTreeNode[]
378387
}
379388

380389
export const useSuggestionEngine = ({
381390
inputValue,
391+
cursorPosition,
382392
slashCommands,
383393
localAgents,
384394
fileTree,
@@ -412,8 +422,8 @@ export const useSuggestionEngine = ({
412422
)
413423

414424
const mentionContext = useMemo(
415-
() => parseMentionContext(deferredInput),
416-
[deferredInput],
425+
() => parseMentionContext(deferredInput, cursorPosition),
426+
[deferredInput, cursorPosition],
417427
)
418428

419429
const slashMatches = useMemo<MatchedSlashCommand[]>(() => {

0 commit comments

Comments
 (0)