@@ -9,57 +9,52 @@ import {
99 safeExec ,
1010 safeExecSync ,
1111 // createLogLevelHandler,
12- } from '../utils/package-manager-base .js' ;
12+ } from '../utils/shared .js' ;
1313
14- // regex patterns to avoid recompilation in loops
1514const COMMANDS_SECTION_RE = / ^ C o m m a n d s : \s * $ / i;
1615const FLAGS_SECTION_RE = / ^ F l a g s : \s * $ / i;
1716const SECTION_END_RE = / ^ ( E x a m p l e s | F u l l d o c u m e n t a t i o n | L e a r n m o r e ) / i;
1817const COMMAND_VALIDATION_RE = / ^ [ a - z ] [ a - z 0 - 9 - ] * $ / ;
1918const BUN_OPTION_RE =
2019 / ^ \s * (?: - ( [ a - z A - Z ] ) , ? \s * ) ? - - ( [ a - z ] [ a - z 0 - 9 - ] * ) (?: = < [ ^ > ] + > ) ? \s + ( .+ ) $ / ;
21- // const NON_INDENTED_LINE_RE = /^\s/;
20+ const MAIN_COMMAND_RE = / ^ ( [ a - z ] [ a - z 0 - 9 - ] * ) \s + ( .+ ) $ / ;
21+ const CONTINUATION_COMMAND_RE = / ^ \s { 12 , } ( [ a - z ] [ a - z 0 - 9 - ] * ) \s + ( .+ ) $ / ;
22+ const EMPTY_LINE_FOLLOWED_BY_NON_COMMAND_RE = / ^ \s + [ a - z ] / ;
23+ const DESCRIPTION_SPLIT_RE = / \s { 2 , } / ;
24+ const CAPITAL_LETTER_START_RE = / ^ [ A - Z ] / ;
2225
23- // bun-specific completion handlers
2426const bunOptionHandlers : OptionHandlers = {
25- // Use common handlers
2627 ...commonOptionHandlers ,
2728
28- // bun doesn't have traditional log levels, but has verbose/silent
2929 silent : function ( complete ) {
3030 complete ( 'true' , 'Enable silent mode' ) ;
3131 complete ( 'false' , 'Disable silent mode' ) ;
3232 } ,
3333
3434 backend : function ( complete ) {
35- // From bun help: "clonefile" (default), "hardlink", "symlink", "copyfile"
3635 complete ( 'clonefile' , 'Clone files (default, fastest)' ) ;
3736 complete ( 'hardlink' , 'Use hard links' ) ;
3837 complete ( 'symlink' , 'Use symbolic links' ) ;
3938 complete ( 'copyfile' , 'Copy files' ) ;
4039 } ,
4140
4241 linker : function ( complete ) {
43- // From bun help: "isolated" or "hoisted"
4442 complete ( 'isolated' , 'Isolated linker strategy' ) ;
4543 complete ( 'hoisted' , 'Hoisted linker strategy' ) ;
4644 } ,
4745
4846 omit : function ( complete ) {
49- // From bun help: 'dev', 'optional', or 'peer'
5047 complete ( 'dev' , 'Omit devDependencies' ) ;
5148 complete ( 'optional' , 'Omit optionalDependencies' ) ;
5249 complete ( 'peer' , 'Omit peerDependencies' ) ;
5350 } ,
5451
5552 shell : function ( complete ) {
56- // From bun help: 'bun' or 'system'
5753 complete ( 'bun' , 'Use Bun shell' ) ;
5854 complete ( 'system' , 'Use system shell' ) ;
5955 } ,
6056
6157 'unhandled-rejections' : function ( complete ) {
62- // From bun help: "strict", "throw", "warn", "none", or "warn-with-error-code"
6358 complete ( 'strict' , 'Strict unhandled rejection handling' ) ;
6459 complete ( 'throw' , 'Throw on unhandled rejections' ) ;
6560 complete ( 'warn' , 'Warn on unhandled rejections' ) ;
@@ -68,11 +63,9 @@ const bunOptionHandlers: OptionHandlers = {
6863 } ,
6964} ;
7065
71- // Parse bun help text to extract commands and their descriptions
7266export function parseBunHelp ( helpText : string ) : Record < string , string > {
7367 const helpLines = stripAnsiEscapes ( helpText ) . split ( / \r ? \n / ) ;
7468
75- // Find "Commands:" section
7669 let startIndex = - 1 ;
7770 for ( let i = 0 ; i < helpLines . length ; i ++ ) {
7871 if ( COMMANDS_SECTION_RE . test ( helpLines [ i ] . trim ( ) ) ) {
@@ -85,44 +78,35 @@ export function parseBunHelp(helpText: string): Record<string, string> {
8578
8679 const commands : Record < string , string > = { } ;
8780
88- // Parse bun's unique command format
81+ // parse bun's unique command format
8982 for ( let i = startIndex ; i < helpLines . length ; i ++ ) {
9083 const line = helpLines [ i ] ;
9184
92- // Stop when we hit Flags section or empty line followed by non-command content
85+ // stop when we hit Flags section or empty line followed by non-command content
9386 if (
9487 FLAGS_SECTION_RE . test ( line . trim ( ) ) ||
9588 ( line . trim ( ) === '' &&
9689 i + 1 < helpLines . length &&
97- ! helpLines [ i + 1 ] . match ( / ^ \s + [ a - z ] / ) )
90+ ! helpLines [ i + 1 ] . match ( EMPTY_LINE_FOLLOWED_BY_NON_COMMAND_RE ) )
9891 )
9992 break ;
10093
10194 // Skip empty lines
10295 if ( line . trim ( ) === '' ) continue ;
10396
104- // Handle different bun command formats:
105- // Format 1: " run ./my-script.ts Execute a file with Bun"
106- // Format 2: " lint Run a package.json script" (continuation)
107- // Format 3: " install Install dependencies for a package.json (bun i)"
108-
109- // Try to match command at start of line (2 spaces)
110- const mainCommandMatch = line . match ( / ^ ( [ a - z ] [ a - z 0 - 9 - ] * ) \s + ( .+ ) $ / ) ;
97+ const mainCommandMatch = line . match ( MAIN_COMMAND_RE ) ;
11198 if ( mainCommandMatch ) {
11299 const [ , command , rest ] = mainCommandMatch ;
113100 if ( COMMAND_VALIDATION_RE . test ( command ) ) {
114- // Extract description - find the last part that looks like a description
115- // Split by multiple spaces and take the last part that contains letters
116- const parts = rest . split ( / \s { 2 , } / ) ;
101+ const parts = rest . split ( DESCRIPTION_SPLIT_RE ) ;
117102 let description = parts [ parts . length - 1 ] ;
118103
119- // If the last part starts with a capital letter, it's likely the description
120- if ( description && / ^ [ A - Z ] / . test ( description ) ) {
104+ // If the last part starts with capital letter, it's likely the description
105+ if ( description && CAPITAL_LETTER_START_RE . test ( description ) ) {
121106 commands [ command ] = description . trim ( ) ;
122107 } else if ( parts . length > 1 ) {
123- // Otherwise, look for the first part that starts with a capital
124108 for ( const part of parts ) {
125- if ( / ^ [ A - Z ] / . test ( part ) ) {
109+ if ( CAPITAL_LETTER_START_RE . test ( part ) ) {
126110 commands [ command ] = part . trim ( ) ;
127111 break ;
128112 }
@@ -131,8 +115,7 @@ export function parseBunHelp(helpText: string): Record<string, string> {
131115 }
132116 }
133117
134- // Handle continuation lines (12+ spaces)
135- const continuationMatch = line . match ( / ^ \s { 12 , } ( [ a - z ] [ a - z 0 - 9 - ] * ) \s + ( .+ ) $ / ) ;
118+ const continuationMatch = line . match ( CONTINUATION_COMMAND_RE ) ;
136119 if ( continuationMatch ) {
137120 const [ , command , description ] = continuationMatch ;
138121 if ( COMMAND_VALIDATION_RE . test ( command ) ) {
@@ -144,7 +127,6 @@ export function parseBunHelp(helpText: string): Record<string, string> {
144127 return commands ;
145128}
146129
147- // Get bun commands from the main help output
148130export async function getBunCommandsFromMainHelp ( ) : Promise <
149131 Record < string , string >
150132> {
@@ -200,7 +182,7 @@ export function parseBunOptions(
200182 return optionsOut ;
201183}
202184
203- // Load dynamic options synchronously when requested
185+ // load dynamic options synchronously when requested
204186function loadBunOptionsSync ( cmd : LazyCommand , command : string ) : void {
205187 const output = safeExecSync ( `bun ${ command } --help` ) ;
206188 if ( ! output ) return ;
0 commit comments