Twirl – Loading Spinners Galore!

I wrote a small library to display loading spinners in the terminal and I’d like to share it with you :slight_smile:

Before I waffle about it, here is a quick demo:
showcase

Twirl comes with several different loading spinner styles, most of which are featured in the GIF you see up above.

Usage looks something like this:

pub fn main() !void {
    var writer = std.fs.File.stdout().writer("");

    // This is where you choose the visual style of the spinner.
    //                               VVVVVVVVVV
    var spinner: twirl.Spinner = .of(.ascii_bar);

    // This sets the framerate. You can also use `loopsPerMinute`.
    //      VVVVVVVVVVVVVVVVVVV
    spinner.framesPerSecond(10);

    // This waits for the next frame before continuing.
    //                      VVVVVVVVVVVVV
    while (true) : (spinner.waitAndNext()) {

        // Spinners can be printed to the console using the `{f}` formatter:
        try writer.interface.print(at(1, 1) ++ "{f} Waiting for file 'test' to exist...", .{spinner});

        std.fs.cwd().access("test", .{}) catch |e| switch (e) {
            error.FileNotFound => continue,
            else => return e,
        };

        try writer.interface.writeAll("Found it!");

        break;
    }
}

/// Move terminal cursor to specified row and column.
fn at(comptime x: usize, comptime y: usize) []const u8 {
    return std.fmt.comptimePrint("\x1B[{d};{d}H", .{ y, x });
}

There are three modes of usage, which are best explained by taking a look at the examples. examples/showcase.zig produces what is shown in the GIF above. The other three examples show you how to use twirl.

There shouldn’t be a situation where twirl can’t work. If there is, let me know!

Also, if you have a style in mind that I haven’t implemented yet, please tell me about it! I’d like to add more styles :slight_smile:

Anyway, let me know what you think of the project and of the code. Feedback much appreciated!

5 Likes