At https://codeberg.org/ziglang/zig/src/branch/master/lib/std/Io/Terminal.zig#L110, there is try t.writer.writeAll(color_string); in the .escape_codes branch.
In https://codeberg.org/ziglang/zig/src/branch/master/lib/std/Io/Terminal.zig#L136 there is try t.writer.flush(); in the .windows_api branch.
This seems unusual, is there a a reason?
Why not flushing in the .escape_codes branch?
Thanks
Usually after writing a colour code, you want to print some text in that colour too before flushing, so having an immediate flush doesn’t make any sense.
The same doesn’t seem to be true for the windows api - presumably the current colour is applied to the entire flushed buffer at once, necessitating a flush when you want to change colours.
5 Likes
In short: flushing is slow, so this code only flushes in the part it HAS to.
But if the code runs on an Unix system, try t.writer.writeAll(color_string); is not followed by a flush.
Thanks.
Yes exactly, because a flush isn’t needed to make the colour change correctly.
The flush is only needed on windows.
The flush isn’t something the set color function guarantees, just something it is forced to do on windows to work right.
If your code needs a flush, you’re supposed to just do that yourself
Just so we’re on the same page, .windows_api is only used when ANSI escape codes are not supported (that is, .windows_api should rarely be used even on Windows and is purely a fallback; Windows Terminal supports ANSI escape codes).
With ANSI escape codes, the formatting is part of the output, so when a flush happens is irrelevant.
With the fallback Windows API, the formatting is separate from the output, so if you set a color, then anything that’s yet to be flushed will get whatever color is currently set when flushing, which is not what you want.
writeAll("foo");
setColor(.blue);
writeAll("bar");
setColor(.red);
writeAll("baz");
flush();
Without the flush in setColor for .windows_api, this could end up with foobarbaz printed entirely red.
10 Likes
Thanks @squeek502 for more details.
1 Like