@@ -21,8 +21,8 @@ export type ComposerPromptSegment =
2121 context : TerminalContextDraft | null ;
2222 } ;
2323
24- const MENTION_TOKEN_REGEX = / ( ^ | \s ) @ ( [ ^ \s @ ] + ) (? = \s ) / g;
2524const SKILL_TOKEN_REGEX = / ( ^ | \s ) \$ ( [ a - z A - Z ] [ a - z A - Z 0 - 9 : _ - ] * ) (? = \s ) / g;
25+ const MENTION_TOKEN_REGEX = / ( ^ | \s ) @ (?: " ( (?: \\ .| [ ^ " \\ ] ) * ) " | ( [ ^ \s @ " ] + ) ) (? = \s ) / g;
2626
2727function rangeIncludesIndex ( start : number , end : number , index : number ) : boolean {
2828 return start <= index && index < end ;
@@ -52,13 +52,18 @@ type InlineTokenMatch =
5252 end : number ;
5353 } ;
5454
55- function collectInlineTokenMatches ( text : string ) : InlineTokenMatch [ ] {
56- const matches : InlineTokenMatch [ ] = [ ] ;
55+ type MentionTokenMatch = Extract < InlineTokenMatch , { type : "mention" } > ;
56+
57+ function collectMentionTokenMatches ( text : string ) : MentionTokenMatch [ ] {
58+ const matches : MentionTokenMatch [ ] = [ ] ;
5759
5860 for ( const match of text . matchAll ( MENTION_TOKEN_REGEX ) ) {
5961 const fullMatch = match [ 0 ] ;
6062 const prefix = match [ 1 ] ?? "" ;
61- const path = match [ 2 ] ?? "" ;
63+ const quotedPath = match [ 2 ] ;
64+ const unquotedPath = match [ 3 ] ;
65+ const path =
66+ quotedPath !== undefined ? quotedPath . replace ( / \\ ( .) / g, "$1" ) : ( unquotedPath ?? "" ) ;
6267 const matchIndex = match . index ?? 0 ;
6368 const start = matchIndex + prefix . length ;
6469 const end = start + fullMatch . length - prefix . length ;
@@ -67,6 +72,12 @@ function collectInlineTokenMatches(text: string): InlineTokenMatch[] {
6772 }
6873 }
6974
75+ return matches ;
76+ }
77+
78+ function collectInlineTokenMatches ( text : string ) : InlineTokenMatch [ ] {
79+ const matches : InlineTokenMatch [ ] = collectMentionTokenMatches ( text ) ;
80+
7081 for ( const match of text . matchAll ( SKILL_TOKEN_REGEX ) ) {
7182 const fullMatch = match [ 0 ] ;
7283 const prefix = match [ 1 ] ?? "" ;
@@ -148,10 +159,10 @@ function forEachPromptTextSlice(
148159
149160function forEachMentionMatch (
150161 prompt : string ,
151- visitor : ( match : RegExpMatchArray , promptOffset : number ) => boolean | void ,
162+ visitor : ( match : MentionTokenMatch , promptOffset : number ) => boolean | void ,
152163) : boolean {
153164 return forEachPromptTextSlice ( prompt , ( text , promptOffset ) => {
154- for ( const match of text . matchAll ( MENTION_TOKEN_REGEX ) ) {
165+ for ( const match of collectMentionTokenMatches ( text ) ) {
155166 if ( visitor ( match , promptOffset ) === true ) {
156167 return true ;
157168 }
@@ -203,11 +214,8 @@ export function selectionTouchesMentionBoundary(
203214 }
204215
205216 return forEachMentionMatch ( prompt , ( match , promptOffset ) => {
206- const fullMatch = match [ 0 ] ;
207- const prefix = match [ 1 ] ?? "" ;
208- const matchIndex = match . index ?? 0 ;
209- const mentionStart = promptOffset + matchIndex + prefix . length ;
210- const mentionEnd = mentionStart + fullMatch . length - prefix . length ;
217+ const mentionStart = promptOffset + match . start ;
218+ const mentionEnd = promptOffset + match . end ;
211219 const beforeMentionIndex = mentionStart - 1 ;
212220 const afterMentionIndex = mentionEnd ;
213221
0 commit comments