diff --git a/README.md b/README.md index 358d609..8afd68f 100644 --- a/README.md +++ b/README.md @@ -16,17 +16,17 @@ const zterm = @import("zterm"); pub fn main() !void { var sp = zterm.Spinner{ - .loading_charset = &[_][]const u8{"⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"}, - .loading_message = "Selling all your data to the CCP...", + .charset = &[_][]const u8{"⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"}, .finished_charset = "✓", - .finished_message = "Lock your doors.", + .message = "Selling all your data to the CCP...", }; try sp.start(); time.sleep(3 * time.ns_per_s); - var stdOut = std.io.getStdOut(); - try stdOut.writeAll("\rCalculating very important stuff while selling your data...\n"); + sp.setMessage("Calculating very important stuff while selling your data..."); + time.sleep(2 * time.ns_per_s); + sp.setMessage("Sold all your data successfully!"); try sp.stop(); } diff --git a/src/Spinner.zig b/src/Spinner.zig index 70d68d8..4b12a95 100644 --- a/src/Spinner.zig +++ b/src/Spinner.zig @@ -5,17 +5,13 @@ const Thread = std.Thread; const time = std.time; const Spinner = @This(); -const default_loading_charset = [_][]const u8{ "|", "/", "-", "\\" }; -const default_finished_charset = "✓"; - -loading_charset: []const []const u8 = &default_loading_charset, -loading_message: []const u8 = "", - -finished_charset: []const u8 = default_finished_charset, -finished_message: []const u8 = "", +// Must be only accessed when thread_lock is held by the current thread. +charset: []const []const u8 = &[_][]const u8{ "|", "/", "-", "\\" }, +message: []const u8 = "", keep_going: Atomic(bool) = Atomic(bool).init(false), spinner_thread: ?Thread = null, +thread_lock: Mutex = Mutex{}, framerate_ns: u64 = 100 * time.ns_per_ms, @@ -24,16 +20,37 @@ pub fn start(sp: *Spinner) !void { sp.spinner_thread = try Thread.spawn(.{}, writer, .{sp}); } -pub fn stop(sp: *Spinner) !void { +pub fn stop(sp: *Spinner, config: struct { + charset: ?[]const u8 = null, + message: ?[]const u8 = null, +}) !void { sp.keep_going.store(false, .SeqCst); - if (sp.spinner_thread) |*thread| thread.join(); + (sp.spinner_thread orelse unreachable).join(); var stdErr = std.io.getStdErr(); + sp.thread_lock.lock(); + defer sp.thread_lock.unlock(); + try stdErr.writeAll("\r"); - try stdErr.writeAll(sp.finished_charset); + try stdErr.writeAll(config.charset orelse sp.charset[0]); try stdErr.writeAll(" "); - try stdErr.writeAll(sp.finished_message); + try stdErr.writeAll(config.message orelse sp.message); + try stdErr.writeAll("\n"); +} + +pub fn setCharset(sp: *Spinner, charset: []const []const u8) void { + sp.thread_lock.lock(); + defer sp.thread_lock.unlock(); + + sp.charset = charset; +} + +pub fn setMessage(sp: *Spinner, message: []const u8) void { + sp.thread_lock.lock(); + defer sp.thread_lock.unlock(); + + sp.message = message; } fn writer(sp: *Spinner) !void { @@ -41,14 +58,15 @@ fn writer(sp: *Spinner) !void { var current_char_idx: usize = 0; while (true) : (current_char_idx += 1) { - if (!sp.keep_going.load(.SeqCst)) break; - if (current_char_idx >= sp.loading_charset.len - 1) current_char_idx = 0; + if (!sp.keep_going.load(.SeqCst)) return; + if (current_char_idx >= sp.charset.len - 1) current_char_idx = 0; - try stdErr.writeAll("\r"); - - try stdErr.writeAll(sp.loading_charset[current_char_idx]); + sp.thread_lock.lock(); + try stdErr.writeAll(sp.charset[current_char_idx]); try stdErr.writeAll(" "); - try stdErr.writeAll(sp.loading_message); + try stdErr.writeAll(sp.message); + try stdErr.writeAll("\r"); + sp.thread_lock.unlock(); time.sleep(sp.framerate_ns); } diff --git a/zterm.zig b/zterm.zig index 3324e0b..216a620 100644 --- a/zterm.zig +++ b/zterm.zig @@ -6,17 +6,17 @@ const zterm = struct { pub fn main() !void { var sp = zterm.Spinner{ - .loading_charset = &[_][]const u8{"⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"}, - .loading_message = "Selling all your data to the CCP...", - .finished_charset = "✓", - .finished_message = "Lock your doors.", + .charset = &[_][]const u8{ "⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷" }, + .message = "Selling all your data to the CCP...", }; try sp.start(); time.sleep(3 * time.ns_per_s); - var stdOut = std.io.getStdOut(); - try stdOut.writeAll("\rCalculating very important stuff while selling your data...\n"); - time.sleep(2 * time.ns_per_s); + sp.setMessage("Calculating very important stuff while selling your data..."); - try sp.stop(); + time.sleep(2 * time.ns_per_s); + try sp.stop(.{ + .charset = "✓", + .message = "Successfully sold all your data to the CCP! You data is not in safe hands!", + }); }