@@ -11,6 +11,42 @@ import { useCommandDialog } from "@tui/component/dialog-command"
1111import { Locale } from "@/util/locale"
1212import type { PromptInfo } from "./history"
1313
14+ function removeLineRange ( input : string ) {
15+ const colonIndex = input . lastIndexOf ( ":" )
16+ return colonIndex !== - 1 ? input . substring ( 0 , colonIndex ) : input
17+ }
18+
19+ function extractLineRange ( input : string ) {
20+ const colonIndex = input . lastIndexOf ( ":" )
21+ if ( colonIndex === - 1 ) {
22+ return { baseQuery : input }
23+ }
24+
25+ const baseName = input . substring ( 0 , colonIndex )
26+ const linePart = input . substring ( colonIndex + 1 )
27+ const lineMatch = linePart . match ( / ^ ( \d + ) (?: - ( \d + ) ) ? $ / )
28+
29+ if ( ! lineMatch ) {
30+ return { baseQuery : baseName }
31+ }
32+
33+ const startLine = Number ( lineMatch [ 1 ] )
34+ const endLine = lineMatch [ 2 ] ? Number ( lineMatch [ 2 ] ) : undefined
35+
36+ if ( endLine !== undefined && startLine > endLine ) {
37+ return { baseQuery : baseName }
38+ }
39+
40+ return {
41+ lineRange : {
42+ baseName,
43+ startLine,
44+ endLine,
45+ } ,
46+ baseQuery : baseName ,
47+ }
48+ }
49+
1450export type AutocompleteRef = {
1551 onInput : ( value : string ) => void
1652 onKeyDown : ( e : KeyEvent ) => void
@@ -107,10 +143,12 @@ export function Autocomplete(props: {
107143 async ( query ) => {
108144 if ( ! store . visible || store . visible === "/" ) return [ ]
109145
146+ const { lineRange, baseQuery } = extractLineRange ( query ?? "" )
147+
110148 // Get files from SDK
111149 const result = await sdk . client . find . files ( {
112150 query : {
113- query : query ?? "" ,
151+ query : baseQuery ,
114152 } ,
115153 } )
116154
@@ -120,15 +158,27 @@ export function Autocomplete(props: {
120158 if ( ! result . error && result . data ) {
121159 const width = store . position . width - 4
122160 options . push (
123- ...result . data . map (
124- ( item ) : AutocompleteOption => ( {
125- display : Locale . truncateMiddle ( item , width ) ,
161+ ...result . data . map ( ( item ) : AutocompleteOption => {
162+ let url = `file://${ process . cwd ( ) } /${ item } `
163+ let filename = item
164+ if ( lineRange && ! item . endsWith ( "/" ) ) {
165+ filename = `${ item } :${ lineRange . startLine } ${ lineRange . endLine ? `-${ lineRange . endLine } ` : "" } `
166+ const urlObj = new URL ( url )
167+ urlObj . searchParams . set ( "start" , String ( lineRange . startLine ) )
168+ if ( lineRange . endLine !== undefined ) {
169+ urlObj . searchParams . set ( "end" , String ( lineRange . endLine ) )
170+ }
171+ url = urlObj . toString ( )
172+ }
173+
174+ return {
175+ display : Locale . truncateMiddle ( filename , width ) ,
126176 onSelect : ( ) => {
127- insertPart ( item , {
177+ insertPart ( filename , {
128178 type : "file" ,
129179 mime : "text/plain" ,
130- filename : item ,
131- url : `file:// ${ process . cwd ( ) } / ${ item } ` ,
180+ filename,
181+ url,
132182 source : {
133183 type : "file" ,
134184 text : {
@@ -140,8 +190,8 @@ export function Autocomplete(props: {
140190 } ,
141191 } )
142192 } ,
143- } ) ,
144- ) ,
193+ }
194+ } ) ,
145195 )
146196 }
147197
@@ -328,8 +378,8 @@ export function Autocomplete(props: {
328378 ) . filter ( ( x ) => x . disabled !== true )
329379 const currentFilter = filter ( )
330380 if ( ! currentFilter ) return mixed . slice ( 0 , 10 )
331- const result = fuzzysort . go ( currentFilter , mixed , {
332- keys : [ ( obj ) => obj . display . trimEnd ( ) , "description" , ( obj ) => obj . aliases ?. join ( " " ) ?? "" ] ,
381+ const result = fuzzysort . go ( removeLineRange ( currentFilter ) , mixed , {
382+ keys : [ ( obj ) => removeLineRange ( obj . display . trimEnd ( ) ) , "description" , ( obj ) => obj . aliases ?. join ( " " ) ?? "" ] ,
333383 limit : 10 ,
334384 } )
335385 return result . map ( ( arr ) => arr . obj )
0 commit comments