Small Rust scripts
1#!/usr/bin/env -S cargo +nightly -Zscript
2
3---
4[package]
5edition = "2024"
6[dependencies]
7argh = "0.1"
8humantime = "2.1.0"
9---
10
11use std::thread;
12use std::time::{Duration, Instant};
13
14use argh::FromArgs;
15
16#[derive(FromArgs)]
17#[argh(description = "Keep track of how long a task runs or set a timer for some period of time.")]
18struct App {
19 #[argh(
20 option,
21 description = "how long to wait before starting the stopwatch."
22 )]
23 delay: Option<humantime::Duration>,
24
25 #[argh(
26 option,
27 description = "how long to wait between timer updates.",
28 default = "\"1ms\".parse::<humantime::Duration>().unwrap()"
29 )]
30 pause: humantime::Duration,
31
32 #[argh(option, description = "how long to run the stopwatch.")]
33 duration: Option<humantime::Duration>,
34
35 #[argh(switch, description = "disable terminal bell when stopped.")]
36 no_ring: bool,
37}
38
39fn main() {
40 let app: App = argh::from_env();
41
42 let delay: Option<Duration> = app.delay.map(|d| d.into());
43 let pause = app.pause.into();
44 let duration = app
45 .duration
46 .map(|d| d.into())
47 .unwrap_or_else(|| Duration::new(u64::MAX, 0));
48 let no_ring = app.no_ring;
49
50 if let Some(delay) = delay {
51 println!("Waiting {:?}...", delay);
52 thread::sleep(delay);
53 }
54
55 let bell = if no_ring { "" } else { "\x07" };
56
57 let now = Instant::now();
58
59 print!("\x1B[?25l");
60 let mut elapsed = now.elapsed();
61 while elapsed < duration {
62 print!("\rElapsed: {}\x1B[K", humantime::format_duration(elapsed));
63 thread::sleep(pause);
64 elapsed = now.elapsed();
65 }
66 print!("\x1B[?25h");
67
68 print!(
69 "\x1B[2K\rElapsed: {}\nStopped{}",
70 humantime::format_duration(elapsed),
71 bell
72 );
73}