summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Andreas Benkard <code@mail.matthias.benkard.de>2025-08-16 12:50:23 +0200
committerMatthias Andreas Benkard <code@mail.matthias.benkard.de>2025-08-16 12:50:23 +0200
commit9edc1338b92d1ead4c5f2fad8c0516037963f7b6 (patch)
tree64f3ed617771f9327bd49e3732adb9271e3559cc
parent754a74da6052c9f5e8dc4a536c58ccc11cb66369 (diff)
Unify output handling.
Now every command always uses an OutputWriter instead of conditionally writing directly to stdout using std.debug.print.
-rw-r--r--src/cmd/chdir.zig43
-rw-r--r--src/cmd/cls.zig12
-rw-r--r--src/cmd/copy.zig90
-rw-r--r--src/cmd/date.zig8
-rw-r--r--src/cmd/dir.zig15
-rw-r--r--src/cmd/echo.zig22
-rw-r--r--src/cmd/external.zig47
-rw-r--r--src/cmd/help.zig14
-rw-r--r--src/cmd/lib/types.zig25
-rw-r--r--src/cmd/mkdir.zig8
-rw-r--r--src/cmd/move.zig8
-rw-r--r--src/cmd/path.zig29
-rw-r--r--src/cmd/pipe.zig6
-rw-r--r--src/cmd/redirect.zig6
-rw-r--r--src/cmd/remove.zig15
-rw-r--r--src/cmd/rename.zig22
-rw-r--r--src/cmd/rmdir.zig8
-rw-r--r--src/cmd/sort.zig15
-rw-r--r--src/cmd/time.zig8
-rw-r--r--src/cmd/type.zig36
-rw-r--r--src/cmd/ver.zig8
-rw-r--r--src/eval.zig17
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 };
},
}