Skip to content

Commit 4240153

Browse files
authored
feat(help): Improve help command output. (#425)
This PR updates the output of the help command. It groups commands into "Vite+Commands" and "Package Manager Commands" to make the separation obvious. It also reorders the commands roughly based on importance, and mirrors the original Vite's order (dev, build, etc.). I also added the info command to forward `vite info` to package managers. This is one of the commands I use all the time, so I think it's good to have at the top level, especially since it takes many args and would be confusing. ![CleanShot 2026-01-14 at 17.36.51@2x.png](https://app.graphite.com/user-attachments/assets/c82284b3-d432-4591-ae52-53103174362a.png) The output of the local cli was aligned as well, and looks like this now: https://github.com/voidzero-dev/vite-plus/blob/help-update/packages/cli/snap-tests/command-helper/snap.txt#L6
1 parent c913e1e commit 4240153

6 files changed

Lines changed: 191 additions & 59 deletions

File tree

packages/cli/binding/src/cli.rs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,13 @@ pub enum CustomTaskSubcommand {
5555
#[clap(allow_hyphen_values = true, trailing_var_arg = true)]
5656
args: Vec<String>,
5757
},
58-
/// Build application
58+
/// Build for production
5959
#[command(disable_help_flag = true)]
6060
Build {
6161
#[clap(allow_hyphen_values = true, trailing_var_arg = true)]
6262
args: Vec<String>,
6363
},
64-
/// Run test
64+
/// Run tests
6565
#[command(disable_help_flag = true)]
6666
Test {
6767
#[clap(allow_hyphen_values = true, trailing_var_arg = true)]
@@ -92,7 +92,6 @@ pub enum CustomTaskSubcommand {
9292
args: Vec<String>,
9393
},
9494
/// Install command.
95-
/// It will be passed to the package manager's install command currently.
9695
#[command(disable_help_flag = true, alias = "i")]
9796
Install {
9897
#[clap(allow_hyphen_values = true, trailing_var_arg = true)]
@@ -611,6 +610,11 @@ pub async fn main(
611610
// Get args from parameter or env::args()
612611
// When running from NAPI, args should be passed explicitly to skip node/script paths
613612
let args_vec: Vec<String> = args.unwrap_or_else(|| env::args().skip(1).collect());
613+
let args_vec = normalize_help_args(args_vec);
614+
if should_print_help(&args_vec) {
615+
print_help();
616+
return Ok(ExitStatus::SUCCESS);
617+
}
614618

615619
// Parse CLI args using vite_task::CLIArgs
616620
// Prepend "vite" as program name for clap
@@ -703,6 +707,47 @@ pub async fn main(
703707
}
704708
}
705709

710+
fn normalize_help_args(args: Vec<String>) -> Vec<String> {
711+
args
712+
}
713+
714+
fn should_print_help(args: &[String]) -> bool {
715+
matches!(
716+
args,
717+
[arg] if arg == "-h" || arg == "--help"
718+
)
719+
}
720+
721+
fn print_help() {
722+
let version = env!("CARGO_PKG_VERSION");
723+
let bold = "\x1b[1m";
724+
let bold_underline = "\x1b[1;4m";
725+
let reset = "\x1b[0m";
726+
println!(
727+
"vite+/{version}
728+
729+
{bold_underline}Usage:{reset} {bold}vite{reset} <COMMAND>
730+
731+
{bold_underline}Vite+ Commands:{reset}
732+
{bold}dev{reset} Run development server
733+
{bold}build{reset} Build for production
734+
{bold}preview{reset} Preview production build
735+
{bold}lint{reset} Lint code
736+
{bold}test{reset} Run tests
737+
{bold}fmt{reset} Format code
738+
{bold}lib{reset} Build library
739+
{bold}doc{reset} Build documentation
740+
{bold}run{reset} Run tasks
741+
{bold}cache{reset} Manage the task cache
742+
743+
{bold_underline}Package Manager Commands:{reset}
744+
{bold}install{reset} Install all dependencies
745+
746+
Options:
747+
-h, --help Print help"
748+
);
749+
}
750+
706751
pub fn init_tracing() {
707752
use std::sync::OnceLock;
708753

packages/cli/snap-tests/command-helper/snap.txt

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
> vite -h # help message
2-
Vite+<repeat>
3-
4-
Usage: vite <COMMAND>
5-
6-
Commands:
7-
run Run tasks
8-
lint Lint code
9-
fmt Format code
10-
build Build application
11-
test Run test
12-
lib Build library
13-
dev Run development server
14-
preview Preview production build
15-
doc Build documentation
16-
install Install command. It will be passed to the package manager's install command currently
17-
cache Manage the task cache
18-
help Print this message or the help of the given subcommand(s)
2+
vite+/<semver>
3+
4+
Usage: vite <COMMAND>
5+
6+
Vite+ Commands:
7+
dev Run development server
8+
build Build for production
9+
preview Preview production build
10+
lint Lint code
11+
test Run tests
12+
fmt Format code
13+
lib Build library
14+
doc Build documentation
15+
run Run tasks
16+
cache Manage the task cache
17+
18+
Package Manager Commands:
19+
install Install all dependencies
1920

2021
Options:
2122
-h, --help Print help

packages/global/binding/src/cli.rs

Lines changed: 79 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::process::ExitStatus;
22

3-
use clap::{Parser, Subcommand};
3+
use clap::{CommandFactory, Parser, Subcommand};
44
use vite_error::Error;
55
use vite_install::commands::{
66
add::SaveDependencyType, install::InstallCommandOptions, outdated::Format,
@@ -15,16 +15,7 @@ use crate::commands::{
1515

1616
#[derive(Parser, Debug)]
1717
#[clap(author, version, about, long_about = None)]
18-
#[command(
19-
disable_help_subcommand = true,
20-
help_template = "\
21-
vite+/{version}
22-
23-
{usage-heading} {usage}
24-
25-
{all-args}{after-help}
26-
"
27-
)]
18+
#[command(disable_help_subcommand = true)]
2819
pub struct Args {
2920
#[clap(subcommand)]
3021
pub commands: Commands,
@@ -406,6 +397,24 @@ pub enum Commands {
406397
#[arg(last = true, allow_hyphen_values = true)]
407398
pass_through_args: Option<Vec<String>>,
408399
},
400+
/// View package information from registry
401+
#[command(alias = "view", alias = "show")]
402+
Info {
403+
/// Package name with optional version
404+
#[arg(required = true)]
405+
package: String,
406+
407+
/// Specific field to view
408+
field: Option<String>,
409+
410+
/// Output in JSON format
411+
#[arg(long)]
412+
json: bool,
413+
414+
/// Additional arguments to pass through to the package manager
415+
#[arg(last = true, allow_hyphen_values = true)]
416+
pass_through_args: Option<Vec<String>>,
417+
},
409418
/// Link packages for local development
410419
#[command(alias = "ln")]
411420
Link {
@@ -433,7 +442,7 @@ pub enum Commands {
433442
#[arg(allow_hyphen_values = true, trailing_var_arg = true)]
434443
args: Vec<String>,
435444
},
436-
/// Package manager utilities
445+
/// Forward command to the package manager.
437446
#[command(subcommand)]
438447
Pm(PmCommands),
439448
/// Execute a package binary without installing it as a dependency
@@ -1064,6 +1073,17 @@ pub async fn main(cwd: AbsolutePathBuf, mut args: Args) -> Result<std::process::
10641073
.await?;
10651074
return Ok(exit_status);
10661075
}
1076+
Commands::Info { package, field, json, pass_through_args } => {
1077+
let exit_status = PmCommand::new(cwd)
1078+
.execute(PmCommands::View {
1079+
package: package.clone(),
1080+
field: field.clone(),
1081+
json: *json,
1082+
pass_through_args: pass_through_args.clone(),
1083+
})
1084+
.await?;
1085+
return Ok(exit_status);
1086+
}
10671087
Commands::Pm(pm_command) => {
10681088
let exit_status = PmCommand::new(cwd).execute(pm_command.clone()).await?;
10691089
return Ok(exit_status);
@@ -1078,6 +1098,53 @@ pub async fn main(cwd: AbsolutePathBuf, mut args: Args) -> Result<std::process::
10781098
};
10791099
}
10801100

1101+
pub fn command_with_help() -> clap::Command {
1102+
let bold = "\x1b[1m";
1103+
let bold_underline = "\x1b[1;4m";
1104+
let reset = "\x1b[0m";
1105+
let version = env!("CARGO_PKG_VERSION");
1106+
1107+
let after_help = format!(
1108+
"{bold_underline}Vite+ Commands:{reset}
1109+
{bold}dev{reset} Run development server
1110+
{bold}build{reset} Build for production
1111+
{bold}lint{reset} Lint code
1112+
{bold}test{reset} Run tests
1113+
{bold}fmt{reset} Format code
1114+
{bold}doc{reset} Build documentation
1115+
{bold}lib{reset} Build library
1116+
{bold}migrate{reset} Migrate an existing project to Vite+
1117+
{bold}cache{reset} Manage the task cache
1118+
{bold}new{reset} Generate a new project
1119+
{bold}run{reset} Run tasks
1120+
1121+
{bold_underline}Package Manager Commands:{reset}
1122+
{bold}install{reset} Install all dependencies, or add packages if package names are provided
1123+
{bold}add{reset} Add packages to dependencies
1124+
{bold}remove{reset} Remove packages from dependencies
1125+
{bold}dedupe{reset} Deduplicate dependencies by removing older versions
1126+
{bold}dlx{reset} Execute a package binary without installing it as a dependency
1127+
{bold}info{reset} View package information from registry
1128+
{bold}link{reset} Link packages for local development
1129+
{bold}outdated{reset} Check for outdated packages
1130+
{bold}pm{reset} Forward command to the package manager
1131+
{bold}unlink{reset} Unlink packages
1132+
{bold}update{reset} Update packages to their latest versions
1133+
{bold}why{reset} Show why a package is installed
1134+
"
1135+
);
1136+
let help_template = format!(
1137+
"vite+/{version}
1138+
1139+
{{usage-heading}} {{usage}}{{after-help}}
1140+
{bold_underline}Options:{reset}
1141+
{{options}}
1142+
"
1143+
);
1144+
1145+
Args::command().after_help(after_help).help_template(help_template)
1146+
}
1147+
10811148
pub fn init_tracing() {
10821149
use std::sync::OnceLock;
10831150

packages/global/binding/src/commands/pm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::{
1515
cli::{ConfigCommands, OwnerCommands, PmCommands},
1616
};
1717

18-
/// Package manager utilities command.
18+
/// Forward command to the package manager.
1919
///
2020
/// This command provides a unified interface to package manager utilities
2121
/// across pnpm, npm, and yarn.

packages/global/binding/src/lib.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ mod migration;
66
mod package_manager;
77
mod utils;
88

9-
use clap::Parser as _;
9+
use std::ffi::{OsStr, OsString};
10+
11+
use clap::FromArgMatches as _;
1012
use napi::{anyhow, bindgen_prelude::*};
1113
use napi_derive::napi;
1214
pub use utils::run_command;
@@ -90,5 +92,19 @@ pub async fn run(options: CliOptions) -> Result<i32> {
9092

9193
fn parse_args() -> Args {
9294
// Parse CLI arguments (skip first arg which is the node binary)
93-
Args::parse_from(std::env::args_os().skip(1))
95+
let args = normalize_help_args(std::env::args_os().skip(1).collect());
96+
let matches = crate::cli::command_with_help().get_matches_from(args);
97+
Args::from_arg_matches(&matches).unwrap_or_else(|e| e.exit())
98+
}
99+
100+
fn normalize_help_args(args: Vec<OsString>) -> Vec<OsString> {
101+
if matches!(args.first(), Some(arg) if arg == OsStr::new("help")) {
102+
return vec![OsString::from("--help")];
103+
}
104+
105+
if args.len() >= 2 && args[1] == OsStr::new("help") {
106+
return vec![args[0].clone(), OsString::from("--help")];
107+
}
108+
109+
args
94110
}

packages/global/snap-tests/cli-helper-message/snap.txt

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,32 @@ vite+/<semver>
33

44
Usage: vite <COMMAND>
55

6-
Commands:
7-
install Install all dependencies, or add packages if package names are provided
8-
add Add packages to dependencies
9-
remove Remove packages from dependencies
10-
update Update packages to their latest versions
11-
dedupe Deduplicate dependencies by removing older versions
12-
outdated Check for outdated packages
13-
why Show why a package is installed
14-
link Link packages for local development
15-
unlink Unlink packages
16-
pm Package manager utilities
17-
dlx Execute a package binary without installing it as a dependency
18-
gen Generate a new project
19-
migrate Migrate an existing project to vite+<repeat>
20-
dev Run development server
21-
build Build application
22-
test Run test
23-
lint Lint code
24-
fmt Format code
25-
lib Build library
26-
doc Build documentation
27-
run Run tasks
28-
cache Manage the task cache
6+
Vite+ Commands:
7+
dev Run development server
8+
build Build for production
9+
lint Lint code
10+
test Run tests
11+
fmt Format code
12+
doc Build documentation
13+
lib Build library
14+
migrate Migrate an existing project to Vite+<repeat>
15+
cache Manage the task cache
16+
new Generate a new project
17+
run Run tasks
18+
19+
Package Manager Commands:
20+
install Install all dependencies, or add packages if package names are provided
21+
add Add packages to dependencies
22+
remove Remove packages from dependencies
23+
dedupe Deduplicate dependencies by removing older versions
24+
dlx Execute a package binary without installing it as a dependency
25+
info View package information from registry
26+
link Link packages for local development
27+
outdated Check for outdated packages
28+
pm Forward command to the package manager
29+
unlink Unlink packages
30+
update Update packages to their latest versions
31+
why Show why a package is installed
2932

3033
Options:
3134
-h, --help Print help
@@ -235,7 +238,7 @@ Options:
235238
-h, --help Print help
236239

237240
> vite pm -h # show pm help message
238-
Package manager utilities
241+
Forward command to the package manager
239242

240243
Usage: vite pm <COMMAND>
241244

0 commit comments

Comments
 (0)