diff options
author | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2025-08-16 13:02:47 +0200 |
---|---|---|
committer | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2025-08-16 13:02:47 +0200 |
commit | 3e53d3ae08d41b21d9edcd0f9bbd9e0edbdfb138 (patch) | |
tree | 613aafbc1bfd848d739a60452199fbed28e877b6 /src/cmd/lib | |
parent | 9edc1338b92d1ead4c5f2fad8c0516037963f7b6 (diff) |
Unify input handling.
Diffstat (limited to 'src/cmd/lib')
-rw-r--r-- | src/cmd/lib/types.zig | 59 |
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, }; } |