zig napping

Approximately every six months, I approach #zig - a language in its pre-release stage, so there's constantly something new emerging in it.

This time, I wrote `nap` - an "analog" of the `sleep` utility that takes a string in the format 1h15m and then prints the remaining time until the command execution is completed every N seconds.

https://github.com/ninedraft/nap

To implement this, I had to port `time.ParseDuration` from #go - for some reason, I couldn't find an equivalent in the standard Zig library.

I liked several aspects:

- I managed to write the code in a single pass.

- The error messages from the compiler have improved and were helpful throughout the process.

- It turns out there are two community package managers now - https://github.com/nektro/zigmod and https://github.com/mattnite/gyro. Gyro seems to be slightly more mature. However, it doesn't really matter until the language is released.

- The support in vscode has also improved - the Zig LSP works well, although there are some minor things missing, like "run tests by clicking a button above the test code."

durationParse signature

pub fn durationParse(buf: []const u8) DurationParseError!Duration {
    var d: Duration = 0;
    var str = buf[0..];

    if (str.len == 0) {
        return DurationParseError.InvalidFormat;
    }

    if (eql(u8, str, "0")) {
        return 0;
    }

    while (str.len != 0) {
        var v: u64 = 0;

Also #TIL: zig has a std.ComptimeStringMap map. It works at compile time and can be used to create global mappings from strings to other values.

const unitMap = ComptimeStringMap(u64, .{
    .{ "ns", 1 },
    .{ "us", time.ns_per_us },
    .{ "µs", time.ns_per_us }, // U+00B5 = micro symbol
    .{ "μs", time.ns_per_us }, // U+03BC = Greek letter mu
    .{ "ms", time.ns_per_ms },
    .{ "s", time.ns_per_s },
    .{ "m", time.ns_per_min },
    .{ "h", time.ns_per_hour },
});