Skip to content

Instantly share code, notes, and snippets.

@nektro
Last active February 24, 2022 02:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nektro/5b06c9050472e2a0bad73de4c8f9b563 to your computer and use it in GitHub Desktop.
Save nektro/5b06c9050472e2a0bad73de4c8f9b563 to your computer and use it in GitHub Desktop.
A single line progress bar
const std = @import("std");
const string = []const u8;
const Progress = @This();
const ansi = @import("ansi");
const range = @import("range").range;
const extras = @import("extras");
total: usize,
current: usize = 0,
last_print: i64 = 0,
width: u8 = 80,
prefix: string = "",
suffix: string = "",
// https://mike42.me/blog/2018-06-make-better-cli-progress-bars-with-unicode-block-characters
const bars = [_]string{ "", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█" };
pub fn print(self: Progress) void {
const current = @intToFloat(f64, self.current);
const total = @intToFloat(f64, self.total);
const prog: f64 = current / total;
std.debug.print("{s}{} / {} ", .{ self.prefix, fmtByteCountIEC(self.current), fmtByteCountIEC(self.total) });
const width: f64 = @intToFloat(f64, self.width) * 8;
std.debug.print("[", .{});
const barprog = @floatToInt(usize, prog * width);
for (range(barprog / 8)) |_| std.debug.print("█", .{});
std.debug.print("{s}", .{bars[barprog % 8]});
for (range((@floatToInt(usize, width) - barprog) / 8)) |_| std.debug.print(" ", .{});
std.debug.print("] ", .{});
std.debug.print("{d:.3}%: {s}\n", .{ prog * 100, self.suffix });
}
pub fn refresh(self: Progress) void {
std.debug.print(comptime ansi.csi.CursorUp(1), .{});
std.debug.print(comptime ansi.csi.EraseInLine(0), .{});
self.print();
}
pub fn update(self: *Progress, amt: usize) void {
self.current += amt;
const now = std.time.milliTimestamp();
if (now - self.last_print < 50) return;
self.last_print = now;
self.refresh();
}
fn fmtByteCountIEC(b: usize) std.fmt.Formatter(formatByteCountIEC) {
return .{ .data = b };
}
fn formatByteCountIEC(b: usize, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
_ = fmt;
_ = options;
try reduceNumber(writer, b, 1024, "B", "KMGTPEZY");
}
fn reduceNumber(writer: anytype, input: usize, comptime unit: usize, comptime base: string, comptime prefixes: string) !void {
if (input < unit) {
try writer.print("{d} {s}", .{ input, base });
}
var div = unit;
var exp: usize = 0;
var n = input / unit;
while (n >= unit) : (n /= unit) {
div *= unit;
exp += 1;
}
try writer.print("{d:.3} {s}{s}", .{ @intToFloat(f64, input) / @intToFloat(f64, div), prefixes[exp..][0..1], base });
}
id: a2g2w2oc7r56kzq49kbqqp6u2v1bu5hgttjt00udpmiwwcse
name: Progress
main: Progress.zig
license: MIT
description: A single line progress bar
dependencies:
- src: git https://github.com/nektro/zig-ansi
- src: git https://github.com/nektro/zig-range
- src: git https://github.com/nektro/zig-extras
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment