0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-02-01 20:25:12 -05:00

fix(cli): Fix the bug where the command description is not displayed. (#19604)

This commit is contained in:
nasa 2023-06-28 09:57:20 +09:00 committed by GitHub
parent 6c6b20b9ea
commit d82b5f3bec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 614 additions and 549 deletions

View file

@ -818,7 +818,22 @@ fn clap_root() -> Command {
} }
fn bench_subcommand() -> Command { fn bench_subcommand() -> Command {
Command::new("bench").defer(|cmd| { Command::new("bench")
.about("Run benchmarks")
.long_about(
"Run benchmarks using Deno's built-in bench tool.
Evaluate the given modules, run all benches declared with 'Deno.bench()'
and report results to standard output:
deno bench src/fetch_bench.ts src/signal_bench.ts
Directory arguments are expanded to all contained files matching the
glob {*_,*.,}bench.{js,mjs,ts,mts,jsx,tsx}:
deno bench src/",
)
.defer(|cmd| {
runtime_args(cmd, true, false) runtime_args(cmd, true, false)
.arg(check_arg(true)) .arg(check_arg(true))
.arg( .arg(
@ -840,7 +855,9 @@ fn bench_subcommand() -> Command {
Arg::new("filter") Arg::new("filter")
.long("filter") .long("filter")
.allow_hyphen_values(true) .allow_hyphen_values(true)
.help("Run benchmarks with this string or pattern in the bench name"), .help(
"Run benchmarks with this string or pattern in the bench name",
),
) )
.arg( .arg(
Arg::new("files") Arg::new("files")
@ -858,25 +875,22 @@ fn bench_subcommand() -> Command {
.arg(watch_arg(false)) .arg(watch_arg(false))
.arg(no_clear_screen_arg()) .arg(no_clear_screen_arg())
.arg(script_arg().last(true)) .arg(script_arg().last(true))
.about("Run benchmarks")
.long_about(
"Run benchmarks using Deno's built-in bench tool.
Evaluate the given modules, run all benches declared with 'Deno.bench()'
and report results to standard output:
deno bench src/fetch_bench.ts src/signal_bench.ts
Directory arguments are expanded to all contained files matching the
glob {*_,*.,}bench.{js,mjs,ts,mts,jsx,tsx}:
deno bench src/",
)
}) })
} }
fn bundle_subcommand() -> Command { fn bundle_subcommand() -> Command {
Command::new("bundle").defer(|cmd| { Command::new("bundle")
.about("Bundle module and dependencies into single file")
.long_about(
"Output a single JavaScript file with all dependencies.
deno bundle https://deno.land/std/examples/colors.ts colors.bundle.js
If no output file is given, the output is written to standard output:
deno bundle https://deno.land/std/examples/colors.ts",
)
.defer(|cmd| {
compile_args(cmd) compile_args(cmd)
.hide(true) .hide(true)
.arg(check_arg(true)) .arg(check_arg(true))
@ -893,29 +907,11 @@ fn bundle_subcommand() -> Command {
.arg(watch_arg(false)) .arg(watch_arg(false))
.arg(no_clear_screen_arg()) .arg(no_clear_screen_arg())
.arg(executable_ext_arg()) .arg(executable_ext_arg())
.about("Bundle module and dependencies into single file")
.long_about(
"Output a single JavaScript file with all dependencies.
deno bundle https://deno.land/std/examples/colors.ts colors.bundle.js
If no output file is given, the output is written to standard output:
deno bundle https://deno.land/std/examples/colors.ts",
)
}) })
} }
fn cache_subcommand() -> Command { fn cache_subcommand() -> Command {
Command::new("cache").defer(|cmd| { Command::new("cache")
compile_args(cmd)
.arg(check_arg(false))
.arg(
Arg::new("file")
.num_args(1..)
.required(true)
.value_hint(ValueHint::FilePath),
)
.about("Cache the dependencies") .about("Cache the dependencies")
.long_about( .long_about(
"Cache and compile remote dependencies recursively. "Cache and compile remote dependencies recursively.
@ -928,11 +924,26 @@ them in the local cache, without running any code:
Future runs of this module will trigger no downloads or compilation unless Future runs of this module will trigger no downloads or compilation unless
--reload is specified.", --reload is specified.",
) )
.defer(|cmd| {
compile_args(cmd).arg(check_arg(false)).arg(
Arg::new("file")
.num_args(1..)
.required(true)
.value_hint(ValueHint::FilePath),
)
}) })
} }
fn check_subcommand() -> Command { fn check_subcommand() -> Command {
Command::new("check") Command::new("check")
.about("Type-check the dependencies")
.long_about(
"Download and type-check without execution.
deno check https://deno.land/std/http/file_server.ts
Unless --reload is specified, this command will not re-download already cached dependencies.",
)
.defer(|cmd| compile_args_without_check_args(cmd).arg( .defer(|cmd| compile_args_without_check_args(cmd).arg(
Arg::new("all") Arg::new("all")
.long("all") .long("all")
@ -955,18 +966,35 @@ fn check_subcommand() -> Command {
.required(true) .required(true)
.value_hint(ValueHint::FilePath), .value_hint(ValueHint::FilePath),
) )
.about("Type-check the dependencies") )
.long_about(
"Download and type-check without execution.
deno check https://deno.land/std/http/file_server.ts
Unless --reload is specified, this command will not re-download already cached dependencies.",
))
} }
fn compile_subcommand() -> Command { fn compile_subcommand() -> Command {
Command::new("compile").defer(|cmd| { Command::new("compile")
.about("UNSTABLE: Compile the script into a self contained executable")
.long_about(
"UNSTABLE: Compiles the given script into a self contained executable.
deno compile -A https://deno.land/std/http/file_server.ts
deno compile --output color_util https://deno.land/std/examples/colors.ts
Any flags passed which affect runtime behavior, such as '--unstable',
'--allow-*', '--v8-flags', etc. are encoded into the output executable and
used at runtime as if they were passed to a similar 'deno run' command.
The executable name is inferred by default: Attempt to take the file stem of
the URL path. The above example would become 'file_server'. If the file stem
is something generic like 'main', 'mod', 'index' or 'cli', and the path has no
parent, take the file name of the parent path. Otherwise settle with the
generic name. If the resulting name has an '@...' suffix, strip it.
Cross-compiling to different target architectures is supported using the
`--target` flag. On the first invocation with deno will download proper
binary and cache it in $DENO_DIR. The aarch64-apple-darwin target is not
supported in canary.
",
)
.defer(|cmd| {
runtime_args(cmd, true, false) runtime_args(cmd, true, false)
.arg(script_arg().required(true)) .arg(script_arg().required(true))
.arg(check_arg(true)) .arg(check_arg(true))
@ -1003,41 +1031,11 @@ fn compile_subcommand() -> Command {
]), ]),
) )
.arg(executable_ext_arg()) .arg(executable_ext_arg())
.about("UNSTABLE: Compile the script into a self contained executable")
.long_about(
"UNSTABLE: Compiles the given script into a self contained executable.
deno compile -A https://deno.land/std/http/file_server.ts
deno compile --output color_util https://deno.land/std/examples/colors.ts
Any flags passed which affect runtime behavior, such as '--unstable',
'--allow-*', '--v8-flags', etc. are encoded into the output executable and
used at runtime as if they were passed to a similar 'deno run' command.
The executable name is inferred by default: Attempt to take the file stem of
the URL path. The above example would become 'file_server'. If the file stem
is something generic like 'main', 'mod', 'index' or 'cli', and the path has no
parent, take the file name of the parent path. Otherwise settle with the
generic name. If the resulting name has an '@...' suffix, strip it.
Cross-compiling to different target architectures is supported using the
`--target` flag. On the first invocation with deno will download proper
binary and cache it in $DENO_DIR. The aarch64-apple-darwin target is not
supported in canary.
",
)
}) })
} }
fn completions_subcommand() -> Command { fn completions_subcommand() -> Command {
Command::new("completions").defer(|cmd| { Command::new("completions")
cmd
.disable_help_subcommand(true)
.arg(
Arg::new("shell")
.value_parser(["bash", "fish", "powershell", "zsh", "fig"])
.required(true),
)
.about("Generate shell completions") .about("Generate shell completions")
.long_about( .long_about(
"Output shell completion script to standard output. "Output shell completion script to standard output.
@ -1045,12 +1043,17 @@ fn completions_subcommand() -> Command {
deno completions bash > /usr/local/etc/bash_completion.d/deno.bash deno completions bash > /usr/local/etc/bash_completion.d/deno.bash
source /usr/local/etc/bash_completion.d/deno.bash", source /usr/local/etc/bash_completion.d/deno.bash",
) )
.defer(|cmd| {
cmd.disable_help_subcommand(true).arg(
Arg::new("shell")
.value_parser(["bash", "fish", "powershell", "zsh", "fig"])
.required(true),
)
}) })
} }
fn coverage_subcommand() -> Command { fn coverage_subcommand() -> Command {
Command::new("coverage").defer(|cmd| { Command::new("coverage")
cmd
.about("Print coverage reports") .about("Print coverage reports")
.long_about( .long_about(
"Print coverage reports from coverage profiles. "Print coverage reports from coverage profiles.
@ -1086,6 +1089,8 @@ Generate html reports from lcov:
genhtml -o html_cov cov.lcov genhtml -o html_cov cov.lcov
", ",
) )
.defer(|cmd| {
cmd
.arg( .arg(
Arg::new("ignore") Arg::new("ignore")
.long("ignore") .long("ignore")
@ -1147,8 +1152,7 @@ Generate html reports from lcov:
} }
fn doc_subcommand() -> Command { fn doc_subcommand() -> Command {
Command::new("doc").defer(|cmd| { Command::new("doc")
cmd
.about("Show documentation for a module") .about("Show documentation for a module")
.long_about( .long_about(
"Show documentation for a module. "Show documentation for a module.
@ -1174,6 +1178,8 @@ Show documentation for runtime built-ins:
deno doc deno doc
deno doc --builtin Deno.Listener", deno doc --builtin Deno.Listener",
) )
.defer(|cmd| {
cmd
.arg(import_map_arg()) .arg(import_map_arg())
.arg(reload_arg()) .arg(reload_arg())
.arg(lock_arg()) .arg(lock_arg())
@ -1208,8 +1214,7 @@ Show documentation for runtime built-ins:
} }
fn eval_subcommand() -> Command { fn eval_subcommand() -> Command {
Command::new("eval").defer(|cmd| { Command::new("eval")
runtime_args(cmd, false, true)
.about("Eval script") .about("Eval script")
.long_about( .long_about(
"Evaluate JavaScript from the command line. "Evaluate JavaScript from the command line.
@ -1222,6 +1227,8 @@ To evaluate as TypeScript:
This command has implicit access to all permissions (--allow-all).", This command has implicit access to all permissions (--allow-all).",
) )
.defer(|cmd| {
runtime_args(cmd, false, true)
.arg(check_arg(false)) .arg(check_arg(false))
.arg( .arg(
// TODO(@satyarohith): remove this argument in 2.0. // TODO(@satyarohith): remove this argument in 2.0.
@ -1253,8 +1260,7 @@ This command has implicit access to all permissions (--allow-all).",
} }
fn fmt_subcommand() -> Command { fn fmt_subcommand() -> Command {
Command::new("fmt").defer(|cmd| { Command::new("fmt")
cmd
.about("Format source files") .about("Format source files")
.long_about( .long_about(
"Auto-format JavaScript, TypeScript, Markdown, and JSON files. "Auto-format JavaScript, TypeScript, Markdown, and JSON files.
@ -1275,6 +1281,8 @@ Ignore formatting a file by adding an ignore comment at the top of the file:
// deno-fmt-ignore-file", // deno-fmt-ignore-file",
) )
.defer(|cmd| {
cmd
.arg(config_arg()) .arg(config_arg())
.arg(no_config_arg()) .arg(no_config_arg())
.arg( .arg(
@ -1368,8 +1376,10 @@ Ignore formatting a file by adding an ignore comment at the top of the file:
} }
fn init_subcommand() -> Command { fn init_subcommand() -> Command {
Command::new("init").defer(|cmd| { Command::new("init")
cmd.about("Initialize a new project").arg( .about("Initialize a new project")
.defer(|cmd| {
cmd.arg(
Arg::new("dir") Arg::new("dir")
.required(false) .required(false)
.value_hint(ValueHint::DirPath), .value_hint(ValueHint::DirPath),
@ -1379,7 +1389,7 @@ fn init_subcommand() -> Command {
fn info_subcommand() -> Command { fn info_subcommand() -> Command {
Command::new("info") Command::new("info")
.defer(|cmd| cmd.about("Show info about cache or info related to source file") .about("Show info about cache or info related to source file")
.long_about( .long_about(
"Information about a module or the cache directories. "Information about a module or the cache directories.
@ -1400,6 +1410,7 @@ DENO_DIR: Directory containing Deno-managed files.
Remote modules cache: Subdirectory containing downloaded remote modules. Remote modules cache: Subdirectory containing downloaded remote modules.
TypeScript compiler cache: Subdirectory containing TS compiler output.", TypeScript compiler cache: Subdirectory containing TS compiler output.",
) )
.defer(|cmd| cmd
.arg(Arg::new("file").required(false).value_hint(ValueHint::FilePath)) .arg(Arg::new("file").required(false).value_hint(ValueHint::FilePath))
.arg(reload_arg().requires("file")) .arg(reload_arg().requires("file"))
.arg(ca_file_arg()) .arg(ca_file_arg())
@ -1427,26 +1438,6 @@ TypeScript compiler cache: Subdirectory containing TS compiler output.",
fn install_subcommand() -> Command { fn install_subcommand() -> Command {
Command::new("install") Command::new("install")
.defer(|cmd| runtime_args(cmd, true, true).arg(Arg::new("cmd").required(true).num_args(1..).value_hint(ValueHint::FilePath))
.arg(check_arg(true))
.arg(
Arg::new("name")
.long("name")
.short('n')
.help("Executable file name")
.required(false))
.arg(
Arg::new("root")
.long("root")
.help("Installation root")
.value_parser(value_parser!(PathBuf))
.value_hint(ValueHint::DirPath))
.arg(
Arg::new("force")
.long("force")
.short('f')
.help("Forcefully overwrite existing installation")
.action(ArgAction::SetTrue))
.about("Install script as an executable") .about("Install script as an executable")
.long_about( .long_about(
"Installs a script as an executable in the installation root's bin directory. "Installs a script as an executable in the installation root's bin directory.
@ -1475,18 +1466,32 @@ The installation root is determined, in order of precedence:
- DENO_INSTALL_ROOT environment variable - DENO_INSTALL_ROOT environment variable
- $HOME/.deno - $HOME/.deno
These must be added to the path manually if required.")) These must be added to the path manually if required.")
} .defer(|cmd| runtime_args(cmd, true, true).arg(Arg::new("cmd").required(true).num_args(1..).value_hint(ValueHint::FilePath))
.arg(check_arg(true))
fn uninstall_subcommand() -> Command { .arg(
Command::new("uninstall") Arg::new("name")
.defer(|cmd| cmd.arg(Arg::new("name").required(true)) .long("name")
.short('n')
.help("Executable file name")
.required(false))
.arg( .arg(
Arg::new("root") Arg::new("root")
.long("root") .long("root")
.help("Installation root") .help("Installation root")
.value_parser(value_parser!(PathBuf)) .value_parser(value_parser!(PathBuf))
.value_hint(ValueHint::DirPath)) .value_hint(ValueHint::DirPath))
.arg(
Arg::new("force")
.long("force")
.short('f')
.help("Forcefully overwrite existing installation")
.action(ArgAction::SetTrue))
)
}
fn uninstall_subcommand() -> Command {
Command::new("uninstall")
.about("Uninstall a script previously installed with deno install") .about("Uninstall a script previously installed with deno install")
.long_about( .long_about(
"Uninstalls an executable script in the installation root's bin directory. "Uninstalls an executable script in the installation root's bin directory.
@ -1500,7 +1505,15 @@ To change the installation root, use --root:
The installation root is determined, in order of precedence: The installation root is determined, in order of precedence:
- --root option - --root option
- DENO_INSTALL_ROOT environment variable - DENO_INSTALL_ROOT environment variable
- $HOME/.deno")) - $HOME/.deno")
.defer(|cmd| cmd.arg(Arg::new("name").required(true))
.arg(
Arg::new("root")
.long("root")
.help("Installation root")
.value_parser(value_parser!(PathBuf))
.value_hint(ValueHint::DirPath))
)
} }
static LSP_HELP: &str = concat!( static LSP_HELP: &str = concat!(
@ -1517,12 +1530,12 @@ https://deno.land/manual@v",
fn lsp_subcommand() -> Command { fn lsp_subcommand() -> Command {
Command::new("lsp") Command::new("lsp")
.defer(|cmd| cmd.about("Start the language server").long_about(LSP_HELP)) .about("Start the language server")
.long_about(LSP_HELP)
} }
fn lint_subcommand() -> Command { fn lint_subcommand() -> Command {
Command::new("lint").defer(|cmd| { Command::new("lint")
cmd
.about("Lint source files") .about("Lint source files")
.long_about( .long_about(
"Lint JavaScript/TypeScript source code. "Lint JavaScript/TypeScript source code.
@ -1556,6 +1569,8 @@ Ignore linting a file by adding an ignore comment at the top of the file:
// deno-lint-ignore-file // deno-lint-ignore-file
", ",
) )
.defer(|cmd| {
cmd
.arg( .arg(
Arg::new("rules") Arg::new("rules")
.long("rules") .long("rules")
@ -1630,7 +1645,8 @@ Ignore linting a file by adding an ignore comment at the top of the file:
fn repl_subcommand() -> Command { fn repl_subcommand() -> Command {
Command::new("repl") Command::new("repl")
.defer(|cmd| runtime_args(cmd, true, true).about("Read Eval Print Loop") .about("Read Eval Print Loop")
.defer(|cmd| runtime_args(cmd, true, true)
.arg(check_arg(false)) .arg(check_arg(false))
.arg( .arg(
Arg::new("eval-file") Arg::new("eval-file")
@ -1693,7 +1709,14 @@ Specifying the filename '-' to read the file from stdin.
} }
fn task_subcommand() -> Command { fn task_subcommand() -> Command {
Command::new("task").defer(|cmd| { Command::new("task")
.about("Run a task defined in the configuration file")
.long_about(
"Run a task defined in the configuration file
deno task build",
)
.defer(|cmd| {
cmd cmd
.allow_external_subcommands(true) .allow_external_subcommands(true)
.subcommand_value_name("TASK") .subcommand_value_name("TASK")
@ -1705,17 +1728,26 @@ fn task_subcommand() -> Command {
.help("Specify the directory to run the task in") .help("Specify the directory to run the task in")
.value_hint(ValueHint::DirPath), .value_hint(ValueHint::DirPath),
) )
.about("Run a task defined in the configuration file")
.long_about(
"Run a task defined in the configuration file
deno task build",
)
}) })
} }
fn test_subcommand() -> Command { fn test_subcommand() -> Command {
Command::new("test").defer(|cmd| runtime_args(cmd, true, true) Command::new("test")
.about("Run tests")
.long_about(
"Run tests using Deno's built-in test runner.
Evaluate the given modules, run all tests declared with 'Deno.test()' and
report results to standard output:
deno test src/fetch_test.ts src/signal_test.ts
Directory arguments are expanded to all contained files matching the glob
{*_,*.,}test.{js,mjs,ts,mts,jsx,tsx}:
deno test src/",
)
.defer(|cmd| runtime_args(cmd, true, true)
.arg(check_arg(true)) .arg(check_arg(true))
.arg( .arg(
Arg::new("ignore") Arg::new("ignore")
@ -1817,25 +1849,11 @@ fn test_subcommand() -> Command {
) )
.arg(no_clear_screen_arg()) .arg(no_clear_screen_arg())
.arg(script_arg().last(true)) .arg(script_arg().last(true))
.about("Run tests") )
.long_about(
"Run tests using Deno's built-in test runner.
Evaluate the given modules, run all tests declared with 'Deno.test()' and
report results to standard output:
deno test src/fetch_test.ts src/signal_test.ts
Directory arguments are expanded to all contained files matching the glob
{*_,*.,}test.{js,mjs,ts,mts,jsx,tsx}:
deno test src/",
))
} }
fn types_subcommand() -> Command { fn types_subcommand() -> Command {
Command::new("types").defer(|cmd| { Command::new("types")
cmd
.about("Print runtime TypeScript declarations") .about("Print runtime TypeScript declarations")
.long_about( .long_about(
"Print runtime TypeScript declarations. "Print runtime TypeScript declarations.
@ -1844,12 +1862,10 @@ fn types_subcommand() -> Command {
The declaration file could be saved and used for typing information.", The declaration file could be saved and used for typing information.",
) )
})
} }
fn upgrade_subcommand() -> Command { fn upgrade_subcommand() -> Command {
Command::new("upgrade").defer(|cmd| { Command::new("upgrade")
cmd
.about("Upgrade deno executable to given version") .about("Upgrade deno executable to given version")
.long_about( .long_about(
"Upgrade deno executable to the given version. "Upgrade deno executable to the given version.
@ -1864,6 +1880,8 @@ update to a different location, use the --output flag
deno upgrade --output $HOME/my_deno", deno upgrade --output $HOME/my_deno",
) )
.defer(|cmd| {
cmd
.arg( .arg(
Arg::new("version") Arg::new("version")
.long("version") .long("version")
@ -1901,7 +1919,7 @@ update to a different location, use the --output flag
fn vendor_subcommand() -> Command { fn vendor_subcommand() -> Command {
Command::new("vendor") Command::new("vendor")
.defer(|cmd| cmd.about("Vendor remote modules into a local directory") .about("Vendor remote modules into a local directory")
.long_about( .long_about(
"Vendor remote modules into a local directory. "Vendor remote modules into a local directory.
@ -1916,6 +1934,7 @@ Remote modules and multiple modules may also be specified:
deno vendor main.ts test.deps.ts https://deno.land/std/path/mod.ts", deno vendor main.ts test.deps.ts https://deno.land/std/path/mod.ts",
) )
.defer(|cmd| cmd
.arg( .arg(
Arg::new("specifiers") Arg::new("specifiers")
.num_args(1..) .num_args(1..)

View file

@ -1,5 +1,6 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use std::process::Stdio;
use test_util as util; use test_util as util;
#[test] #[test]
@ -14,6 +15,51 @@ fn help_flag() {
assert!(status.success()); assert!(status.success());
} }
#[test]
fn help_output() {
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("--help")
.stdout(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let stdout = std::str::from_utf8(&output.stdout).unwrap();
let subcommand_descriptions = vec![
"Run a JavaScript or TypeScript program",
"Run benchmarks",
"Bundle module and dependencies into single file",
"Cache the dependencies",
"Type-check the dependencies",
"UNSTABLE: Compile the script into a self contained executable",
"Generate shell completions",
"Print coverage reports",
"Show documentation for a module",
"Eval script",
"Format source files",
"Initialize a new project",
"Show info about cache or info related to source file",
"Install script as an executable",
"Uninstall a script previously installed with deno install",
"Start the language server",
"Lint source files",
"Read Eval Print Loop",
"Run a task defined in the configuration file",
"Run tests",
"Print runtime TypeScript declarations",
"Upgrade deno executable to given version",
"Vendor remote modules into a local directory",
"Print this message or the help of the given subcommand(s)",
];
for description in subcommand_descriptions {
assert!(stdout.contains(description));
}
}
#[test] #[test]
fn version_short_flag() { fn version_short_flag() {
let status = util::deno_cmd() let status = util::deno_cmd()