@@ -2,45 +2,49 @@ pub mod input;
22pub mod parse;
33pub mod utils;
44
5- use std:: path:: PathBuf ;
6-
75// Reexport some crates for the generated main
86pub use clap;
97pub use colored;
108
119#[ cfg( feature = "bench" ) ]
1210pub 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 ) *
0 commit comments