Skip to content

Commit 8be64d4

Browse files
committed
Allow passing allocator to parsers with withAllocatorParser()
1 parent a4e784d commit 8be64d4

5 files changed

Lines changed: 222 additions & 6 deletions

File tree

.envrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
use flake

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
.zig-cache
22
zig-out
3+
.direnv/

clap.zig

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -770,15 +770,16 @@ pub fn parseEx(
770770

771771
const parser = comptime switch (param.takes_value) {
772772
.none => null,
773-
.one, .many => @field(value_parsers, param.id.value()),
773+
.one, .many => withAllocatorParser(@field(value_parsers, param.id.value())),
774774
};
775775

776776
const name = longest.name[0..longest.name.len].*;
777+
777778
switch (param.takes_value) {
778779
.none => @field(arguments, &name) +|= 1,
779-
.one => @field(arguments, &name) = try parser(arg.value.?),
780+
.one => @field(arguments, &name) = try parser(arg.value.?, allocator),
780781
.many => {
781-
const value = try parser(arg.value.?);
782+
const value = try parser(arg.value.?, allocator);
782783
try @field(arguments, &name).append(allocator, value);
783784
},
784785
}
@@ -801,7 +802,7 @@ pub fn parseEx(
801802

802803
const parser = comptime switch (param.takes_value) {
803804
.none => null,
804-
.one, .many => @field(value_parsers, param.id.value()),
805+
.one, .many => withAllocatorParser(@field(value_parsers, param.id.value())),
805806
};
806807

807808
// We keep track of how many positionals we have received. This is used to pick which
@@ -811,8 +812,8 @@ pub fn parseEx(
811812
const last = positionals.len == i + 1;
812813
if ((last and positional_count >= i) or positional_count == i) {
813814
switch (@typeInfo(@TypeOf(pos.*))) {
814-
.optional => pos.* = try parser(arg.value.?),
815-
else => try pos.append(allocator, try parser(arg.value.?)),
815+
.optional => pos.* = try parser(arg.value.?, allocator),
816+
else => try pos.append(allocator, try parser(arg.value.?, allocator)),
816817
}
817818

818819
if (opt.terminating_positional <= positional_count)
@@ -852,6 +853,44 @@ pub fn parseEx(
852853
};
853854
}
854855

856+
fn AllocatorParserReturnType(parser: anytype) type {
857+
const parser_info = switch (@typeInfo(@TypeOf(parser))) {
858+
.@"fn" => |info| info,
859+
else => {
860+
return void;
861+
},
862+
};
863+
return parser_info.return_type orelse void;
864+
}
865+
866+
fn AllocatorParser(parser: anytype) type {
867+
return fn (value: anytype, allocator: std.mem.Allocator) AllocatorParserReturnType(parser);
868+
}
869+
870+
pub fn withAllocatorParser(parser: anytype) AllocatorParser(parser) {
871+
const parser_info = switch (@typeInfo(@TypeOf(parser))) {
872+
.@"fn" => |info| info,
873+
else => {
874+
@compileError("withAllocatorParser() must be called with a non-null parser implementation");
875+
},
876+
};
877+
return struct {
878+
pub fn parseWithAllocator(value: anytype, allocator: std.mem.Allocator) AllocatorParserReturnType(parser) {
879+
switch (parser_info.params.len) {
880+
2 => {
881+
return parser(value, allocator);
882+
},
883+
1 => {
884+
return parser(value);
885+
},
886+
else => {
887+
return error.InvalidArgumentParser;
888+
},
889+
}
890+
}
891+
}.parseWithAllocator;
892+
}
893+
855894
/// The result of `parseEx`. Is owned by the caller and should be freed with `deinit`.
856895
pub fn ResultEx(
857896
comptime Id: type,

flake.lock

Lines changed: 78 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
{
2+
description = "Utility to control Neovim colorscheme from the terminal";
3+
4+
inputs = {
5+
zig2nix.url = "github:Cloudef/zig2nix";
6+
};
7+
8+
outputs = {zig2nix, ...}: let
9+
flake-utils = zig2nix.inputs.flake-utils;
10+
in (flake-utils.lib.eachDefaultSystem (system: let
11+
# Zig flake helper
12+
# Check the flake.nix in zig2nix project for more options:
13+
# <https://github.com/Cloudef/zig2nix/blob/master/flake.nix>
14+
env = zig2nix.outputs.zig-env.${system} {};
15+
system-triple = env.lib.zigTripleFromString system;
16+
in
17+
with builtins;
18+
with env.lib;
19+
with env.pkgs.lib; rec {
20+
# nix build .#target.{zig-target}
21+
# e.g. nix build .#target.x86_64-linux-gnu
22+
packages.target = genAttrs allTargetTriples (target:
23+
env.packageForTarget target ({
24+
src = cleanSource ./.;
25+
26+
nativeBuildInputs = with env.pkgs; [];
27+
buildInputs = with env.pkgsForTarget target; [];
28+
29+
# Smaller binaries and avoids shipping glibc.
30+
zigPreferMusl = true;
31+
32+
# This disables LD_LIBRARY_PATH mangling, binary patching etc...
33+
# The package won't be usable inside nix.
34+
zigDisableWrap = true;
35+
36+
zigBuildFlags = ["-Doptimize=ReleaseFast"];
37+
38+
meta = {
39+
description = "A simple and easy to use command line argument parser library for Zig.";
40+
license = licenses.mit;
41+
maintainers = with lib.maintainers; [];
42+
};
43+
}
44+
// optionalAttrs (!pathExists ./build.zig.zon) {
45+
pname = "my-zig-project";
46+
version = "0.0.0";
47+
}));
48+
49+
# nix build .
50+
packages.default = packages.target.${system-triple}.override {
51+
# Prefer nix friendly settings.
52+
zigPreferMusl = false;
53+
zigDisableWrap = false;
54+
};
55+
56+
# For bundling with nix bundle for running outside of nix
57+
# example: https://github.com/ralismark/nix-appimage
58+
apps.bundle.target = genAttrs allTargetTriples (target: let
59+
pkg = packages.target.${target};
60+
in {
61+
type = "app";
62+
program = "${pkg}/bin/default";
63+
});
64+
65+
# default bundle
66+
apps.bundle.default = apps.bundle.target.${system-triple};
67+
68+
# nix run .
69+
apps.default = env.app [] "zig build run -- \"$@\"";
70+
71+
# nix run .#build
72+
apps.build = env.app [] "zig build \"$@\"";
73+
74+
# nix run .#test
75+
apps.test = env.app [] "zig build test -- \"$@\"";
76+
77+
# nix run .#docs
78+
apps.docs = env.app [] "zig build docs -- \"$@\"";
79+
80+
# nix run .#deps
81+
apps.deps = env.showExternalDeps;
82+
83+
# nix run .#zon2json
84+
apps.zon2json = env.app [env.zon2json] "zon2json \"$@\"";
85+
86+
# nix run .#zon2json-lock
87+
apps.zon2json-lock = env.app [env.zon2json-lock] "zon2json-lock \"$@\"";
88+
89+
# nix run .#zon2nix
90+
apps.zon2nix = env.app [env.zon2nix] "zon2nix \"$@\"";
91+
92+
# nix develop
93+
devShells.default =
94+
env.mkShell {
95+
};
96+
}));
97+
}

0 commit comments

Comments
 (0)