summaryrefslogtreecommitdiff
path: root/src/cmd/lib
diff options
context:
space:
mode:
authorMatthias Andreas Benkard <code@mail.matthias.benkard.de>2025-08-16 13:02:47 +0200
committerMatthias Andreas Benkard <code@mail.matthias.benkard.de>2025-08-16 13:02:47 +0200
commit3e53d3ae08d41b21d9edcd0f9bbd9e0edbdfb138 (patch)
tree613aafbc1bfd848d739a60452199fbed28e877b6 /src/cmd/lib
parent9edc1338b92d1ead4c5f2fad8c0516037963f7b6 (diff)
Unify input handling.
Diffstat (limited to 'src/cmd/lib')
-rw-r--r--src/cmd/lib/types.zig59
1 files changed, 56 insertions, 3 deletions
diff --git a/src/cmd/lib/types.zig b/src/cmd/lib/types.zig
index f663a64..f6a32c0 100644
--- a/src/cmd/lib/types.zig
+++ b/src/cmd/lib/types.zig
@@ -72,6 +72,59 @@ pub const InputSource = struct {
}
};
+pub const StdinInputReader = struct {
+ pub fn readLine(self: *StdinInputReader, allocator: Allocator) !?[]const u8 {
+ _ = self;
+ const stdin = std.io.getStdIn().reader();
+
+ // Read line from stdin with proper DOS handling
+ const line = stdin.readUntilDelimiterOrEofAlloc(allocator, '\n', 4096) catch |err| switch (err) {
+ error.StreamTooLong => {
+ // Line too long, skip to next line
+ while (true) {
+ const ch = stdin.readByte() catch return null;
+ if (ch == '\n') break;
+ }
+ return try allocator.dupe(u8, "");
+ },
+ else => return null,
+ };
+
+ if (line) |input| {
+ // Check for Ctrl+Z (EOF marker) - ASCII 26 or ^Z text
+ if ((input.len == 1 and input[0] == 26) or
+ (input.len == 2 and input[0] == '^' and input[1] == 'Z'))
+ {
+ allocator.free(input);
+ return null; // EOF
+ }
+
+ // Remove trailing \r if present (DOS line endings)
+ if (input.len > 0 and input[input.len - 1] == '\r') {
+ const trimmed = try allocator.dupe(u8, input[0 .. input.len - 1]);
+ allocator.free(input);
+ return trimmed;
+ } else {
+ return input;
+ }
+ } else {
+ return null; // EOF
+ }
+ }
+};
+
+pub const InputReader = union(enum) {
+ source: *InputSource,
+ stdin: *StdinInputReader,
+
+ pub fn readLine(self: *InputReader, allocator: Allocator) !?[]const u8 {
+ switch (self.*) {
+ .source => |source| return source.readLine(allocator),
+ .stdin => |stdin| return stdin.readLine(allocator),
+ }
+ }
+};
+
pub const OutputWriter = union(enum) {
capture: *OutputCapture,
stdout: *StdoutOutputCapture,
@@ -89,14 +142,14 @@ pub const ExecuteCommandFn = *const fn (Command, Allocator, ?*OutputCapture, ?*I
pub const CommandContext = struct {
allocator: Allocator,
output_writer: OutputWriter,
- input_source: ?*InputSource,
+ input_reader: InputReader,
execute_command: ExecuteCommandFn,
- pub fn init(allocator: Allocator, output_writer: OutputWriter, input_source: ?*InputSource, execute_command: ExecuteCommandFn) CommandContext {
+ pub fn init(allocator: Allocator, output_writer: OutputWriter, input_reader: InputReader, execute_command: ExecuteCommandFn) CommandContext {
return CommandContext{
.allocator = allocator,
.output_writer = output_writer,
- .input_source = input_source,
+ .input_reader = input_reader,
.execute_command = execute_command,
};
}