mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
config: arg parser supports custom types with error tracking
This commit is contained in:
@ -155,6 +155,15 @@ fn parseIntoField(
|
|||||||
// 3 arg = (self, alloc, input) => void
|
// 3 arg = (self, alloc, input) => void
|
||||||
3 => try @field(dst, field.name).parseCLI(alloc, value),
|
3 => try @field(dst, field.name).parseCLI(alloc, value),
|
||||||
|
|
||||||
|
// 4 arg = (self, alloc, errors, input) => void
|
||||||
|
4 => if (comptime canTrackErrors(T)) {
|
||||||
|
try @field(dst, field.name).parseCLI(alloc, &dst._errors, value);
|
||||||
|
} else {
|
||||||
|
var list: ErrorList = .{};
|
||||||
|
try @field(dst, field.name).parseCLI(alloc, &list, value);
|
||||||
|
if (!list.empty()) return error.InvalidValue;
|
||||||
|
},
|
||||||
|
|
||||||
else => @compileError("parseCLI invalid argument count"),
|
else => @compileError("parseCLI invalid argument count"),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,22 +200,22 @@ fn parseIntoField(
|
|||||||
|
|
||||||
bool => try parseBool(value orelse "t"),
|
bool => try parseBool(value orelse "t"),
|
||||||
|
|
||||||
u8 => try std.fmt.parseInt(
|
u8 => std.fmt.parseInt(
|
||||||
u8,
|
u8,
|
||||||
value orelse return error.ValueRequired,
|
value orelse return error.ValueRequired,
|
||||||
0,
|
0,
|
||||||
),
|
) catch return error.InvalidValue,
|
||||||
|
|
||||||
u32 => try std.fmt.parseInt(
|
u32 => std.fmt.parseInt(
|
||||||
u32,
|
u32,
|
||||||
value orelse return error.ValueRequired,
|
value orelse return error.ValueRequired,
|
||||||
0,
|
0,
|
||||||
),
|
) catch return error.InvalidValue,
|
||||||
|
|
||||||
f64 => try std.fmt.parseFloat(
|
f64 => std.fmt.parseFloat(
|
||||||
f64,
|
f64,
|
||||||
value orelse return error.ValueRequired,
|
value orelse return error.ValueRequired,
|
||||||
),
|
) catch return error.InvalidValue,
|
||||||
|
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
@ -229,7 +238,7 @@ fn parseBool(v: []const u8) !bool {
|
|||||||
if (mem.eql(u8, v, str)) return false;
|
if (mem.eql(u8, v, str)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return error.InvalidBooleanValue;
|
return error.InvalidValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
test "parse: simple" {
|
test "parse: simple" {
|
||||||
@ -469,6 +478,62 @@ test "parseIntoField: struct with parse func" {
|
|||||||
try testing.expectEqual(@as([]const u8, "HELLO!"), data.a.v);
|
try testing.expectEqual(@as([]const u8, "HELLO!"), data.a.v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "parseIntoField: struct with parse func with error tracking" {
|
||||||
|
const testing = std.testing;
|
||||||
|
var arena = ArenaAllocator.init(testing.allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
const alloc = arena.allocator();
|
||||||
|
|
||||||
|
var data: struct {
|
||||||
|
a: struct {
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
pub fn parseCLI(
|
||||||
|
_: Self,
|
||||||
|
parse_alloc: Allocator,
|
||||||
|
errors: *ErrorList,
|
||||||
|
value: ?[]const u8,
|
||||||
|
) !void {
|
||||||
|
_ = value;
|
||||||
|
try errors.add(parse_alloc, .{ .message = "OH NO!" });
|
||||||
|
}
|
||||||
|
} = .{},
|
||||||
|
|
||||||
|
_errors: ErrorList = .{},
|
||||||
|
} = .{};
|
||||||
|
|
||||||
|
try parseIntoField(@TypeOf(data), alloc, &data, "a", "42");
|
||||||
|
try testing.expect(!data._errors.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
test "parseIntoField: struct with parse func with unsupported error tracking" {
|
||||||
|
const testing = std.testing;
|
||||||
|
var arena = ArenaAllocator.init(testing.allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
const alloc = arena.allocator();
|
||||||
|
|
||||||
|
var data: struct {
|
||||||
|
a: struct {
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
pub fn parseCLI(
|
||||||
|
_: Self,
|
||||||
|
parse_alloc: Allocator,
|
||||||
|
errors: *ErrorList,
|
||||||
|
value: ?[]const u8,
|
||||||
|
) !void {
|
||||||
|
_ = value;
|
||||||
|
try errors.add(parse_alloc, .{ .message = "OH NO!" });
|
||||||
|
}
|
||||||
|
} = .{},
|
||||||
|
} = .{};
|
||||||
|
|
||||||
|
try testing.expectError(
|
||||||
|
error.InvalidValue,
|
||||||
|
parseIntoField(@TypeOf(data), alloc, &data, "a", "42"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns an iterator (implements "next") that reads CLI args by line.
|
/// Returns an iterator (implements "next") that reads CLI args by line.
|
||||||
/// Each CLI arg is expected to be a single line. This is used to implement
|
/// Each CLI arg is expected to be a single line. This is used to implement
|
||||||
/// configuration files.
|
/// configuration files.
|
||||||
|
Reference in New Issue
Block a user