tools

various tools I have been using throughout the years
Log | Files | Refs | README | LICENSE

main.zig (5005B)


      1 const command = @import("command.zig");
      2 const options = @import("options.zig");
      3 const pausable_timer = @import("pausable_timer.zig");
      4 const std = @import("std");
      5 const builtin = @import("builtin");
      6 const step = @import("step.zig");
      7 
      8 pub fn main(init: std.process.Init) !void {
      9     const allocator = init.gpa;
     10 
     11     const program_and_args = try init.minimal.args.toSlice(init.arena.allocator());
     12 
     13     const program = program_and_args[0];
     14     const program_args = program_and_args[1..];
     15 
     16     var stdout_buffer: [1024]u8 = undefined;
     17     var stdout_writer = std.Io.File.stdout().writer(init.io, &stdout_buffer);
     18     const stdout = &stdout_writer.interface;
     19 
     20     const opts = options.parseArgs(program_args) catch {
     21         try printUsage(allocator, stdout, program);
     22         std.process.exit(1);
     23     };
     24 
     25     switch (opts) {
     26         .help => {
     27             try printUsage(allocator, stdout, program);
     28         },
     29         .settings => |settings| {
     30             try run(init, allocator, stdout, settings);
     31         },
     32     }
     33 }
     34 
     35 fn run(init: std.process.Init, allocator: std.mem.Allocator, out: *std.Io.Writer, settings: options.Settings) !void {
     36     var poller = try command.Poller.init(allocator);
     37     defer poller.deinit();
     38 
     39     const status_file: ?std.Io.File = if (settings.file) |path| try std.Io.Dir.cwd().createFile(init.io, path, .{}) else null;
     40     defer if (status_file) |f| f.close(init.io);
     41     defer if (settings.file) |path| std.Io.Dir.cwd().deleteFile(init.io, path) catch |err| {
     42         std.log.debug("failed to delete status file: {any}", .{err});
     43     };
     44 
     45     if (poller.interactive()) {
     46         try out.print("\n", .{});
     47         try out.flush();
     48     }
     49 
     50     var current = step.Step{};
     51     while (true) {
     52         var timer = pausable_timer.PausableTimer.init(init.io);
     53 
     54         var remaining = current.length(settings);
     55 
     56         while (remaining > 0) : ({
     57             remaining = current.length(settings) -| timer.read(init.io);
     58         }) {
     59             if (poller.interactive()) {
     60                 try out.print("\x1b[F\x1b[2K\r", .{});
     61                 try out.flush();
     62             }
     63             try printStatus(
     64                 allocator,
     65                 out,
     66                 status_file,
     67                 init.io,
     68                 current,
     69                 remaining,
     70             );
     71 
     72             if (try poller.pollTimeout(std.time.ns_per_s)) |command_| {
     73                 switch (command_) {
     74                     command.Command.Quit => {
     75                         try out.print("\n", .{});
     76                         try out.flush();
     77                         return;
     78                     },
     79                     command.Command.Pause => {
     80                         timer.togglePause(init.io);
     81                     },
     82                     command.Command.Reset => {
     83                         if (timer.paused and remaining == current.length(settings)) {
     84                             current = step.Step{};
     85                         }
     86 
     87                         timer.reset(init.io);
     88                     },
     89                 }
     90             }
     91         }
     92 
     93         current = current.next();
     94         if (settings.notifications and current.length(settings) > 0) {
     95             notify(init.io, allocator, current.step_type.message());
     96         }
     97     }
     98 }
     99 
    100 fn notify(io: std.Io, allocator: std.mem.Allocator, message: []const u8) void {
    101     if (builtin.os.tag == .macos) {
    102         const script = std.fmt.allocPrint(allocator, "display notification \"{s}\" with title \"pracomer\"", .{message}) catch return;
    103         defer allocator.free(script);
    104         const argv = [_][]const u8{ "osascript", "-e", script };
    105         var proc = std.process.spawn(io, .{
    106             .argv = &argv,
    107         }) catch return;
    108         _ = proc.wait(io) catch |err| {
    109             std.log.debug("failed to wait for process: {any}", .{err});
    110         };
    111     } else {
    112         const argv = [_][]const u8{ "notify-send", "-u", "critical", message };
    113         var proc = std.process.spawn(io, .{
    114             .argv = &argv,
    115         }) catch return;
    116         _ = proc.wait(io) catch |err| {
    117             std.log.debug("failed to wait for process: {any}", .{err});
    118         };
    119     }
    120 }
    121 
    122 fn printStatus(
    123     allocator: std.mem.Allocator,
    124     out: *std.Io.Writer,
    125     status_file: ?std.Io.File,
    126     io: std.Io,
    127     current: step.Step,
    128     remaining: u64,
    129 ) !void {
    130     const msg = try current.render(allocator, remaining);
    131     defer allocator.free(msg);
    132 
    133     try out.print("{s}\n", .{msg});
    134     try out.flush();
    135 
    136     if (status_file) |f| {
    137         var buf: [1024]u8 = undefined;
    138         var fw = f.writer(io, &buf);
    139         try fw.seekTo(0);
    140         try fw.interface.writeAll(msg);
    141         try fw.interface.writeAll("\n");
    142         try fw.flush();
    143     }
    144 }
    145 
    146 fn printUsage(
    147     allocator: std.mem.Allocator,
    148     out: *std.Io.Writer,
    149     program: []const u8,
    150 ) !void {
    151     const usage = try options.usage(allocator, program);
    152     defer allocator.free(usage);
    153 
    154     try out.print("{s}", .{usage});
    155     try out.flush();
    156 }
    157 
    158 test "main.zig" {
    159     std.testing.refAllDecls(@This());
    160 }