Thanks @AndrewCodeDev, the README is maybe a little too nice (documentation looks very similar), but I was in a good mood. 
To use the module it is important to know where the entry
directory is, and where the walking
directory is relative to the entry
.
Although it seems simple in logic, it is not always easy to understand and apply, especially when we keep going up and down through directories.
Even the module is not run directly in terminal, the entry
is always current working directory cwd
, from where the application starts.
Here, in first example, cwd
is the terminal directory.
const std = @import("std");
const print = std.debug.print;
const zdirwalker = @import("zdirwalker");
const DirWalker = zdirwalker.DirWalker;
const ArrayList = zdirwalker.ArrayList;
const Info = zdirwalker.Info;
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
defer if (gpa.deinit() == .leak) print("{s}\n", .{"memory leak"});
var tester = try DirWalker(ArrayList(Info)).init(allocator);
defer tester.deinit();
//+ `"."` is the current working directory (cwd)
//+ usually cwd is the project directory (i.e. the build.zig directory)
//+ in this case `<some_path>/zdirwalker`
tester = try tester.walk(".");
print("========================================\n", .{});
print(
"root_name: {s}\n root_path: {s}\n",
.{ tester.root.name, tester.root.path },
);
print("========================================\n", .{});
//+ this can be a very long list, we will only print the first 5 entries
var index: usize = 0;
for (tester.content.items) |cont| {
if (index < 5) {
print(
"cont_name: {s}\n cont_path: {s}\n",
.{ cont.name, cont.path },
);
print("----------------------------------------\n", .{});
index += 1;
} else break;
}
}
Exemple is egs/cwddir
in repo and we can run like:
zdirwalker$ zig build run-cwddir
...
For this run, entry
is <some_path>/zdirwalker
and walking
is zdirwalker
.
The same example, run like this, leads to totally different results:
zdirwalker$ cd zig-out
zdirwalker/zig-out$ ./egs/cwddir
...
Here, entry
is <some_path>/zdirwalker/zig-out
and walking
is zig-out
.
Next example is egs/exedir-twoup-onedown
in repo.
The code is as in the first example, but with this change:
...
//+ `directory` is two levels up and one down from executable directory
//+ in this case `<some_path>/zdirwalker/src`
var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
var directory = try std.fs.selfExeDirPath(&buffer);
directory = try std.fs.path.join(
allocator,
&[_][]const u8{ directory, "../../src" },
);
defer allocator.free(directory);
tester = try tester.walk(directory);
...
For this example, entry
is <some_path>/zdirwalker
, the concept of entry
remains, but we don’t care about it because walking
is an absolute path.
The first step:
var directory = try std.fs.selfExeDirPath(&buffer);
returns an absolute path of the executable.
The second step:
directory = try std.fs.path.join(
allocator,
&[_][]const u8{ directory, "../../src" },
);
returns the walking
absolute path.
Note that the join part to directory
must be a fully qualified relative path to directory
.
Mistakes can easily be made in defining these relative path.
We can run like:
zdirwalker$ zig build run-exedir-twoup-onedown
...
or
zdirwalker$ cd zig-out
zdirwalker/zig-out$ ./egs/exedir-twoup-onedown
...
The terminal output remains the same:
========================================
root_name: src
root_path: <some_path>/zdirwalker/src
========================================
cont_name: zdirwalker
cont_path: zdirwalker.zig
----------------------------------------
Finally, I would like to point out some aspects about build.zig
, which may be of interest:
- each step can run independently of each other or with a minimal and necessary dependency (e.g. code coverage
cov
need tests tst
)
cov
step now run as expected, it was a bit of a challenge for me to get it to work before there was a zig-out
directory
fmt
step now really formats zig files by default, as it was initially I found it very confusing and had to dig to understand how it worked (Hey! Format my files, don’t print this weird message.) 
- all removes are relative to
project root
and zig-out
directory
- examples are taken directly from the examples directory, no need for a list of examples in the
build.zig
file
Getting the examples to work was by far the biggest challenge for me as some library errors were propagating in the standalone project, but @dimdin helped me out and now it works as expected.
Here are all steps:
zdirwalker$ zig build -l
install (default) Copy build artifacts to prefix path
uninstall Remove build artifacts from prefix path
lib Build static library (zig-out/lib)
tst Run tests
cov Generate code coverage (zig-out/cov)
doc Generate documentation (zig-out/doc)
fmt Silent formatting
rm-cache Remove cache (zig-cache)
rm-out Remove output (zig-out)
rm-bin Remove binary (zig-out/bin)
rm-cov Remove code coverage (zig-out/cov)
rm-doc Remove documentation (zig-out/doc)
rm-egs Remove examples (zig-out/egs)
rm-lib Remove library (zig-out/lib)
run-cwddir Run example cwddir
run-cwddir-oneup Run example cwddir-oneup
run-exedir Run example exedir
run-exedir-oneup Run example exedir-oneup
run-exedir-twoup-onedown Run example exedir-twoup-onedown
I’m sorry for this very long post, but I didn’t know how to make it shorter.
All the best!