const std = @import("std"); const mem = std.mem; const stdout = std.io.getStdOut().writer(); const process = std.process; const fs = std.fs; const warn = std.debug.warn; const print = std.debug.print; const cli_arguments = @import("./cli_arguments.zig"); pub fn get_file_size(path: []const u8) !u64 { var file = try fs.cwd().openFile(path, .{}); defer file.close(); // Find the size of the file and create a buffer with this size. var file_stat = try file.stat(); return file_stat.size; } fn print_file(path: []const u8) !void { const size = try get_file_size(path); // print("path: {}, size: {}\n", .{path, size}); // Create another allocator, for the file. var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); const allocator = &arena.allocator; const buffer = try allocator.alloc(u8, size + 1); // Last value will be a null-byte. buffer[size] = 0; const content = try fs.cwd().readFile(path, buffer); print("{}", .{content}); } pub fn cat() !void { // Here we use an ArenaAllocator backed by a DirectAllocator because `cat` is a short-lived, // one shot program. We don't need to waste time freeing memory and finding places to squish // bytes into. So we free everything all at once at the very end. var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); const allocator = &arena.allocator; var args = try process.argsAlloc(allocator); defer process.argsFree(allocator, args); // Skipping the executable binary name. var arg_idx: usize = 1; const gui_file_path = cli_arguments.nextArg(args, &arg_idx) orelse { warn("Expected first argument to be path to gui file\n", .{}); return error.InvalidArgs; }; try print_file(gui_file_path); } pub fn main() !void { try cat(); }