diff --git a/lib/std/Progress.zig b/lib/std/Progress.zig index 61c1ee2a32..f0b0e2dbd5 100644 --- a/lib/std/Progress.zig +++ b/lib/std/Progress.zig @@ -210,8 +210,11 @@ fn refreshWithHeldLock(self: *Progress) void { std.debug.assert(self.is_windows_terminal); var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; - if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE) - unreachable; + if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE) { + // stop trying to write to this file + self.terminal = null; + break :winapi; + } var cursor_pos = windows.COORD{ .X = info.dwCursorPosition.X - @intCast(windows.SHORT, self.columns_written), @@ -231,7 +234,7 @@ fn refreshWithHeldLock(self: *Progress) void { cursor_pos, &written, ) != windows.TRUE) { - // Stop trying to write to this file. + // stop trying to write to this file self.terminal = null; break :winapi; } @@ -241,10 +244,16 @@ fn refreshWithHeldLock(self: *Progress) void { fill_chars, cursor_pos, &written, - ) != windows.TRUE) unreachable; - - if (windows.kernel32.SetConsoleCursorPosition(file.handle, cursor_pos) != windows.TRUE) - unreachable; + ) != windows.TRUE) { + // stop trying to write to this file + self.terminal = null; + break :winapi; + } + if (windows.kernel32.SetConsoleCursorPosition(file.handle, cursor_pos) != windows.TRUE) { + // stop trying to write to this file + self.terminal = null; + break :winapi; + } } else { // we are in a "dumb" terminal like in acme or writing to a file self.output_buffer[end] = '\n'; @@ -288,7 +297,7 @@ fn refreshWithHeldLock(self: *Progress) void { } _ = file.write(self.output_buffer[0..end]) catch { - // Stop trying to write to this file once it errors. + // stop trying to write to this file self.terminal = null; }; if (self.timer) |*timer| { diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 545f205634..718812961d 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -119,7 +119,7 @@ pub fn detectTTYConfig() TTY.Config { if (stderr_file.supportsAnsiEscapeCodes()) { return .escape_codes; } else if (native_os == .windows and stderr_file.isTty()) { - return .windows_api; + return .{ .windows_api = stderr_file }; } else { return .no_color; } @@ -415,9 +415,9 @@ pub fn writeStackTrace( if (stack_trace.index > stack_trace.instruction_addresses.len) { const dropped_frames = stack_trace.index - stack_trace.instruction_addresses.len; - tty_config.setColor(out_stream, .Bold); + tty_config.setColor(out_stream, .Bold) catch {}; try out_stream.print("({d} additional stack frames skipped...)\n", .{dropped_frames}); - tty_config.setColor(out_stream, .Reset); + tty_config.setColor(out_stream, .Reset) catch {}; } } @@ -605,59 +605,39 @@ pub const TTY = struct { Reset, }; - pub const Config = enum { + pub const Config = union(enum) { no_color, escape_codes, - // TODO give this a payload of file handle - windows_api, + windows_api: File, - pub fn setColor(conf: Config, out_stream: anytype, color: Color) void { + pub fn setColor(conf: Config, out_stream: anytype, color: Color) !void { nosuspend switch (conf) { .no_color => return, - .escape_codes => switch (color) { - .Red => out_stream.writeAll(RED) catch return, - .Green => out_stream.writeAll(GREEN) catch return, - .Cyan => out_stream.writeAll(CYAN) catch return, - .White => out_stream.writeAll(WHITE) catch return, - .Dim => out_stream.writeAll(DIM) catch return, - .Bold => out_stream.writeAll(BOLD) catch return, - .Reset => out_stream.writeAll(RESET) catch return, - }, - .windows_api => if (native_os == .windows) { - const stderr_file = io.getStdErr(); - const S = struct { - var attrs: windows.WORD = undefined; - var init_attrs = false; + .escape_codes => { + const color_string = switch (color) { + .Red => RED, + .Green => GREEN, + .Cyan => CYAN, + .White => WHITE, + .Dim => DIM, + .Bold => BOLD, + .Reset => RESET, }; - if (!S.init_attrs) { - S.init_attrs = true; - var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; - // TODO handle error - _ = windows.kernel32.GetConsoleScreenBufferInfo(stderr_file.handle, &info); - S.attrs = info.wAttributes; - } - - // TODO handle errors - switch (color) { - .Red => { - _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_INTENSITY) catch {}; - }, - .Green => { - _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY) catch {}; - }, - .Cyan => { - _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {}; - }, - .White, .Bold => { - _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {}; - }, - .Dim => { - _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_INTENSITY) catch {}; - }, - .Reset => { - _ = windows.SetConsoleTextAttribute(stderr_file.handle, S.attrs) catch {}; - }, - } + try out_stream.writeAll(color_string); + }, + .windows_api => |file| if (native_os == .windows) { + var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; + if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE) + return error.FailedRetrievingTerminalInfo; + const attributes = switch (color) { + .Red => windows.FOREGROUND_RED | windows.FOREGROUND_INTENSITY, + .Green => windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY, + .Cyan => windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY, + .White, .Bold => windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY, + .Dim => windows.FOREGROUND_INTENSITY, + .Reset => info.wAttributes, + }; + try windows.SetConsoleTextAttribute(file.handle, attributes); } else { unreachable; }, @@ -751,7 +731,7 @@ fn printLineInfo( comptime printLineFromFile: anytype, ) !void { nosuspend { - tty_config.setColor(out_stream, .Bold); + try tty_config.setColor(out_stream, .Bold); if (line_info) |*li| { try out_stream.print("{s}:{d}:{d}", .{ li.file_name, li.line, li.column }); @@ -759,11 +739,11 @@ fn printLineInfo( try out_stream.writeAll("???:?:?"); } - tty_config.setColor(out_stream, .Reset); + try tty_config.setColor(out_stream, .Reset); try out_stream.writeAll(": "); - tty_config.setColor(out_stream, .Dim); + try tty_config.setColor(out_stream, .Dim); try out_stream.print("0x{x} in {s} ({s})", .{ address, symbol_name, compile_unit_name }); - tty_config.setColor(out_stream, .Reset); + try tty_config.setColor(out_stream, .Reset); try out_stream.writeAll("\n"); // Show the matching source code line if possible @@ -774,9 +754,9 @@ fn printLineInfo( const space_needed = @intCast(usize, li.column - 1); try out_stream.writeByteNTimes(' ', space_needed); - tty_config.setColor(out_stream, .Green); + try tty_config.setColor(out_stream, .Green); try out_stream.writeAll("^"); - tty_config.setColor(out_stream, .Reset); + try tty_config.setColor(out_stream, .Reset); } try out_stream.writeAll("\n"); } else |err| switch (err) { diff --git a/lib/std/testing.zig b/lib/std/testing.zig index 3bb3d6e14b..6a75999f71 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -387,9 +387,9 @@ fn SliceDiffer(comptime T: type) type { for (self.expected) |value, i| { var full_index = self.start_index + i; const diff = if (i < self.actual.len) !std.meta.eql(self.actual[i], value) else true; - if (diff) self.ttyconf.setColor(writer, .Red); + if (diff) try self.ttyconf.setColor(writer, .Red); try writer.print("[{}]: {any}\n", .{ full_index, value }); - if (diff) self.ttyconf.setColor(writer, .Reset); + if (diff) try self.ttyconf.setColor(writer, .Reset); } } }; @@ -427,9 +427,9 @@ const BytesDiffer = struct { } fn writeByteDiff(self: BytesDiffer, writer: anytype, comptime fmt: []const u8, byte: u8, diff: bool) !void { - if (diff) self.ttyconf.setColor(writer, .Red); + if (diff) try self.ttyconf.setColor(writer, .Red); try writer.print(fmt, .{byte}); - if (diff) self.ttyconf.setColor(writer, .Reset); + if (diff) try self.ttyconf.setColor(writer, .Reset); } const ChunkIterator = struct { diff --git a/src/Compilation.zig b/src/Compilation.zig index 06d978ecae..911089df02 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -428,29 +428,29 @@ pub const AllErrors = struct { switch (msg) { .src => |src| { try counting_stderr.writeByteNTimes(' ', indent); - ttyconf.setColor(stderr, .Bold); + try ttyconf.setColor(stderr, .Bold); try counting_stderr.print("{s}:{d}:{d}: ", .{ src.src_path, src.line + 1, src.column + 1, }); - ttyconf.setColor(stderr, color); + try ttyconf.setColor(stderr, color); try counting_stderr.writeAll(kind); try counting_stderr.writeAll(": "); // This is the length of the part before the error message: // e.g. "file.zig:4:5: error: " const prefix_len = @intCast(usize, counting_stderr.context.bytes_written); - ttyconf.setColor(stderr, .Reset); - ttyconf.setColor(stderr, .Bold); + try ttyconf.setColor(stderr, .Reset); + try ttyconf.setColor(stderr, .Bold); if (src.count == 1) { try src.writeMsg(stderr, prefix_len); try stderr.writeByte('\n'); } else { try src.writeMsg(stderr, prefix_len); - ttyconf.setColor(stderr, .Dim); + try ttyconf.setColor(stderr, .Dim); try stderr.print(" ({d} times)\n", .{src.count}); } - ttyconf.setColor(stderr, .Reset); + try ttyconf.setColor(stderr, .Reset); if (src.source_line) |line| { for (line) |b| switch (b) { '\t' => try stderr.writeByte(' '), @@ -462,19 +462,19 @@ pub const AllErrors = struct { // -1 since span.main includes the caret const after_caret = src.span.end - src.span.main -| 1; try stderr.writeByteNTimes(' ', src.column - before_caret); - ttyconf.setColor(stderr, .Green); + try ttyconf.setColor(stderr, .Green); try stderr.writeByteNTimes('~', before_caret); try stderr.writeByte('^'); try stderr.writeByteNTimes('~', after_caret); try stderr.writeByte('\n'); - ttyconf.setColor(stderr, .Reset); + try ttyconf.setColor(stderr, .Reset); } for (src.notes) |note| { try note.renderToWriter(ttyconf, stderr, "note", .Cyan, indent); } if (src.reference_trace.len != 0) { - ttyconf.setColor(stderr, .Reset); - ttyconf.setColor(stderr, .Dim); + try ttyconf.setColor(stderr, .Reset); + try ttyconf.setColor(stderr, .Dim); try stderr.print("referenced by:\n", .{}); for (src.reference_trace) |reference| { switch (reference) { @@ -498,23 +498,23 @@ pub const AllErrors = struct { } } try stderr.writeByte('\n'); - ttyconf.setColor(stderr, .Reset); + try ttyconf.setColor(stderr, .Reset); } }, .plain => |plain| { - ttyconf.setColor(stderr, color); + try ttyconf.setColor(stderr, color); try stderr.writeByteNTimes(' ', indent); try stderr.writeAll(kind); try stderr.writeAll(": "); - ttyconf.setColor(stderr, .Reset); + try ttyconf.setColor(stderr, .Reset); if (plain.count == 1) { try stderr.print("{s}\n", .{plain.msg}); } else { try stderr.print("{s}", .{plain.msg}); - ttyconf.setColor(stderr, .Dim); + try ttyconf.setColor(stderr, .Dim); try stderr.print(" ({d} times)\n", .{plain.count}); } - ttyconf.setColor(stderr, .Reset); + try ttyconf.setColor(stderr, .Reset); for (plain.notes) |note| { try note.renderToWriter(ttyconf, stderr, "note", .Cyan, indent + 4); }