jetzig/cli/util.zig
Bob Farrell f954439489 CLI generate command
Provide `jetzig generate ...` commands for views, middleware, and
partials.
2024-03-09 18:47:08 +00:00

97 lines
3.1 KiB
Zig

const std = @import("std");
/// Decode a base64 string, used for parsing out build artifacts generated by the CLI program's
/// build.zig which are stored in the executable as a module.
pub fn base64Decode(allocator: std.mem.Allocator, input: []const u8) ![]const u8 {
const decoder = std.base64.Base64Decoder.init(
std.base64.url_safe_no_pad.alphabet_chars,
std.base64.url_safe_no_pad.pad_char,
);
const size = try decoder.calcSizeForSlice(input);
const ptr = try allocator.alloc(u8, size);
try decoder.decode(ptr, input);
return ptr;
}
/// Print a success confirmation.
pub fn printSuccess() void {
std.debug.print("\n", .{});
}
/// Print a failure confirmation.
pub fn printFailure() void {
std.debug.print("\n", .{});
}
/// Verifies that cwd is the root of a Jetzig project
pub fn detectJetzigProjectDir() !std.fs.Dir {
var dir = try std.fs.cwd().openDir(".", .{});
const max_parent_dirs: usize = 100; // Prevent symlink loops or other weird stuff.
for (0..max_parent_dirs) |_| {
if (try isPath(dir, "build.zig", .file) and try isPath(dir, "src/app/views", .dir)) return dir;
dir = dir.openDir("..", .{}) catch |err| {
switch (err) {
error.FileNotFound, error.NotDir => {
std.debug.print(
"Encountered unexpected detecting Jetzig project directory: {s}\n",
.{@errorName(err)},
);
return error.JetzigCommandError;
},
else => return err,
}
};
continue;
}
std.debug.print(
\\Exceeded maximum parent directory depth.
\\Unable to detect Jetzig project directory.
\\
,
.{},
);
return error.JetzigCommandError;
}
fn isPath(dir: std.fs.Dir, sub_path: []const u8, path_type: enum { file, dir }) !bool {
switch (path_type) {
.file => {
_ = dir.statFile(sub_path) catch |err| {
switch (err) {
error.FileNotFound => return false,
else => return err,
}
};
return true;
},
.dir => {
var test_dir = dir.openDir(sub_path, .{}) catch |err| {
switch (err) {
error.FileNotFound, error.NotDir => return false,
else => return err,
}
};
test_dir.close();
return true;
},
}
}
// Strip leading and trailing whitespace from a u8 slice.
pub fn strip(input: []const u8) []const u8 {
return std.mem.trim(u8, input, &std.ascii.whitespace);
}
/// Attempts to confirm if a string input is in CamelCase. False if the first character is
/// not alphabetic lower-case or if the input contains underscores.
pub fn isCamelCase(input: []const u8) bool {
if (input.len == 0) return false;
if (!std.mem.containsAtLeast(u8, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 1, &[_]u8{input[0]})) return false;
if (std.mem.containsAtLeast(u8, input, 1, "_")) return false;
return true;
}