Skip to content

Commit

Permalink
add scaffolding for repl
Browse files Browse the repository at this point in the history
- module
- clap
  • Loading branch information
suaviloquence committed Aug 17, 2024
1 parent f678fb3 commit ef74020
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 26 deletions.
120 changes: 120 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ serde_json = "1.0"
serde = { version = "1.0", features = ["derive", "rc"] }
futures = "0.3"
url = "2.5"
clap = { version = "4.5.16", features = ["derive"] }

[workspace]
members = [".", "filter-proc-macro", "filter-types"]
Expand Down
1 change: 1 addition & 0 deletions src/frontend/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod ast;
mod parser;
mod repl;
mod scanner;

pub use parser::{ParseError, Parser};
Expand Down
2 changes: 2 additions & 0 deletions src/frontend/repl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#[derive(Debug, Clone)]
pub struct Repl {}

Check failure on line 2 in src/frontend/repl.rs

View workflow job for this annotation

GitHub Actions / run cargo tests

struct `Repl` is never constructed

Check warning on line 2 in src/frontend/repl.rs

View workflow job for this annotation

GitHub Actions / verify formatting and lints

struct `Repl` is never constructed
79 changes: 53 additions & 26 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,42 +1,69 @@
#![forbid(unsafe_code)]
use std::env;
use std::path::PathBuf;

use anyhow::Context;
use clap::Parser as _;
use scrapelect::{frontend::Parser, interpreter::Interpreter};
use url::Url;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
let mut args = env::args();
// skip name
let name = args.next().context("usage: scrapelect <filename> <url>")?;
#[derive(Debug, clap::Parser)]
#[command(version, args_conflicts_with_subcommands = true)]
struct Interface {
#[command(subcommand)]
mode: Option<Mode>,
// There is some magic going on where `Option<RunArgs>` makes it required
// when the subcommand is not provided.
#[command(flatten)]
run: Option<RunArgs>,
}

#[derive(Debug, clap::Args)]
struct RunArgs {
/// The `.scrp` file describing how to convert the web page into structured data
file: PathBuf,
/// The URL of the web page to start scraping at.
url: Url,
}

let filename = args
.next()
.with_context(|| format!("usage: {name} <filename> <url>"))?;
#[derive(Debug, clap::Subcommand)]
enum Mode {
Run(RunArgs),
Repl,
}

let url = args
.next()
.with_context(|| format!("usage: {name} <filename = {filename}> <url>"))?;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let args = Interface::parse();

let pgm = std::fs::read_to_string(&filename)
.with_context(|| format!("error reading file {filename}"))?;
match (args.mode, args.run) {
(Some(Mode::Run(run_args)), None) | (None, Some(run_args)) => {
let pgm = std::fs::read_to_string(&run_args.file)
.with_context(|| format!("error reading file {}", run_args.file.display()))?;

let parser = Parser::new(&pgm);
let parser = Parser::new(&pgm);

let ast = parser
.parse()
.with_context(|| format!("parse error in {filename}:"))?;
let ast = parser
.parse()
.with_context(|| format!("parse error in {}:", run_args.file.display()))?;

let interpreter = Interpreter::new(&ast);
let interpreter = Interpreter::new(&ast);

let results = interpreter
.interpret(
url.parse()
.with_context(|| format!("Couldn't parse `{url}` into a URL"))?,
)
.await?;
let results = interpreter.interpret(run_args.url).await?;

println!("{}", serde_json::to_string_pretty(&results)?);
println!("{}", serde_json::to_string_pretty(&results)?);
}
// TODO: investigate if the (None, None) branch is reachable (I think it isn't)
(Some(Mode::Repl), None) | (None, None) => {
todo!()
}
(Some(_), Some(_)) => {
unreachable!(
"This should be impossible to reach with clap's `args_conflicts_with_subcommands`.
If you see this error message, please file a GitHub issue with the arguments
you provided to `scrapelect`."
)
}
}

Ok(())
}

0 comments on commit ef74020

Please sign in to comment.