Hello, I made a function that looks for an executable in PATH. If it does not find the exec, it returns an error:
pub fn findExecutable(exe_name: []const u8) !void {
std.debug.print("Hello from find exec, {s}\n", .{exe_name});
const allocator = std.heap.page_allocator;
const path_var: []u8 = try std.process.getEnvVarOwned(allocator, "PATH");
defer allocator.free(path_var);
std.debug.print("{}\n", .{@TypeOf(path_var)});
var path_segments = std.mem.tokenizeSequence(u8, path_var, ":");
std.debug.print("{}\n", .{@TypeOf(path_segments)});
var segment = path_segments.next();
var found: bool = false;
while (segment != null) {
std.debug.print("got segment {s}\n", .{segment.?});
defer segment = path_segments.next();
var iter_dir = std.fs.cwd().openDir(
segment.?,
.{ .iterate = true },
) catch {
std.debug.print("{s} not found, skipping\n", .{segment.?});
continue;
};
defer {
iter_dir.close();
}
var iter = iter_dir.iterate();
while (try iter.next()) |entry| {
if (entry.kind == .file) {
std.debug.print("got file {s}\n", .{entry.name});
if (std.mem.eql(u8, entry.name, exe_name)) {
std.debug.print("Found exe {s}\n", .{exe_name});
found = true;
break;
}
}
}
if (found) {
break;
}
}
if (!found) {
return FindExecError.ExecutableNotFound;
}
}
How can I handle this in my main (build.zig) function elegantly?
What I tried so far:
try findExecutable("looool") catch |err| switch(err) {
error.ExecutableNotFound => {
try std.io.getStdErr().writer().print("Executable not found, please install it.\n");
return;
},
else => {
return (err);
},
};
Not only is this bulky, it also does not compile:
build.zig:7:46: error: expected error union type, found 'void'
try findExecutable("looool") catch |err| switch(err) {
^~~~~~
I don’t want to catch any error other than ExecutableNotFound
explicitely. How can I do that?