diff --git a/Cargo.lock b/Cargo.lock index 6339e32..8cdb399 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,55 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + [[package]] name = "anyhow" version = "1.0.86" @@ -189,6 +238,46 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "4.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" + [[package]] name = "clipboard-win" version = "4.5.0" @@ -206,6 +295,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + [[package]] name = "colored" version = "2.1.0" @@ -747,6 +842,12 @@ dependencies = [ "syn", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" version = "0.12.1" @@ -1429,6 +1530,7 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" name = "scout" version = "0.1.0" dependencies = [ + "clap", "colored", "fantoccini", "futures", @@ -1596,6 +1698,12 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "2.0.64" diff --git a/Cargo.toml b/Cargo.toml index 2d83477..58ff771 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ colored = "2" fantoccini = "0.19.3" tokio = { version = "1", features = ["full"] } serde_json = "1.0" +clap = { version = "4.5.7", features = ["derive"] } # The profile that 'cargo dist' will build with [profile.dist] diff --git a/README.md b/README.md index d539732..3bc3813 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,10 @@ Eventually Scout installation will come bundled with the necessary pre-reqs. For See [Releases](https://github.com/maxmindlin/scout-lang/releases) for up to date Scout binary installation instructions. +# Usage + +The `scout` binary ran with a filename will read and interpret a script file. Without a script will start the REPL. Run `scout --help` to see additional options. + # License -Scout is dual-licensed with MIT & Apache 2.0, at your option. \ No newline at end of file +Scout is dual-licensed with MIT & Apache 2.0, at your option. diff --git a/src/main.rs b/src/main.rs index 9c05ebe..cecb6b9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ -use std::{env, fs, process::Command, sync::Arc}; +use std::{fs, process::Command, sync::Arc}; +use clap::Parser as CLIParser; use futures::lock::Mutex; use repl::run_repl; use scout_interpreter::{env::Env, eval, ScrapeResultsPtr}; @@ -8,16 +9,23 @@ use scout_parser::{ast::NodeKind, Parser}; mod repl; +#[derive(CLIParser, Debug)] +struct Args { + file: Option, + + #[arg(long)] + debug: bool, +} + async fn run( - args: Vec, + file: Option, crawler: &fantoccini::Client, results: ScrapeResultsPtr, ) -> Result<(), Box> { - match args.len() { - 1 => run_repl(crawler, results).await, - 2 => { - let filename = &args[1]; - let contents = fs::read_to_string(filename)?; + match file { + None => run_repl(crawler, results).await, + Some(f) => { + let contents = fs::read_to_string(f)?; let lex = Lexer::new(&contents); let mut parser = Parser::new(lex); @@ -34,12 +42,13 @@ async fn run( Err(e) => Err(format!("Parser error: {:#?}", e).into()), } } - _ => Err("Unsupported number of args".into()), } } #[tokio::main] async fn main() { + let args = Args::parse(); + let child = Command::new("geckodriver") .arg("--port") .arg("4444") @@ -51,14 +60,19 @@ async fn main() { // sleep to allow driver to start std::thread::sleep(std::time::Duration::from_millis(50)); + let mut caps = serde_json::map::Map::new(); + if !args.debug { + let opts = serde_json::json!({ "args": ["--headless"] }); + caps.insert("moz:firefoxOptions".into(), opts); + } let crawler = fantoccini::ClientBuilder::native() + .capabilities(caps) .connect("http://localhost:4444") .await .expect("error starting browser"); let results = ScrapeResultsPtr::default(); - let args: Vec = env::args().collect(); - if let Err(e) = run(args, &crawler, results.clone()).await { + if let Err(e) = run(args.file, &crawler, results.clone()).await { println!("Error: {}", e); } let json_results = results.lock().await.to_json();