summaryrefslogtreecommitdiff
path: root/timer.ha
diff options
context:
space:
mode:
authorJulian Hurst <ark@mansus.space>2025-03-10 02:41:31 +0100
committerJulian Hurst <ark@mansus.space>2025-03-10 02:41:31 +0100
commit9b0fdeea0b7dd80e5d198b1e95b6ceb077153050 (patch)
tree19e4dda136e52cf026e8aab9ba2f043cbaba4a6f /timer.ha
parent741f56de2c1bd4bce52dd35bc921111284e995ab (diff)
downloadtimer-9b0fdeea0b7dd80e5d198b1e95b6ceb077153050.tar.gz
Improve duration argument parsing
Diffstat (limited to 'timer.ha')
-rw-r--r--timer.ha87
1 files changed, 71 insertions, 16 deletions
diff --git a/timer.ha b/timer.ha
index 75d99b4..0f01f0e 100644
--- a/timer.ha
+++ b/timer.ha
@@ -7,7 +7,7 @@ use strings;
use strconv;
use math;
-type uniterror = !void;
+type parseerror = !void;
fn timer_handler(file: *ev::file) void = {
const loop = ev::getloop(file);
@@ -59,21 +59,61 @@ fn human_readable(duration: time::duration) str = {
return fmt::asprintf("{%}:{%}:{%}", hours, mods, mins, mods, secs, mods);
};
-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;
+fn parse_duration(duration: const str) (time::duration | parseerror | strconv::invalid | strconv::overflow) = {
+ const spl = strings::split(duration, ":");
+ defer free(spl);
+ if (len(spl) >= 4 || len(spl) < 1) {
+ return parseerror;
};
- const d = strconv::stoi(strings::sub(duration, 0, len(duration) - 1))?;
- return d * unit;
+ const hours = if (len(spl) == 3) {
+ yield strconv::stoi(spl[0])?;
+ } else {
+ yield 0;
+ };
+
+ const mins = if (len(spl) >= 2) {
+ yield strconv::stoi(spl[len(spl)-2])?;
+ } else {
+ yield 0;
+ };
+
+ const secs = strconv::stoi(spl[len(spl)-1])?;
+
+ const hours = hours * time::HOUR;
+ const mins = mins * time::MINUTE;
+ const secs = secs * time::SECOND;
+ return hours + mins + secs;
+};
+
+fn parse_duration_hms(duration: const str) (time::duration | parseerror | strconv::invalid | strconv::overflow) = {
+ let start = 0z;
+ const hours = match (strings::index(duration, 'h')) {
+ case let i: size =>
+ const s = strconv::stoi(strings::sub(duration, start, i))!;
+ start = i + 1;
+ yield s;
+ case void =>
+ yield 0;
+ };
+ const mins = match (strings::index(duration, 'm')) {
+ case let i: size =>
+ const s = strconv::stoi(strings::sub(duration, start, i))!;
+ start = i + 1;
+ yield s;
+ case void =>
+ yield 0;
+ };
+ const secs = match (strings::index(duration, 's')) {
+ case let i: size =>
+ fmt::error(start)!;
+ yield strconv::stoi(strings::sub(duration, start, i))!;
+ case void =>
+ yield 0;
+ };
+ const hours = hours * time::HOUR;
+ const mins = mins * time::MINUTE;
+ const secs = secs * time::SECOND;
+ return hours + mins + secs;
};
export fn main() void = {
@@ -89,7 +129,22 @@ export fn main() void = {
};
const duration = cmd.args[0];
- const duration = parse_duration(duration)!;
+
+ const f = if (strings::contains(duration, ':')) {
+ yield &parse_duration;
+ } else {
+ yield &parse_duration_hms;
+ };
+ const duration = match (f(duration)) {
+ case let d: time::duration =>
+ yield d;
+ case parseerror =>
+ fmt::fatal("Error parsing the given duration");
+ case let e: strconv::invalid =>
+ fmt::fatal(strconv::strerror(e));
+ case let e: strconv::overflow =>
+ fmt::fatal(strconv::strerror(e));
+ };
const loop = ev::newloop()!;