"{q}" prints strings nicely but what about a single character?

test "print u8 with {q}" {
    const expected: u8 = 'a';
    const actual: u8 = '\t';

    // this does not compile
    // errdefer std.debug.print("expected {q}, found {q}\n", .{
    //     expected,
    //     actual,
    // });

    // this does not escape control characters
    errdefer std.debug.print("expected '{c}', found '{c}'\n", .{
        expected,
        actual,
    });

    // this prints double quotes instead of single quotes
    errdefer std.debug.print("expected {q}, found {q}\n", .{
        (&expected)[0..1],
        (&actual)[0..1],
    });

    // this prints numbers instead of characters
    try std.testing.expectEqual(expected, actual);
}

It would be nice to print ASCII characters with "{qc}" and Unicode with "{qu}". Is this already planned? Did I miss the announcement?

Edit: I fail to understand "{u}" documentation. How can a 21-bit integer be an UTF-8 sequence?

a utf-8 sequence is 1-4 bytes, that is 8-32 bits, some of which encode the length and indicate bytes that are part of a larger sequence, the larger 4 byte sequence has 24 bits of usable values.

You also have it backwards, utf-8 is an encoding for a sequence of 21 bit unicode code points.


to actually answer your question:you can implement it yourself, ofc re-using code from std.Io.Writer.printStringEscaped

And for other reference, there is a {qf} specifier to call a format function with a std.zig.StringEscapeWriter (just a writer implementation, dont need to change fn signature), however print still writes the "" around it. So it doesnt help this case.

3 Likes
std.debug.print("expected '{f}', found '{f}'\n", .{
    std.zig.fmtChar(expected),
    std.zig.fmtChar(actual),
});
expected 'a', found '\t'
6 Likes