Skip to content

Commit 0fe5cec

Browse files
committed
clap: use builder pattern and disable derive feature
1 parent 64dcb9e commit 0fe5cec

File tree

4 files changed

+68
-140
lines changed

4 files changed

+68
-140
lines changed

Cargo.lock

Lines changed: 0 additions & 78 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ bench = ["criterion"]
1515

1616
[dependencies]
1717
attohttpc = { version = "0.16.0", default_features = false, features = ["tls"] }
18-
clap = "3.0.0-beta.2"
18+
clap = { version = "3.0.0-beta.2", default_features = false, features = ["std"] }
1919
colored = "2.0.0"
2020
dirs = "3.0.1"
2121

src/lib.rs

Lines changed: 65 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,45 +2,49 @@ pub mod input;
22
pub mod parse;
33
pub mod utils;
44

5-
use std::path::PathBuf;
6-
75
// Reexport some crates for the generated main
86
pub use clap;
97
pub use colored;
108

119
#[cfg(feature = "bench")]
1210
pub use criterion;
1311

14-
use clap::Clap;
15-
16-
#[derive(Debug, Clap)]
17-
#[clap(
18-
name = "Advent of Code",
19-
about = concat!("Main page of the event: https://adventofcode.com/")
20-
)]
21-
pub struct Opt {
22-
/// Read input from stdin instead of downloading it
23-
#[clap(short = 'i', long, conflicts_with = "file")]
24-
pub stdin: bool,
25-
26-
/// Read input from file instead of downloading it
27-
#[clap(short, long, conflicts_with = "stdin")]
28-
pub file: Option<PathBuf>,
29-
30-
/// Days to execute. By default all implemented days will run.
31-
#[clap(name = "day num", short, long = "day")]
32-
pub days: Vec<String>,
33-
34-
// TODO: better handling of bench CLI
35-
/// Run criterion benchmarks
36-
#[clap(short, long)]
37-
pub bench: bool,
38-
}
39-
40-
impl Opt {
41-
pub fn day_enabled(&self, day: &str) -> bool {
42-
day.starts_with("day") && self.days.iter().any(|d| d == &day[3..])
43-
}
12+
use clap::{App, Arg, ValueHint};
13+
14+
pub fn args(year: u16) -> App<'static> {
15+
App::new(format!("Advent of Code {}", year))
16+
.author("Rémi D. <[email protected]>")
17+
.about("Main page of the event: https://adventofcode.com/")
18+
.arg(
19+
Arg::new("stdin")
20+
.short('i')
21+
.long("stdin")
22+
.conflicts_with("file")
23+
.about("Read input from stdin instead of downloading it"),
24+
)
25+
.arg(
26+
Arg::new("file")
27+
.takes_value(true)
28+
.short('f')
29+
.long("file")
30+
.conflicts_with("stdin")
31+
.value_hint(ValueHint::FilePath)
32+
.about("Read input from file instead of downloading it"),
33+
)
34+
.arg(
35+
Arg::new("days")
36+
.takes_value(true)
37+
.short('d')
38+
.long("day")
39+
.value_name("day num")
40+
.about("Days to execute. By default all implemented days will run"),
41+
)
42+
.arg(
43+
Arg::new("bench")
44+
.short('b')
45+
.long("bench")
46+
.about("Run criterion benchmarks"),
47+
)
4448
}
4549

4650
#[macro_export]
@@ -50,48 +54,50 @@ macro_rules! base_main {
5054
use std::io::Read;
5155
use std::time::Instant;
5256

53-
use $crate::clap::Clap;
5457
use $crate::{bench_day, extract_day, parse, run_day};
5558

5659
const YEAR: u16 = $year;
5760

5861
fn main() {
59-
let mut opt = $crate::Opt::parse();
62+
let mut opt = $crate::args(YEAR).get_matches();
6063

61-
if opt.bench {
64+
if opt.is_present("bench") {
6265
bench();
6366
} else {
64-
if opt.days.is_empty() {
65-
opt.days = parse!(extract_day {}; $( $tail )*)
66-
.iter()
67-
.map(|s| s[3..].to_string())
68-
.collect();
69-
} else {
70-
let days = parse! { extract_day {}; $( $tail )* };
71-
72-
let ignored_days: Vec<_> = opt.days
73-
.iter()
74-
.filter(|day| !days.contains(&format!("day{}", day).as_str()))
75-
.map(String::as_str)
76-
.collect();
77-
78-
if !ignored_days.is_empty() {
79-
eprintln!(r"/!\ Ignoring unimplemented days: {}", ignored_days.join(", "));
67+
let days: Vec<_> = {
68+
if let Some(opt_days) = opt.values_of("days") {
69+
let opt_days: Vec<_> = opt_days.collect();
70+
let days = parse! { extract_day {}; $( $tail )* };
71+
72+
let ignored_days: Vec<_> = opt_days
73+
.iter()
74+
.filter(|day| !days.contains(&format!("day{}", day).as_str()))
75+
.copied()
76+
.collect();
77+
78+
if !ignored_days.is_empty() {
79+
eprintln!(r"/!\ Ignoring unimplemented days: {}", ignored_days.join(", "));
80+
}
81+
82+
opt_days
83+
.into_iter()
84+
.filter(|day| days.contains(&format!("day{}", day).as_str()))
85+
.collect()
86+
} else {
87+
parse!(extract_day {}; $( $tail )*)
88+
.iter()
89+
.map(|s| &s[3..])
90+
.collect()
8091
}
92+
};
8193

82-
opt.days = opt.days
83-
.into_iter()
84-
.filter(|day| days.contains(&format!("day{}", day).as_str()))
85-
.collect();
86-
}
87-
88-
if opt.days.len() > 1 && (opt.stdin || opt.file.is_some()) {
94+
if days.len() > 1 && (opt.is_present("stdin") || opt.is_present("file")) {
8995
eprintln!(r"/!\ You are using a personalized output over several days which can");
9096
eprintln!(r" be missleading. If you only intend to run solutions for a");
9197
eprintln!(r" specific day, you can specify it by using the `-d DAY_NUM` flag.");
9298
}
9399

94-
for (i, day) in opt.days.iter().enumerate() {
100+
for (i, day) in days.iter().enumerate() {
95101
parse! {
96102
run_day { i, format!("day{}", day), YEAR, opt };
97103
$( $tail )*

src/parse/gen_run.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ macro_rules! run_day {
1212
println!("Day {}", day);
1313

1414
let data = {
15-
if $opt.stdin {
15+
if $opt.is_present("stdin") {
1616
let mut data = String::new();
1717
std::io::stdin().read_to_string(&mut data)
1818
.expect("failed to read from stdin");
1919
data
20-
} else if let Some(path) = $opt.file.as_ref() {
20+
} else if let Some(path) = $opt.value_of("file") {
2121
read_to_string(path)
2222
.expect("failed to read specified file")
2323
} else {

0 commit comments

Comments
 (0)