From 1d89fdc16a446c139bf37ecfe1c7ef07d89d4894 Mon Sep 17 00:00:00 2001 From: Jimmi Holst Christensen Date: Fri, 21 Feb 2025 21:24:16 +0100 Subject: fix: More than 2 positionals not parsing correctly Fixes #149 --- clap.zig | 70 ++++++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/clap.zig b/clap.zig index c12839e..b666f56 100644 --- a/clap.zig +++ b/clap.zig @@ -795,7 +795,7 @@ pub fn parseEx( const i = positionals_index; positionals_index += 1; - if (stream.positional != arg.param) + if (arg.param.names.longest().kind != .positional) // This is a trick to emulate a runtime `continue` in an `inline for`. break :continue_params_loop; @@ -809,15 +809,17 @@ pub fn parseEx( // positional parameters, the rest are stored in the last `positional` field. const pos = &positionals[i]; const last = positionals.len == i + 1; - if ((last and positional_count >= i) or positional_count == i) + if ((last and positional_count >= i) or positional_count == i) { switch (@typeInfo(@TypeOf(pos.*))) { .optional => pos.* = try parser(arg.value.?), else => try pos.append(allocator, try parser(arg.value.?)), - }; + } - if (opt.terminating_positional <= positional_count) - break :arg_loop; - positional_count += 1; + if (opt.terminating_positional <= positional_count) + break :arg_loop; + positional_count += 1; + continue :arg_loop; + } } } @@ -1110,42 +1112,58 @@ test "single positional" { test "multiple positionals" { const params = comptime parseParamsComptime( + \\ \\ \\ \\ ); - // { - // var iter = args.SliceIterator{ .args = &.{} }; - // var res = try parseEx(Help, ¶ms, parsers.default, &iter, .{ - // .allocator = std.testing.allocator, - // }); - // defer res.deinit(); + { + var iter = args.SliceIterator{ .args = &.{} }; + var res = try parseEx(Help, ¶ms, parsers.default, &iter, .{ + .allocator = std.testing.allocator, + }); + defer res.deinit(); - // try std.testing.expect(res.positionals[0] == null); - // try std.testing.expect(res.positionals[1] == null); - // } + try std.testing.expect(res.positionals[0] == null); + try std.testing.expect(res.positionals[1] == null); + try std.testing.expect(res.positionals[2] == null); + } - // { - // var iter = args.SliceIterator{ .args = &.{"1"} }; - // var res = try parseEx(Help, ¶ms, parsers.default, &iter, .{ - // .allocator = std.testing.allocator, - // }); - // defer res.deinit(); + { + var iter = args.SliceIterator{ .args = &.{"1"} }; + var res = try parseEx(Help, ¶ms, parsers.default, &iter, .{ + .allocator = std.testing.allocator, + }); + defer res.deinit(); - // try std.testing.expectEqual(@as(u8, 1), res.positionals[0].?); - // try std.testing.expect(res.positionals[1] == null); - // } + try std.testing.expectEqual(@as(u8, 1), res.positionals[0].?); + try std.testing.expect(res.positionals[1] == null); + try std.testing.expect(res.positionals[2] == null); + } + + { + var iter = args.SliceIterator{ .args = &.{ "1", "2" } }; + var res = try parseEx(Help, ¶ms, parsers.default, &iter, .{ + .allocator = std.testing.allocator, + }); + defer res.deinit(); + + try std.testing.expectEqual(@as(u8, 1), res.positionals[0].?); + try std.testing.expectEqual(@as(u8, 2), res.positionals[1].?); + try std.testing.expect(res.positionals[2] == null); + } { - var iter = args.SliceIterator{ .args = &.{ "1", "b" } }; + var iter = args.SliceIterator{ .args = &.{ "1", "2", "b" } }; var res = try parseEx(Help, ¶ms, parsers.default, &iter, .{ .allocator = std.testing.allocator, }); defer res.deinit(); try std.testing.expectEqual(@as(u8, 1), res.positionals[0].?); - try std.testing.expectEqualStrings("b", res.positionals[1].?); + try std.testing.expectEqual(@as(u8, 2), res.positionals[1].?); + try std.testing.expectEqualStrings("b", res.positionals[2].?); } } -- cgit v1.2.3