summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock12
-rw-r--r--cli/Cargo.toml1
-rw-r--r--cli/args/flags.rs473
-rw-r--r--cli/main.rs21
-rw-r--r--cli/tools/task.rs17
5 files changed, 301 insertions, 223 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 65e70f9b4..efda3f836 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -152,15 +152,16 @@ dependencies = [
[[package]]
name = "anstream"
-version = "0.6.13"
+version = "0.6.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
+checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
+ "is_terminal_polyfill",
"utf8parse",
]
@@ -1146,6 +1147,7 @@ dependencies = [
name = "deno"
version = "1.46.0-rc.3"
dependencies = [
+ "anstream",
"async-trait",
"base32",
"base64 0.21.7",
@@ -3872,6 +3874,12 @@ dependencies = [
]
[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+
+[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/cli/Cargo.toml b/cli/Cargo.toml
index d0b871f49..087b52477 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -83,6 +83,7 @@ libsui = "0.3.0"
napi_sym.workspace = true
node_resolver.workspace = true
+anstream = "0.6.14"
async-trait.workspace = true
base32.workspace = true
base64.workspace = true
diff --git a/cli/args/flags.rs b/cli/args/flags.rs
index a273d8b37..de6358359 100644
--- a/cli/args/flags.rs
+++ b/cli/args/flags.rs
@@ -9,6 +9,7 @@ use clap::ArgMatches;
use clap::ColorChoice;
use clap::Command;
use clap::ValueHint;
+use color_print::cstr;
use deno_config::glob::FilePatterns;
use deno_config::glob::PathOrPatternSet;
use deno_core::anyhow::bail;
@@ -376,6 +377,7 @@ pub struct WatchFlagsWithPaths {
pub struct TaskFlags {
pub cwd: Option<String>,
pub task: Option<String>,
+ pub is_run: bool,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
@@ -1107,7 +1109,7 @@ impl Flags {
}
}
-static ENV_VARIABLES_HELP: &str = color_print::cstr!(
+static ENV_VARIABLES_HELP: &str = cstr!(
r#"<y>Environment variables:</>
<g>DENO_AUTH_TOKENS</> A semi-colon separated list of bearer tokens and hostnames
to use when fetching remote modules from private repositories
@@ -1132,7 +1134,7 @@ static ENV_VARIABLES_HELP: &str = color_print::cstr!(
<g>NPM_CONFIG_REGISTRY</> URL to use for the npm registry."#
);
-static DENO_HELP: &str = color_print::cstr!(
+static DENO_HELP: &str = cstr!(
"Deno: <g>A modern JavaScript and TypeScript runtime</>
<p(245)>Usage:</> <g>{usage}</>
@@ -1249,6 +1251,19 @@ pub fn flags_from_vec(args: Vec<OsString>) -> clap::error::Result<Flags> {
help_parse(&mut flags, subcommand);
return Ok(flags);
+ } else if let Some(help_subcommand_matches) =
+ matches.subcommand_matches("help")
+ {
+ app.build();
+ let subcommand =
+ if let Some(sub) = help_subcommand_matches.subcommand_name() {
+ app.find_subcommand(sub).unwrap().clone()
+ } else {
+ app
+ };
+
+ help_parse(&mut flags, subcommand);
+ return Ok(flags);
}
if let Some((subcommand, mut m)) = matches.remove_subcommand() {
@@ -1283,15 +1298,6 @@ pub fn flags_from_vec(args: Vec<OsString>) -> clap::error::Result<Flags> {
"upgrade" => upgrade_parse(&mut flags, &mut m),
"vendor" => vendor_parse(&mut flags, &mut m),
"publish" => publish_parse(&mut flags, &mut m),
- "help" => {
- let subcommand = if let Some((sub, _)) = matches.remove_subcommand() {
- app.find_subcommand(sub).unwrap().clone()
- } else {
- app
- };
-
- help_parse(&mut flags, subcommand)
- }
_ => unreachable!(),
}
} else {
@@ -1373,12 +1379,7 @@ fn help_parse(flags: &mut Flags, mut subcommand: Command) {
for (mut i, (arg, heading)) in args.into_iter().enumerate() {
if let Some(heading) = heading {
let heading_i = HEADING_ORDER.iter().position(|h| h == &heading).unwrap();
- i += (if heading == UNSTABLE_HEADING {
- // ensures the unstable section is always last
- 50
- } else {
- heading_i
- }) * 100;
+ i += heading_i * 100;
}
subcommand = subcommand.mut_arg(arg, |arg| arg.display_order(i));
@@ -1546,11 +1547,10 @@ fn command(
fn help_subcommand(app: &Command) -> Command {
command("help", None, UnstableArgsConfig::None)
- .hide(true)
+ .disable_version_flag(true)
.disable_help_subcommand(true)
.subcommands(app.get_subcommands().map(|command| {
Command::new(command.get_name().to_owned())
- .hide(true)
.disable_help_flag(true)
.disable_version_flag(true)
}))
@@ -1582,13 +1582,15 @@ You can add multiple dependencies at once:
fn remove_subcommand() -> Command {
command(
"remove",
- "Remove dependencies from the configuration file.
+ cstr!(
+ "Remove dependencies from the configuration file.
deno remove @std/path
You can remove multiple dependencies at once:
<p(245)>deno remove @std/path @std/assert</>
-",
+"
+ ),
UnstableArgsConfig::None,
)
.defer(|cmd| {
@@ -1637,7 +1639,9 @@ glob {*_,*.,}bench.{js,mjs,ts,mts,jsx,tsx}:
Arg::new("filter")
.long("filter")
.allow_hyphen_values(true)
- .help("Run benchmarks with this string or pattern in the bench name"),
+ .help(
+ "Run benchmarks with this string or regexp pattern in the bench name",
+ ),
)
.arg(
Arg::new("files")
@@ -1743,7 +1747,7 @@ Unless --reload is specified, this command will not re-download already cached d
// past alias for --all
Arg::new("remote")
.long("remote")
- .help("Type-check all modules, including remote")
+ .help("Type-check all modules, including remote ones")
.action(ArgAction::SetTrue)
.conflicts_with("no-remote")
.hide(true)
@@ -1790,11 +1794,11 @@ supported in canary.
Arg::new("include")
.long("include")
.help(
- "Includes an additional module in the compiled executable's module
- graph. Use this flag if a dynamically imported module or a web worker main
- module fails to load in the executable. This flag can be passed multiple
- times, to include multiple additional modules.",
- )
+ cstr!("Includes an additional module in the compiled executable's module graph.
+ <p(245)>Use this flag if a dynamically imported module or a web worker main module
+ fails to load in the executable. This flag can be passed multiple times,
+ to include multiple additional modules.</>",
+ ))
.action(ArgAction::Append)
.value_hint(ValueHint::FilePath)
.help_heading(COMPILE_HEADING),
@@ -1804,7 +1808,7 @@ supported in canary.
.long("output")
.short('o')
.value_parser(value_parser!(String))
- .help("Output file (defaults to $PWD/<inferred-name>)")
+ .help(cstr!("Output file <p(245)>(defaults to $PWD/<<inferred-name>>)</>"))
.value_hint(ValueHint::FilePath)
.help_heading(COMPILE_HEADING),
)
@@ -1936,10 +1940,9 @@ Generate html reports from lcov:
.long("output")
.value_parser(value_parser!(String))
.help(
- "Exports the coverage report in lcov format to the given file.
- Filename should be passed along with '=' For example '--output=foo.lcov'
- If no --output arg is specified then the report is written to stdout.",
- )
+ cstr!("Exports the coverage report in lcov format to the given file.
+ <p(245)>If no --output arg is specified then the report is written to stdout.</>",
+ ))
.require_equals(true)
.value_hint(ValueHint::FilePath),
)
@@ -1952,7 +1955,7 @@ Generate html reports from lcov:
.arg(
Arg::new("detailed")
.long("detailed")
- .help("Output coverage report in detailed format in the terminal.")
+ .help("Output coverage report in detailed format in the terminal")
.action(ArgAction::SetTrue),
)
.arg(
@@ -2019,7 +2022,7 @@ Show documentation for runtime built-ins:
.arg(
Arg::new("name")
.long("name")
- .help("The name that will be displayed in the docs")
+ .help("The name that will be used in the docs (ie for breadcrumbs)")
.action(ArgAction::Set)
.require_equals(true).help_heading(DOC_HEADING)
)
@@ -2042,14 +2045,14 @@ Show documentation for runtime built-ins:
.arg(
Arg::new("strip-trailing-html")
.long("strip-trailing-html")
- .help("Remove trailing .html from various links. Will still generate files with a .html extension.")
+ .help("Remove trailing .html from various links. Will still generate files with a .html extension")
.requires("html")
.action(ArgAction::SetTrue).help_heading(DOC_HEADING)
)
.arg(
Arg::new("default-symbol-map")
.long("default-symbol-map")
- .help("Uses the provided mapping of default name to wanted name for usage blocks.")
+ .help("Uses the provided mapping of default name to wanted name for usage blocks")
.requires("html")
.action(ArgAction::Set)
.require_equals(true).help_heading(DOC_HEADING)
@@ -2135,7 +2138,7 @@ This command has implicit access to all permissions (--allow-all).",
Arg::new("code_arg")
.num_args(1..)
.action(ArgAction::Append)
- .help("Code arg")
+ .help("Code to evaluate")
.value_name("CODE_ARG")
.required_unless_present("help"),
)
@@ -2167,7 +2170,7 @@ Ignore formatting a file by adding an ignore comment at the top of the file:
.arg(config_arg())
.arg(no_config_arg())
.arg(
- Arg::new("check")
+ Arg::new("check")
.long("check")
.help("Check if the source files are formatted")
.num_args(0)
@@ -2214,7 +2217,7 @@ Ignore formatting a file by adding an ignore comment at the top of the file:
.default_missing_value("true")
.require_equals(true)
.help(
- "Use tabs instead of spaces for indentation. Defaults to false.",
+ cstr!( "Use tabs instead of spaces for indentation <p(245)>[default: false]</>"),
)
.help_heading(FMT_HEADING),
)
@@ -2222,7 +2225,7 @@ Ignore formatting a file by adding an ignore comment at the top of the file:
Arg::new("line-width")
.long("line-width")
.alias("options-line-width")
- .help("Define maximum line width. Defaults to 80.")
+ .help(cstr!("Define maximum line width <p(245)>[default: 80]</>"))
.value_parser(value_parser!(NonZeroU32))
.help_heading(FMT_HEADING),
)
@@ -2230,7 +2233,7 @@ Ignore formatting a file by adding an ignore comment at the top of the file:
Arg::new("indent-width")
.long("indent-width")
.alias("options-indent-width")
- .help("Define indentation width. Defaults to 2.")
+ .help(cstr!("Define indentation width <p(245)>[default: 2]</>"))
.value_parser(value_parser!(NonZeroU8))
.help_heading(FMT_HEADING),
)
@@ -2242,7 +2245,7 @@ Ignore formatting a file by adding an ignore comment at the top of the file:
.value_parser(value_parser!(bool))
.default_missing_value("true")
.require_equals(true)
- .help("Use single quotes. Defaults to false.")
+ .help(cstr!("Use single quotes <p(245)>[default: false]</>"))
.help_heading(FMT_HEADING),
)
.arg(
@@ -2250,7 +2253,7 @@ Ignore formatting a file by adding an ignore comment at the top of the file:
.long("prose-wrap")
.alias("options-prose-wrap")
.value_parser(["always", "never", "preserve"])
- .help("Define how prose should be wrapped. Defaults to always.")
+ .help(cstr!("Define how prose should be wrapped <p(245)>[default: always]</>"))
.help_heading(FMT_HEADING),
)
.arg(
@@ -2262,14 +2265,14 @@ Ignore formatting a file by adding an ignore comment at the top of the file:
.default_missing_value("true")
.require_equals(true)
.help(
- "Don't use semicolons except where necessary. Defaults to false.",
+ cstr!("Don't use semicolons except where necessary <p(245)>[default: false]</>"),
)
.help_heading(FMT_HEADING),
)
.arg(
Arg::new("unstable-css")
.long("unstable-css")
- .help("Enable formatting CSS, SCSS, Sass and Less files.")
+ .help("Enable formatting CSS, SCSS, Sass and Less files")
.value_parser(FalseyValueParser::new())
.action(ArgAction::SetTrue)
.help_heading(FMT_HEADING),
@@ -2277,21 +2280,23 @@ Ignore formatting a file by adding an ignore comment at the top of the file:
.arg(
Arg::new("unstable-html")
.long("unstable-html")
- .help("Enable formatting HTML files.")
+ .help("Enable formatting HTML files")
.value_parser(FalseyValueParser::new())
- .action(ArgAction::SetTrue),
+ .action(ArgAction::SetTrue)
+ .help_heading(FMT_HEADING),
)
.arg(
Arg::new("unstable-component")
.long("unstable-component")
- .help("Enable formatting Svelte, Vue, Astro and Angular files.")
+ .help("Enable formatting Svelte, Vue, Astro and Angular files")
.value_parser(FalseyValueParser::new())
- .action(ArgAction::SetTrue),
+ .action(ArgAction::SetTrue)
+ .help_heading(FMT_HEADING),
)
.arg(
Arg::new("unstable-yaml")
.long("unstable-yaml")
- .help("Enable formatting YAML files.")
+ .help("Enable formatting YAML files")
.value_parser(FalseyValueParser::new())
.action(ArgAction::SetTrue)
.help_heading(FMT_HEADING),
@@ -2304,7 +2309,12 @@ fn init_subcommand() -> Command {
|cmd| {
cmd
.arg(Arg::new("dir").value_hint(ValueHint::DirPath))
- .arg(Arg::new("lib").long("lib").action(ArgAction::SetTrue))
+ .arg(
+ Arg::new("lib")
+ .long("lib")
+ .help("Generate an example library project")
+ .action(ArgAction::SetTrue),
+ )
.arg(
Arg::new("serve")
.long("serve")
@@ -2707,18 +2717,18 @@ fn repl_subcommand() -> Command {
.num_args(1..)
.use_value_delimiter(true)
.require_equals(true)
- .help("Evaluates the provided file(s) as scripts when the REPL starts. Accepts file paths and URLs.")
+ .help("Evaluates the provided file(s) as scripts when the REPL starts. Accepts file paths and URLs")
.value_hint(ValueHint::AnyPath),
)
.arg(
Arg::new("eval")
.long("eval")
- .help("Evaluates the provided code when the REPL starts.")
+ .help("Evaluates the provided code when the REPL starts")
.value_name("code"),
)
- .after_help(color_print::cstr!("<y>Environment variables:</>
+ .after_help(cstr!("<y>Environment variables:</>
<g>DENO_REPL_HISTORY</> Set REPL history file path. History file is disabled when the value is empty.
- <p(245)>(defaults to $DENO_DIR/deno_history.txt)</>"))
+ <p(245)>[default: $DENO_DIR/deno_history.txt]</>"))
)
.arg(env_file_arg())
}
@@ -2734,16 +2744,14 @@ fn run_args(command: Command, top_level: bool) -> Command {
.arg(if top_level {
script_arg().trailing_var_arg(true).hide(true)
} else {
- script_arg()
- .required_unless_present_any(["help", "v8-flags"])
- .trailing_var_arg(true)
+ script_arg().trailing_var_arg(true)
})
.arg(env_file_arg())
.arg(no_code_cache_arg())
}
fn run_subcommand() -> Command {
- run_args(command("run", color_print::cstr!("Run a JavaScript or TypeScript program, or a task or script.
+ run_args(command("run", cstr!("Run a JavaScript or TypeScript program, or a task or script.
By default all programs are run in sandbox without access to disk, network or ability to spawn subprocesses.
<p(245)>deno run https://examples.deno.land/hello-world.ts</>
@@ -2774,13 +2782,13 @@ fn serve_subcommand() -> Command {
.arg(
Arg::new("port")
.long("port")
- .help("The TCP port to serve on, defaulting to 8000. Pass 0 to pick a random free port.")
+ .help("The TCP port to serve on, defaulting to 8000. Pass 0 to pick a random free port")
.value_parser(value_parser!(u16)),
)
.arg(
Arg::new("host")
.long("host")
- .help("The TCP address to serve on, defaulting to 0.0.0.0 (all interfaces).")
+ .help("The TCP address to serve on, defaulting to 0.0.0.0 (all interfaces)")
.value_parser(serve_host_validator),
)
.arg(
@@ -2874,7 +2882,7 @@ Directory arguments are expanded to all contained files matching the glob
.arg(
Arg::new("trace-ops")
.long("trace-ops")
- .help("Deprecated alias for --trace-leaks.")
+ .help("Deprecated alias for --trace-leaks")
.hide(true)
.action(ArgAction::SetTrue)
.help_heading(TEST_HEADING),
@@ -2882,7 +2890,7 @@ Directory arguments are expanded to all contained files matching the glob
.arg(
Arg::new("trace-leaks")
.long("trace-leaks")
- .help("Enable tracing of leaks. Useful when debugging leaking ops in test, but impacts test execution time.")
+ .help("Enable tracing of leaks. Useful when debugging leaking ops in test, but impacts test execution time")
.action(ArgAction::SetTrue)
.help_heading(TEST_HEADING),
)
@@ -2897,7 +2905,7 @@ Directory arguments are expanded to all contained files matching the glob
Arg::new("fail-fast")
.long("fail-fast")
.alias("failfast")
- .help("Stop after N errors. Defaults to stopping after first failure.")
+ .help("Stop after N errors. Defaults to stopping after first failure")
.num_args(0..=1)
.require_equals(true)
.value_name("N")
@@ -2923,7 +2931,7 @@ Directory arguments are expanded to all contained files matching the glob
Arg::new("filter")
.allow_hyphen_values(true)
.long("filter")
- .help("Run tests with this string or pattern in the test name")
+ .help("Run tests with this string or regexp pattern in the test name")
.help_heading(TEST_HEADING),
)
.arg(
@@ -2946,14 +2954,14 @@ Directory arguments are expanded to all contained files matching the glob
.conflicts_with("inspect")
.conflicts_with("inspect-wait")
.conflicts_with("inspect-brk")
- .help("Collect coverage profile data into DIR. If DIR is not specified, it uses 'coverage/'.")
+ .help("Collect coverage profile data into DIR. If DIR is not specified, it uses 'coverage/'")
.help_heading(TEST_HEADING),
)
.arg(
Arg::new("clean")
.long("clean")
- .help("Empty the temporary coverage profile data directory before running tests.
- Note: running multiple `deno test --clean` calls in series or parallel for the same coverage directory may cause race conditions.")
+ .help(cstr!("Empty the temporary coverage profile data directory before running tests.
+ <p(245)>Note: running multiple `deno test --clean` calls in series or parallel for the same coverage directory may cause race conditions.</>"))
.action(ArgAction::SetTrue)
.help_heading(TEST_HEADING),
)
@@ -2990,13 +2998,13 @@ Directory arguments are expanded to all contained files matching the glob
.long("junit-path")
.value_name("PATH")
.value_hint(ValueHint::FilePath)
- .help("Write a JUnit XML test report to PATH. Use '-' to write to stdout which is the default when PATH is not provided.")
+ .help("Write a JUnit XML test report to PATH. Use '-' to write to stdout which is the default when PATH is not provided")
.help_heading(TEST_HEADING)
)
.arg(
Arg::new("reporter")
.long("reporter")
- .help("Select reporter to use. Default to 'pretty'.")
+ .help("Select reporter to use. Default to 'pretty'")
.value_parser(["pretty", "dot", "junit", "tap"])
.help_heading(TEST_HEADING)
)
@@ -3013,7 +3021,7 @@ Directory arguments are expanded to all contained files matching the glob
fn parallel_arg(descr: &str, jobs_fallback: bool) -> Arg {
let arg = Arg::new("parallel")
.long("parallel")
- .help(format!("Run {descr} in parallel. Parallelism defaults to the number of available CPUs or the value of the DENO_JOBS environment variable."))
+ .help(format!("Run {descr} in parallel. Parallelism defaults to the number of available CPUs or the value of the DENO_JOBS environment variable"))
.action(ArgAction::SetTrue);
if jobs_fallback {
arg.conflicts_with("jobs")
@@ -3216,7 +3224,8 @@ fn publish_subcommand() -> Command {
).arg(
Arg::new("no-provenance")
.long("no-provenance")
- .help("Disable provenance attestation. Enabled by default on Github actions, publicly links the package to where it was built and published from.")
+ .help(cstr!("Disable provenance attestation.
+ <p(245)>Enabled by default on Github actions, publicly links the package to where it was built and published from.</>"))
.action(ArgAction::SetTrue)
.help_heading(PUBLISH_HEADING)
)
@@ -3248,33 +3257,51 @@ fn compile_args_without_check_args(app: Command) -> Command {
fn permission_args(app: Command) -> Command {
app
- .after_help(color_print::cstr!(r#"<y>Permission options:</>
-Docs: https://docs.deno.com/go/permissions
-
- <g>-A, --allow-all</> Allow all permissions.
- <g>-R, --{allow,deny}-read[=<<PATH>...]</> Allow / deny file system read access. Optionally specify allowed / denied paths.
- <p(245)>--allow-read | --allow-read="/etc,/var/log.txt" | --deny-read="/etc/hosts"</>
- <g>-W, --{allow,write}-read[=<<PATH>...]</> Allow / deny file system write access. Optionally specify allowed / denied paths.
- <p(245)>--allow-write | --allow-write="/etc,/var/log.txt" | --deny-write="/etc/hosts"</>
- <g>-N, --{allow,deny}-net[=<<IP_OR_HOSTNAME>...]</> Allow / deny network access. Optionally specify allowed IP addresses and host names, with ports as necessary.
- <p(245)>--allow-net | --allow-net="localhost:8080,deno.land" | --deny-net="deno.com"</>
- <g>-E --{allow,deny}-env[=<<VARIABLE_NAME>...]</> Allow / deny access to environment variables. Optionally specify accessible / inacessible environment variables.
- <p(245)>--allow-env | --allow-env="PORT,HOME,PATH" | --deny-env="ACCESS_TOKEN"</>
- <g>-S --{allow,deny}-sys[=<<API_NAME>...]</> Allow / deny access to OS information. Optionally allow / deny specific APIs by function name.
- <p(245)>--allow-sys | --allow-sys="systemMemoryInfo,osRelease" | --deny-sys="hostname"</>
- <g>--{allow,deny}-run[=<<PROGRAM_NAME>...]</> Allow / deny running subprocesses. Optionally specify allowed / denied runnable program names.
- <p(245)>--allow-run | --allow-run="whoami,ps" | --deny-run="cat"</>
- <g>--{allow,deny}-ffi[=<<PATH>...]</> (Unstable) Allow / deny loading dynamic libraries. Optionally specify allowed / denied directories or files.
- <p(245)>--allow-ffi | --allow-ffi="./libfoo.so" | --deny-ffi="./libfoo.so"</>
- <g>--{allow,deny}-hrtime</> Allow / deny high-resolution time measurement. Note: this can enable timing attacks and fingerprinting.
- <g>--no-prompt</> Always throw if required permission wasn't passed. Can also be set via the DENO_NO_PROMPT environment variable.
+ .after_help(cstr!(r#"<y>Permission options:</>
+Docs: <c>https://docs.deno.com/go/permissions</>
+
+ <g>-A, --allow-all</> Allow all permissions.
+ <g>--no-prompt</> Always throw if required permission wasn't passed.
+ <p(245)>Can also be set via the DENO_NO_PROMPT environment variable.</>
+ <g>-R, --allow-read[=<<PATH>...]</> Allow file system read access. Optionally specify allowed paths.
+ <p(245)>--allow-read | --allow-read="/etc,/var/log.txt"</>
+ <g>-W, --allow-write[=<<PATH>...]</> Allow file system write access. Optionally specify allowed paths.
+ <p(245)>--allow-write | --allow-write="/etc,/var/log.txt"</>
+ <g>-N, --allow-net[=<<IP_OR_HOSTNAME>...]</> Allow network access. Optionally specify allowed IP addresses and host names, with ports as necessary.
+ <p(245)>--allow-net | --allow-net="localhost:8080,deno.land"</>
+ <g>-E, --allow-env[=<<VARIABLE_NAME>...]</> Allow access to environment variables. Optionally specify accessible environment variables.
+ <p(245)>--allow-env | --allow-env="PORT,HOME,PATH"</>
+ <g>-S, --allow-sys[=<<API_NAME>...]</> Allow access to OS information. Optionally allow specific APIs by function name.
+ <p(245)>--allow-sys | --allow-sys="systemMemoryInfo,osRelease"</>
+ <g>--allow-run[=<<PROGRAM_NAME>...]</> Allow running subprocesses. Optionally specify allowed runnable program names.
+ <p(245)>--allow-run | --allow-run="whoami,ps"</>
+ <g>--allow-ffi[=<<PATH>...]</> (Unstable) Allow loading dynamic libraries. Optionally specify allowed directories or files.
+ <p(245)>--allow-ffi | --allow-ffi="./libfoo.so"</>
+ <g>--allow-hrtime</> Allow high-resolution time measurement. Note: this can enable timing attacks and fingerprinting.
+ <p(245)>--allow-hrtime</>
+ <g> --deny-read[=<<PATH>...]</> Deny file system read access. Optionally specify denied paths.
+ <p(245)>--deny-read | --deny-read="/etc,/var/log.txt"</>
+ <g> --deny-write[=<<PATH>...]</> Deny file system write access. Optionally specify denied paths.
+ <p(245)>--deny-write | --deny-write="/etc,/var/log.txt"</>
+ <g> --deny-net[=<<IP_OR_HOSTNAME>...]</> Deny network access. Optionally specify defined IP addresses and host names, with ports as necessary.
+ <p(245)>--deny-net | --deny-net="localhost:8080,deno.land"</>
+ <g> --deny-env[=<<VARIABLE_NAME>...]</> Deny access to environment variables. Optionally specify inacessible environment variables.
+ <p(245)>--deny-env | --deny-env="PORT,HOME,PATH"</>
+ <g>-S, --deny-sys[=<<API_NAME>...]</> Deny access to OS information. Optionally deny specific APIs by function name.
+ <p(245)>--deny-sys | --deny-sys="systemMemoryInfo,osRelease"</>
+ <g>--deny-run[=<<PROGRAM_NAME>...]</> Deny running subprocesses. Optionally specify denied runnable program names.
+ <p(245)>--deny-run | --deny-run="whoami,ps"</>
+ <g>--deny-ffi[=<<PATH>...]</> (Unstable) Deny loading dynamic libraries. Optionally specify denied directories or files.
+ <p(245)>--deny-ffi | --deny-ffi="./libfoo.so"</>
+ <g>--deny-hrtime</> Deny high-resolution time measurement.
+ <p(245)>--deny-hrtime</>
"#))
.arg(
Arg::new("allow-all")
.short('A')
.long("allow-all")
.action(ArgAction::SetTrue)
- .help("Allow all permissions.")
+ .help("Allow all permissions")
.hide(true),
)
.arg(
@@ -3285,7 +3312,7 @@ Docs: https://docs.deno.com/go/permissions
.use_value_delimiter(true)
.require_equals(true)
.value_name("PATH")
- .help("Allow file system read access. Optionally specify allowed paths.")
+ .help("Allow file system read access. Optionally specify allowed paths")
.value_parser(value_parser!(String))
.value_hint(ValueHint::AnyPath)
.hide(true),
@@ -3297,7 +3324,7 @@ Docs: https://docs.deno.com/go/permissions
.use_value_delimiter(true)
.require_equals(true)
.value_name("PATH")
- .help("Deny file system read access. Optionally specify denied paths.")
+ .help("Deny file system read access. Optionally specify denied paths")
.value_parser(value_parser!(String))
.value_hint(ValueHint::AnyPath)
.hide(true),
@@ -3310,7 +3337,7 @@ Docs: https://docs.deno.com/go/permissions
.use_value_delimiter(true)
.require_equals(true)
.value_name("PATH")
- .help("Allow file system write access. Optionally specify allowed paths.")
+ .help("Allow file system write access. Optionally specify allowed paths")
.value_parser(value_parser!(String))
.value_hint(ValueHint::AnyPath)
.hide(true),
@@ -3322,7 +3349,7 @@ Docs: https://docs.deno.com/go/permissions
.use_value_delimiter(true)
.require_equals(true)
.value_name("PATH")
- .help("Deny file system write access. Optionally specify denied paths.")
+ .help("Deny file system write access. Optionally specify denied paths")
.value_parser(value_parser!(String))
.value_hint(ValueHint::AnyPath)
.hide(true),
@@ -3335,7 +3362,7 @@ Docs: https://docs.deno.com/go/permissions
.use_value_delimiter(true)
.require_equals(true)
.value_name("IP_OR_HOSTNAME")
- .help("Allow network access. Optionally specify allowed IP addresses and host names, with ports as necessary.")
+ .help("Allow network access. Optionally specify allowed IP addresses and host names, with ports as necessary")
.value_parser(flags_net::validator)
.hide(true),
)
@@ -3346,7 +3373,7 @@ Docs: https://docs.deno.com/go/permissions
.use_value_delimiter(true)
.require_equals(true)
.value_name("IP_OR_HOSTNAME")
- .help("Deny network access. Optionally specify denied IP addresses and host names, with ports as necessary.")
+ .help("Deny network access. Optionally specify denied IP addresses and host names, with ports as necessary")
.value_parser(flags_net::validator)
.hide(true),
)
@@ -3358,7 +3385,7 @@ Docs: https://docs.deno.com/go/permissions
.use_value_delimiter(true)
.require_equals(true)
.value_name("VARIABLE_NAME")
- .help("Allow access to system environment information. Optionally specify accessible environment variables.")
+ .help("Allow access to system environment information. Optionally specify accessible environment variables")
.value_parser(|key: &str| {
if key.is_empty() || key.contains(&['=', '\0'] as &[char]) {
return Err(format!("invalid key \"{key}\""));
@@ -3379,7 +3406,7 @@ Docs: https://docs.deno.com/go/permissions
.use_value_delimiter(true)
.require_equals(true)
.value_name("VARIABLE_NAME")
- .help("Deny access to system environment information. Optionally specify accessible environment variables.")
+ .help("Deny access to system environment information. Optionally specify accessible environment variables")
.value_parser(|key: &str| {
if key.is_empty() || key.contains(&['=', '\0'] as &[char]) {
return Err(format!("invalid key \"{key}\""));
@@ -3401,7 +3428,7 @@ Docs: https://docs.deno.com/go/permissions
.use_value_delimiter(true)
.require_equals(true)
.value_name("API_NAME")
- .help("Allow access to OS information. Optionally allow specific APIs by function name.")
+ .help("Allow access to OS information. Optionally allow specific APIs by function name")
.value_parser(|key: &str| parse_sys_kind(key).map(ToString::to_string))
.hide(true),
)
@@ -3412,7 +3439,7 @@ Docs: https://docs.deno.com/go/permissions
.use_value_delimiter(true)
.require_equals(true)
.value_name("API_NAME")
- .help("Deny access to OS information. Optionally deny specific APIs by function name.")
+ .help("Deny access to OS information. Optionally deny specific APIs by function name")
.value_parser(|key: &str| parse_sys_kind(key).map(ToString::to_string))
.hide(true),
)
@@ -3423,7 +3450,7 @@ Docs: https://docs.deno.com/go/permissions
.use_value_delimiter(true)
.require_equals(true)
.value_name("PROGRAM_NAME")
- .help("Allow running subprocesses. Optionally specify allowed runnable program names.")
+ .help("Allow running subprocesses. Optionally specify allowed runnable program names")
.hide(true),
)
.arg(
@@ -3433,7 +3460,7 @@ Docs: https://docs.deno.com/go/permissions
.use_value_delimiter(true)
.require_equals(true)
.value_name("PROGRAM_NAME")
- .help("Deny running subprocesses. Optionally specify denied runnable program names.")
+ .help("Deny running subprocesses. Optionally specify denied runnable program names")
.hide(true),
)
.arg(
@@ -3443,7 +3470,7 @@ Docs: https://docs.deno.com/go/permissions
.use_value_delimiter(true)
.require_equals(true)
.value_name("PATH")
- .help("(Unstable) Allow loading dynamic libraries. Optionally specify allowed directories or files.")
+ .help("(Unstable) Allow loading dynamic libraries. Optionally specify allowed directories or files")
.value_parser(value_parser!(String))
.value_hint(ValueHint::AnyPath)
.hide(true),
@@ -3455,7 +3482,7 @@ Docs: https://docs.deno.com/go/permissions
.use_value_delimiter(true)
.require_equals(true)
.value_name("PATH")
- .help("(Unstable) Deny loading dynamic libraries. Optionally specify denied directories or files.")
+ .help("(Unstable) Deny loading dynamic libraries. Optionally specify denied directories or files")
.value_parser(value_parser!(String))
.value_hint(ValueHint::AnyPath)
.hide(true),
@@ -3464,14 +3491,14 @@ Docs: https://docs.deno.com/go/permissions
Arg::new("allow-hrtime")
.long("allow-hrtime")
.action(ArgAction::SetTrue)
- .help("Allow high-resolution time measurement. Note: this can enable timing attacks and fingerprinting.")
+ .help("Allow high-resolution time measurement. Note: this can enable timing attacks and fingerprinting")
.hide(true),
)
.arg(
Arg::new("deny-hrtime")
.long("deny-hrtime")
.action(ArgAction::SetTrue)
- .help("Deny high-resolution time measurement. Note: this can prevent timing attacks and fingerprinting.")
+ .help("Deny high-resolution time measurement. Note: this can prevent timing attacks and fingerprinting")
.hide(true),
)
.arg(
@@ -3515,7 +3542,8 @@ fn inspect_args(app: Command) -> Command {
Arg::new("inspect")
.long("inspect")
.value_name("HOST_AND_PORT")
- .help("Activate inspector on host:port (default: 127.0.0.1:9229)")
+ .default_missing_value("127.0.0.1:9229")
+ .help(cstr!("Activate inspector on host:port <p(245)>[default: 127.0.0.1:9229]</>"))
.num_args(0..=1)
.require_equals(true)
.value_parser(value_parser!(SocketAddr))
@@ -3525,6 +3553,7 @@ fn inspect_args(app: Command) -> Command {
Arg::new("inspect-brk")
.long("inspect-brk")
.value_name("HOST_AND_PORT")
+ .default_missing_value("127.0.0.1:9229")
.help(
"Activate inspector on host:port, wait for debugger to connect and break at the start of user script",
)
@@ -3537,6 +3566,7 @@ fn inspect_args(app: Command) -> Command {
Arg::new("inspect-wait")
.long("inspect-wait")
.value_name("HOST_AND_PORT")
+ .default_missing_value("127.0.0.1:9229")
.help(
"Activate inspector on host:port and wait for debugger to connect before running user code",
)
@@ -3552,10 +3582,10 @@ fn import_map_arg() -> Arg {
.long("import-map")
.alias("importmap")
.value_name("FILE")
- .help(
- "Load import map file from local file or remote URL.
- Docs: https://docs.deno.com/runtime/manual/basics/import_maps",
- )
+ .help(cstr!(
+ "Load import map file from local file or remote URL
+ <p(245)>Docs: https://docs.deno.com/runtime/manual/basics/import_maps</>",
+ ))
.value_hint(ValueHint::FilePath)
.help_heading(DEPENDENCY_MANAGEMENT_HEADING)
}
@@ -3565,11 +3595,11 @@ fn env_file_arg() -> Arg {
.long("env-file")
.alias("env")
.value_name("FILE")
- .help(
- "Load environment variables from local file.
- Only the first environment variable with a given key is used.
- Existing process environment variables are not overwritten.",
- )
+ .help(cstr!(
+ "Load environment variables from local file
+ <p(245)>Only the first environment variable with a given key is used.
+ Existing process environment variables are not overwritten.</>"
+ ))
.value_hint(ValueHint::FilePath)
.default_missing_value(".env")
.require_equals(true)
@@ -3585,7 +3615,7 @@ fn reload_arg() -> Arg {
.long("reload")
.value_name("CACHE_BLOCKLIST")
.help(
- color_print::cstr!("Reload source code cache (recompile TypeScript)
+ cstr!("Reload source code cache (recompile TypeScript)
<p(245)>no value Reload everything
jsr:@std/http/file-server,jsr:@std/assert/assert-equals Reloads specific modules
npm: Reload all npm modules
@@ -3683,9 +3713,9 @@ fn v8_flags_arg() -> Arg {
.use_value_delimiter(true)
.require_equals(true)
.value_name("V8_FLAGS")
- .help("To see a list of all available flags use --v8-flags=--help.
- Flags can also be set via the DENO_V8_FLAGS environment variable.
- Any flags set with this flag are appended after the DENO_V8_FLAGS environment variable")
+ .help( cstr!("To see a list of all available flags use --v8-flags=--help
+ <p(245)>Flags can also be set via the DENO_V8_FLAGS environment variable.
+ Any flags set with this flag are appended after the DENO_V8_FLAGS environment variable</>"))
}
fn seed_arg() -> Arg {
@@ -3713,14 +3743,14 @@ fn hmr_arg(takes_files: bool) -> Arg {
.use_value_delimiter(true)
.require_equals(true)
.help(
- color_print::cstr!(
+ cstr!(
"Watch for file changes and restart process automatically.
<p(245)>Local files from entry point module graph are watched by default.
Additional paths might be watched by passing them as arguments to this flag.</>"),
)
.value_hint(ValueHint::AnyPath)
} else {
- arg.action(ArgAction::SetTrue).help(color_print::cstr!(
+ arg.action(ArgAction::SetTrue).help(cstr!(
"Watch for file changes and restart process automatically.
<p(245)>Only local files from entry point module graph are watched.</>"
))
@@ -3740,14 +3770,14 @@ fn watch_arg(takes_files: bool) -> Arg {
.use_value_delimiter(true)
.require_equals(true)
.help(
- color_print::cstr!(
+ cstr!(
"Watch for file changes and restart process automatically.
<p(245)>Local files from entry point module graph are watched by default.
Additional paths might be watched by passing them as arguments to this flag.</>"),
)
.value_hint(ValueHint::AnyPath)
} else {
- arg.action(ArgAction::SetTrue).help(color_print::cstr!(
+ arg.action(ArgAction::SetTrue).help(cstr!(
"Watch for file changes and restart process automatically.
<p(245)>Only local files from entry point module graph are watched.</>"
))
@@ -3789,10 +3819,7 @@ fn no_check_arg() -> Arg {
.require_equals(true)
.value_name("NO_CHECK_TYPE")
.long("no-check")
- .help(
- "Skip type-checking. If the value of '--no-check=remote' is supplied,
- diagnostic errors from remote modules will be ignored.",
- )
+ .help("Skip type-checking. If the value of \"remote\" is supplied, diagnostic errors from remote modules will be ignored")
.help_heading(TYPE_CHECKING_HEADING)
}
@@ -3807,17 +3834,16 @@ fn check_arg(checks_local_by_default: bool) -> Arg {
if checks_local_by_default {
arg.help(
- "Set type-checking behavior. This subcommand type-checks local modules by
- default, so adding --check is redundant.
- If the value of \"all\" is supplied, remote modules will be included.
- Alternatively, the 'deno check' subcommand can be used.",
- )
+ cstr!("Set type-checking behavior. This subcommand type-checks local modules by default, so adding --check is redundant
+ <p(245)>If the value of \"all\" is supplied, remote modules will be included.
+ Alternatively, the 'deno check' subcommand can be used</>",
+ ))
} else {
- arg.help(
- "Enable type-checking. This subcommand does not type-check by default.
- If the value of \"all\" is supplied, remote modules will be included.
- Alternatively, the 'deno check' subcommand can be used.",
- )
+ arg.help(cstr!(
+ "Enable type-checking. This subcommand does not type-check by default
+ <p(245)>If the value of \"all\" is supplied, remote modules will be included.
+ Alternatively, the 'deno check' subcommand can be used</>"
+ ))
}
}
@@ -3854,7 +3880,7 @@ fn lock_write_arg() -> Arg {
Arg::new("lock-write")
.action(ArgAction::SetTrue)
.long("lock-write")
- .help("Force overwriting the lock file.")
+ .help("Force overwriting the lock file")
.conflicts_with("no-lock")
.hide(true)
}
@@ -3873,10 +3899,10 @@ fn config_arg() -> Arg {
.short('c')
.long("config")
.value_name("FILE")
- .help("Configure different aspects of deno including TypeScript, linting, and code formatting.
- Typically the configuration file will be called `deno.json` or `deno.jsonc` and
+ .help(cstr!("Configure different aspects of deno including TypeScript, linting, and code formatting
+ <p(245)>Typically the configuration file will be called `deno.json` or `deno.jsonc` and
automatically detected; in that case this flag is not necessary.
- Docs: https://docs.deno.com/go/config")
+ Docs: https://docs.deno.com/go/config</>"))
.value_hint(ValueHint::FilePath)
}
@@ -3884,7 +3910,7 @@ fn no_config_arg() -> Arg {
Arg::new("no-config")
.long("no-config")
.action(ArgAction::SetTrue)
- .help("Disable automatic loading of the configuration file.")
+ .help("Disable automatic loading of the configuration file")
.conflicts_with("config")
}
@@ -3923,10 +3949,7 @@ fn vendor_arg() -> Arg {
.value_parser(value_parser!(bool))
.default_missing_value("true")
.require_equals(true)
- .help(
- "Enables or disables the use of a local vendor folder
- for remote modules and node_modules folder for npm packages",
- )
+ .help("Toggles local vendor folder usage for remote modules and a node_modules folder for npm packages")
.help_heading(DEPENDENCY_MANAGEMENT_HEADING)
}
@@ -3950,7 +3973,8 @@ fn allow_scripts_arg() -> Arg {
.require_equals(true)
.value_name("PACKAGE")
.value_parser(parse_packages_allowed_scripts)
- .help("Allow running npm lifecycle scripts for the given packages. Note: Scripts will only be executed when using a node_modules directory (`--node-modules-dir`)")
+ .help(cstr!("Allow running npm lifecycle scripts for the given packages
+ <p(245)>Note: Scripts will only be executed when using a node_modules directory (`--node-modules-dir`)</>"))
}
enum UnstableArgsConfig {
@@ -3972,7 +3996,8 @@ impl Iterator for UnstableArgsIter {
let arg = if self.idx == 0 {
Arg::new("unstable")
.long("unstable")
- .help("Enable all unstable features and APIs. Instead of using this flag, consider enabling individual unstable features.\n To view the list of individual unstable feature flags, run this command again with --help=unstable.")
+ .help(cstr!("Enable all unstable features and APIs. Instead of using this flag, consider enabling individual unstable features
+ <p(245)>To view the list of individual unstable feature flags, run this command again with --help=unstable</>"))
.action(ArgAction::SetTrue)
.hide(matches!(self.cfg, UnstableArgsConfig::None))
} else if self.idx == 1 {
@@ -4006,9 +4031,7 @@ impl Iterator for UnstableArgsIter {
} else if self.idx == 3 {
Arg::new("unstable-sloppy-imports")
.long("unstable-sloppy-imports")
- .help(
- "Enable unstable resolving of specifiers by extension probing, .js to .ts, and directory probing.",
- )
+ .help("Enable unstable resolving of specifiers by extension probing, .js to .ts, and directory probing")
.env("DENO_UNSTABLE_SLOPPY_IMPORTS")
.value_parser(FalseyValueParser::new())
.action(ArgAction::SetTrue)
@@ -4628,7 +4651,7 @@ fn repl_parse(flags: &mut Flags, matches: &mut ArgMatches) {
fn run_parse(
flags: &mut Flags,
matches: &mut ArgMatches,
- mut app: Command,
+ app: Command,
bare: bool,
) -> clap::error::Result<()> {
// todo(dsherret): remove this in Deno 2.0
@@ -4679,35 +4702,31 @@ fn run_parse(
}
runtime_args_parse(flags, matches, true, true);
+ ext_arg_parse(flags, matches);
flags.code_cache_enabled = !matches.get_flag("no-code-cache");
- let mut script_arg =
- matches.remove_many::<String>("script_arg").ok_or_else(|| {
- if bare {
- app.override_usage("deno [OPTIONS] [COMMAND] [SCRIPT_ARG]...").error(
- clap::error::ErrorKind::MissingRequiredArgument,
- "[SCRIPT_ARG] may only be omitted with --v8-flags=--help, else to use the repl with arguments, please use the `deno repl` subcommand",
- )
- } else {
- app.find_subcommand_mut("run").unwrap().error(
- clap::error::ErrorKind::MissingRequiredArgument,
- "[SCRIPT_ARG] may only be omitted with --v8-flags=--help",
- )
- }
- })?;
-
- let script = script_arg.next().unwrap();
- flags.argv.extend(script_arg);
-
- ext_arg_parse(flags, matches);
- temp_netlify_deno_1_hack(flags, &script);
-
- flags.subcommand = DenoSubcommand::Run(RunFlags {
- script,
- watch: watch_arg_parse_with_paths(matches),
- bare,
- });
+ if let Some(mut script_arg) = matches.remove_many::<String>("script_arg") {
+ let script = script_arg.next().unwrap();
+ flags.argv.extend(script_arg);
+ temp_netlify_deno_1_hack(flags, &script);
+ flags.subcommand = DenoSubcommand::Run(RunFlags {
+ script,
+ watch: watch_arg_parse_with_paths(matches),
+ bare,
+ });
+ } else if bare {
+ return Err(app.override_usage("deno [OPTIONS] [COMMAND] [SCRIPT_ARG]...").error(
+ clap::error::ErrorKind::MissingRequiredArgument,
+ "[SCRIPT_ARG] may only be omitted with --v8-flags=--help, else to use the repl with arguments, please use the `deno repl` subcommand",
+ ));
+ } else {
+ flags.subcommand = DenoSubcommand::Task(TaskFlags {
+ cwd: None,
+ task: None,
+ is_run: true,
+ });
+ }
Ok(())
}
@@ -4781,6 +4800,7 @@ fn task_parse(flags: &mut Flags, matches: &mut ArgMatches) {
let mut task_flags = TaskFlags {
cwd: matches.remove_one::<String>("cwd"),
task: None,
+ is_run: false,
};
if let Some((task, mut matches)) = matches.remove_subcommand() {
@@ -5153,34 +5173,9 @@ fn runtime_args_parse(
}
fn inspect_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
- let default = || "127.0.0.1:9229".parse::<SocketAddr>().unwrap();
- flags.inspect = if matches.contains_id("inspect") {
- Some(
- matches
- .remove_one::<SocketAddr>("inspect")
- .unwrap_or_else(default),
- )
- } else {
- None
- };
- flags.inspect_brk = if matches.contains_id("inspect-brk") {
- Some(
- matches
- .remove_one::<SocketAddr>("inspect-brk")
- .unwrap_or_else(default),
- )
- } else {
- None
- };
- flags.inspect_wait = if matches.contains_id("inspect-wait") {
- Some(
- matches
- .remove_one::<SocketAddr>("inspect-wait")
- .unwrap_or_else(default),
- )
- } else {
- None
- };
+ flags.inspect = matches.remove_one::<SocketAddr>("inspect");
+ flags.inspect_brk = matches.remove_one::<SocketAddr>("inspect-brk");
+ flags.inspect_wait = matches.remove_one::<SocketAddr>("inspect-wait");
}
fn import_map_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
@@ -5886,10 +5881,7 @@ mod tests {
);
let r = flags_from_vec(svec!["deno", "run", "--v8-flags=--expose-gc"]);
- assert!(r
- .unwrap_err()
- .to_string()
- .contains("[SCRIPT_ARG] may only be omitted with --v8-flags=--help"));
+ assert!(r.is_ok());
}
#[test]
@@ -10341,6 +10333,7 @@ mod tests {
subcommand: DenoSubcommand::Task(TaskFlags {
cwd: None,
task: Some("build".to_string()),
+ is_run: false,
}),
argv: svec!["hello", "world"],
..Flags::default()
@@ -10354,6 +10347,7 @@ mod tests {
subcommand: DenoSubcommand::Task(TaskFlags {
cwd: None,
task: Some("build".to_string()),
+ is_run: false,
}),
..Flags::default()
}
@@ -10366,6 +10360,7 @@ mod tests {
subcommand: DenoSubcommand::Task(TaskFlags {
cwd: Some("foo".to_string()),
task: Some("build".to_string()),
+ is_run: false,
}),
..Flags::default()
}
@@ -10390,6 +10385,7 @@ mod tests {
subcommand: DenoSubcommand::Task(TaskFlags {
cwd: None,
task: Some("build".to_string()),
+ is_run: false,
}),
argv: svec!["--", "hello", "world"],
config_flag: ConfigFlag::Path("deno.json".to_owned()),
@@ -10406,6 +10402,7 @@ mod tests {
subcommand: DenoSubcommand::Task(TaskFlags {
cwd: Some("foo".to_string()),
task: Some("build".to_string()),
+ is_run: false,
}),
argv: svec!["--", "hello", "world"],
..Flags::default()
@@ -10423,6 +10420,7 @@ mod tests {
subcommand: DenoSubcommand::Task(TaskFlags {
cwd: None,
task: Some("build".to_string()),
+ is_run: false,
}),
argv: svec!["--"],
..Flags::default()
@@ -10439,6 +10437,7 @@ mod tests {
subcommand: DenoSubcommand::Task(TaskFlags {
cwd: None,
task: Some("build".to_string()),
+ is_run: false,
}),
argv: svec!["-1", "--test"],
..Flags::default()
@@ -10455,6 +10454,7 @@ mod tests {
subcommand: DenoSubcommand::Task(TaskFlags {
cwd: None,
task: Some("build".to_string()),
+ is_run: false,
}),
argv: svec!["--test"],
..Flags::default()
@@ -10472,6 +10472,7 @@ mod tests {
subcommand: DenoSubcommand::Task(TaskFlags {
cwd: None,
task: Some("build".to_string()),
+ is_run: false,
}),
log_level: Some(log::Level::Error),
..Flags::default()
@@ -10488,6 +10489,7 @@ mod tests {
subcommand: DenoSubcommand::Task(TaskFlags {
cwd: None,
task: None,
+ is_run: false,
}),
..Flags::default()
}
@@ -10503,6 +10505,7 @@ mod tests {
subcommand: DenoSubcommand::Task(TaskFlags {
cwd: None,
task: None,
+ is_run: false,
}),
config_flag: ConfigFlag::Path("deno.jsonc".to_string()),
..Flags::default()
@@ -10519,6 +10522,7 @@ mod tests {
subcommand: DenoSubcommand::Task(TaskFlags {
cwd: None,
task: None,
+ is_run: false,
}),
config_flag: ConfigFlag::Path("deno.jsonc".to_string()),
..Flags::default()
@@ -11052,4 +11056,43 @@ mod tests {
.to_string()
.contains("Usage: deno [OPTIONS] [COMMAND] [SCRIPT_ARG]..."));
}
+
+ #[test]
+ fn equal_help_output() {
+ for command in clap_root().get_subcommands() {
+ if command.get_name() == "help" {
+ continue;
+ }
+
+ let long_flag = if let DenoSubcommand::Help(help) =
+ flags_from_vec(svec!["deno", command.get_name(), "--help"])
+ .unwrap()
+ .subcommand
+ {
+ help.help.to_string()
+ } else {
+ unreachable!()
+ };
+ let short_flag = if let DenoSubcommand::Help(help) =
+ flags_from_vec(svec!["deno", command.get_name(), "-h"])
+ .unwrap()
+ .subcommand
+ {
+ help.help.to_string()
+ } else {
+ unreachable!()
+ };
+ let subcommand = if let DenoSubcommand::Help(help) =
+ flags_from_vec(svec!["deno", "help", command.get_name()])
+ .unwrap()
+ .subcommand
+ {
+ help.help.to_string()
+ } else {
+ unreachable!()
+ };
+ assert_eq!(long_flag, short_flag, "{} subcommand", command.get_name());
+ assert_eq!(long_flag, subcommand, "{} subcommand", command.get_name());
+ }
+ }
}
diff --git a/cli/main.rs b/cli/main.rs
index 6a7575dee..290eee120 100644
--- a/cli/main.rs
+++ b/cli/main.rs
@@ -218,9 +218,10 @@ async fn run_subcommand(flags: Arc<Flags>) -> Result<i32, AnyError> {
let task_flags = TaskFlags {
cwd: None,
task: Some(run_flags.script.clone()),
+ is_run: true,
};
new_flags.subcommand = DenoSubcommand::Task(task_flags.clone());
- let result = tools::task::execute_script(Arc::new(new_flags), task_flags.clone(), true).await;
+ let result = tools::task::execute_script(Arc::new(new_flags), task_flags.clone()).await;
match result {
Ok(v) => Ok(v),
Err(_) => {
@@ -240,7 +241,7 @@ async fn run_subcommand(flags: Arc<Flags>) -> Result<i32, AnyError> {
tools::serve::serve(flags, serve_flags).await
}),
DenoSubcommand::Task(task_flags) => spawn_subcommand(async {
- tools::task::execute_script(flags, task_flags, false).await
+ tools::task::execute_script(flags, task_flags).await
}),
DenoSubcommand::Test(test_flags) => {
spawn_subcommand(async {
@@ -290,7 +291,21 @@ async fn run_subcommand(flags: Arc<Flags>) -> Result<i32, AnyError> {
tools::registry::publish(flags, publish_flags).await
}),
DenoSubcommand::Help(help_flags) => spawn_subcommand(async move {
- display::write_to_stdout_ignore_sigpipe(help_flags.help.ansi().to_string().as_bytes())
+ use std::io::Write;
+
+ let mut stream = anstream::AutoStream::new(std::io::stdout(), if colors::use_color() {
+ anstream::ColorChoice::Auto
+ } else {
+ anstream::ColorChoice::Never
+ });
+
+ match stream.write_all(help_flags.help.ansi().to_string().as_bytes()) {
+ Ok(()) => Ok(()),
+ Err(e) => match e.kind() {
+ std::io::ErrorKind::BrokenPipe => Ok(()),
+ _ => Err(e),
+ },
+ }
}),
};
diff --git a/cli/tools/task.rs b/cli/tools/task.rs
index 0110d1741..23da5b4fb 100644
--- a/cli/tools/task.rs
+++ b/cli/tools/task.rs
@@ -29,13 +29,24 @@ use std::sync::Arc;
pub async fn execute_script(
flags: Arc<Flags>,
task_flags: TaskFlags,
- using_run: bool,
) -> Result<i32, AnyError> {
let factory = CliFactory::from_flags(flags);
let cli_options = factory.cli_options()?;
let start_dir = &cli_options.start_dir;
if !start_dir.has_deno_or_pkg_json() {
- bail!("deno task couldn't find deno.json(c). See https://docs.deno.com/go/config")
+ if task_flags.is_run {
+ bail!(
+ r#"deno run couldn't find deno.json(c).
+If you meant to run a script, specify it, e.g., `deno run ./script.ts`.
+To run a task, ensure the config file exists.
+Examples:
+- Script: `deno run ./script.ts`
+- Task: `deno run dev`
+See https://docs.deno.com/go/config"#
+ )
+ } else {
+ bail!("deno task couldn't find deno.json(c). See https://docs.deno.com/go/config")
+ }
}
let force_use_pkg_json =
std::env::var_os(crate::task_runner::USE_PKG_JSON_HIDDEN_ENV_VAR_NAME)
@@ -142,7 +153,7 @@ pub async fn execute_script(
}
},
None => {
- if using_run {
+ if task_flags.is_run {
return Err(anyhow!("Task not found: {}", task_name));
}
log::error!("Task not found: {}", task_name);