use fmt; use ev; use getopt; use os; use time; use strings; use strconv; use math; type uniterror = !void; fn timer_handler(file: *ev::file) void = { const loop = ev::getloop(file); const t = ev::getuser(file): *time::instant; const t = *t; const tn = time::now(time::clock::MONOTONIC); const currentduration = time::diff(tn, t); fmt::fprint(os::stderr, "\x1B[1K\r")!; fmt::fprint(os::stderr, math::ceilf64(currentduration: f64 / time::SECOND: f64): u64)!; if (currentduration <= 0) { ev::stop(loop); }; }; fn parse_duration(duration: const str) (time::duration | uniterror | strconv::invalid | strconv::overflow) = { const s = strings::toutf8(duration); const unit = s[len(s)-1]; const unit = switch (unit) { case 's' => yield time::SECOND; case 'm' => yield time::MINUTE; case 'h' => yield time::HOUR; case => return uniterror; }; const d = strconv::stoi(strings::sub(duration, 0, len(duration) - 1))?; return d * unit; }; export fn main() void = { const cmd = getopt::parse(os::args, "timer for alarms", "duration", ); defer getopt::finish(&cmd); if (len(cmd.args) != 1) { getopt::printusage(os::stderr, os::args[0], cmd.help)!; os::exit(os::status::FAILURE); }; const duration = cmd.args[0]; const duration = parse_duration(duration)!; const loop = ev::newloop()!; const t = time::now(time::clock::MONOTONIC); const t = time::add(t, duration); defer ev::finish(&loop); const f = ev::newtimer(&loop, &timer_handler, time::clock::MONOTONIC)!; ev::setuser(f, &t); ev::timer_configure(f, 1 * time::SECOND, 1 * time::SECOND); for (ev::dispatch(&loop, -1)!) void; fmt::println()!; };