diff options
author | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2025-08-16 12:50:23 +0200 |
---|---|---|
committer | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2025-08-16 12:50:23 +0200 |
commit | 9edc1338b92d1ead4c5f2fad8c0516037963f7b6 (patch) | |
tree | 64f3ed617771f9327bd49e3732adb9271e3559cc /src | |
parent | 754a74da6052c9f5e8dc4a536c58ccc11cb66369 (diff) |
Unify output handling.
Now every command always uses an OutputWriter instead of conditionally
writing directly to stdout using std.debug.print.
Diffstat (limited to 'src')
-rw-r--r-- | src/cmd/chdir.zig | 43 | ||||
-rw-r--r-- | src/cmd/cls.zig | 12 | ||||
-rw-r--r-- | src/cmd/copy.zig | 90 | ||||
-rw-r--r-- | src/cmd/date.zig | 8 | ||||
-rw-r--r-- | src/cmd/dir.zig | 15 | ||||
-rw-r--r-- | src/cmd/echo.zig | 22 | ||||
-rw-r--r-- | src/cmd/external.zig | 47 | ||||
-rw-r--r-- | src/cmd/help.zig | 14 | ||||
-rw-r--r-- | src/cmd/lib/types.zig | 25 | ||||
-rw-r--r-- | src/cmd/mkdir.zig | 8 | ||||
-rw-r--r-- | src/cmd/move.zig | 8 | ||||
-rw-r--r-- | src/cmd/path.zig | 29 | ||||
-rw-r--r-- | src/cmd/pipe.zig | 6 | ||||
-rw-r--r-- | src/cmd/redirect.zig | 6 | ||||
-rw-r--r-- | src/cmd/remove.zig | 15 | ||||
-rw-r--r-- | src/cmd/rename.zig | 22 | ||||
-rw-r--r-- | src/cmd/rmdir.zig | 8 | ||||
-rw-r--r-- | src/cmd/sort.zig | 15 | ||||
-rw-r--r-- | src/cmd/time.zig | 8 | ||||
-rw-r--r-- | src/cmd/type.zig | 36 | ||||
-rw-r--r-- | src/cmd/ver.zig | 8 | ||||
-rw-r--r-- | src/eval.zig | 17 |
22 files changed, 165 insertions, 297 deletions
diff --git a/src/cmd/chdir.zig b/src/cmd/chdir.zig index e2895bf..1adfdd8 100644 --- a/src/cmd/chdir.zig +++ b/src/cmd/chdir.zig @@ -1,6 +1,5 @@ const std = @import("std"); const Allocator = std.mem.Allocator; -const print = std.debug.print; const paths = @import("../paths.zig"); const formatDosPath = paths.formatDosPath; @@ -17,11 +16,8 @@ pub const Chdir = struct { // No arguments - display current directory const cwd = std.fs.cwd().realpathAlloc(ctx.allocator, ".") catch { const error_msg = "Unable to determine current directory\n"; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }; defer ctx.allocator.free(cwd); @@ -32,11 +28,8 @@ pub const Chdir = struct { const output = try std.fmt.allocPrint(ctx.allocator, "{s}\n", .{formatted_path}); defer ctx.allocator.free(output); - if (ctx.output_capture) |capture| { - try capture.write(output); - } else { - print("{s}", .{output}); - } + var writer = ctx.output_writer; + try writer.write(output); return CommandStatus{ .Code = 0 }; } else { // Change directory @@ -47,22 +40,16 @@ pub const Chdir = struct { // Go to parent directory std.process.changeCurDir("..") catch { const error_msg = "The system cannot find the path specified.\n"; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }; } else if (std.mem.eql(u8, target_path, "\\") or std.mem.eql(u8, target_path, "/")) { // Go to root directory - simplified to just go to "/" std.process.changeCurDir("/") catch { const error_msg = "The system cannot find the path specified.\n"; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }; } else { @@ -71,22 +58,16 @@ pub const Chdir = struct { for (target_path) |ch| { if (ch == 0) { const error_msg = "Invalid path: contains null character\n"; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; } } std.process.changeCurDir(target_path) catch { const error_msg = "The system cannot find the path specified.\n"; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }; } diff --git a/src/cmd/cls.zig b/src/cmd/cls.zig index 4e7b8c6..a017278 100644 --- a/src/cmd/cls.zig +++ b/src/cmd/cls.zig @@ -1,6 +1,5 @@ const std = @import("std"); const Allocator = std.mem.Allocator; -const print = std.debug.print; const types = @import("./lib/types.zig"); const CommandStatus = types.CommandStatus; @@ -10,9 +9,14 @@ pub const Cls = struct { pub fn eval(cls: Cls, ctx: CommandContext) !CommandStatus { _ = cls; - if (ctx.output_capture == null) { - // Clear screen - only works when not redirected - print("\x1B[2J\x1B[H", .{}); + // Clear screen - only works when going to stdout, not when redirected + switch (ctx.output_writer) { + .stdout => |writer| { + try writer.write("\x1B[2J\x1B[H"); + }, + .capture => { + // Do nothing when output is captured/redirected + }, } return CommandStatus{ .Code = 0 }; } diff --git a/src/cmd/copy.zig b/src/cmd/copy.zig index 3ca8af0..1c3c3ba 100644 --- a/src/cmd/copy.zig +++ b/src/cmd/copy.zig @@ -1,6 +1,5 @@ const std = @import("std"); const Allocator = std.mem.Allocator; -const print = std.debug.print; const syntax = @import("../syntax.zig"); const FileSpec = syntax.FileSpec; @@ -21,20 +20,14 @@ pub const Copy = struct { const dest_path = switch (copy.to) { .Con => { const error_msg = "Cannot copy from CON to CON\n"; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }, .Lpt1, .Lpt2, .Lpt3, .Prn => { const error_msg = "Cannot copy to device\n"; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }, .Path => |path| path, @@ -47,11 +40,8 @@ pub const Copy = struct { error.PathAlreadyExists => "File already exists - use different name\n", else => "Cannot create file\n", }; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }; defer dest_file.close(); @@ -60,11 +50,6 @@ pub const Copy = struct { const stdin = std.io.getStdIn().reader(); var line_count: u32 = 0; - // Skip output redirection since we're doing interactive input - if (ctx.output_capture == null) { - // In interactive mode, show no prompt (DOS behavior) - } - while (true) { if (stdin.readUntilDelimiterOrEofAlloc(ctx.allocator, '\n', 4096)) |maybe_line| { if (maybe_line) |line| { @@ -97,20 +82,14 @@ pub const Copy = struct { const msg = try std.fmt.allocPrint(ctx.allocator, " 1 File(s) copied\n", .{}); defer ctx.allocator.free(msg); - if (ctx.output_capture) |capture| { - try capture.write(msg); - } else { - print("{s}", .{msg}); - } + var writer = ctx.output_writer; + try writer.write(msg); return CommandStatus{ .Code = 0 }; }, .Lpt1, .Lpt2, .Lpt3, .Prn => { const error_msg = "Cannot copy from device\n"; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }, .Path => |path| path, @@ -126,11 +105,8 @@ pub const Copy = struct { error.AccessDenied => "Access denied\n", else => "Cannot access source file\n", }; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }; defer source_file.close(); @@ -140,39 +116,27 @@ pub const Copy = struct { while (true) { const bytes_read = source_file.readAll(&buffer) catch { const error_msg = "Error reading file\n"; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }; if (bytes_read == 0) break; - if (ctx.output_capture) |capture| { - try capture.write(buffer[0..bytes_read]); - } else { - print("{s}", .{buffer[0..bytes_read]}); - } + var writer = ctx.output_writer; + try writer.write(buffer[0..bytes_read]); if (bytes_read < buffer.len) break; } const msg = " 1 File(s) copied\n"; - if (ctx.output_capture) |capture| { - try capture.write(msg); - } else { - print("{s}", .{msg}); - } + var writer = ctx.output_writer; + try writer.write(msg); return CommandStatus{ .Code = 0 }; }, .Lpt1, .Lpt2, .Lpt3, .Prn => { const error_msg = "Cannot copy to device\n"; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }, .Path => |path| path, @@ -186,20 +150,14 @@ pub const Copy = struct { error.PathAlreadyExists => "File already exists\n", else => "Cannot copy file\n", }; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }; const msg = " 1 File(s) copied\n"; - if (ctx.output_capture) |capture| { - try capture.write(msg); - } else { - print("{s}", .{msg}); - } + var writer = ctx.output_writer; + try writer.write(msg); return CommandStatus{ .Code = 0 }; } }; diff --git a/src/cmd/date.zig b/src/cmd/date.zig index 3a7d72b..5f6aee6 100644 --- a/src/cmd/date.zig +++ b/src/cmd/date.zig @@ -1,6 +1,5 @@ const std = @import("std"); const Allocator = std.mem.Allocator; -const print = std.debug.print; const types = @import("./lib/types.zig"); const CommandStatus = types.CommandStatus; @@ -56,11 +55,8 @@ pub const Date = struct { const output = try std.fmt.allocPrint(ctx.allocator, "Current date is {d:0>2}/{d:0>2}/{d}\n", .{ month, day, year }); defer ctx.allocator.free(output); - if (ctx.output_capture) |capture| { - try capture.write(output); - } else { - print("{s}", .{output}); - } + var writer = ctx.output_writer; + try writer.write(output); return CommandStatus{ .Code = 0 }; } }; diff --git a/src/cmd/dir.zig b/src/cmd/dir.zig index 27d0e30..ffb38e2 100644 --- a/src/cmd/dir.zig +++ b/src/cmd/dir.zig @@ -1,7 +1,6 @@ const std = @import("std"); const Allocator = std.mem.Allocator; const ArrayList = std.ArrayList; -const print = std.debug.print; const c = @cImport({ @cInclude("errno.h"); @@ -138,11 +137,8 @@ pub const Dir = struct { var dir_iterator = std.fs.cwd().openDir(dir.path, .{ .iterate = true }) catch { const error_msg = "File not found\n"; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }; defer dir_iterator.close(); @@ -226,11 +222,8 @@ pub const Dir = struct { try output_buffer.writer().print(" {d} Dir(s) {s:>14} bytes free\n", .{ dir_count, formatted_free_bytes }); } - if (ctx.output_capture) |capture| { - try capture.write(output_buffer.items); - } else { - print("{s}", .{output_buffer.items}); - } + var writer = ctx.output_writer; + try writer.write(output_buffer.items); return CommandStatus{ .Code = 0 }; } }; diff --git a/src/cmd/echo.zig b/src/cmd/echo.zig index 4f2731b..16a41eb 100644 --- a/src/cmd/echo.zig +++ b/src/cmd/echo.zig @@ -1,6 +1,5 @@ const std = @import("std"); const Allocator = std.mem.Allocator; -const print = std.debug.print; const types = @import("./lib/types.zig"); const CommandStatus = types.CommandStatus; @@ -20,11 +19,8 @@ pub const EchoOn = struct { _ = echo_on; const output = "ECHO is on\n"; - if (ctx.output_capture) |capture| { - try capture.write(output); - } else { - print("{s}", .{output}); - } + var writer = ctx.output_writer; + try writer.write(output); return CommandStatus{ .Code = 0 }; } }; @@ -34,11 +30,8 @@ pub const EchoPlain = struct { _ = echo_plain; const output = "ECHO is on\n"; - if (ctx.output_capture) |capture| { - try capture.write(output); - } else { - print("{s}", .{output}); - } + var writer = ctx.output_writer; + try writer.write(output); return CommandStatus{ .Code = 0 }; } }; @@ -49,11 +42,8 @@ pub const EchoText = struct { pub fn eval(echo_text: EchoText, ctx: CommandContext) !CommandStatus { const output = try std.fmt.allocPrint(ctx.allocator, "{s}\n", .{echo_text.message}); defer ctx.allocator.free(output); - if (ctx.output_capture) |capture| { - try capture.write(output); - } else { - print("{s}", .{output}); - } + var writer = ctx.output_writer; + try writer.write(output); return CommandStatus{ .Code = 0 }; } }; diff --git a/src/cmd/external.zig b/src/cmd/external.zig index 68fc758..0f4e65f 100644 --- a/src/cmd/external.zig +++ b/src/cmd/external.zig @@ -1,7 +1,6 @@ const std = @import("std"); const Allocator = std.mem.Allocator; const ArrayList = std.ArrayList; -const print = std.debug.print; const types = @import("./lib/types.zig"); const CommandStatus = types.CommandStatus; @@ -15,8 +14,13 @@ pub const External = struct { pub fn eval(external: External, ctx: CommandContext) !CommandStatus { const allocator = ctx.allocator; - const output_capture = ctx.output_capture; const input_source = ctx.input_source; + + // Check if we need to capture output (not going to stdout) + const needs_capture = switch (ctx.output_writer) { + .stdout => false, + .capture => true, + }; // Try to execute external command var child_args = ArrayList([]const u8).init(allocator); defer child_args.deinit(); @@ -30,8 +34,8 @@ pub const External = struct { // Set up pipes for capturing output child.stdin_behavior = if (input_source != null) .Pipe else .Inherit; - child.stdout_behavior = if (output_capture != null) .Pipe else .Inherit; - child.stderr_behavior = if (output_capture != null) .Pipe else .Inherit; + child.stdout_behavior = if (needs_capture) .Pipe else .Inherit; + child.stderr_behavior = if (needs_capture) .Pipe else .Inherit; const spawn_result = child.spawn(); if (spawn_result) |_| { @@ -41,31 +45,22 @@ pub const External = struct { const error_msg = try std.fmt.allocPrint(allocator, "'{s}' is not recognized as an internal or external command,\noperable program or batch file.\n", .{external.program}); defer allocator.free(error_msg); - if (output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }, error.AccessDenied => { const error_msg = "Access is denied.\n"; - if (output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }, else => { const error_msg = try std.fmt.allocPrint(allocator, "Cannot execute '{s}': {}\n", .{ external.program, err }); defer allocator.free(error_msg); - if (output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }, } @@ -89,14 +84,15 @@ pub const External = struct { } // Handle output capture - if (output_capture) |capture| { + if (needs_capture) { + var writer = ctx.output_writer; // Read stdout if (child.stdout) |stdout| { var buffer: [4096]u8 = undefined; while (true) { const bytes_read = stdout.read(&buffer) catch break; if (bytes_read == 0) break; - try capture.write(buffer[0..bytes_read]); + try writer.write(buffer[0..bytes_read]); } } @@ -106,7 +102,7 @@ pub const External = struct { while (true) { const bytes_read = stderr.read(&buffer) catch break; if (bytes_read == 0) break; - try capture.write(buffer[0..bytes_read]); + try writer.write(buffer[0..bytes_read]); } } } @@ -119,11 +115,8 @@ pub const External = struct { }; defer allocator.free(error_msg); - if (output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }; diff --git a/src/cmd/help.zig b/src/cmd/help.zig index 4c91464..0a19e98 100644 --- a/src/cmd/help.zig +++ b/src/cmd/help.zig @@ -48,11 +48,8 @@ fn showGeneralHelp(ctx: CommandContext) !CommandStatus { \\ ; - if (ctx.output_capture) |output| { - try output.write(help_text); - } else { - try std.io.getStdOut().writeAll(help_text); - } + var writer = ctx.output_writer; + try writer.write(help_text); return CommandStatus{ .Code = 0 }; } @@ -63,11 +60,8 @@ fn showCommandHelp(command: []const u8, ctx: CommandContext) !CommandStatus { const help_text = getCommandSpecificHelp(cmd_upper); - if (ctx.output_capture) |output| { - try output.write(help_text); - } else { - try std.io.getStdOut().writeAll(help_text); - } + var writer = ctx.output_writer; + try writer.write(help_text); return CommandStatus{ .Code = 0 }; } diff --git a/src/cmd/lib/types.zig b/src/cmd/lib/types.zig index c1ce3c7..f663a64 100644 --- a/src/cmd/lib/types.zig +++ b/src/cmd/lib/types.zig @@ -32,6 +32,13 @@ pub const OutputCapture = struct { } }; +pub const StdoutOutputCapture = struct { + pub fn write(self: *StdoutOutputCapture, data: []const u8) !void { + _ = self; + try std.io.getStdOut().writeAll(data); + } +}; + pub const InputSource = struct { data: []const u8, position: usize, @@ -65,18 +72,30 @@ pub const InputSource = struct { } }; +pub const OutputWriter = union(enum) { + capture: *OutputCapture, + stdout: *StdoutOutputCapture, + + pub fn write(self: *OutputWriter, data: []const u8) !void { + switch (self.*) { + .capture => |capture| try capture.write(data), + .stdout => |stdout| try stdout.write(data), + } + } +}; + pub const ExecuteCommandFn = *const fn (Command, Allocator, ?*OutputCapture, ?*InputSource) anyerror!CommandStatus; pub const CommandContext = struct { allocator: Allocator, - output_capture: ?*OutputCapture, + output_writer: OutputWriter, input_source: ?*InputSource, execute_command: ExecuteCommandFn, - pub fn init(allocator: Allocator, output_capture: ?*OutputCapture, input_source: ?*InputSource, execute_command: ExecuteCommandFn) CommandContext { + pub fn init(allocator: Allocator, output_writer: OutputWriter, input_source: ?*InputSource, execute_command: ExecuteCommandFn) CommandContext { return CommandContext{ .allocator = allocator, - .output_capture = output_capture, + .output_writer = output_writer, .input_source = input_source, .execute_command = execute_command, }; diff --git a/src/cmd/mkdir.zig b/src/cmd/mkdir.zig index a1ea62d..649cc45 100644 --- a/src/cmd/mkdir.zig +++ b/src/cmd/mkdir.zig @@ -1,6 +1,5 @@ const std = @import("std"); const Allocator = std.mem.Allocator; -const print = std.debug.print; const types = @import("./lib/types.zig"); const CommandStatus = types.CommandStatus; @@ -20,11 +19,8 @@ pub const Mkdir = struct { error.NotDir => "The system cannot find the path specified\n", else => "Unable to create directory\n", }; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }; diff --git a/src/cmd/move.zig b/src/cmd/move.zig index 40e745d..557566f 100644 --- a/src/cmd/move.zig +++ b/src/cmd/move.zig @@ -1,6 +1,5 @@ const std = @import("std"); const Allocator = std.mem.Allocator; -const print = std.debug.print; const types = @import("./lib/types.zig"); const CommandStatus = types.CommandStatus; @@ -11,11 +10,8 @@ pub const Move = struct { _ = move; const error_msg = "MOVE command not yet implemented\n"; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; } }; diff --git a/src/cmd/path.zig b/src/cmd/path.zig index ca4de9a..009621f 100644 --- a/src/cmd/path.zig +++ b/src/cmd/path.zig @@ -1,6 +1,5 @@ const std = @import("std"); const Allocator = std.mem.Allocator; -const print = std.debug.print; const types = @import("./lib/types.zig"); const CommandStatus = types.CommandStatus; @@ -15,20 +14,14 @@ pub const PathGet = struct { error.EnvironmentVariableNotFound => { // PATH not set, show empty const output = "PATH=(not set)\n"; - if (ctx.output_capture) |capture| { - try capture.write(output); - } else { - print("{s}", .{output}); - } + var writer = ctx.output_writer; + try writer.write(output); return CommandStatus{ .Code = 0 }; }, else => { const error_msg = "Cannot access PATH environment variable\n"; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }, }; @@ -36,11 +29,8 @@ pub const PathGet = struct { const output = try std.fmt.allocPrint(ctx.allocator, "PATH={s}\n", .{current_path}); defer ctx.allocator.free(output); - if (ctx.output_capture) |capture| { - try capture.write(output); - } else { - print("{s}", .{output}); - } + var writer = ctx.output_writer; + try writer.write(output); return CommandStatus{ .Code = 0 }; } }; @@ -54,11 +44,8 @@ pub const PathSet = struct { // since Zig's std.process doesn't provide a simple way to set env vars const output = try std.fmt.allocPrint(ctx.allocator, "PATH would be set to: {s}\n(Note: Environment variable setting not implemented in this shell)\n", .{path_set.value}); defer ctx.allocator.free(output); - if (ctx.output_capture) |capture| { - try capture.write(output); - } else { - print("{s}", .{output}); - } + var writer = ctx.output_writer; + try writer.write(output); return CommandStatus{ .Code = 0 }; } }; diff --git a/src/cmd/pipe.zig b/src/cmd/pipe.zig index 39bee8c..c3d08e4 100644 --- a/src/cmd/pipe.zig +++ b/src/cmd/pipe.zig @@ -18,7 +18,11 @@ pub const PipeCommand = struct { pub fn eval(pipe: PipeCommand, ctx: CommandContext) !CommandStatus { const execute_command = ctx.execute_command; const allocator = ctx.allocator; - const output_capture = ctx.output_capture; + // Extract output_capture from the output_writer for pipe logic + const output_capture = switch (ctx.output_writer) { + .capture => |capture| capture, + .stdout => null, + }; // Create output capture for the left command var left_output = OutputCapture.init(allocator); diff --git a/src/cmd/redirect.zig b/src/cmd/redirect.zig index 10218f6..92a666a 100644 --- a/src/cmd/redirect.zig +++ b/src/cmd/redirect.zig @@ -22,7 +22,11 @@ pub const RedirectCommand = struct { pub fn eval(redirect: RedirectCommand, ctx: CommandContext) !CommandStatus { const allocator = ctx.allocator; - const output_capture = ctx.output_capture; + // Extract output_capture from the output_writer for redirection logic + const output_capture = switch (ctx.output_writer) { + .capture => |capture| capture, + .stdout => null, + }; const execute_command = ctx.execute_command; // Check if we have any output redirections diff --git a/src/cmd/remove.zig b/src/cmd/remove.zig index ba59504..8cf52b3 100644 --- a/src/cmd/remove.zig +++ b/src/cmd/remove.zig @@ -1,6 +1,5 @@ const std = @import("std"); const Allocator = std.mem.Allocator; -const print = std.debug.print; const types = @import("./lib/types.zig"); const CommandStatus = types.CommandStatus; @@ -16,11 +15,8 @@ pub const Remove = struct { if (std.mem.indexOf(u8, file_path, "*") != null or std.mem.indexOf(u8, file_path, "?") != null) { // Simple wildcard deletion - just show error for now const error_msg = "Wildcard deletion not yet implemented\n"; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; } @@ -32,11 +28,8 @@ pub const Remove = struct { error.IsDir => "Access denied - cannot delete directory\n", else => "Cannot delete file\n", }; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }; diff --git a/src/cmd/rename.zig b/src/cmd/rename.zig index 386e0f7..58a5702 100644 --- a/src/cmd/rename.zig +++ b/src/cmd/rename.zig @@ -1,6 +1,5 @@ const std = @import("std"); const Allocator = std.mem.Allocator; -const print = std.debug.print; const syntax = @import("../syntax.zig"); const FileSpec = syntax.FileSpec; @@ -17,11 +16,8 @@ pub const Rename = struct { const from_path = switch (rename.from) { .Con, .Lpt1, .Lpt2, .Lpt3, .Prn => { const error_msg = "Cannot rename device\n"; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }, .Path => |path| path, @@ -30,11 +26,8 @@ pub const Rename = struct { const to_path = switch (rename.to) { .Con, .Lpt1, .Lpt2, .Lpt3, .Prn => { const error_msg = "Cannot rename to device\n"; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }, .Path => |path| path, @@ -48,11 +41,8 @@ pub const Rename = struct { error.RenameAcrossMountPoints => "Cannot rename across different drives\n", else => "Cannot rename file\n", }; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }; diff --git a/src/cmd/rmdir.zig b/src/cmd/rmdir.zig index a1c3cc0..3033ffa 100644 --- a/src/cmd/rmdir.zig +++ b/src/cmd/rmdir.zig @@ -1,6 +1,5 @@ const std = @import("std"); const Allocator = std.mem.Allocator; -const print = std.debug.print; const types = @import("./lib/types.zig"); const CommandStatus = types.CommandStatus; @@ -21,11 +20,8 @@ pub const Rmdir = struct { error.NotDir => "The system cannot find the path specified\n", else => "Unable to remove directory\n", }; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }; diff --git a/src/cmd/sort.zig b/src/cmd/sort.zig index 8b797d1..0f73940 100644 --- a/src/cmd/sort.zig +++ b/src/cmd/sort.zig @@ -1,7 +1,6 @@ const std = @import("std"); const Allocator = std.mem.Allocator; const ArrayList = std.ArrayList; -const print = std.debug.print; const types = @import("./lib/types.zig"); const CommandStatus = types.CommandStatus; @@ -28,11 +27,8 @@ pub const Sort = struct { } else { // Read from stdin (simplified - just show message) const msg = "SORT: Use input redirection (< file.txt) to sort file contents\n"; - if (ctx.output_capture) |capture| { - try capture.write(msg); - } else { - print("{s}", .{msg}); - } + var writer = ctx.output_writer; + try writer.write(msg); return CommandStatus{ .Code = 0 }; } @@ -51,11 +47,8 @@ pub const Sort = struct { try output_buffer.writer().print("{s}\n", .{line}); } - if (ctx.output_capture) |capture| { - try capture.write(output_buffer.items); - } else { - print("{s}", .{output_buffer.items}); - } + var writer = ctx.output_writer; + try writer.write(output_buffer.items); return CommandStatus{ .Code = 0 }; } diff --git a/src/cmd/time.zig b/src/cmd/time.zig index c30ca47..5c86b49 100644 --- a/src/cmd/time.zig +++ b/src/cmd/time.zig @@ -1,6 +1,5 @@ const std = @import("std"); const Allocator = std.mem.Allocator; -const print = std.debug.print; const types = @import("./lib/types.zig"); const CommandStatus = types.CommandStatus; @@ -19,11 +18,8 @@ pub const Time = struct { const output = try std.fmt.allocPrint(ctx.allocator, "Current time is {d:0>2}:{d:0>2}:{d:0>2}\n", .{ hours, minutes, seconds }); defer ctx.allocator.free(output); - if (ctx.output_capture) |capture| { - try capture.write(output); - } else { - print("{s}", .{output}); - } + var writer = ctx.output_writer; + try writer.write(output); return CommandStatus{ .Code = 0 }; } }; diff --git a/src/cmd/type.zig b/src/cmd/type.zig index 86ccfda..147c2a9 100644 --- a/src/cmd/type.zig +++ b/src/cmd/type.zig @@ -1,7 +1,6 @@ const std = @import("std"); const Allocator = std.mem.Allocator; const ArrayList = std.ArrayList; -const print = std.debug.print; const syntax = @import("../syntax.zig"); const FileSpec = syntax.FileSpec; @@ -17,20 +16,14 @@ pub const Type = struct { const file_path = switch (type_cmd.file) { .Con => { const error_msg = "Cannot TYPE from CON\n"; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }, .Lpt1, .Lpt2, .Lpt3, .Prn => { const error_msg = "Cannot TYPE from device\n"; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }, .Path => |path| path, @@ -43,11 +36,8 @@ pub const Type = struct { error.AccessDenied => "Access is denied.\n", else => "Cannot access file.\n", }; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }; defer file.close(); @@ -60,11 +50,8 @@ pub const Type = struct { error.AccessDenied => "Access is denied.\n", else => "Error reading file.\n", }; - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }; @@ -91,11 +78,8 @@ pub const Type = struct { } } - if (ctx.output_capture) |capture| { - try capture.write(processed_output.items); - } else { - print("{s}", .{processed_output.items}); - } + var writer = ctx.output_writer; + try writer.write(processed_output.items); // If we read less than the buffer size, we're done if (bytes_read < buffer.len) break; diff --git a/src/cmd/ver.zig b/src/cmd/ver.zig index 5e99c03..7ff0c60 100644 --- a/src/cmd/ver.zig +++ b/src/cmd/ver.zig @@ -1,6 +1,5 @@ const std = @import("std"); const Allocator = std.mem.Allocator; -const print = std.debug.print; const types = @import("./lib/types.zig"); const CommandStatus = types.CommandStatus; @@ -11,11 +10,8 @@ pub const Ver = struct { _ = ver; const output = "MB-DOSE Version 6.22\n"; - if (ctx.output_capture) |capture| { - try capture.write(output); - } else { - print("{s}", .{output}); - } + var writer = ctx.output_writer; + try writer.write(output); return CommandStatus{ .Code = 0 }; } }; diff --git a/src/eval.zig b/src/eval.zig index bd5804d..3381302 100644 --- a/src/eval.zig +++ b/src/eval.zig @@ -25,6 +25,8 @@ const Redirect = syntax.Redirect; const cmdTypes = @import("cmd/lib/types.zig"); pub const CommandStatus = cmdTypes.CommandStatus; const OutputCapture = cmdTypes.OutputCapture; +const StdoutOutputCapture = cmdTypes.StdoutOutputCapture; +const OutputWriter = cmdTypes.OutputWriter; const InputSource = cmdTypes.InputSource; const CommandContext = cmdTypes.CommandContext; @@ -36,7 +38,13 @@ pub fn executeCommand(command: Command, allocator: Allocator) !CommandStatus { } pub fn executeCommandWithOutput(command: Command, allocator: Allocator, output_capture: ?*OutputCapture, input_source: ?*InputSource) !CommandStatus { - const ctx = CommandContext.init(allocator, output_capture, input_source, executeCommandWithOutput); + var stdout_capture = StdoutOutputCapture{}; + const output_writer = if (output_capture) |capture| + OutputWriter{ .capture = capture } + else + OutputWriter{ .stdout = &stdout_capture }; + + const ctx = CommandContext.init(allocator, output_writer, input_source, executeCommandWithOutput); switch (command) { .Empty => return CommandStatus{ .Code = 0 }, @@ -112,11 +120,8 @@ pub fn executeCommandWithOutput(command: Command, allocator: Allocator, output_c else => { const error_msg = try std.fmt.allocPrint(ctx.allocator, "Command not implemented: {any}\n", .{builtin_cmd}); defer ctx.allocator.free(error_msg); - if (ctx.output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } + var writer = ctx.output_writer; + try writer.write(error_msg); return CommandStatus{ .Code = 1 }; }, } |