@@ -12,6 +12,38 @@ import { useTerminalDimensions } from "@opentui/solid"
1212import { Locale } from "@/util/locale"
1313import type { PromptInfo } from "./history"
1414
15+ function removeLineRange ( input : string ) {
16+ const hashIndex = input . lastIndexOf ( "#" )
17+ return hashIndex !== - 1 ? input . substring ( 0 , hashIndex ) : input
18+ }
19+
20+ function extractLineRange ( input : string ) {
21+ const hashIndex = input . lastIndexOf ( "#" )
22+ if ( hashIndex === - 1 ) {
23+ return { baseQuery : input }
24+ }
25+
26+ const baseName = input . substring ( 0 , hashIndex )
27+ const linePart = input . substring ( hashIndex + 1 )
28+ const lineMatch = linePart . match ( / ^ ( \d + ) (?: - ( \d * ) ) ? $ / )
29+
30+ if ( ! lineMatch ) {
31+ return { baseQuery : baseName }
32+ }
33+
34+ const startLine = Number ( lineMatch [ 1 ] )
35+ const endLine = lineMatch [ 2 ] && startLine < Number ( lineMatch [ 2 ] ) ? Number ( lineMatch [ 2 ] ) : undefined
36+
37+ return {
38+ lineRange : {
39+ baseName,
40+ startLine,
41+ endLine,
42+ } ,
43+ baseQuery : baseName ,
44+ }
45+ }
46+
1547export type AutocompleteRef = {
1648 onInput : ( value : string ) => void
1749 onKeyDown : ( e : KeyEvent ) => void
@@ -142,9 +174,11 @@ export function Autocomplete(props: {
142174 async ( query ) => {
143175 if ( ! store . visible || store . visible === "/" ) return [ ]
144176
177+ const { lineRange, baseQuery } = extractLineRange ( query ?? "" )
178+
145179 // Get files from SDK
146180 const result = await sdk . client . find . files ( {
147- query : query ?? "" ,
181+ query : baseQuery ,
148182 } )
149183
150184 const options : AutocompleteOption [ ] = [ ]
@@ -153,15 +187,27 @@ export function Autocomplete(props: {
153187 if ( ! result . error && result . data ) {
154188 const width = props . anchor ( ) . width - 4
155189 options . push (
156- ...result . data . map (
157- ( item ) : AutocompleteOption => ( {
158- display : Locale . truncateMiddle ( item , width ) ,
190+ ...result . data . map ( ( item ) : AutocompleteOption => {
191+ let url = `file://${ process . cwd ( ) } /${ item } `
192+ let filename = item
193+ if ( lineRange && ! item . endsWith ( "/" ) ) {
194+ filename = `${ item } #${ lineRange . startLine } ${ lineRange . endLine ? `-${ lineRange . endLine } ` : "" } `
195+ const urlObj = new URL ( url )
196+ urlObj . searchParams . set ( "start" , String ( lineRange . startLine ) )
197+ if ( lineRange . endLine !== undefined ) {
198+ urlObj . searchParams . set ( "end" , String ( lineRange . endLine ) )
199+ }
200+ url = urlObj . toString ( )
201+ }
202+
203+ return {
204+ display : Locale . truncateMiddle ( filename , width ) ,
159205 onSelect : ( ) => {
160- insertPart ( item , {
206+ insertPart ( filename , {
161207 type : "file" ,
162208 mime : "text/plain" ,
163- filename : item ,
164- url : `file:// ${ process . cwd ( ) } / ${ item } ` ,
209+ filename,
210+ url,
165211 source : {
166212 type : "file" ,
167213 text : {
@@ -173,8 +219,8 @@ export function Autocomplete(props: {
173219 } ,
174220 } )
175221 } ,
176- } ) ,
177- ) ,
222+ }
223+ } ) ,
178224 )
179225 }
180226
@@ -383,8 +429,8 @@ export function Autocomplete(props: {
383429 return prev
384430 }
385431
386- const result = fuzzysort . go ( currentFilter , mixed , {
387- keys : [ ( obj ) => obj . display . trimEnd ( ) , "description" , ( obj ) => obj . aliases ?. join ( " " ) ?? "" ] ,
432+ const result = fuzzysort . go ( removeLineRange ( currentFilter ) , mixed , {
433+ keys : [ ( obj ) => removeLineRange ( obj . display . trimEnd ( ) ) , "description" , ( obj ) => obj . aliases ?. join ( " " ) ?? "" ] ,
388434 limit : 10 ,
389435 scoreFn : ( objResults ) => {
390436 const displayResult = objResults [ 0 ]
0 commit comments