progress

progress
git clone git://brookjeynes.dev/bjeynes/progress.git
Log | Files | Refs | README | LICENSE

commit 1c40be0c4f0008229c9968d970ecca794816e6b6
parent 63ffdabd94070e4604584fe36708d1db3b6b29fc
Author: brookjeynes <me@brookjeynes.dev>
Date:   Wed, 22 Apr 2026 09:55:16 +1000

feat: update library from zig v0.14.0 -> v0.16.0

Diffstat:
MCHANGELOG.md | 3+++
MREADME.md | 2+-
Mbuild.zig | 36+++++++++++++++++++++---------------
Mbuild.zig.zon | 4++--
Mexamples/bar/complex.zig | 11++++++-----
Mexamples/bar/simple.zig | 9+++++----
Mexamples/bar/thread.zig | 11++++++-----
Mexamples/spinner/complex.zig | 9+++++----
Mexamples/spinner/simple.zig | 9+++++----
Msrc/bar.zig | 107+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/spinner.zig | 63+++++++++++++++++++++++++++++++--------------------------------
Msrc/termsize.zig | 14++++++--------
12 files changed, 144 insertions(+), 134 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## v2.0.0 (2026-04-22) +- chore: Update project to Zig v0.16.0 + ## v1.2.1 (2025-03-26) - chore: Update project to Zig v0.14.0 diff --git a/README.md b/README.md @@ -58,4 +58,4 @@ For more information, see the source code or documentation (`zig build docs`). ## Contributing Contributions, issues, and feature requests are always welcome! This project is -using the latest stable release of Zig (0.14.0). +using the latest stable release of Zig (0.16.0). diff --git a/build.zig b/build.zig @@ -1,22 +1,24 @@ const std = @import("std"); +const name = "progress"; + pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); - const progress = b.addModule("progress", .{ + const mod = b.addModule(name, .{ .root_source_file = b.path("src/root.zig"), .target = target, .optimize = optimize, }); + const progress = b.addLibrary(.{ + .name = name, + .root_module = mod, + }); + const docs = b.addInstallDirectory(.{ - .source_dir = b.addStaticLibrary(.{ - .name = "progress", - .root_source_file = b.path("src/root.zig"), - .target = target, - .optimize = optimize, - }).getEmittedDocs(), + .source_dir = progress.getEmittedDocs(), .install_dir = .prefix, .install_subdir = "docs", }); @@ -28,11 +30,13 @@ pub fn build(b: *std.Build) void { const run_step = b.step(b.fmt("run-bar-{s}", .{example}), b.fmt("Run bar/{s}.zig example", .{example})); const exe = b.addExecutable(.{ .name = example, - .root_source_file = b.path(b.fmt("examples/bar/{s}.zig", .{example})), - .target = target, - .optimize = optimize, + .root_module = b.createModule(.{ + .root_source_file = b.path(b.fmt("examples/bar/{s}.zig", .{example})), + .target = target, + .optimize = optimize, + }), }); - exe.root_module.addImport("progress", progress); + exe.root_module.addImport(name, mod); const run_cmd = b.addRunArtifact(exe); run_cmd.step.dependOn(&b.addInstallArtifact(exe, .{}).step); @@ -48,11 +52,13 @@ pub fn build(b: *std.Build) void { const run_step = b.step(b.fmt("run-spinner-{s}", .{example}), b.fmt("Run spinner/{s}.zig example", .{example})); const exe = b.addExecutable(.{ .name = example, - .root_source_file = b.path(b.fmt("examples/spinner/{s}.zig", .{example})), - .target = target, - .optimize = optimize, + .root_module = b.createModule(.{ + .root_source_file = b.path(b.fmt("examples/spinner/{s}.zig", .{example})), + .target = target, + .optimize = optimize, + }), }); - exe.root_module.addImport("progress", progress); + exe.root_module.addImport(name, mod); const run_cmd = b.addRunArtifact(exe); run_cmd.step.dependOn(&b.addInstallArtifact(exe, .{}).step); diff --git a/build.zig.zon b/build.zig.zon @@ -1,8 +1,8 @@ .{ .name = .progress, - .version = "1.2.0", + .version = "2.0.0", .fingerprint = 0x2201f246209e1a21, - .minimum_zig_version = "0.14.0", + .minimum_zig_version = "0.16.0", .dependencies = .{}, diff --git a/examples/bar/complex.zig b/examples/bar/complex.zig @@ -1,10 +1,11 @@ const std = @import("std"); const ProgressBar = @import("progress").Bar; -pub fn main() !void { - const stdout = std.io.getStdOut().writer(); +pub fn main(init: std.process.Init) !void { + var stdout_buf: [4096]u8 = undefined; + var stdout_writer = std.Io.File.stdout().writer(init.io, &stdout_buf); - var pb1 = ProgressBar.init(28, stdout.any(), .{ + var pb1 = ProgressBar.init(28, &stdout_writer, .{ .bar_prefix = '[', .bar_suffix = ']', .bar_fill_char = '=', @@ -15,7 +16,7 @@ pub fn main() !void { }); pb1.setColour(.Blue); - var pb2 = ProgressBar.init(15, stdout.any(), .{ + var pb2 = ProgressBar.init(15, &stdout_writer, .{ .bar_prefix = '|', .bar_suffix = '|', .bar_fill_char = '━', @@ -39,7 +40,7 @@ pub fn main() !void { if (pb.current_progress == 14) pb.updateDescription("Bar 1: nearly there"); } - std.time.sleep(std.time.ns_per_ms * 150); + try std.Io.sleep(init.io, std.Io.Duration.fromMilliseconds(150), .awake); } } } diff --git a/examples/bar/simple.zig b/examples/bar/simple.zig @@ -1,14 +1,15 @@ const std = @import("std"); const ProgressBar = @import("progress").Bar; -pub fn main() !void { - const stdout = std.io.getStdOut().writer(); - var pb = ProgressBar.init(10, stdout.any(), .{}); +pub fn main(init: std.process.Init) !void { + var stdout_buf: [4096]u8 = undefined; + var stdout_writer = std.Io.File.stdout().writer(init.io, &stdout_buf); + var pb = ProgressBar.init(10, &stdout_writer, .{}); while (!pb.isFinished()) { pb.add(1); try pb.render(); - std.time.sleep(std.time.ns_per_ms * 150); + try std.Io.sleep(init.io, std.Io.Duration.fromMilliseconds(150), .awake); } } diff --git a/examples/bar/thread.zig b/examples/bar/thread.zig @@ -3,19 +3,20 @@ const ProgressBar = @import("progress").Bar; pub fn threadWorker(bar: *ProgressBar, seed: usize) !void { var rand_impl = std.Random.DefaultPrng.init(seed); - const num = @mod(rand_impl.random().int(u64), 1000); + const num = @mod(rand_impl.random().int(i64), 1000); for (0..5) |_| { bar.add(1); try bar.render(); - std.time.sleep(std.time.ns_per_ms * num); + try std.Io.sleep(bar.writer.io, std.Io.Duration.fromMilliseconds(num), .awake); } } -pub fn main() !void { - const stdout = std.io.getStdOut().writer(); - var pb = ProgressBar.init(100, stdout.any(), .{ +pub fn main(init: std.process.Init) !void { + var stdout_buf: [4096]u8 = undefined; + var stdout_writer = std.Io.File.stdout().writer(init.io, &stdout_buf); + var pb = ProgressBar.init(100, &stdout_writer, .{ .description = "Progress bar with threads", .show_iterations = true, .show_percentage = true, diff --git a/examples/spinner/complex.zig b/examples/spinner/complex.zig @@ -1,9 +1,10 @@ const std = @import("std"); const ProgressSpinner = @import("progress").Spinner; -pub fn main() !void { - const stdout = std.io.getStdOut().writer(); - var ps = ProgressSpinner.init(stdout.any(), .{ +pub fn main(init: std.process.Init) !void { + var stdout_buf: [4096]u8 = undefined; + var stdout_writer = std.Io.File.stdout().writer(init.io, &stdout_buf); + var ps = ProgressSpinner.init(&stdout_writer, .{ .description = "Task 1", .symbols = &[_]u21{ '⣾', '⣷', '⣯', '⣟', '⡿', '⢿', '⣻', '⣽' }, .completion_character = '✓', @@ -22,6 +23,6 @@ pub fn main() !void { if (iterations == 30) try ps.updateDescriptionNewline("Task 4.0"); if (iterations == 40) try ps.finish(); - std.time.sleep(std.time.ns_per_ms * 150); + try std.Io.sleep(init.io, std.Io.Duration.fromMilliseconds(150), .awake); } } diff --git a/examples/spinner/simple.zig b/examples/spinner/simple.zig @@ -1,9 +1,10 @@ const std = @import("std"); const ProgressSpinner = @import("progress").Spinner; -pub fn main() !void { - const stdout = std.io.getStdOut().writer(); - var ps = ProgressSpinner.init(stdout.any(), .{ +pub fn main(init: std.process.Init) !void { + var stdout_buf: [4096]u8 = undefined; + var stdout_writer = std.Io.File.stdout().writer(init.io, &stdout_buf); + var ps = ProgressSpinner.init(&stdout_writer, .{ .symbols = ProgressSpinner.PredefinedSymbols.default, }); @@ -14,6 +15,6 @@ pub fn main() !void { if (iterations == 20) try ps.finish(); - std.time.sleep(std.time.ns_per_ms * 150); + try std.Io.sleep(init.io, std.Io.Duration.fromMilliseconds(150), .awake); } } diff --git a/src/bar.zig b/src/bar.zig @@ -3,7 +3,6 @@ const termsize = @import("termsize.zig"); const ansi_term = @import("ansi-term.zig"); const Error = error{ - FailedToRender, ///Used when the progress bar is too small to render all the content. BarTooSmall, }; @@ -41,9 +40,9 @@ const Bar = @This(); ///Direct access is not thread safe. Use `currentProgress()` if you need thread safety. current_progress: usize = 0, max_progress: usize = 0, -bw: std.io.BufferedWriter(4096, std.io.AnyWriter), +writer: *std.Io.File.Writer, config: Config, -mutex: std.Thread.Mutex = std.Thread.Mutex{}, +mutex: std.Io.Mutex = std.Io.Mutex.init, ///Direct access is not thread safe. Use `isFinished()` if you need thread safety. finished: bool = false, ///The progress bar foreground colour. @@ -51,10 +50,10 @@ colour: ansi_term.Colour = .Default, ///The progress bar background colour. bg_colour: ansi_term.Colour = .Default, -pub fn init(max_progress: usize, writer: std.io.AnyWriter, config: Config) Bar { +pub fn init(max_progress: usize, writer: *std.Io.File.Writer, config: Config) Bar { return Bar{ .max_progress = max_progress, - .bw = std.io.bufferedWriter(writer), + .writer = writer, .config = config, }; } @@ -62,8 +61,8 @@ pub fn init(max_progress: usize, writer: std.io.AnyWriter, config: Config) Bar { ///Add `num` to the progress bar. ///If `num` is greater than `max_progress`, `current_progress` will be set to the max. pub fn add(self: *Bar, num: usize) void { - self.mutex.lock(); - defer self.mutex.unlock(); + self.mutex.lockUncancelable(self.writer.io); + defer self.mutex.unlock(self.writer.io); if (self.current_progress + num < self.max_progress) { self.current_progress += num; @@ -74,12 +73,12 @@ pub fn add(self: *Bar, num: usize) void { ///Render the progress bar. pub fn render(self: *Bar) !void { - const winsize = try termsize.termSize(std.io.getStdOut()) orelse termsize.TermSize{ .width = default_bar_width, .height = 0 }; + const winsize = try termsize.termSize(std.Io.File.stdout(), self.writer.io) orelse termsize.TermSize{ .width = default_bar_width, .height = 0 }; const width = if (self.config.width) |w| @min(w, winsize.width) else winsize.width; var unicode_conversion_buf: [8]u8 = undefined; - self.mutex.lock(); - defer self.mutex.unlock(); + try self.mutex.lock(self.writer.io); + defer self.mutex.unlock(self.writer.io); if (self.finished) return; @@ -110,9 +109,9 @@ pub fn render(self: *Bar) !void { const num_len: usize = @intFromFloat(@ceil(@log10(@as(f32, @floatFromInt(self.max_progress + 1))))); count += 8 + (num_len * 2); // "[ {num_len} / {num_len} ]" - try ansi_term.setCursorColumn(self.bw.writer(), std.math.sub(usize, width + padding, count) catch return Error.BarTooSmall); + try ansi_term.setCursorColumn(&self.writer.interface, std.math.sub(usize, width + padding, count) catch return Error.BarTooSmall); - _ = try self.bw.writer().print("[ {[curr]: >[padding]} / {[max]} ]\r", .{ .curr = self.current_progress, .padding = num_len, .max = self.max_progress }); + try self.writer.interface.print("[ {[curr]: >[padding]} / {[max]} ]\r", .{ .curr = self.current_progress, .padding = num_len, .max = self.max_progress }); } break :brk count; @@ -122,118 +121,118 @@ pub fn render(self: *Bar) !void { if (extra_chars > width) return Error.BarTooSmall; if (self.config.description) |desc| { - _ = try self.bw.write(desc); - try ansi_term.cursorForward(self.bw.writer(), 1); + try self.writer.interface.writeAll(desc); + try ansi_term.cursorForward(&self.writer.interface, 1); } if (self.config.show_percentage) { - try self.bw.writer().print("{d: >3}%", .{@as(u32, @intFromFloat(percentage * 100))}); - try ansi_term.cursorForward(self.bw.writer(), 1); + try self.writer.interface.print("{d: >3}%", .{@as(u32, @intFromFloat(percentage * 100))}); + try ansi_term.cursorForward(&self.writer.interface, 1); } const prefix_bytes = try std.unicode.utf8Encode(self.config.bar_prefix, &unicode_conversion_buf); - _ = try self.bw.write(unicode_conversion_buf[0..prefix_bytes]); + try self.writer.interface.writeAll(unicode_conversion_buf[0..prefix_bytes]); const max_percentage_pos: usize = std.math.sub(usize, width, extra_front_chars + extra_back_chars) catch 0; const current_percentage_pos: usize = @intFromFloat(percentage * @as(f32, @floatFromInt(std.math.sub(usize, width, extra_front_chars + extra_back_chars) catch 0))); for (0..max_percentage_pos) |write_pos| { if (write_pos > current_percentage_pos) { if (self.config.show_background) { - try ansi_term.writeColour(self.bw.writer(), self.bg_colour); + try ansi_term.writeColour(&self.writer.interface, self.bg_colour); const fill_char_bytes = try std.unicode.utf8Encode(self.config.bar_fill_char, &unicode_conversion_buf); - _ = try self.bw.write(unicode_conversion_buf[0..fill_char_bytes]); - try ansi_term.resetColour(self.bw.writer()); + try self.writer.interface.writeAll(unicode_conversion_buf[0..fill_char_bytes]); + try ansi_term.resetColour(&self.writer.interface); } continue; } - try ansi_term.writeColour(self.bw.writer(), self.colour); + try ansi_term.writeColour(&self.writer.interface, self.colour); const fill_char_bytes = try std.unicode.utf8Encode(self.config.bar_fill_char, &unicode_conversion_buf); - _ = try self.bw.write(unicode_conversion_buf[0..fill_char_bytes]); - try ansi_term.resetColour(self.bw.writer()); + try self.writer.interface.writeAll(unicode_conversion_buf[0..fill_char_bytes]); + try ansi_term.resetColour(&self.writer.interface); } - try ansi_term.hideCursor(self.bw.writer()); - try ansi_term.setCursorColumn(self.bw.writer(), width - extra_back_chars); + try ansi_term.hideCursor(&self.writer.interface); + try ansi_term.setCursorColumn(&self.writer.interface, width - extra_back_chars); const suffix_bytes = try std.unicode.utf8Encode(self.config.bar_suffix, &unicode_conversion_buf); - _ = try self.bw.write(unicode_conversion_buf[0..suffix_bytes]); + try self.writer.interface.writeAll(unicode_conversion_buf[0..suffix_bytes]); if (self.current_progress >= self.max_progress and !self.finished) { self.finished = true; if (self.config.clear_on_finish) try self.clear(); - if (self.config.write_newline_on_finish) _ = try self.bw.write("\n"); - try ansi_term.showCursor(self.bw.writer()); + if (self.config.write_newline_on_finish) try self.writer.interface.writeAll("\n"); + try ansi_term.showCursor(&self.writer.interface); } - try self.bw.flush(); + try self.writer.interface.flush(); } ///Set the progress bar colour. pub fn setColour(self: *Bar, colour: ansi_term.Colour) void { - self.mutex.lock(); - defer self.mutex.unlock(); + self.mutex.lockUncancelable(self.writer.io); + defer self.mutex.unlock(self.writer.io); self.colour = colour; } ///Set the progress bar background colour. pub fn setBgColour(self: *Bar, colour: ansi_term.Colour) void { - self.mutex.lock(); - defer self.mutex.unlock(); + self.mutex.lockUncancelable(self.writer.io); + defer self.mutex.unlock(self.writer.io); self.bg_colour = colour; } ///Show the progress bar background. pub fn showBg(self: *Bar) void { - self.mutex.lock(); - defer self.mutex.unlock(); + self.mutex.lockUncancelable(self.writer.io); + defer self.mutex.unlock(self.writer.io); self.config.show_background = true; } ///Hide the progress bar background. pub fn hideBg(self: *Bar) void { - self.mutex.lock(); - defer self.mutex.unlock(); + self.mutex.lockUncancelable(self.writer.io); + defer self.mutex.unlock(self.writer.io); self.config.show_background = false; } ///Returns `true` if the progress bar is finished and `false` otherwise. pub fn isFinished(self: *Bar) bool { - self.mutex.lock(); - defer self.mutex.unlock(); + self.mutex.lockUncancelable(self.writer.io); + defer self.mutex.unlock(self.writer.io); return self.current_progress >= self.max_progress or self.finished; } ///Returns the current progress. pub fn currentProgress(self: *Bar) usize { - self.mutex.lock(); - defer self.mutex.unlock(); + self.mutex.lockUncancelable(self.writer.io); + defer self.mutex.unlock(self.writer.io); return self.current_progress; } ///Finish the progress bar. pub fn finish(self: *Bar) !void { - self.mutex.lock(); - defer self.mutex.unlock(); + try self.mutex.lock(self.writer.io); + defer self.mutex.unlock(self.writer.io); self.finished = true; self.current_progress = self.max_progress; - try ansi_term.showCursor(self.bw.writer()); - try self.bw.flush(); + try ansi_term.showCursor(&self.writer.interface); + try self.writer.interface.flush(); } ///Reset the progress bar. pub fn reset(self: *Bar) void { - self.mutex.lock(); - defer self.mutex.unlock(); + self.mutex.lockUncancelable(self.writer.io); + defer self.mutex.unlock(self.writer.io); self.finished = false; self.current_progress = 0; @@ -244,8 +243,8 @@ pub fn reset(self: *Bar) void { ///If `num` is equal to `max_progress`, `finished` is set true. ///If `num` is greater than `max_progress`, `current_progress` will be set to the max. pub fn set(self: *Bar, num: usize) void { - self.mutex.lock(); - defer self.mutex.unlock(); + self.mutex.lockUncancelable(self.writer.io); + defer self.mutex.unlock(self.writer.io); if (num >= self.max_progress) { self.finished = true; @@ -258,8 +257,8 @@ pub fn set(self: *Bar, num: usize) void { ///Update the description. pub fn updateDescription(self: *Bar, description: []const u8) void { - self.mutex.lock(); - defer self.mutex.unlock(); + self.mutex.lockUncancelable(self.writer.io); + defer self.mutex.unlock(self.writer.io); self.config.description = description; } @@ -268,7 +267,7 @@ pub fn updateDescription(self: *Bar, description: []const u8) void { /// ///This function is not thread safe. pub fn clear(self: *Bar) !void { - try ansi_term.clearCurrentLine(self.bw.writer()); - try ansi_term.setCursorColumn(self.bw.writer(), 0); - try self.bw.flush(); + try ansi_term.clearCurrentLine(&self.writer.interface); + try ansi_term.setCursorColumn(&self.writer.interface, 0); + try self.writer.interface.flush(); } diff --git a/src/spinner.zig b/src/spinner.zig @@ -1,5 +1,4 @@ const std = @import("std"); -const termsize = @import("termsize.zig"); const ansi_term = @import("ansi-term.zig"); pub const PredefinedSymbols = enum { @@ -29,16 +28,16 @@ const Config = struct { const Spinner = @This(); -bw: std.io.BufferedWriter(4096, std.io.AnyWriter), +writer: *std.Io.File.Writer, config: Config, -mutex: std.Thread.Mutex = std.Thread.Mutex{}, +mutex: std.Io.Mutex = std.Io.Mutex.init, ///Direct access is not thread safe. Use `isFinished()` if you need thread safety. finished: bool = false, current_symbol_idx: usize = 0, -pub fn init(writer: std.io.AnyWriter, config: Config) Spinner { +pub fn init(writer: *std.Io.File.Writer, config: Config) Spinner { return Spinner{ - .bw = std.io.bufferedWriter(writer), + .writer = writer, .config = config, }; } @@ -47,53 +46,53 @@ fn renderComplete(self: *Spinner, completion_char: u21) !void { try self.clear(); var buf: [8]u8 = undefined; const bytes = try std.unicode.utf8Encode(completion_char, &buf); - _ = try self.bw.write(buf[0..bytes]); + try self.writer.interface.writeAll(buf[0..bytes]); if (self.config.description) |desc| { - try ansi_term.cursorForward(self.bw.writer(), 1); - _ = try self.bw.write(desc); + try ansi_term.cursorForward(&self.writer.interface, 1); + try self.writer.interface.writeAll(desc); } if (self.config.clear_on_finish) try self.clear(); - try self.bw.flush(); + try self.writer.interface.flush(); } ///Render the progress spinner and advance a visual cycle. pub fn render(self: *Spinner) !void { - self.mutex.lock(); - defer self.mutex.unlock(); + try self.mutex.lock(self.writer.io); + defer self.mutex.unlock(self.writer.io); if (self.finished) return; try self.clear(); - try ansi_term.hideCursor(self.bw.writer()); + try ansi_term.hideCursor(&self.writer.interface); var buf: [8]u8 = undefined; const bytes = try std.unicode.utf8Encode(self.config.symbols[self.current_symbol_idx], &buf); - _ = try self.bw.write(buf[0..bytes]); + try self.writer.interface.writeAll(buf[0..bytes]); if (self.config.description) |desc| { - try ansi_term.cursorForward(self.bw.writer(), 1); - _ = try self.bw.write(desc); + try ansi_term.cursorForward(&self.writer.interface, 1); + try self.writer.interface.writeAll(desc); } - try self.bw.flush(); + try self.writer.interface.flush(); self.current_symbol_idx = (self.current_symbol_idx + 1) % self.config.symbols.len; } ///Returns `true` if the progress spinner is finished and `false` otherwise. pub fn isFinished(self: *Spinner) bool { - self.mutex.lock(); - defer self.mutex.unlock(); + self.mutex.lockUncancelable(self.writer.io); + defer self.mutex.unlock(self.writer.io); return self.finished; } ///Finish the progress spinner. pub fn finish(self: *Spinner) !void { - self.mutex.lock(); - defer self.mutex.unlock(); + try self.mutex.lock(self.writer.io); + defer self.mutex.unlock(self.writer.io); self.finished = true; @@ -102,24 +101,24 @@ pub fn finish(self: *Spinner) !void { } if (self.config.clear_on_finish) try self.clear(); - if (self.config.write_newline_on_finish) _ = try self.bw.write("\n"); + if (self.config.write_newline_on_finish) try self.writer.interface.writeAll("\n"); - try ansi_term.showCursor(self.bw.writer()); - try self.bw.flush(); + try ansi_term.showCursor(&self.writer.interface); + try self.writer.interface.flush(); } ///Update the description. pub fn updateDescription(self: *Spinner, description: []const u8) void { - self.mutex.lock(); - defer self.mutex.unlock(); + self.mutex.lockUncancelable(self.writer.io); + defer self.mutex.unlock(self.writer.io); self.config.description = description; } ///Update the description and continue the spinner on a newline. pub fn updateDescriptionNewline(self: *Spinner, description: []const u8) !void { - self.mutex.lock(); - defer self.mutex.unlock(); + try self.mutex.lock(self.writer.io); + defer self.mutex.unlock(self.writer.io); if (self.config.completion_character) |char| { try self.renderComplete(char); @@ -127,15 +126,15 @@ pub fn updateDescriptionNewline(self: *Spinner, description: []const u8) !void { self.config.description = description; - _ = try self.bw.write("\n"); - try self.bw.flush(); + try self.writer.interface.writeAll("\n"); + try self.writer.interface.flush(); } ///Clear the progress spinner. /// ///This function is not thread safe. pub fn clear(self: *Spinner) !void { - try ansi_term.clearCurrentLine(self.bw.writer()); - try ansi_term.setCursorColumn(self.bw.writer(), 0); - try self.bw.flush(); + try ansi_term.clearCurrentLine(&self.writer.interface); + try ansi_term.setCursorColumn(&self.writer.interface, 0); + try self.writer.interface.flush(); } diff --git a/src/termsize.zig b/src/termsize.zig @@ -24,7 +24,6 @@ const std = @import("std"); const builtin = @import("builtin"); -const io = std.io; const os = std.os; /// Terminal size dimensions @@ -35,23 +34,22 @@ pub const TermSize = struct { height: u16, }; -/// supports windows, linux, macos -/// /// ## example /// /// ```zig /// const std = @import("std"); -/// const termSize = @import("termSize"); +/// const termSize = @import("termsize"); /// -/// fn main() !void { +/// fn main(init: std.process.Init) !void { /// std.debug.print( /// "{any}", -/// termSize.termSize(std.os.getStdOut()), +/// termSize.termSize(std.Io.File.stdout(), init.io), /// ); /// } /// ``` -pub fn termSize(file: std.fs.File) !?TermSize { - if (!file.supportsAnsiEscapeCodes()) { +pub fn termSize(file: std.Io.File, io: std.Io) !?TermSize { + const supports_ansi = file.supportsAnsiEscapeCodes(io) catch return null; + if (!supports_ansi) { return null; } return switch (builtin.os.tag) {