@@ -12,18 +12,22 @@ async function checkCliHasCompletions(
1212 packageManager : string
1313) : Promise < boolean > {
1414 try {
15- debugLog ( `Checking if ${ cliName } has completions via ${ packageManager } ` ) ;
16- const command = `${ packageManager } ${ cliName } complete --` ;
17- const result = execSync ( command , {
15+ const result = execSync ( `${ cliName } complete --` , {
1816 encoding : 'utf8' ,
1917 stdio : [ 'pipe' , 'pipe' , 'ignore' ] ,
2018 timeout : 1000 ,
2119 } ) ;
22- const hasCompletions = ! ! result . trim ( ) ;
23- debugLog ( `${ cliName } supports completions: ${ hasCompletions } ` ) ;
24- return hasCompletions ;
25- } catch ( error ) {
26- debugLog ( `Error checking completions for ${ cliName } :` , error ) ;
20+ if ( result . trim ( ) ) return true ;
21+ } catch { }
22+
23+ try {
24+ const result = execSync ( `${ packageManager } ${ cliName } complete --` , {
25+ encoding : 'utf8' ,
26+ stdio : [ 'pipe' , 'pipe' , 'ignore' ] ,
27+ timeout : 1000 ,
28+ } ) ;
29+ return ! ! result . trim ( ) ;
30+ } catch {
2731 return false ;
2832 }
2933}
@@ -33,24 +37,35 @@ async function getCliCompletions(
3337 packageManager : string ,
3438 args : string [ ]
3539) : Promise < string [ ] > {
40+ const completeArgs = args . map ( ( arg ) =>
41+ arg . includes ( ' ' ) ? `"${ arg } "` : arg
42+ ) ;
43+
3644 try {
37- const completeArgs = args . map ( ( arg ) =>
38- arg . includes ( ' ' ) ? `"${ arg } "` : arg
45+ const result = execSync (
46+ `${ cliName } complete -- ${ completeArgs . join ( ' ' ) } ` ,
47+ {
48+ encoding : 'utf8' ,
49+ stdio : [ 'pipe' , 'pipe' , 'ignore' ] ,
50+ timeout : 1000 ,
51+ }
3952 ) ;
40- const completeCommand = `${ packageManager } ${ cliName } complete -- ${ completeArgs . join ( ' ' ) } ` ;
41- debugLog ( `Getting completions with command: ${ completeCommand } ` ) ;
42-
43- const result = execSync ( completeCommand , {
44- encoding : 'utf8' ,
45- stdio : [ 'pipe' , 'pipe' , 'ignore' ] ,
46- timeout : 1000 ,
47- } ) ;
53+ if ( result . trim ( ) ) {
54+ return result . trim ( ) . split ( '\n' ) . filter ( Boolean ) ;
55+ }
56+ } catch { }
4857
49- const completions = result . trim ( ) . split ( '\n' ) . filter ( Boolean ) ;
50- debugLog ( `Got ${ completions . length } completions from ${ cliName } ` ) ;
51- return completions ;
52- } catch ( error ) {
53- debugLog ( `Error getting completions from ${ cliName } :` , error ) ;
58+ try {
59+ const result = execSync (
60+ `${ packageManager } ${ cliName } complete -- ${ completeArgs . join ( ' ' ) } ` ,
61+ {
62+ encoding : 'utf8' ,
63+ stdio : [ 'pipe' , 'pipe' , 'ignore' ] ,
64+ timeout : 1000 ,
65+ }
66+ ) ;
67+ return result . trim ( ) . split ( '\n' ) . filter ( Boolean ) ;
68+ } catch {
5469 return [ ] ;
5570 }
5671}
@@ -69,11 +84,18 @@ export class PackageManagerCompletion extends RootCommand {
6984 this . packageManager = packageManager ;
7085 }
7186
72- // Enhanced parse method with package manager logic
87+ private stripPackageManagerCommands ( args : string [ ] ) : string [ ] {
88+ if ( args . length === 0 ) return args ;
89+ const execCommands = [ 'exec' , 'x' , 'run' , 'dlx' ] ;
90+ if ( execCommands . includes ( args [ 0 ] ) ) return args . slice ( 1 ) ;
91+ return args ;
92+ }
93+
7394 async parse ( args : string [ ] ) {
74- // Handle package manager completions first
75- if ( args . length >= 1 && args [ 0 ] . trim ( ) !== '' ) {
76- const potentialCliName = args [ 0 ] ;
95+ const normalizedArgs = this . stripPackageManagerCommands ( args ) ;
96+
97+ if ( normalizedArgs . length >= 1 && normalizedArgs [ 0 ] . trim ( ) !== '' ) {
98+ const potentialCliName = normalizedArgs [ 0 ] ;
7799 const knownCommands = [ ...this . commands . keys ( ) ] ;
78100
79101 if ( ! knownCommands . includes ( potentialCliName ) ) {
@@ -83,33 +105,33 @@ export class PackageManagerCompletion extends RootCommand {
83105 ) ;
84106
85107 if ( hasCompletions ) {
86- const cliArgs = args . slice ( 1 ) ;
108+ const cliArgs = normalizedArgs . slice ( 1 ) ;
87109 const suggestions = await getCliCompletions (
88110 potentialCliName ,
89111 this . packageManager ,
90112 cliArgs
91113 ) ;
92114
93115 if ( suggestions . length > 0 ) {
94- // Print completions directly in the same format as the core library
116+ debugLog (
117+ `Returning ${ suggestions . length } completions for ${ potentialCliName } `
118+ ) ;
95119 for ( const suggestion of suggestions ) {
96120 if ( suggestion . startsWith ( ':' ) ) continue ;
97-
98121 if ( suggestion . includes ( '\t' ) ) {
99122 const [ value , description ] = suggestion . split ( '\t' ) ;
100123 console . log ( `${ value } \t${ description } ` ) ;
101124 } else {
102125 console . log ( suggestion ) ;
103126 }
104127 }
105- console . log ( ':4' ) ; // Shell completion directive (NoFileComp)
128+ console . log ( ':4' ) ;
106129 return ;
107130 }
108131 }
109132 }
110133 }
111134
112- // Fall back to regular completion logic (shows basic package manager commands)
113135 return super . parse ( args ) ;
114136 }
115137}
0 commit comments