@@ -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,29 @@ async function getCliCompletions(
3337 packageManager : string ,
3438 args : string [ ]
3539) : Promise < string [ ] > {
36- try {
37- const completeArgs = args . map ( ( arg ) =>
38- arg . includes ( ' ' ) ? `"${ arg } "` : arg
39- ) ;
40- const completeCommand = `${ packageManager } ${ cliName } complete -- ${ completeArgs . join ( ' ' ) } ` ;
41- debugLog ( `Getting completions with command: ${ completeCommand } ` ) ;
40+ const completeArgs = args . map ( ( arg ) =>
41+ arg . includes ( ' ' ) ? `"${ arg } "` : arg
42+ ) ;
4243
43- const result = execSync ( completeCommand , {
44+ try {
45+ const result = execSync ( `${ cliName } complete -- ${ completeArgs . join ( ' ' ) } ` , {
4446 encoding : 'utf8' ,
4547 stdio : [ 'pipe' , 'pipe' , 'ignore' ] ,
4648 timeout : 1000 ,
4749 } ) ;
50+ if ( result . trim ( ) ) {
51+ return result . trim ( ) . split ( '\n' ) . filter ( Boolean ) ;
52+ }
53+ } catch { }
4854
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 ) ;
55+ try {
56+ const result = execSync ( `${ packageManager } ${ cliName } complete -- ${ completeArgs . join ( ' ' ) } ` , {
57+ encoding : 'utf8' ,
58+ stdio : [ 'pipe' , 'pipe' , 'ignore' ] ,
59+ timeout : 1000 ,
60+ } ) ;
61+ return result . trim ( ) . split ( '\n' ) . filter ( Boolean ) ;
62+ } catch {
5463 return [ ] ;
5564 }
5665}
@@ -69,11 +78,18 @@ export class PackageManagerCompletion extends RootCommand {
6978 this . packageManager = packageManager ;
7079 }
7180
72- // Enhanced parse method with package manager logic
81+ private stripPackageManagerCommands ( args : string [ ] ) : string [ ] {
82+ if ( args . length === 0 ) return args ;
83+ const execCommands = [ 'exec' , 'x' , 'run' , 'dlx' ] ;
84+ if ( execCommands . includes ( args [ 0 ] ) ) return args . slice ( 1 ) ;
85+ return args ;
86+ }
87+
7388 async parse ( args : string [ ] ) {
74- // Handle package manager completions first
75- if ( args . length >= 1 && args [ 0 ] . trim ( ) !== '' ) {
76- const potentialCliName = args [ 0 ] ;
89+ const normalizedArgs = this . stripPackageManagerCommands ( args ) ;
90+
91+ if ( normalizedArgs . length >= 1 && normalizedArgs [ 0 ] . trim ( ) !== '' ) {
92+ const potentialCliName = normalizedArgs [ 0 ] ;
7793 const knownCommands = [ ...this . commands . keys ( ) ] ;
7894
7995 if ( ! knownCommands . includes ( potentialCliName ) ) {
@@ -83,33 +99,31 @@ export class PackageManagerCompletion extends RootCommand {
8399 ) ;
84100
85101 if ( hasCompletions ) {
86- const cliArgs = args . slice ( 1 ) ;
102+ const cliArgs = normalizedArgs . slice ( 1 ) ;
87103 const suggestions = await getCliCompletions (
88104 potentialCliName ,
89105 this . packageManager ,
90106 cliArgs
91107 ) ;
92108
93109 if ( suggestions . length > 0 ) {
94- // Print completions directly in the same format as the core library
110+ debugLog ( `Returning ${ suggestions . length } completions for ${ potentialCliName } ` ) ;
95111 for ( const suggestion of suggestions ) {
96112 if ( suggestion . startsWith ( ':' ) ) continue ;
97-
98113 if ( suggestion . includes ( '\t' ) ) {
99114 const [ value , description ] = suggestion . split ( '\t' ) ;
100115 console . log ( `${ value } \t${ description } ` ) ;
101116 } else {
102117 console . log ( suggestion ) ;
103118 }
104119 }
105- console . log ( ':4' ) ; // Shell completion directive (NoFileComp)
120+ console . log ( ':4' ) ;
106121 return ;
107122 }
108123 }
109124 }
110125 }
111126
112- // Fall back to regular completion logic (shows basic package manager commands)
113127 return super . parse ( args ) ;
114128 }
115129}
0 commit comments