Skip to content

Commit 101b712

Browse files
committed
helper struct Line
1 parent 6dd52dd commit 101b712

File tree

4 files changed

+112
-55
lines changed

4 files changed

+112
-55
lines changed

src/input.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use std::io::{stdin, stdout};
55
use std::path::PathBuf;
66
use std::time::Instant;
77

8+
use crate::print::Line;
9+
810
const BASE_URL: &str = "https://adventofcode.com";
911
const INPUT_DIR: &str = "input";
1012
const CONN_TOKEN_FILE: &str = ".token";
@@ -19,7 +21,11 @@ pub fn get_input(year: u16, day: u8) -> Result<String, Box<dyn Error>> {
1921
.send()?;
2022
let elapsed = start.elapsed();
2123

22-
crate::print_with_duration("downloaded input file", None, Some(elapsed));
24+
println!(
25+
" - {}",
26+
Line::new("downloaded input file").with_duration(elapsed)
27+
);
28+
2329
resp.text()
2430
})?;
2531

src/lib.rs

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,17 @@
11
pub mod input;
22
pub mod parse;
3+
pub mod print;
34
pub mod run;
45
pub mod try_unwrap;
56

6-
use std::cmp::min;
7-
use std::iter;
87
use std::path::PathBuf;
9-
use std::time::Duration;
108

119
// Reexport some crates for the generated main
1210
pub use clap;
1311
pub use colored;
1412
pub use criterion;
1513

1614
use clap::Clap;
17-
use colored::*;
18-
19-
const DISPLAY_WIDTH: usize = 40;
20-
21-
pub fn print_with_duration(line: &str, output: Option<ColoredString>, duration: Option<Duration>) {
22-
let duration = duration
23-
.map(|duration| format!(" ({:.2?})", duration))
24-
.unwrap_or_else(String::new);
25-
26-
print!(" - {}{}", line, duration.dimmed());
27-
28-
if let Some(output) = output {
29-
let width = " - ".len() + line.chars().count() + 1 + duration.chars().count();
30-
let dots = DISPLAY_WIDTH - min(DISPLAY_WIDTH - 5, width) - 2;
31-
let dots: String = iter::repeat('.').take(dots).collect();
32-
print!(" {}", dots.dimmed());
33-
34-
if output.contains('\n') {
35-
println!();
36-
37-
for line in output.trim_matches('\n').lines() {
38-
println!(" {}", line.bold());
39-
}
40-
} else {
41-
println!(" {}", output.bold());
42-
}
43-
} else {
44-
println!()
45-
}
46-
}
4715

4816
#[derive(Debug, Clap)]
4917
#[clap(

src/print.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use colored::*;
2+
3+
use std::cmp::min;
4+
use std::fmt;
5+
use std::iter;
6+
use std::time::Duration;
7+
8+
const DEFAULT_WIDTH: usize = 30;
9+
10+
/// Simple helper struct used to display lines with a dotted separator.
11+
/// For example: "line text (1.2 ms) .............. status".
12+
pub struct Line {
13+
text: String,
14+
duration: Option<Duration>,
15+
state: Option<ColoredString>,
16+
}
17+
18+
impl Line {
19+
pub fn new(text: impl Into<String>) -> Self {
20+
Self {
21+
text: text.into(),
22+
duration: None,
23+
state: None,
24+
}
25+
}
26+
27+
pub fn with_duration(mut self, duration: Duration) -> Self {
28+
self.duration = Some(duration);
29+
self
30+
}
31+
32+
pub fn with_state(mut self, state: impl Into<ColoredString>) -> Self {
33+
self.state = Some(state.into());
34+
self
35+
}
36+
}
37+
38+
impl fmt::Display for Line {
39+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
40+
let display_width = f.width().unwrap_or(DEFAULT_WIDTH);
41+
42+
let duration = self
43+
.duration
44+
.map(|duration| format!(" ({:.2?})", duration))
45+
.unwrap_or_else(String::new);
46+
47+
write!(f, "{}{}", self.text, duration.dimmed())?;
48+
49+
if let Some(state) = &self.state {
50+
let width = self.text.chars().count() + 1 + duration.chars().count();
51+
let dots = display_width - min(display_width - 5, width) - 2;
52+
let dots: String = iter::repeat('.').take(dots).collect();
53+
write!(f, " {}", dots.dimmed())?;
54+
55+
if state.contains('\n') {
56+
for line in state.trim_matches('\n').lines() {
57+
write!(f, "\n {}", line.bold())?;
58+
}
59+
} else {
60+
write!(f, " {}", state.clone().bold())?;
61+
}
62+
}
63+
64+
Ok(())
65+
}
66+
}

src/run.rs

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ macro_rules! run_day {
44
{ $i: expr, $curr_day: expr, $year: expr, $opt: expr },
55
{ day $day: ident { $gen: tt { $( $sol: tt )* } } }
66
) => {{
7-
use $crate::colored::*;
8-
97
if stringify!($day) == $curr_day {
108
if $i != 0 { println!() }
119
let day = $curr_day[3..].parse().expect("days must be integers");
@@ -43,16 +41,19 @@ macro_rules! run_gen {
4341

4442
// Run generator
4543
( $day: ident, $data: expr, { gen $generator: ident } ) => {{
44+
use $crate::print::Line;
45+
4646
let start = Instant::now();
4747
let input = $day::$generator($data);
4848
let elapsed = start.elapsed();
49-
$crate::print_with_duration("generator", None, Some(elapsed));
49+
println!(" - {}", Line::new("generator").with_duration(elapsed));
5050
Some(input)
5151
}};
5252

5353
// Run fallible generator
5454
( $day: ident, $data: expr, { gen_fallible $generator: ident } ) => {{
5555
use $crate::colored::*;
56+
use $crate::print::Line;
5657
use $crate::try_unwrap::TryUnwrap;
5758

5859
let start = Instant::now();
@@ -61,11 +62,16 @@ macro_rules! run_gen {
6162

6263
match result.try_unwrap() {
6364
Ok(input) => {
64-
$crate::print_with_duration("generator", None, Some(elapsed));
65+
println!(" - {}", Line::new("generator").with_duration(elapsed));
6566
Some(input)
6667
}
6768
Err(msg) => {
68-
$crate::print_with_duration("generator", Some(msg.red()), Some(elapsed));
69+
println!(
70+
" - {}",
71+
Line::new("generator")
72+
.with_duration(elapsed)
73+
.with_state(msg.red())
74+
);
6975
None
7076
}
7177
}
@@ -76,44 +82,55 @@ macro_rules! run_gen {
7682
macro_rules! run_sol {
7783
// Run solution
7884
( $day: ident, $input: expr, { sol $solution: ident } ) => {{
85+
use $crate::colored::*;
86+
use $crate::print::Line;
87+
7988
let start = Instant::now();
8089
let response = $day::$solution($input);
8190
let elapsed = start.elapsed();
8291

83-
$crate::print_with_duration(
84-
stringify!($solution),
85-
Some(format!("{}", response).normal()),
86-
Some(elapsed),
92+
println!(
93+
" - {}",
94+
Line::new(stringify!($solution))
95+
.with_duration(elapsed)
96+
.with_state(format!("{}", response).normal())
8797
);
8898
}};
8999

90100
// Run fallible solution
91101
( $day: ident, $input: expr, { sol_fallible $solution: ident } ) => {{
92102
use $crate::colored::*;
103+
use $crate::print::Line;
93104
use $crate::try_unwrap::TryUnwrap;
94105

95106
let start = Instant::now();
96107
let response = $day::$solution($input);
97108
let elapsed = start.elapsed();
109+
let line = Line::new(stringify!($solution)).with_duration(elapsed);
98110

99-
match response.try_unwrap() {
100-
Ok(response) => {
101-
$crate::print_with_duration(
102-
stringify!($solution),
103-
Some(format!("{}", response).normal()),
104-
Some(elapsed),
105-
);
106-
}
107-
Err(msg) => {
108-
$crate::print_with_duration(stringify!($solution), Some(msg.red()), Some(elapsed));
111+
println!(
112+
" - {}",
113+
match response.try_unwrap() {
114+
Ok(response) => {
115+
line.with_state(format!("{}", response).normal())
116+
}
117+
Err(msg) => {
118+
line.with_state(msg.red())
119+
}
109120
}
110-
}
121+
);
111122
}};
112123
}
113124

114125
#[macro_export]
115126
macro_rules! skip_sol {
116127
({ $kind: tt $solution: ident }) => {{
117-
$crate::print_with_duration(stringify!($solution), Some("skipped".dimmed()), None);
128+
use $crate::colored::*;
129+
use $crate::print::Line;
130+
131+
println!(
132+
" - {}",
133+
Line::new(stringify!($solution)).with_state("skipped".dimmed())
134+
);
118135
}};
119136
}

0 commit comments

Comments
 (0)