diff --git a/README.md b/README.md index 1c063efb0118cc05ffa4ce987104cca4e7babd2d..bb8c98f177a024af1132a481d19b30ea7d67f927 100644 --- a/README.md +++ b/README.md @@ -18,13 +18,13 @@ zig build run ![image](https://user-images.githubusercontent.com/5464072/127479686-fda8f860-a705-4fd6-9768-a3e1f53a6bc7.png) ## Usage -- `pub fn answer(comptime prompt: []const u8, value: []const u8) []const u8` +- `pub fn answer(writer, reader, comptime prompt: []const u8, value: []const u8) []const u8` - Prints just the done string. -- `pub fn forEnum(comptime prompt: []const u8, alloc: *std.mem.Allocator, comptime options: enum, default: ?options) !options` +- `pub fn forEnum(writer, reader, comptime prompt: []const u8, alloc: *std.mem.Allocator, comptime options: enum, default: ?options) !options` - Accepts an enum and prompts the user to pick on of the fields. -- `pub fn forString(comptime prompt: []const u8, alloc: *std.mem.Allocator, default: ?[]const u8) ![]const u8` +- `pub fn forString(writer, reader, comptime prompt: []const u8, alloc: *std.mem.Allocator, default: ?[]const u8) ![]const u8` - Base function, asks prompt and returns non-empty answer. -- `pub fn forConfirm(comptime prompt: []const u8, alloc: *std.mem.Allocator) !bool` +- `pub fn forConfirm(writer, reader, comptime prompt: []const u8, alloc: *std.mem.Allocator) !bool` - Calls `forEnum` with `y/n` ## TODO diff --git a/src/lib.zig b/src/lib.zig index e6db6642e5ad068ed10981c3f981897fa125d829..c56e542789ad065e84b64cd3919a36cbafcdb673 100644 --- a/src/lib.zig +++ b/src/lib.zig @@ -2,10 +2,10 @@ const std = @import("std"); const ansi = @import("ansi"); const range = @import("range").range; -pub fn answer(comptime prompt: []const u8, comptime T: type, comptime valfmt: []const u8, value: T) T { - std.debug.print(comptime ansi.color.Fg(.Green, "? "), .{}); - std.debug.print(comptime ansi.color.Bold(prompt ++ " "), .{}); - std.debug.print(comptime ansi.color.Fg(.Cyan, valfmt ++ "\n"), .{value}); +pub fn answer(out: anytype, comptime prompt: []const u8, comptime T: type, comptime valfmt: []const u8, value: T) !T { + try out.print(comptime ansi.color.Fg(.Green, "? "), .{}); + try out.print(comptime ansi.color.Bold(prompt ++ " "), .{}); + try out.print(comptime ansi.color.Fg(.Cyan, valfmt ++ "\n"), .{value}); return value; } @@ -14,11 +14,11 @@ const PromptRet = struct { value: []const u8, }; -fn doprompt(in: std.fs.File.Reader, alloc: *std.mem.Allocator, default: ?[]const u8) !PromptRet { +fn doprompt(out: anytype, in: anytype, alloc: *std.mem.Allocator, default: ?[]const u8) !PromptRet { var n: usize = 1; var value: []const u8 = undefined; while (true) : (n += 1) { - std.debug.print(comptime ansi.color.Faint("> "), .{}); + try out.print(comptime ansi.color.Faint("> "), .{}); const input = try in.readUntilDelimiterAlloc(alloc, '\n', 100); if (input.len == 0) if (default) |d| { @@ -33,32 +33,31 @@ fn doprompt(in: std.fs.File.Reader, alloc: *std.mem.Allocator, default: ?[]const return PromptRet{ .n = n, .value = value }; } -fn clean(n: usize) void { +fn clean(out: anytype, n: usize) !void { for (range(n)) |_| { - std.debug.print(comptime ansi.csi.CursorUp(1), .{}); - std.debug.print(comptime ansi.csi.EraseInLine(0), .{}); + try out.print(comptime ansi.csi.CursorUp(1), .{}); + try out.print(comptime ansi.csi.EraseInLine(0), .{}); } } -pub fn forEnum(comptime prompt: []const u8, alloc: *std.mem.Allocator, comptime options: type, default: ?options) !options { +pub fn forEnum(out: anytype, in: anytype, comptime prompt: []const u8, alloc: *std.mem.Allocator, comptime options: type, default: ?options) !options { comptime std.debug.assert(@typeInfo(options) == .Enum); - std.debug.print(comptime ansi.color.Fg(.Green, "? "), .{}); - std.debug.print(comptime ansi.color.Bold(prompt ++ " "), .{}); + try out.print(comptime ansi.color.Fg(.Green, "? "), .{}); + try out.print(comptime ansi.color.Bold(prompt ++ " "), .{}); - std.debug.print(ansi.style.Faint ++ "(", .{}); + try out.print(ansi.style.Faint ++ "(", .{}); inline for (std.meta.fields(options)) |f, i| { - if (i != 0) std.debug.print("/", .{}); - std.debug.print(f.name, .{}); + if (i != 0) try out.print("/", .{}); + try out.print(f.name, .{}); } - std.debug.print(")" ++ ansi.style.ResetIntensity ++ " ", .{}); + try out.print(")" ++ ansi.style.ResetIntensity ++ " ", .{}); - const stdin = std.io.getStdIn().reader(); var value: options = undefined; var i: usize = 0; while (true) { const def: ?[]const u8 = if (default) |d| @tagName(d) else null; - const p = try doprompt(stdin, alloc, def); + const p = try doprompt(out, in, alloc, def); defer if (!std.mem.eql(u8, p.value, def orelse "")) alloc.free(p.value); i += p.n; @@ -67,43 +66,41 @@ pub fn forEnum(comptime prompt: []const u8, alloc: *std.mem.Allocator, comptime break; } } - clean(i); - _ = answer(prompt, []const u8, "{s}", @tagName(value)); + try clean(out, i); + _ = try answer(out, prompt, []const u8, "{s}", @tagName(value)); return value; } -pub fn forString(comptime prompt: []const u8, alloc: *std.mem.Allocator, default: ?[]const u8) ![]const u8 { - std.debug.print(comptime ansi.color.Fg(.Green, "? "), .{}); - std.debug.print(comptime ansi.color.Bold(prompt ++ " "), .{}); +pub fn forString(out: anytype, in: anytype, comptime prompt: []const u8, alloc: *std.mem.Allocator, default: ?[]const u8) ![]const u8 { + try out.print(comptime ansi.color.Fg(.Green, "? "), .{}); + try out.print(comptime ansi.color.Bold(prompt ++ " "), .{}); if (default != null) { - std.debug.print(ansi.style.Faint ++ "(", .{}); - std.debug.print("{s}", .{default.?}); - std.debug.print(")" ++ ansi.style.ResetIntensity ++ " ", .{}); + try out.print(ansi.style.Faint ++ "(", .{}); + try out.print("{s}", .{default.?}); + try out.print(")" ++ ansi.style.ResetIntensity ++ " ", .{}); } - const stdin = std.io.getStdIn().reader(); - const p = try doprompt(stdin, alloc, default); - clean(p.n); - return answer(prompt, []const u8, "{s}", p.value); + const p = try doprompt(out, in, alloc, default); + try clean(out, p.n); + return try answer(out, prompt, []const u8, "{s}", p.value); } -pub fn forConfirm(comptime prompt: []const u8, alloc: *std.mem.Allocator) !bool { - return (try forEnum(prompt, alloc, enum { y, n }, .y)) == .y; +pub fn forConfirm(out: anytype, in: anytype, comptime prompt: []const u8, alloc: *std.mem.Allocator) !bool { + return (try forEnum(out, in, prompt, alloc, enum { y, n }, .y)) == .y; } // pub fn forNumber(comptime prompt: []const u8, alloc: *std.mem.Allocator, comptime T: type, default: ?T) !T { -// std.debug.print(comptime ansi.color.Fg(.Green, "? "), .{}); -// std.debug.print(comptime ansi.color.Bold(prompt ++ " "), .{}); +// try out.print(comptime ansi.color.Fg(.Green, "? "), .{}); +// try out.print(comptime ansi.color.Bold(prompt ++ " "), .{}); // if (default != null) { -// std.debug.print(ansi.style.Faint ++ "(", .{}); -// std.debug.print("{d}", .{default.?}); -// std.debug.print(")" ++ ansi.style.ResetIntensity ++ " ", .{}); +// try out.print(ansi.style.Faint ++ "(", .{}); +// try out.print("{d}", .{default.?}); +// try out.print(")" ++ ansi.style.ResetIntensity ++ " ", .{}); // } -// const stdin = std.io.getStdIn().reader(); // var value: T = undefined; // var i: usize = 0; // while (true) { diff --git a/src/main.zig b/src/main.zig index 4c0b594e84b6a182952bf0b08073fb26ba8d4214..2b4814fd4d8e51497d2b1aebdb401cbeaca873a2 100644 --- a/src/main.zig +++ b/src/main.zig @@ -9,22 +9,25 @@ pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const alloc = &gpa.allocator; - _ = try inquirer.forConfirm("Is this for delivery?", alloc); + const in = std.io.getStdIn().reader(); + const out = std.io.getStdOut().writer(); - _ = try inquirer.forString("What's your phone number?", alloc, null); + _ = try inquirer.forConfirm(out, in, "Is this for delivery?", alloc); - _ = try inquirer.forEnum("What size do you need?", alloc, enum { Small, Medium, Large }, null); + _ = try inquirer.forString(out, in, "What's your phone number?", alloc, null); - // _ = try inquirer.forNumber("How many do you need?", alloc, u32, 1); + _ = try inquirer.forEnum(out, in, "What size do you need?", alloc, enum { Small, Medium, Large }, null); + + // _ = try inquirer.forNumber(out,in,"How many do you need?", alloc, u32, 1); // TODO forNumber is causing a compiler crash // TODO toppings for string list - _ = try inquirer.forEnum("You also get a free 2L:", alloc, enum { Pepsi, @"7up", Coke }, null); + _ = try inquirer.forEnum(out, in, "You also get a free 2L:", alloc, enum { Pepsi, @"7up", Coke }, null); - const comment = try inquirer.forString("Any comments on your purchase experience?", alloc, "Nope, all good!"); + const comment = try inquirer.forString(out, in, "Any comments on your purchase experience?", alloc, "Nope, all good!"); if (std.mem.eql(u8, comment, "")) { - _ = try inquirer.forEnum("For leaving a comment, you get a freebie:", alloc, enum { Cake, Fries }, null); + _ = try inquirer.forEnum(out, in, "For leaving a comment, you get a freebie:", alloc, enum { Cake, Fries }, null); } }