@@ -2,102 +2,119 @@ 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;
10- pub use criterion;
118
12- use clap:: Clap ;
13-
14- #[ derive( Debug , Clap ) ]
15- #[ clap(
16- name = "Advent of Code" ,
17- about = concat!( "Main page of the event: https://adventofcode.com/" )
18- ) ]
19- pub struct Opt {
20- /// Read input from stdin instead of downloading it
21- #[ clap( short = 'i' , long, conflicts_with = "file" ) ]
22- pub stdin : bool ,
23-
24- /// Read input from file instead of downloading it
25- #[ clap( short, long, conflicts_with = "stdin" ) ]
26- pub file : Option < PathBuf > ,
27-
28- /// Days to execute. By default all implemented days will run.
29- #[ clap( name = "day num" , short, long = "day" ) ]
30- pub days : Vec < String > ,
31-
32- // TODO: better handling of bench CLI
33- /// Run criterion benchmarks
34- #[ clap( short, long) ]
35- pub bench : bool ,
36- }
9+ #[ cfg( feature = "bench" ) ]
10+ pub use criterion;
3711
38- impl Opt {
39- pub fn day_enabled ( & self , day : & str ) -> bool {
40- day. starts_with ( "day" ) && self . days . iter ( ) . any ( |d| d == & day[ 3 ..] )
41- }
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+ )
4248}
4349
4450#[ macro_export]
45- macro_rules! main {
51+ macro_rules! base_main {
4652 ( year $year: expr; $( $tail: tt ) * ) => {
4753 use std:: fs:: read_to_string;
4854 use std:: io:: Read ;
4955 use std:: time:: Instant ;
5056
51- use $crate:: clap:: Clap ;
52- use $crate:: criterion:: * ;
5357 use $crate:: { bench_day, extract_day, parse, run_day} ;
5458
5559 const YEAR : u16 = $year;
5660
5761 fn main( ) {
58- let mut opt = $crate:: Opt :: parse ( ) ;
62+ let mut opt = $crate:: args ( YEAR ) . get_matches ( ) ;
5963
60- if opt. bench {
64+ if opt. is_present ( " bench" ) {
6165 bench( ) ;
62- }
63-
64- if opt. days. is_empty( ) {
65- opt. days = parse!( extract_day { } ; $( $tail ) * )
66- . iter( )
67- . map( |s| s[ 3 ..] . to_string( ) )
68- . collect( ) ;
6966 } 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( ) ;
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( )
91+ }
92+ } ;
7793
78- if !ignored_days. is_empty( ) {
79- eprintln!( r"/!\ Ignoring unimplemented days: {}" , ignored_days. join( ", " ) ) ;
94+ if days. len( ) > 1 && ( opt. is_present( "stdin" ) || opt. is_present( "file" ) ) {
95+ eprintln!( r"/!\ You are using a personalized output over several days which can" ) ;
96+ eprintln!( r" be missleading. If you only intend to run solutions for a" ) ;
97+ eprintln!( r" specific day, you can specify it by using the `-d DAY_NUM` flag." ) ;
8098 }
8199
82- opt. days = opt. days
83- . into_iter( )
84- . filter( |day| days. contains( & format!( "day{}" , day) . as_str( ) ) )
85- . collect( ) ;
100+ for ( i, day) in days. iter( ) . enumerate( ) {
101+ parse! {
102+ run_day { i, format!( "day{}" , day) , YEAR , opt } ;
103+ $( $tail ) *
104+ } ;
105+ }
86106 }
107+ }
108+ }
109+ }
87110
88- if opt . days . len ( ) > 1 && ( opt . stdin || opt . file . is_some ( ) ) {
89- eprintln! ( r"/!\ You are using a personalized output over several days which can" ) ;
90- eprintln! ( r" be missleading. If you only intend to run solutions for a" ) ;
91- eprintln! ( r" specific day, you can specify it by using the `-d DAY_NUM` flag." ) ;
92- }
111+ # [ cfg ( feature = "bench" ) ]
112+ # [ macro_export ]
113+ macro_rules! main {
114+ ( year $year : expr ; $ ( $tail : tt ) * ) => {
115+ $crate :: base_main! { year $year ; $ ( $tail ) * }
93116
94- for ( i, day) in opt. days. iter( ) . enumerate( ) {
95- parse! {
96- run_day { i, format!( "day{}" , day) , YEAR , opt } ;
97- $( $tail ) *
98- } ;
99- }
100- }
117+ use $crate:: criterion:: Criterion ;
101118
102119 fn bench( ) {
103120 let mut criterion = Criterion :: default ( ) . configure_from_args( ) ;
@@ -109,5 +126,17 @@ macro_rules! main {
109126
110127 criterion. final_summary( ) ;
111128 }
112- } ;
129+ }
130+ }
131+
132+ #[ cfg( not( feature = "bench" ) ) ]
133+ #[ macro_export]
134+ macro_rules! main {
135+ ( year $year: expr; $( $tail: tt ) * ) => {
136+ $crate:: base_main! { year $year; $( $tail ) * }
137+
138+ fn bench( ) {
139+ println!( "Benchmarks not available, please enable `bench` feature for cargo-main." ) ;
140+ }
141+ }
113142}
0 commit comments