@@ -62,12 +62,12 @@ export type Positional = {
6262 completion : Handler ;
6363} ;
6464
65- type Items = {
65+ type Item = {
6666 description : string ;
6767 value : string ;
6868}
6969
70- type Handler = ( previousArgs : string [ ] , toComplete : string , endsWithSpace : boolean ) => ( Items [ ] | Promise < Items [ ] > ) ;
70+ type Handler = ( previousArgs : string [ ] , toComplete : string , endsWithSpace : boolean ) => ( Item [ ] | Promise < Item [ ] > ) ;
7171
7272type Option = {
7373 description : string ;
@@ -107,7 +107,7 @@ export class Completion {
107107 async parse ( args : string [ ] , potentialCommand : string ) {
108108 const matchedCommand = this . commands . get ( potentialCommand ) ?? this . commands . get ( '' ) ! ;
109109 let directive = ShellCompDirective . ShellCompDirectiveDefault ;
110- const completions : string [ ] = [ ] ;
110+ const completions : Item [ ] = [ ] ;
111111
112112 const endsWithSpace = args [ args . length - 1 ] === "" ;
113113 if ( endsWithSpace ) {
@@ -126,7 +126,6 @@ export class Completion {
126126 completions . push (
127127 ...flagSuggestions
128128 . filter ( comp => comp . value . startsWith ( toComplete ) )
129- . map ( comp => `${ comp . value } \t${ comp . description ?? "" } ` )
130129 ) ;
131130 directive = ShellCompDirective . ShellCompDirectiveNoFileComp ;
132131 completions . forEach ( comp => console . log ( comp ) ) ;
@@ -147,9 +146,7 @@ export class Completion {
147146
148147 if ( handler ) {
149148 const suggestions = await handler ( previousArgs , valueToComplete , endsWithSpace ) ;
150- completions . push ( ...suggestions . map (
151- comp => `${ comp . value } \t${ comp . description ?? "" } `
152- ) ) ;
149+ completions . push ( ...suggestions )
153150 }
154151 } else if ( ! endsWithSpace ) {
155152 const options = new Map ( matchedCommand . options ) ;
@@ -173,36 +170,69 @@ export class Completion {
173170
174171 completions . push (
175172 ...availableFlags . map (
176- flag => ` ${ flag } \t ${ options . get ( flag ) ! . description ?? "" } `
173+ flag => ( { value : flag , description : options . get ( flag ) ! . description ?? "" } )
177174 )
178175 ) ;
179176 } else {
180177 const { handler } = matchedCommand . options . get ( toComplete ) ! ;
181178
182179 if ( handler ) {
183180 const suggestions = await handler ( previousArgs , toComplete , endsWithSpace ) ;
184- completions . push ( ...suggestions . map (
185- comp => `${ comp . value } \t${ comp . description ?? "" } `
186- ) ) ;
181+ completions . push ( ...suggestions )
187182 }
188183 }
189184 } else {
190- const availableSubcommands = [ ...this . commands . keys ( ) ]
191- . filter ( cmd => cmd . startsWith ( potentialCommand ) && cmd !== potentialCommand )
192- . map ( cmd => cmd . replace ( `${ potentialCommand } ` , "" ) . split ( " " ) [ 0 ] )
193- . filter ( ( subcmd , index , self ) => self . indexOf ( subcmd ) === index ) // Remove duplicates
194- . filter ( subcmd => subcmd . startsWith ( toComplete ) ) ;
195-
196- completions . push (
197- ...availableSubcommands . map (
198- subcmd => `${ subcmd } \t${ this . commands . get ( `${ potentialCommand } ${ subcmd } ` ) ?. description ?? "" } `
199- )
200- ) ;
185+ const potentialCommandParts = potentialCommand . split ( ' ' )
186+ for ( const [ k , v ] of this . commands ) {
187+ // if the command is root, skip it
188+ if ( k === '' ) {
189+ continue
190+ }
191+
192+ const parts = k . split ( ' ' )
193+ for ( let i = 0 ; i < parts . length ; i ++ ) {
194+ const part = parts [ i ]
195+ const potentialPart = potentialCommandParts [ i ] || ''
196+
197+ // Skip if we've already added this suggestion
198+ const alreadyExists = completions . findIndex ( item => item . value === part ) !== - 1
199+ if ( alreadyExists ) {
200+ break
201+ }
202+
203+ // If we're at the current word being completed
204+ if ( i === potentialCommandParts . length - 1 ) {
205+ // Only add if it matches the current partial input
206+ if ( part . startsWith ( potentialPart ) ) {
207+ completions . push ( { value : part , description : v . description } )
208+ }
209+ break
210+ }
211+
212+ // For previous parts, they must match exactly
213+ if ( part !== potentialPart ) {
214+ break
215+ }
216+ }
217+ }
218+ completions . push ( { value : 'dhere1' , description : '' } )
201219
202220 directive = ShellCompDirective . ShellCompDirectiveNoFileComp ;
203221 }
222+ // vite [...items]
223+ // vite dev
224+ // vite lint [item]
225+ // vite dev build
226+
227+ // TODO: prettier (plus check in ci)
228+ // TODO: ci type check
229+
230+ // TODO: positionals (tomorrow night)
231+ // TODO: cac (tomorrow night)
232+ // TODO: check behaviour of the tests (tomorrow night)
233+
204234
205- completions . forEach ( comp => console . log ( comp ) ) ;
235+ completions . forEach ( comp => console . log ( ` ${ comp . value } \t ${ comp . description ?? "" } ` ) ) ;
206236 console . log ( `:${ directive } ` ) ;
207237 }
208238}
0 commit comments