Changes
3 changed files (+146/-7)
-
-
@@ -22,14 +22,78 @@ @cInclude("time.h");@cInclude("sunriset.h"); }); const sunrise_keywords: []const []const u8 = &.{ "sunrise", "rise", "dawn", "sunup", "up", }; const sunset_keywords: []const []const u8 = &.{ "sunset", "set", "dusk", "sundown", "down", }; const EventType = enum { sunset, sunrise, // sunset and sunrise both, pub fn parseArg(current: ?@This(), arg: []const u8, args: *std.process.ArgIterator) ParseArgsError!@This() { // Compatibility inline for (sunrise_keywords) |keyword| { if (std.mem.eql(u8, keyword, arg)) { return .sunrise; } } // Compatibility inline for (sunset_keywords) |keyword| { if (std.mem.eql(u8, keyword, arg)) { return .sunset; } } if (std.mem.eql(u8, "--event", arg) or std.mem.eql(u8, "-e", arg)) { const next = args.next() orelse { std.log.err("{s} option requires a value", .{arg}); return ParseArgsError.MissingValue; }; if (std.mem.eql(u8, "sunrise", next)) { return if (current) |e| switch (e) { .sunset => .both, else => e, } else .sunrise; } if (std.mem.eql(u8, "sunset", next)) { return if (current) |e| switch (e) { .sunrise => .both, else => e, } else .sunset; } std.log.err("Value of {s} must be either `sunrise` or `sunset`: got {s}", .{ arg, next }); return ParseArgsError.InvalidEventType; } return ParseArgsError.UnknownArg; } }; latitude: ?f64 = null, longitude: ?f64 = null, offset_hour: f64 = 0, twilight_angle: f64 = c.TWILIGHT_ANGLE_DAYLIGHT, utc: bool = false, debug: bool = false, report_sunrise: c.OnOff = c.ONOFF_ON, report_sunset: c.OnOff = c.ONOFF_ON, command: CommandOptions = .poll, pub const ParseArgsError = error{
-
@@ -40,6 +104,7 @@ InvalidLongitudeFormat,InvalidDayOfMonth, InvalidMonth, InvalidYearSince2000, InvalidEventType, }; pub const ReportOptions = struct {
-
@@ -115,9 +180,18 @@ }}; pub const ListOptions = struct { event_type: ?EventType = null, days: c_uint = c.DEFAULT_LIST, pub fn parseArg(self: *@This(), arg: []const u8, _: *std.process.ArgIterator) ParseArgsError!void { pub fn parseArg(self: *@This(), arg: []const u8, args: *std.process.ArgIterator) ParseArgsError!void { if (EventType.parseArg(self.event_type, arg, args)) |e| { self.event_type = e; return; } else |err| switch (err) { ParseArgsError.UnknownArg => {}, else => return err, } if (std.fmt.parseUnsigned(c_uint, arg, 10)) |days| { self.days = days; return;
-
@@ -424,6 +498,11 @@ }),else => getTargetDay(now, .{ .is_utc = self.utc }), }; const event_type: EventType = switch (self.command) { .list => |opts| opts.event_type orelse .both, else => .both, }; // This effectful function updates `c.timezone`. c.tzset();
-
@@ -444,8 +523,8 @@ .functionPoll = c.ONOFF_OFF,.functionWait = c.ONOFF_OFF, .utc = if (self.utc) c.ONOFF_ON else c.ONOFF_OFF, .debug = if (self.debug) c.ONOFF_ON else c.ONOFF_OFF, .reportSunrise = self.report_sunrise, .reportSunset = self.report_sunset, .reportSunrise = if (event_type == .sunset) c.ONOFF_OFF else c.ONOFF_ON, .reportSunset = if (event_type == .sunrise) c.ONOFF_OFF else c.ONOFF_ON, .listDays = switch (self.command) { .list => |opts| opts.days, else => c.DEFAULT_LIST,
-
-
-
@@ -68,6 +68,15 @@ \\wait Sleep until sunrise and/or sunset, then exits.\\report Prints sunrise and sunset times. \\list List sunrise and sunset times for next <DAYS>. \\ \\[List Options] \\-e <TYPE>, --event <TYPE> \\ Events to print. Valid values are: \\ * sunrise \\ * sunset \\ When this option is not set, sunwait targets both. \\ You can specify this option multiple times to explicitly \\ tell sunwait to target both. \\ \\[Common Parameters] \\TWILIGHT Twilight type. Valid values are: \\ * daylight
-
@@ -75,8 +84,6 @@ \\ * civil\\ * nautical \\ * astronomical \\ * angle <degree> \\EVENT TYPE Use "rise" for sunrise and "set" for sunset. \\ If this parameter is not set, sunwait targets both. \\OFFSET Time offset for sunrise and sunset time, towards noon. \\ Format must be "MM" (minutes) or "HH:MM". \\
-
-
-
@@ -26,6 +26,7 @@ longitude: []const u8 = "31.132484E",latitude: []const u8 = "29.977435N", days: ?[]const u8 = "3", tz: []const u8 = "UTC", event: ?enum { sunset, sunrise } = null, }; fn list(allocator: std.mem.Allocator, opts: ListOptions) !std.process.Child.RunResult {
-
@@ -47,6 +48,10 @@ try args.append(days);} try args.append(opts.latitude); try args.append(opts.longitude); if (opts.event) |e| { try args.append(@tagName(e)); } return try std.process.Child.run(.{ .allocator = allocator,
-
@@ -130,3 +135,51 @@ try std.testing.expectEqual(legacy.term.Exited, new.term.Exited);try std.testing.expectEqualStrings(legacy.stderr, new.stderr); try std.testing.expectEqualStrings(legacy.stdout, new.stdout); } test "Should behave same on printing only sunrise" { const legacy = try list(std.testing.allocator, .{ .bin = config.legacy_bin, .tz = "Europe/Paris", .utc = true, .event = .sunrise, }); defer std.testing.allocator.free(legacy.stderr); defer std.testing.allocator.free(legacy.stdout); const new = try list(std.testing.allocator, .{ .bin = config.new_bin, .tz = "Europe/Paris", .utc = true, .event = .sunrise, }); defer std.testing.allocator.free(new.stderr); defer std.testing.allocator.free(new.stdout); try std.testing.expectEqual(legacy.term.Exited, new.term.Exited); try std.testing.expectEqualStrings(legacy.stderr, new.stderr); try std.testing.expectEqualStrings(legacy.stdout, new.stdout); } test "Should behave same on printing only sunset" { const legacy = try list(std.testing.allocator, .{ .bin = config.legacy_bin, .tz = "Europe/Paris", .utc = true, .event = .sunset, }); defer std.testing.allocator.free(legacy.stderr); defer std.testing.allocator.free(legacy.stdout); const new = try list(std.testing.allocator, .{ .bin = config.new_bin, .tz = "Europe/Paris", .utc = true, .event = .sunset, }); defer std.testing.allocator.free(new.stderr); defer std.testing.allocator.free(new.stdout); try std.testing.expectEqual(legacy.term.Exited, new.term.Exited); try std.testing.expectEqualStrings(legacy.stderr, new.stderr); try std.testing.expectEqualStrings(legacy.stdout, new.stdout); }
-