From 7eea1e3f0a7e2149e816843c365224b1f38c6324 Mon Sep 17 00:00:00 2001 From: Bob Farrell Date: Sun, 2 Mar 2025 14:14:42 +0000 Subject: [PATCH] Minor CLI improvements Show some progress "..." when running external commands to give the user a bit of extra feedback while commands run. --- build.zig.zon | 4 ++-- cli/commands/bundle.zig | 2 +- cli/commands/init.zig | 2 +- cli/util.zig | 53 +++++++++++++++++++++++++++++++++++++---- 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/build.zig.zon b/build.zig.zon index 072f37e..2fb196d 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -16,8 +16,8 @@ .hash = "jetcommon-0.1.0-jPY_DS1HAAAP8xp5HSWB_ZY7m9JEYUmm8adQFrse0lwB", }, .zmpl = .{ - .url = "https://github.com/jetzig-framework/zmpl/archive/d34fd5aa69cc5f68dc73b1ef844f7cbdebdfc93e.tar.gz", - .hash = "zmpl-0.0.1-SYFGBhRpAwAIJWGukw-MWyAbXq8WCDudBjAAerZ8jZ_u", + .url = "https://github.com/jetzig-framework/zmpl/archive/3ec11289fdee2e0c70975cb5dd85d3041d723912.tar.gz", + .hash = "zmpl-0.0.1-SYFGBuZoAwAMuvHNkO_1BbutpWhg7CdSgYd8t4OaaZeR", }, .zmd = .{ .url = "https://github.com/jetzig-framework/zmd/archive/d6c8aa9a9cde99674ccb096d8f94ed09cba8dab.tar.gz", diff --git a/cli/commands/bundle.zig b/cli/commands/bundle.zig index e689e56..86d44cf 100644 --- a/cli/commands/bundle.zig +++ b/cli/commands/bundle.zig @@ -155,7 +155,7 @@ pub fn run( .windows => {}, else => std.debug.print("Bundle `bundle.tar.gz` generated successfully.", .{}), } - util.printSuccess(); + util.printSuccess(null); } fn locateMarkdownFiles(allocator: std.mem.Allocator, dir: std.fs.Dir, views_path: []const u8, paths: *std.ArrayList([]const u8)) !void { diff --git a/cli/commands/init.zig b/cli/commands/init.zig index 3b960ec..42ae81e 100644 --- a/cli/commands/init.zig +++ b/cli/commands/init.zig @@ -261,7 +261,7 @@ fn copySourceFile( util.printFailure(); return err; }; - util.printSuccess(); + util.printSuccess(null); } // Read a file from Jetzig source code. diff --git a/cli/util.zig b/cli/util.zig index f058881..1cba0f1 100644 --- a/cli/util.zig +++ b/cli/util.zig @@ -23,8 +23,8 @@ const icons = .{ }; /// Print a success confirmation. -pub fn printSuccess() void { - std.debug.print(" " ++ icons.check ++ "\n", .{}); +pub fn printSuccess(message: ?[]const u8) void { + std.debug.print(" " ++ icons.check ++ " {s}\n", .{message orelse ""}); } /// Print a failure confirmation. @@ -198,7 +198,7 @@ pub fn runCommandInDir(allocator: std.mem.Allocator, argv: []const []const u8, d try child.spawn(); switch (options.output) { - .capture => try child.collectOutput(allocator, &stdout, &stderr, 50 * 1024), + .capture => try collectOutput(child, allocator, &stdout, &stderr), .stream => {}, } @@ -222,10 +222,55 @@ pub fn runCommandInDir(allocator: std.mem.Allocator, argv: []const []const u8, d } return error.JetzigCommandError; } else { - printSuccess(); + printSuccess(try std.mem.join(allocator, " ", argv)); } } +fn collectOutput( + child: std.process.Child, + allocator: std.mem.Allocator, + stdout: *std.ArrayListUnmanaged(u8), + stderr: *std.ArrayListUnmanaged(u8), +) !void { + const max_output_bytes = 50 * 1024; + std.debug.assert(child.stdout_behavior == .Pipe); + std.debug.assert(child.stderr_behavior == .Pipe); + var poller = std.io.poll(allocator, enum { stdout, stderr }, .{ + .stdout = child.stdout.?, + .stderr = child.stderr.?, + }); + defer poller.deinit(); + + std.debug.print("(working) .", .{}); + + while (try poller.poll()) { + if (poller.fifo(.stdout).count > max_output_bytes) + return error.StdoutStreamTooLong; + if (poller.fifo(.stderr).count > max_output_bytes) + return error.StderrStreamTooLong; + std.debug.print(".", .{}); + } + + std.debug.print(" (done)\n", .{}); + + try writeFifoDataToArrayList(allocator, stdout, poller.fifo(.stdout)); + try writeFifoDataToArrayList(allocator, stderr, poller.fifo(.stderr)); +} + +// Borrowed from `std.process.Child.writeFifoDataToArrayList` - non-public but needed in our +// modified `collectOutput` +fn writeFifoDataToArrayList(allocator: std.mem.Allocator, list: *std.ArrayListUnmanaged(u8), fifo: *std.io.PollFifo) !void { + if (fifo.head != 0) fifo.realign(); + if (list.capacity == 0) { + list.* = .{ + .items = fifo.buf[0..fifo.count], + .capacity = fifo.buf.len, + }; + fifo.* = std.io.PollFifo.init(fifo.allocator); + } else { + try list.appendSlice(allocator, fifo.buf[0..fifo.count]); + } +} /// Generate a full GitHub URL for passing to `zig fetch`. pub fn githubUrl(allocator: std.mem.Allocator) ![]const u8 { var client = std.http.Client{ .allocator = allocator };