Skip to content

Commit 44ac38d

Browse files
committed
Use std.process.Init
1 parent e8a9c58 commit 44ac38d

7 files changed

Lines changed: 54 additions & 50 deletions

File tree

.githooks/pre-push

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/usr/bin/env sh
2+
3+
set -e
4+
5+
echo "Running tests before push..."
6+
7+
zig fmt --check *.zig src/*.zig
8+
zig build
9+
zig build test

README.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,8 @@ var config = struct {
3232
port: u16 = undefined,
3333
}{};
3434
35-
pub fn main() !void {
36-
var threaded = std.Io.Threaded.init(std.heap.page_allocator, .{});
37-
defer threaded.deinit();
38-
var r = try cli.AppRunner.init(threaded.io(), std.heap.page_allocator);
35+
pub fn main(init: std.process.Init) !void {
36+
var r = cli.AppRunner.init(&init);
3937
4038
// Create an App with a command named "short" that takes host and port options.
4139
const app = cli.App{
@@ -75,10 +73,10 @@ fn run_server() !void {
7573
### Using with the Zig package manager
7674
Add `cli` to your `build.zig.zon`
7775
```
78-
# For zig 0.14.x
76+
# For zig master
7977
zig fetch --save git+https://github.com/sam701/zig-cli
8078
81-
# For zig master
79+
# For zig 0.15
8280
zig fetch --save git+https://github.com/sam701/zig-cli#zig-0.15
8381
```
8482

examples/short.zig

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@ var config = struct {
77
port: u16 = undefined,
88
}{};
99

10-
pub fn main() !void {
11-
var threaded = std.Io.Threaded.init(std.heap.page_allocator, .{});
12-
defer threaded.deinit();
13-
var r = try cli.AppRunner.init(threaded.io(), std.heap.page_allocator);
10+
pub fn main(init: std.process.Init) !void {
11+
var r = cli.AppRunner.init(&init);
1412

1513
// Create an App with a command named "short" that takes host and port options.
1614
const app = cli.App{

examples/simple.zig

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
const std = @import("std");
22
const cli = @import("cli");
33

4-
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
5-
const allocator = gpa.allocator();
6-
74
var config = struct {
85
ip: []const u8 = undefined,
96
int: i32 = undefined,
@@ -52,9 +49,9 @@ fn sub3(r: *cli.AppRunner) !cli.Command {
5249
};
5350
}
5451

55-
fn parseArgs(io: std.Io) cli.AppRunner.Error!cli.ExecFn {
52+
fn parseArgs(init: *const std.process.Init) cli.AppRunner.Error!cli.ExecFn {
5653
// This allocator will be used to allocate config.ip and config.arg2.
57-
var r = try cli.AppRunner.init(io, allocator);
54+
var r = cli.AppRunner.init(init);
5855

5956
const sub2 = cli.Command{
6057
.name = "sub2",
@@ -129,30 +126,9 @@ fn parseArgs(io: std.Io) cli.AppRunner.Error!cli.ExecFn {
129126
return r.getAction(&app);
130127
}
131128

132-
pub fn main() anyerror!void {
133-
var threaded = std.Io.Threaded.init(std.heap.page_allocator, .{});
134-
defer threaded.deinit();
135-
136-
const action = try parseArgs(threaded.io());
137-
const r = action();
138-
freeConfig();
139-
return r;
140-
}
141-
142-
// Usually, you just use an arena allocator to free all allocated resources in a batch.
143-
// This only illustrates the fact that the config data are allocated with the allocator
144-
// you pass to cli.AppRunner.init(allocator).
145-
fn freeConfig() void {
146-
allocator.free(config.ip);
147-
if (config.arg2.len > 0) {
148-
for (config.arg2) |item| {
149-
allocator.free(item);
150-
}
151-
allocator.free(config.arg2);
152-
}
153-
if (gpa.deinit() == .leak) {
154-
@panic("config leaked");
155-
}
129+
pub fn main(init: std.process.Init) anyerror!void {
130+
const action = try parseArgs(&init);
131+
return action();
156132
}
157133

158134
fn run_sub3() !void {

src/app_runner.zig

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,17 @@ pub const AppRunner = struct {
1717
arena: ArenaAllocator,
1818
orig_allocator: Allocator,
1919
io: std.Io,
20+
environ: *const std.process.Environ.Map,
21+
args: *const std.process.Args,
2022

2123
const Self = @This();
22-
pub fn init(io: std.Io, alloc: Allocator) !Self {
24+
pub fn init(orig_init: *const std.process.Init) Self {
2325
return .{
24-
.arena = ArenaAllocator.init(alloc),
25-
.orig_allocator = alloc,
26-
.io = io,
26+
.arena = ArenaAllocator.init(orig_init.gpa),
27+
.orig_allocator = orig_init.gpa,
28+
.io = orig_init.io,
29+
.environ = orig_init.environ_map,
30+
.args = &orig_init.minimal.args,
2731
};
2832
}
2933

@@ -56,10 +60,10 @@ pub const AppRunner = struct {
5660

5761
/// `getAction` returns the action function that should be called by the main app.
5862
pub fn getAction(self: *Self, app: *const App) Error!command.ExecFn {
59-
const iter = try std.process.argsWithAllocator(self.arena.allocator());
63+
const iter = try self.args.iterateAllocator(self.arena.allocator());
6064

6165
// Here we pass the child allocator because any values allocated on the client behalf may not be freed.
62-
var cr = try Parser(std.process.ArgIterator).init(app, iter, self.io, self.orig_allocator);
66+
var cr = try Parser(std.process.Args.Iterator).init(app, iter, self.io, self.orig_allocator, self.environ);
6367
defer cr.deinit();
6468

6569
if (cr.parse()) |action| {

src/parser.zig

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,14 @@ pub fn Parser(comptime Iterator: type) type {
6060
error_data: ?ErrorData = null,
6161

6262
io: std.Io,
63+
environ: *const std.process.Environ.Map,
6364

64-
pub fn init(app: *const command.App, it: Iterator, io: std.Io, alloc: Allocator) !Self {
65+
pub fn init(app: *const command.App, it: Iterator, io: std.Io, alloc: Allocator, environ: *const std.process.Environ.Map) !Self {
6566
return .{
6667
.orig_allocator = alloc,
6768
.arena = ArenaAllocator.init(alloc),
6869
.io = io,
70+
.environ = environ,
6971
.arg_iterator = it,
7072
.app = app,
7173
.command_path = try std.ArrayList(*const command.Command).initCapacity(alloc, 16),
@@ -190,7 +192,7 @@ pub fn Parser(comptime Iterator: type) type {
190192
if (opt.value_ref.element_count > 0) return;
191193

192194
if (try getEnvvarName(opt, self.app.option_envvar_prefix, self.arena.allocator())) |envvar_name| {
193-
if (std.process.getEnvVarOwned(self.arena.allocator(), envvar_name)) |value| {
195+
if (self.environ.get(envvar_name)) |value| {
194196
opt.value_ref.put(value, self.orig_allocator) catch |err| {
195197
self.error_data = ErrorData{ .invalid_value = .{
196198
.entity_type = .option,
@@ -201,7 +203,7 @@ pub fn Parser(comptime Iterator: type) type {
201203
} };
202204
return err;
203205
};
204-
} else |_| {}
206+
}
205207
}
206208
}
207209

src/tests.zig

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ const ppack = @import("./parser.zig");
66
const Parser = ppack.Parser;
77
const ParseResult = ppack.ParseResult;
88
const AppRunner = @import("app_runner.zig").AppRunner;
9+
const value_ref = @import("value_ref.zig");
910

1011
const expect = std.testing.expect;
1112
const alloc = std.testing.allocator;
13+
const environ = std.process.Environ.Map.init(alloc);
1214
const expectError = std.testing.expectError;
1315

1416
const StringSliceIterator = struct {
@@ -21,8 +23,22 @@ const StringSliceIterator = struct {
2123
}
2224
};
2325

24-
fn runner() AppRunner {
25-
return AppRunner.init(std.testing.io, alloc) catch unreachable;
26+
const MockedAppRunner = struct {
27+
arena: std.heap.ArenaAllocator,
28+
29+
pub fn deinit(self: *MockedAppRunner) void {
30+
self.arena.deinit();
31+
}
32+
33+
pub fn mkRef(self: *MockedAppRunner, dest: anytype) *value_ref.ValueRef {
34+
return value_ref.allocRef(dest, self.arena.allocator());
35+
}
36+
};
37+
38+
fn runner() MockedAppRunner {
39+
return .{
40+
.arena = std.heap.ArenaAllocator.init(alloc),
41+
};
2642
}
2743

2844
fn run(app: *const command.App, items: []const []const u8) !void {
@@ -31,6 +47,7 @@ fn run(app: *const command.App, items: []const []const u8) !void {
3147
StringSliceIterator{ .items = items },
3248
std.testing.io,
3349
alloc,
50+
&environ,
3451
);
3552
defer parser.deinit();
3653
_ = try parser.parse();

0 commit comments

Comments
 (0)