Printing and formatting

In Zig we can write a format function in our structs which leads to convenient code.

// nice and clear
lib.io.print_buffered("bestmove {f}\n", .{ self.selected_move });

My lib.io struct has some functions using the io interface.

But now I need to format my Move struct with using a option (bool).
So I cannot use the standard format any longer which makes me contort into:

// not nice and unclear.
lib.io.print_buffered("bestmove ", .{} );
self.selected_move.print_buffered(pos.is_960); // dependancy on bool, prints to lib.io buffered
lib.io.print_buffered("\n", .{});

How to solve that mess?

The release notes for 0.15.1 give some options for how to do this. Here is an example of method 2 Ive used to provide indent context:

// Here I provide a context Type Generating function, This is useful so that I can
// Use my Indent code with multiple types that will need to be indented. May
// Not be necessary for you.
fn IndentContext(T: type) type {
    return struct { data: T, indent: u8 };
}

// This is the function that will be used in the print function (see below)
fn formatExtraWithIndent(ctx: std.ArrayListUnmanaged(u64), indent: u8) std.fmt.Alt(
    IndentContext(std.ArrayListUnmanaged(u64)),
    formatExtra,
) {
    return .{ .data = .{ .data = ctx, .indent = indent } };
}

// Here is the format method that is delegated to when
// I call the format function. ExtraData is just an ArraList(u64)
pub fn formatExtra(
    ctx: IndentContext(std.ArrayListUnmanaged(u64)),
    w: *std.Io.Writer,
) std.Io.Writer.Error!void {
    const extra = ctx.data;
    try w.writeAll("ExtraData {\n");
    for (extra.items, 0..) |item, i| {
        try w.splatByteAll(' ', ctx.indent);
        try w.print("    index: {}, value: {},\n", .{ i, item });
    }
    try w.splatByteAll(' ', ctx.indent);
    try w.writeAll("}\n");
}
/// Later in my code i can call this:

try w.print("    .extra: {f}\n", .{formatExtraWithIndent(self.extra, 4)});
3 Likes

Oho thanks. I will dive into that!

1 Like