Skip to content

Commit

Permalink
feat: parse flags after script name (denoland#2596)
Browse files Browse the repository at this point in the history
  • Loading branch information
bartlomieju authored and ry committed Jun 29, 2019
1 parent cde81c6 commit 38cf346
Showing 1 changed file with 104 additions and 5 deletions.
109 changes: 104 additions & 5 deletions cli/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,8 +434,11 @@ fn resolve_paths(paths: Vec<String>) -> Vec<String> {

/// Parse ArgMatches into internal DenoFlags structure.
/// This method should not make any side effects.
pub fn parse_flags(matches: &ArgMatches) -> DenoFlags {
let mut flags = DenoFlags::default();
pub fn parse_flags(
matches: &ArgMatches,
maybe_flags: Option<DenoFlags>,
) -> DenoFlags {
let mut flags = maybe_flags.unwrap_or_default();

if matches.is_present("log-level") {
flags.log_level = match matches.value_of("log-level").unwrap() {
Expand Down Expand Up @@ -552,6 +555,56 @@ fn parse_run_args(mut flags: DenoFlags, matches: &ArgMatches) -> DenoFlags {
flags
}

/// Parse vector or arguments as DenoFlags.
///
/// This is very specialized utility that parses arguments passed after script URL.
///
/// Only dash (eg. `-r`) and double dash (eg. `--reload`) arguments are supported.
/// Arguments recognized as DenoFlags will be eaten.
/// Parsing stops after double dash `--` argument.
///
/// NOTE: this method ignores `-h/--help` and `-v/--version` flags.
fn parse_script_args(
args: Vec<String>,
mut flags: DenoFlags,
) -> (Vec<String>, DenoFlags) {
let mut argv = vec![];
let mut seen_double_dash = false;

// we have to iterate and parse argument one by one because clap returns error on any
// unrecognized argument
for arg in args.iter() {
if seen_double_dash {
argv.push(arg.to_string());
continue;
}

if arg == "--" {
seen_double_dash = true;
argv.push(arg.to_string());
continue;
}

if !arg.starts_with('-') {
argv.push(arg.to_string());
continue;
}

let cli_app = create_cli_app();
// `get_matches_from_safe` returns error for `-h/-v` flags
let matches =
cli_app.get_matches_from_safe(vec!["deno".to_string(), arg.to_string()]);

if matches.is_ok() {
flags = parse_flags(&matches.unwrap(), Some(flags));
} else {
argv.push(arg.to_string());
}
}

(argv, flags)
}

/// Used for `deno fmt <files>...` subcommand
const PRETTIER_URL: &str = "https://deno.land/std@v0.7.0/prettier/main.ts";
/// Used for `deno install...` subcommand
Expand Down Expand Up @@ -603,7 +656,7 @@ pub fn flags_from_vec(
let cli_app = create_cli_app();
let matches = cli_app.get_matches_from(args);
let mut argv: Vec<String> = vec!["deno".to_string()];
let mut flags = parse_flags(&matches.clone());
let mut flags = parse_flags(&matches.clone(), None);

let subcommand = match matches.subcommand() {
("bundle", Some(bundle_match)) => {
Expand Down Expand Up @@ -711,6 +764,9 @@ pub fn flags_from_vec(
.unwrap()
.map(String::from)
.collect();

let (script_args, flags_) = parse_script_args(script_args, flags);
flags = flags_;
argv.extend(script_args);
}
DenoSubcommand::Run
Expand Down Expand Up @@ -746,6 +802,9 @@ pub fn flags_from_vec(
.unwrap()
.map(String::from)
.collect();

let (script_args, flags_) = parse_script_args(script_args, flags);
flags = flags_;
argv.extend(script_args);
}
DenoSubcommand::Run
Expand Down Expand Up @@ -933,14 +992,15 @@ mod tests {

#[test]
fn test_flags_from_vec_10() {
// notice that flags passed after script name will not
// notice that flags passed after double dash will not
// be parsed to DenoFlags but instead forwarded to
// script args as Deno.args
let (flags, subcommand, argv) = flags_from_vec(svec![
"deno",
"run",
"--allow-write",
"script.ts",
"--",
"-D",
"--allow-net"
]);
Expand All @@ -952,7 +1012,7 @@ mod tests {
}
);
assert_eq!(subcommand, DenoSubcommand::Run);
assert_eq!(argv, svec!["deno", "script.ts", "-D", "--allow-net"]);
assert_eq!(argv, svec!["deno", "script.ts", "--", "-D", "--allow-net"]);
}

#[test]
Expand Down Expand Up @@ -1436,4 +1496,43 @@ mod tests {
assert_eq!(subcommand, DenoSubcommand::Completions);
assert_eq!(argv, svec!["deno"])
}

#[test]
fn test_flags_from_vec_33() {
let (flags, subcommand, argv) =
flags_from_vec(svec!["deno", "script.ts", "--allow-read", "--allow-net"]);
assert_eq!(
flags,
DenoFlags {
allow_net: true,
allow_read: true,
..DenoFlags::default()
}
);
assert_eq!(subcommand, DenoSubcommand::Run);
assert_eq!(argv, svec!["deno", "script.ts"]);

let (flags, subcommand, argv) = flags_from_vec(svec![
"deno",
"--allow-read",
"run",
"script.ts",
"--allow-net",
"-r",
"--help",
"--foo",
"bar"
]);
assert_eq!(
flags,
DenoFlags {
allow_net: true,
allow_read: true,
reload: true,
..DenoFlags::default()
}
);
assert_eq!(subcommand, DenoSubcommand::Run);
assert_eq!(argv, svec!["deno", "script.ts", "--help", "--foo", "bar"]);
}
}

0 comments on commit 38cf346

Please sign in to comment.