Changes
7 changed files (+159/-12)
-
-
@@ -17,10 +17,13 @@ // SPDX-License-Identifier: GPL-3.0-onlyconst std = @import("std"); const ArgIterator = @import("./RunOptions/ArgIterator.zig"); const datetime = @import("./RunOptions/datetime.zig"); const EventType = @import("./RunOptions/event.zig").EventType; const ParseArgsError = @import("./RunOptions/parser.zig").ParseArgsError; const TwilightAngle = @import("./RunOptions/twilight.zig").TwilightAngle; pub const ProcessArgIterator = @import("./RunOptions/ProcessArgIterator.zig"); const c = @cImport({ @cInclude("time.h");
-
@@ -38,7 +41,7 @@const PollOptions = struct { at: ?datetime.Datetime = null, pub fn parseArg(self: *@This(), arg: []const u8, args: *std.process.ArgIterator) ParseArgsError!void { pub fn parseArg(self: *@This(), arg: []const u8, args: ArgIterator) ParseArgsError!void { if (std.mem.eql(u8, "--at", arg)) { const next = args.next() orelse { std.log.err("{s} option requires a value", .{arg});
-
@@ -68,7 +71,7 @@ day_of_month: ?u5 = null,month: ?u4 = null, year_since_2000: ?c_int = null, pub fn parseArg(self: *@This(), arg: []const u8, args: *std.process.ArgIterator) ParseArgsError!void { pub fn parseArg(self: *@This(), arg: []const u8, args: ArgIterator) ParseArgsError!void { if (std.mem.eql(u8, "--date", arg)) { const next = args.next() orelse { std.log.err("{s} option requires a value", .{arg});
-
@@ -177,7 +180,7 @@pub const WaitOptions = struct { event_type: ?EventType = null, pub fn parseArg(self: *@This(), arg: []const u8, args: *std.process.ArgIterator) ParseArgsError!void { pub fn parseArg(self: *@This(), arg: []const u8, args: ArgIterator) ParseArgsError!void { self.event_type = try EventType.parseArg(self.event_type, arg, args); } };
-
@@ -187,7 +190,7 @@ event_type: ?EventType = null,days: c_uint = c.DEFAULT_LIST, from: ?datetime.CalendarDate = null, pub fn parseArg(self: *@This(), arg: []const u8, args: *std.process.ArgIterator) ParseArgsError!void { pub fn parseArg(self: *@This(), arg: []const u8, args: ArgIterator) ParseArgsError!void { if (EventType.parseArg(self.event_type, arg, args)) |e| { self.event_type = e; return;
-
@@ -249,7 +252,7 @@ report: ReportOptions,wait: WaitOptions, list: ListOptions, pub fn parseArg(self: *@This(), arg: []const u8, args: *std.process.ArgIterator) ParseArgsError!void { pub fn parseArg(self: *@This(), arg: []const u8, args: ArgIterator) ParseArgsError!void { switch (self.*) { .help => return ParseArgsError.UnknownArg, .version => return ParseArgsError.UnknownArg,
-
@@ -266,7 +269,7 @@ no_command,with_command, }; pub fn parseArgs(self: *@This(), args: *std.process.ArgIterator) ParseArgsError!void { pub fn parseArgs(self: *@This(), args: ArgIterator) ParseArgsError!void { state: switch (ParseState.no_command) { .no_command => { while (args.next()) |arg| {
-
@@ -320,7 +323,7 @@ },} } fn parseArg(self: *@This(), arg: []const u8, args: *std.process.ArgIterator) ParseArgsError!void { fn parseArg(self: *@This(), arg: []const u8, args: ArgIterator) ParseArgsError!void { if (std.mem.eql(u8, "-v", arg) or std.mem.eql(u8, "--version", arg)) { self.command = .version; return;
-
@@ -710,4 +713,5 @@ }test { _ = @import("RunOptions/datetime.zig"); _ = @import("RunOptions/TestArgIterator.zig"); }
-
-
-
@@ -0,0 +1,31 @@// Copyright (C) 2025 Shota FUJI // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. // // SPDX-License-Identifier: GPL-3.0-only const std = @import("std"); const ArgIterator = @This(); ptr: *anyopaque, vtable: *const VTable, pub const VTable = struct { next: *const fn (*anyopaque) ?[]const u8, }; pub fn next(self: ArgIterator) ?[]const u8 { return self.vtable.next(self.ptr); }
-
-
-
@@ -0,0 +1,49 @@// Copyright (C) 2025 Shota FUJI // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. // // SPDX-License-Identifier: GPL-3.0-only const std = @import("std"); const ArgIterator = @import("./ArgIterator.zig"); const ProcessArgIterator = @This(); args: std.process.ArgIterator, pub fn init(allocator: std.mem.Allocator) std.mem.Allocator.Error!ProcessArgIterator { return .{ .args = try std.process.ArgIterator.initWithAllocator(allocator), }; } pub fn deinit(self: *ProcessArgIterator) void { self.args.deinit(); } pub fn iterator(self: *ProcessArgIterator) ArgIterator { return .{ .ptr = self, .vtable = &.{ .next = &next, }, }; } fn next(ctx: *anyopaque) ?[]const u8 { const self: *ProcessArgIterator = @ptrCast(@alignCast(ctx)); return self.args.next(); }
-
-
-
@@ -0,0 +1,59 @@// Copyright (C) 2025 Shota FUJI // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. // // SPDX-License-Identifier: GPL-3.0-only const std = @import("std"); const ArgIterator = @import("./ArgIterator.zig"); const TestArgIterator = @This(); args: []const []const u8 = &.{""}, index: usize = 0, pub fn init(args: []const []const u8) TestArgIterator { return .{ .args = args }; } pub fn iterator(self: *TestArgIterator) ArgIterator { return .{ .ptr = self, .vtable = &.{ .next = &next, }, }; } fn next(ctx: *anyopaque) ?[]const u8 { const self: *TestArgIterator = @ptrCast(@alignCast(ctx)); if (self.index >= self.args.len) { return null; } defer self.index += 1; return self.args[self.index]; } test { var test_args = TestArgIterator.init(&.{ "foo", "bar", "baz" }); const iter = test_args.iterator(); try std.testing.expectEqualStrings("foo", iter.next().?); try std.testing.expectEqualStrings("bar", iter.next().?); try std.testing.expectEqualStrings("baz", iter.next().?); try std.testing.expectEqual(null, iter.next()); }
-
-
-
@@ -17,6 +17,7 @@ // SPDX-License-Identifier: GPL-3.0-onlyconst std = @import("std"); const ArgIterator = @import("./ArgIterator.zig"); const ParseArgsError = @import("./parser.zig").ParseArgsError; const sunrise_keywords: []const []const u8 = &.{
-
@@ -42,7 +43,7 @@// sunset and sunrise both, pub fn parseArg(current: ?@This(), arg: []const u8, args: *std.process.ArgIterator) ParseArgsError!@This() { pub fn parseArg(current: ?@This(), arg: []const u8, args: ArgIterator) ParseArgsError!@This() { // Compatibility inline for (sunrise_keywords) |keyword| { if (std.mem.eql(u8, keyword, arg)) {
-
-
-
@@ -17,6 +17,7 @@ // SPDX-License-Identifier: GPL-3.0-onlyconst std = @import("std"); const ArgIterator = @import("./ArgIterator.zig"); const ParseArgsError = @import("./parser.zig").ParseArgsError; const legacy_daylight_keywords: []const []const u8 = &.{
-
@@ -62,7 +63,7 @@ custom: f64,const valueless_variants: []const TwilightAngle = &.{ .daylight, .civil, .nautical, .astronomical }; pub fn parseArg(arg: []const u8, args: *std.process.ArgIterator) ParseArgsError!@This() { pub fn parseArg(arg: []const u8, args: ArgIterator) ParseArgsError!@This() { inline for (legacy_daylight_keywords) |keyword| { if (std.mem.eql(u8, keyword, arg)) { return .daylight;
-
-
-
@@ -102,17 +102,19 @@ const allocator = arena.allocator();var opts = RunOptions{}; var args = std.process.ArgIterator.initWithAllocator(allocator) catch { var args = RunOptions.ProcessArgIterator.init(allocator) catch { return ExitCode.out_of_memory.code(); }; defer args.deinit(); const bin_name = args.next() orelse { const iter = args.iterator(); const bin_name = iter.next() orelse { std.log.err("Got no arguments, exiting.", .{}); return ExitCode.generic_error.code(); }; opts.parseArgs(&args) catch { opts.parseArgs(iter) catch { writeHelp(std.io.getStdErr().writer(), bin_name) catch |err| { std.log.err("Unable to write help message to stderr: {s}", .{@errorName(err)}); return ExitCode.stdout_write_error.code();
-