@@ -16,12 +16,7 @@ import {
1616 packageJsonScriptCompletion ,
1717 packageJsonDependencyCompletion ,
1818} from '../completions/completion-producers.js' ;
19- import {
20- getDirectoriesInCwd ,
21- getCommonWorkspaceDirs ,
22- directoryExists ,
23- getDirectoriesMatching ,
24- } from '../utils/filesystem-utils.js' ;
19+ import { getWorkspacePatterns } from '../utils/filesystem-utils.js' ;
2520import {
2621 stripAnsiEscapes ,
2722 measureIndent ,
@@ -35,124 +30,101 @@ import {
3530// regex to detect options section in help text
3631const OPTIONS_SECTION_RE = / ^ \s * O p t i o n s : / i;
3732
38- function getPnpmStorePaths ( ) : string [ ] {
39- const paths = [ '~/.pnpm-store' ] ;
33+ function extractValidValuesFromHelp (
34+ helpText : string ,
35+ optionName : string
36+ ) : string [ ] {
37+ const lines = stripAnsiEscapes ( helpText ) . split ( / \r ? \n / ) ;
38+
39+ for ( let i = 0 ; i < lines . length ; i ++ ) {
40+ const line = lines [ i ] ;
41+ if ( line . includes ( `--${ optionName } ` ) || line . includes ( `${ optionName } :` ) ) {
42+ for ( let j = i ; j < Math . min ( i + 3 , lines . length ) ; j ++ ) {
43+ const searchLine = lines [ j ] ;
44+
45+ const levelMatch = searchLine . match (
46+ / (?: l e v e l s ? | o p t i o n s ? | v a l u e s ? ) [ ^ : ] * : \s * ( [ ^ . ] + ) / i
47+ ) ;
48+ if ( levelMatch ) {
49+ return levelMatch [ 1 ]
50+ . split ( / [ , \s ] + / )
51+ . map ( ( v ) => v . trim ( ) )
52+ . filter ( ( v ) => v && ! v . includes ( '(' ) && ! v . includes ( ')' ) ) ;
53+ }
4054
41- if ( directoryExists ( '.pnpm-store' ) ) {
42- paths . push ( './.pnpm-store' ) ;
55+ if ( optionName === 'reporter' ) {
56+ const reporterMatch = searchLine . match ( / - - r e p o r t e r \s + ( \w + ) / ) ;
57+ if ( reporterMatch ) {
58+ const reporterValues = new Set < string > ( ) ;
59+ for ( const helpLine of lines ) {
60+ const matches = helpLine . matchAll ( / - - r e p o r t e r \s + ( \w + ) / g) ;
61+ for ( const match of matches ) {
62+ reporterValues . add ( match [ 1 ] ) ;
63+ }
64+ }
65+ return Array . from ( reporterValues ) ;
66+ }
67+ }
68+ }
69+ }
4370 }
4471
45- return paths ;
72+ return [ ] ;
4673}
4774
4875// completion handlers for pnpm options that take values
4976const pnpmOptionHandlers = {
50- dir : function ( complete : ( value : string , description : string ) => void ) {
51- complete ( './' , 'Current directory' ) ;
52- complete ( '../' , 'Parent directory' ) ;
53-
54- const dirs = getDirectoriesInCwd ( ) ;
55- for ( const dir of dirs ) {
56- if ( dir !== './' ) {
57- complete ( dir , `Directory: ${ dir . slice ( 2 ) } ` ) ;
58- }
59- }
60- } ,
77+ // Let shell handle directory completions - it's much better at it
78+ // dir, modules-dir, store-dir, lockfile-dir, virtual-store-dir removed
6179
6280 loglevel : function ( complete : ( value : string , description : string ) => void ) {
63- complete ( 'debug' , 'Debug level' ) ;
64- complete ( 'info' , 'Info level' ) ;
65- complete ( 'warn' , 'Warning level' ) ;
66- complete ( 'error' , 'Error level' ) ;
67- complete ( 'silent' , 'Silent level' ) ;
68- } ,
69-
70- reporter : function ( complete : ( value : string , description : string ) => void ) {
71- complete ( 'default' , 'Default reporter' ) ;
72- complete ( 'silent' , 'Silent reporter' ) ;
73- complete ( 'append-only' , 'Append-only reporter' ) ;
74- complete ( 'ndjson' , 'NDJSON reporter' ) ;
75- } ,
76-
77- filter : function ( complete : ( value : string , description : string ) => void ) {
78- complete ( '.' , 'Current working directory' ) ;
79- complete ( '...' , 'Include dependents' ) ;
80-
81- const workspaceDirs = getCommonWorkspaceDirs ( ) ;
82- for ( const dir of workspaceDirs ) {
83- complete ( `${ dir } /*` , `All packages in ${ dir . slice ( 2 ) } ` ) ;
84- }
85-
86- complete ( '@*/*' , 'All scoped packages' ) ;
87- complete ( '@types/*' , 'All type packages' ) ;
88- } ,
89-
90- 'modules-dir' : function (
91- complete : ( value : string , description : string ) => void
92- ) {
93- complete ( 'node_modules' , 'Default modules directory' ) ;
94-
95- const moduleRelatedDirs = getDirectoriesMatching ( 'module' ) . concat (
96- getDirectoriesMatching ( 'lib' )
81+ // Try to get values from help, fall back to known values
82+ const helpValues = extractValidValuesFromHelp (
83+ execSync ( 'pnpm install --help' , { encoding : 'utf8' , timeout : 500 } ) ,
84+ 'loglevel'
9785 ) ;
98- for ( const dir of moduleRelatedDirs ) {
99- complete ( dir . slice ( 2 ) , `Existing directory: ${ dir . slice ( 2 ) } ` ) ;
100- }
101- } ,
10286
103- 'store-dir' : function (
104- complete : ( value : string , description : string ) => void
105- ) {
106- const storePaths = getPnpmStorePaths ( ) ;
107- for ( const path of storePaths ) {
108- complete (
109- path ,
110- path . startsWith ( '~' ) ? 'Default pnpm store' : 'Local store directory'
87+ if ( helpValues . length > 0 ) {
88+ helpValues . forEach ( ( value ) => complete ( value , `Log level: ${ value } ` ) ) ;
89+ } else {
90+ // Fallback based on documented values
91+ [ 'debug' , 'info' , 'warn' , 'error' , 'silent' ] . forEach ( ( level ) =>
92+ complete ( level , `Log level: ${ level } ` )
11193 ) ;
11294 }
11395 } ,
11496
115- 'lockfile-dir' : function (
116- complete : ( value : string , description : string ) => void
117- ) {
118- complete ( './' , 'Current directory' ) ;
119- complete ( '../' , 'Parent directory' ) ;
120- const dirs = getDirectoriesInCwd ( ) ;
121- for ( const dir of dirs . slice ( 0 , 5 ) ) {
122- if ( dir !== './' ) {
123- complete ( dir , `Directory: ${ dir . slice ( 2 ) } ` ) ;
124- }
125- }
97+ reporter : function ( complete : ( value : string , description : string ) => void ) {
98+ // valid values from pnpm help
99+ const reporters = [
100+ { value : 'default' , desc : 'Default reporter when stdout is TTY' } ,
101+ {
102+ value : 'append-only' ,
103+ desc : 'Output always appended, no cursor manipulation' ,
104+ } ,
105+ { value : 'ndjson' , desc : 'Most verbose reporter in NDJSON format' } ,
106+ { value : 'silent' , desc : 'No output logged to console' } ,
107+ ] ;
108+
109+ reporters . forEach ( ( { value, desc } ) => complete ( value , desc ) ) ;
126110 } ,
127111
128- 'virtual-store-dir' : function (
129- complete : ( value : string , description : string ) => void
130- ) {
131- complete ( 'node_modules/.pnpm' , 'Default virtual store' ) ;
132- complete ( '.pnpm' , 'Custom virtual store' ) ;
133-
134- if ( directoryExists ( '.pnpm' ) ) {
135- complete ( './.pnpm' , 'Existing .pnpm directory' ) ;
136- }
137- } ,
112+ filter : function ( complete : ( value : string , description : string ) => void ) {
113+ // Based on pnpm documentation
114+ complete ( '.' , 'Current working directory' ) ;
115+ complete ( '!<selector>' , 'Exclude packages matching selector' ) ;
138116
139- 'hoist-pattern' : function (
140- complete : ( value : string , description : string ) => void
141- ) {
142- complete ( '*' , 'Hoist everything (default)' ) ;
143- complete ( '@types/*' , 'Hoist only type packages' ) ;
144- complete ( 'eslint*' , 'Hoist ESLint packages' ) ;
145- complete ( '*babel*' , 'Hoist Babel packages' ) ;
146- complete ( '*webpack*' , 'Hoist Webpack packages' ) ;
147- } ,
117+ // Get actual workspace patterns from pnpm-workspace.yaml
118+ const workspacePatterns = getWorkspacePatterns ( ) ;
119+ workspacePatterns . forEach ( ( pattern ) => {
120+ complete ( pattern , `Workspace pattern: ${ pattern } ` ) ;
121+ complete ( `${ pattern } ...` , `Include dependencies of ${ pattern } ` ) ;
122+ } ) ;
148123
149- 'public-hoist-pattern' : function (
150- complete : ( value : string , description : string ) => void
151- ) {
152- complete ( '*eslint*' , 'Hoist ESLint packages to root' ) ;
153- complete ( '*prettier*' , 'Hoist Prettier packages to root' ) ;
154- complete ( '@types/*' , 'Hoist type packages to root' ) ;
155- complete ( '*babel*' , 'Hoist Babel packages to root' ) ;
124+ // Common scope patterns
125+ complete ( '@*/*' , 'All scoped packages' ) ;
126+ complete ( '...<pattern>' , 'Include dependencies of pattern' ) ;
127+ complete ( '<pattern>...' , 'Include dependents of pattern' ) ;
156128 } ,
157129} ;
158130
0 commit comments