@@ -26,8 +26,8 @@ pub(super) enum AppTarget {
2626}
2727
2828struct PackageRow {
29- name : String ,
30- path : String ,
29+ name : vite_str :: Str ,
30+ path : vite_str :: Str ,
3131 absolute : AbsolutePathBuf ,
3232 runnable : bool ,
3333}
@@ -49,9 +49,8 @@ fn app_command_parts(subcommand: &SynthesizableSubcommand) -> Option<(&'static s
4949/// disables elicitation; help/version requests are answered by the underlying
5050/// tool and must never be redirected.
5151fn is_bare ( args : & [ String ] ) -> bool {
52- args. iter ( ) . all ( |arg| {
53- arg. starts_with ( '-' ) && !matches ! ( arg. as_str( ) , "-h" | "--help" | "-V" | "--version" )
54- } )
52+ args. iter ( )
53+ . all ( |arg| arg. starts_with ( '-' ) && !super :: help:: is_app_tool_help_or_version_flag ( arg) )
5554}
5655
5756/// Heuristic ranking signal: does `dir` look runnable for `command`?
@@ -62,9 +61,11 @@ fn looks_runnable(dir: &AbsolutePathBuf, command: &str) -> bool {
6261 match command {
6362 // Bare `vp pack` succeeds when the config declares a `pack` block or
6463 // tsdown's default entry exists; a Vite config without `pack` does
65- // not make a package packable.
64+ // not make a package packable. `contains` deliberately counts configs
65+ // with spreads (`pack` may exist behind them): the right direction
66+ // for a never-hide ranking signal.
6667 "pack" => {
67- vite_static_config:: resolve_static_config ( dir) . get ( "pack" ) . is_some ( )
68+ vite_static_config:: resolve_static_config ( dir) . contains ( "pack" )
6869 || dir. as_path ( ) . join ( "src/index.ts" ) . is_file ( )
6970 }
7071 _ => vite_static_config:: has_config_file ( dir) || dir. as_path ( ) . join ( "index.html" ) . is_file ( ) ,
@@ -107,8 +108,8 @@ fn run_package_picker(command: &str, rows: &[PackageRow]) -> Result<Option<usize
107108 . iter ( )
108109 . map ( |row| vite_select:: SelectItem {
109110 label : vite_str:: format!( "{} {}" , row. name, row. path) ,
110- display_name : vite_str :: Str :: from ( row. name . as_str ( ) ) ,
111- description : vite_str :: Str :: from ( row. path . as_str ( ) ) ,
111+ display_name : row. name . clone ( ) ,
112+ description : row. path . clone ( ) ,
112113 group : None ,
113114 } )
114115 . collect ( ) ;
@@ -181,8 +182,8 @@ pub(super) fn resolve_app_target(
181182 . map ( |info| {
182183 let absolute = info. absolute_path . to_absolute_path_buf ( ) ;
183184 PackageRow {
184- name : info. package_json . name . to_string ( ) ,
185- path : info. path . as_str ( ) . to_string ( ) ,
185+ name : info. package_json . name . clone ( ) ,
186+ path : vite_str :: Str :: from ( info. path . as_str ( ) ) ,
186187 runnable : looks_runnable ( & absolute, command) ,
187188 absolute,
188189 }
@@ -198,14 +199,13 @@ pub(super) fn resolve_app_target(
198199 // otherwise the fuzzy picker runs.
199200 if vite_shared:: is_interactive_terminal ( ) {
200201 let single_runnable = rows[ 0 ] . runnable && rows. get ( 1 ) . is_none_or ( |row| !row. runnable ) ;
201- let row = if single_runnable {
202- & rows[ 0 ]
203- } else {
204- match run_package_picker ( command, & rows) ? {
205- Some ( index) => & rows[ index] ,
206- None => return Ok ( AppTarget :: Exit ( ExitStatus ( 130 ) ) ) ,
207- }
202+ let picked = if single_runnable { Some ( 0 ) } else { run_package_picker ( command, & rows) ? } ;
203+ let Some ( index) = picked else {
204+ return Ok ( AppTarget :: Exit ( ExitStatus ( 130 ) ) ) ;
208205 } ;
206+ let row = & rows[ index] ;
207+ // Deliberately stdout via println!: these lines belong to the
208+ // command's own output stream, like the tool output that follows.
209209 println ! ( "Selected package: {} ({})" , row. name, row. path) ;
210210 println ! ( "Tip: run this directly with `vp -C {} {command}`" , row. path) ;
211211 return Ok ( AppTarget :: Dir ( row. absolute . clone ( ) ) ) ;
@@ -244,18 +244,19 @@ mod tests {
244244 assert ! ( !is_bare( & to_args( & [ "--help" ] ) ) ) ;
245245 assert ! ( !is_bare( & to_args( & [ "-h" ] ) ) ) ;
246246 assert ! ( !is_bare( & to_args( & [ "--watch" , "--version" ] ) ) ) ;
247+ // Vite and tsdown are cac-based and use `-v` for version.
248+ assert ! ( !is_bare( & to_args( & [ "-v" ] ) ) ) ;
247249 }
248250
249251 #[ test]
250252 fn only_app_commands_elicit ( ) {
251- let args = vec ! [ ] ;
252253 for ( subcommand, expected) in [
253- ( SynthesizableSubcommand :: Dev { args : args . clone ( ) } , Some ( "dev" ) ) ,
254- ( SynthesizableSubcommand :: Build { args : args . clone ( ) } , Some ( "build" ) ) ,
255- ( SynthesizableSubcommand :: Preview { args : args . clone ( ) } , Some ( "preview" ) ) ,
256- ( SynthesizableSubcommand :: Pack { args : args . clone ( ) } , Some ( "pack" ) ) ,
257- ( SynthesizableSubcommand :: Lint { args : args . clone ( ) } , None ) ,
258- ( SynthesizableSubcommand :: Test { args : args . clone ( ) } , None ) ,
254+ ( SynthesizableSubcommand :: Dev { args : vec ! [ ] } , Some ( "dev" ) ) ,
255+ ( SynthesizableSubcommand :: Build { args : vec ! [ ] } , Some ( "build" ) ) ,
256+ ( SynthesizableSubcommand :: Preview { args : vec ! [ ] } , Some ( "preview" ) ) ,
257+ ( SynthesizableSubcommand :: Pack { args : vec ! [ ] } , Some ( "pack" ) ) ,
258+ ( SynthesizableSubcommand :: Lint { args : vec ! [ ] } , None ) ,
259+ ( SynthesizableSubcommand :: Test { args : vec ! [ ] } , None ) ,
259260 ] {
260261 assert_eq ! ( app_command_parts( & subcommand) . map( |( name, _) | name) , expected) ;
261262 }
0 commit comments