Skip to content

Commit

Permalink
Switch to getopts for flag parsing (denoland#1080)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinkassimo authored and ry committed Oct 24, 2018
1 parent a4fb517 commit 988ec88
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 70 deletions.
1 change: 1 addition & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ main_extern = [
"$rust_build:url",
"$rust_build:remove_dir_all",
"$rust_build:dirs",
"$rust_build:getopts",
"//build_extra/flatbuffers/rust:flatbuffers",
":msg_rs",
]
Expand Down
9 changes: 9 additions & 0 deletions build_extra/rust/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -920,3 +920,12 @@ rust_crate("lock_api") {
source_root = "$registry_github/lock_api-0.1.3/src/lib.rs"
extern = [ ":scopeguard" ]
}

rust_crate("unicode_width") {
source_root = "$registry_github/unicode-width-0.1.5/src/lib.rs"
}

rust_crate("getopts") {
source_root = "$registry_github/getopts-0.2.18/src/lib.rs"
extern = [ ":unicode_width" ]
}
131 changes: 70 additions & 61 deletions src/flags.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
use getopts::Options;
use libc::c_int;
use libdeno;
use log;
Expand Down Expand Up @@ -28,9 +29,9 @@ pub struct DenoFlags {
pub types_flag: bool,
}

pub fn process(flags: &DenoFlags) {
pub fn process(flags: &DenoFlags, usage_string: String) {
if flags.help {
print_usage();
println!("{}", &usage_string);
exit(0);
}

Expand All @@ -41,76 +42,84 @@ pub fn process(flags: &DenoFlags) {
log::set_max_level(log_level);
}

pub fn print_usage() {
println!(
"Usage: deno script.ts
--allow-write Allow file system write access.
--allow-net Allow network access.
--allow-env Allow environment access.
--recompile Force recompilation of TypeScript code.
-v or --version Print the version.
-r or --reload Reload cached remote resources.
-D or --log-debug Log debug output.
-h or --help Print this message.
--v8-options Print V8 command line options.
--deps Print module dependencies.
--types Print runtime TypeScript declarations.
pub fn get_usage(opts: &Options) -> String {
format!(
"Usage: deno script.ts {}
Environment variables:
DENO_DIR Set deno's base directory."
);
DENO_DIR Set deno's base directory.",
opts.usage("")
)
}

// Parses flags for deno. This does not do v8_set_flags() - call that separately.
pub fn set_flags(
args: Vec<String>,
) -> Result<(DenoFlags, Vec<String>), String> {
) -> Result<(DenoFlags, Vec<String>, String), String> {
let args = v8_set_flags(args);

let mut opts = Options::new();
// TODO(kevinkassimo): v8_set_flags intercepts '-help' with single '-'
// Resolve that and then uncomment line below (enabling Go style -long-flag)
// opts.long_only(true);
opts.optflag("", "allow-write", "Allow file system write access.");
opts.optflag("", "allow-net", "Allow network access.");
opts.optflag("", "allow-env", "Allow environment access.");
opts.optflag("", "recompile", "Force recompilation of TypeScript code.");
opts.optflag("h", "help", "Print this message.");
opts.optflag("D", "log-debug", "Log debug output.");
opts.optflag("v", "version", "Print the version.");
opts.optflag("r", "reload", "Reload cached remote resources.");
opts.optflag("", "v8-options", "Print V8 command line options.");
opts.optflag("", "deps", "Print module dependencies.");
opts.optflag("", "types", "Print runtime TypeScript declarations.");

let mut flags = DenoFlags::default();
let mut rest = Vec::new();
let mut arg_iter = args.iter();

while let Some(a) = arg_iter.next() {
if a.len() > 1 && &a[0..2] == "--" {
match a.as_str() {
"--help" => flags.help = true,
"--log-debug" => flags.log_debug = true,
"--version" => flags.version = true,
"--reload" => flags.reload = true,
"--recompile" => flags.recompile = true,
"--allow-write" => flags.allow_write = true,
"--allow-net" => flags.allow_net = true,
"--allow-env" => flags.allow_env = true,
"--deps" => flags.deps_flag = true,
"--types" => flags.types_flag = true,
"--" => break,
other => return Err(format!("bad option {}", other)),
}
} else if a.len() > 1 && &a[0..1] == "-" {
let mut iter = a.chars().skip(1); // skip the "-"
while let Some(f) = iter.next() {
match f {
'h' => flags.help = true,
'D' => flags.log_debug = true,
'v' => flags.version = true,
'r' => flags.reload = true,
other => return Err(format!("bad option -{}", other)),
}
}
} else {
rest.push(a.clone());
let matches = match opts.parse(&args) {
Ok(m) => m,
Err(f) => {
return Err(f.to_string());
}
};

if matches.opt_present("help") {
flags.help = true;
}
if matches.opt_present("log-debug") {
flags.log_debug = true;
}
if matches.opt_present("version") {
flags.version = true;
}
if matches.opt_present("reload") {
flags.reload = true;
}
if matches.opt_present("recompile") {
flags.recompile = true;
}
if matches.opt_present("allow-write") {
flags.allow_write = true;
}
if matches.opt_present("allow-net") {
flags.allow_net = true;
}
if matches.opt_present("allow-env") {
flags.allow_env = true;
}
if matches.opt_present("deps") {
flags.deps_flag = true;
}
if matches.opt_present("types") {
flags.types_flag = true;
}

// add any remaining arguments to `rest`
rest.extend(arg_iter.map(|s| s.clone()));
return Ok((flags, rest));
let rest: Vec<_> = matches.free.iter().map(|s| s.clone()).collect();
return Ok((flags, rest, get_usage(&opts)));
}

#[test]
fn test_set_flags_1() {
let (flags, rest) = set_flags(svec!["deno", "--version"]).unwrap();
let (flags, rest, _) = set_flags(svec!["deno", "--version"]).unwrap();
assert_eq!(rest, svec!["deno"]);
assert_eq!(
flags,
Expand All @@ -123,7 +132,7 @@ fn test_set_flags_1() {

#[test]
fn test_set_flags_2() {
let (flags, rest) =
let (flags, rest, _) =
set_flags(svec!["deno", "-r", "-D", "script.ts"]).unwrap();
assert_eq!(rest, svec!["deno", "script.ts"]);
assert_eq!(
Expand All @@ -138,7 +147,7 @@ fn test_set_flags_2() {

#[test]
fn test_set_flags_3() {
let (flags, rest) =
let (flags, rest, _) =
set_flags(svec!["deno", "-r", "--deps", "script.ts", "--allow-write"])
.unwrap();
assert_eq!(rest, svec!["deno", "script.ts"]);
Expand All @@ -155,7 +164,7 @@ fn test_set_flags_3() {

#[test]
fn test_set_flags_4() {
let (flags, rest) =
let (flags, rest, _) =
set_flags(svec!["deno", "-Dr", "script.ts", "--allow-write"]).unwrap();
assert_eq!(rest, svec!["deno", "script.ts"]);
assert_eq!(
Expand All @@ -171,7 +180,7 @@ fn test_set_flags_4() {

#[test]
fn test_set_flags_5() {
let (flags, rest) = set_flags(svec!["deno", "--types"]).unwrap();
let (flags, rest, _) = set_flags(svec!["deno", "--types"]).unwrap();
assert_eq!(rest, svec!["deno"]);
assert_eq!(
flags,
Expand All @@ -185,14 +194,14 @@ fn test_set_flags_5() {
#[test]
fn test_set_bad_flags_1() {
let err = set_flags(svec!["deno", "--unknown-flag"]).unwrap_err();
assert_eq!(err, "bad option --unknown-flag");
assert_eq!(err, "Unrecognized option: 'unknown-flag'");
}

#[test]
fn test_set_bad_flags_2() {
// This needs to be changed if -z is added as a flag
let err = set_flags(svec!["deno", "-z"]).unwrap_err();
assert_eq!(err, "bad option -z");
assert_eq!(err, "Unrecognized option: 'z'");
}

// Returns args passed to V8, followed by args passed to JS
Expand Down
6 changes: 3 additions & 3 deletions src/isolate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ mod tests {
#[test]
fn test_dispatch_sync() {
let argv = vec![String::from("./deno"), String::from("hello.js")];
let (flags, rest_argv) = flags::set_flags(argv).unwrap();
let (flags, rest_argv, _) = flags::set_flags(argv).unwrap();
let mut isolate = Isolate::new(flags, rest_argv, dispatch_sync);
tokio_util::init(|| {
isolate
Expand Down Expand Up @@ -401,7 +401,7 @@ mod tests {
#[test]
fn test_metrics_sync() {
let argv = vec![String::from("./deno"), String::from("hello.js")];
let (flags, rest_argv) = flags::set_flags(argv).unwrap();
let (flags, rest_argv, _) = flags::set_flags(argv).unwrap();
let mut isolate = Isolate::new(flags, rest_argv, metrics_dispatch_sync);
tokio_util::init(|| {
// Verify that metrics have been properly initialized.
Expand Down Expand Up @@ -436,7 +436,7 @@ mod tests {
#[test]
fn test_metrics_async() {
let argv = vec![String::from("./deno"), String::from("hello.js")];
let (flags, rest_argv) = flags::set_flags(argv).unwrap();
let (flags, rest_argv, _) = flags::set_flags(argv).unwrap();
let mut isolate = Isolate::new(flags, rest_argv, metrics_dispatch_async);
tokio_util::init(|| {
// Verify that metrics have been properly initialized.
Expand Down
12 changes: 7 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate dirs;
extern crate getopts;
extern crate hyper_rustls;
extern crate remove_dir_all;
extern crate ring;
Expand Down Expand Up @@ -69,12 +70,13 @@ fn main() {

log::set_logger(&LOGGER).unwrap();
let args = env::args().collect();
let (flags, rest_argv) = flags::set_flags(args).unwrap_or_else(|err| {
eprintln!("{}", err);
std::process::exit(1)
});
let (flags, rest_argv, usage_string) =
flags::set_flags(args).unwrap_or_else(|err| {
eprintln!("{}", err);
std::process::exit(1)
});
let mut isolate = isolate::Isolate::new(flags, rest_argv, ops::dispatch);
flags::process(&isolate.state.flags);
flags::process(&isolate.state.flags, usage_string);
tokio_util::init(|| {
isolate
.execute("deno_main.js", "denoMain();")
Expand Down
2 changes: 1 addition & 1 deletion third_party
Submodule third_party updated 24 files
+0 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/getopts-0.2.18/.cargo-ok
+2 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/getopts-0.2.18/.gitignore
+22 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/getopts-0.2.18/.travis.yml
+27 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/getopts-0.2.18/Cargo.toml
+20 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/getopts-0.2.18/Cargo.toml.orig
+201 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/getopts-0.2.18/LICENSE-APACHE
+25 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/getopts-0.2.18/LICENSE-MIT
+27 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/getopts-0.2.18/README.md
+17 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/getopts-0.2.18/appveyor.yml
+2,099 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/getopts-0.2.18/src/lib.rs
+8 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/getopts-0.2.18/tests/smoke.rs
+0 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/unicode-width-0.1.5/.cargo-ok
+3 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/unicode-width-0.1.5/.gitignore
+25 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/unicode-width-0.1.5/.travis.yml
+7 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/unicode-width-0.1.5/COPYRIGHT
+29 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/unicode-width-0.1.5/Cargo.toml
+23 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/unicode-width-0.1.5/Cargo.toml.orig
+201 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/unicode-width-0.1.5/LICENSE-APACHE
+25 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/unicode-width-0.1.5/LICENSE-MIT
+39 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/unicode-width-0.1.5/README.md
+321 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/unicode-width-0.1.5/scripts/unicode.py
+131 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/unicode-width-0.1.5/src/lib.rs
+273 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/unicode-width-0.1.5/src/tables.rs
+156 −0 rust_crates/registry/src/github.com-1ecc6299db9ec823/unicode-width-0.1.5/src/tests.rs

0 comments on commit 988ec88

Please sign in to comment.