From d8b4588d5fe685637ebbbb57c139aca7fb12ddf5 Mon Sep 17 00:00:00 2001 From: r00ster91 Date: Sat, 30 Jul 2022 14:13:53 +0200 Subject: [PATCH 1/3] fix(terminal): handle some possible errors and resolve TODOs --- lib/std/Progress.zig | 25 ++++++++---- lib/std/debug.zig | 92 +++++++++++++++++--------------------------- lib/std/testing.zig | 8 ++-- src/Compilation.zig | 30 +++++++-------- 4 files changed, 72 insertions(+), 83 deletions(-) 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); } From d0d845a25b897a8db37b0f60d5ec313f6b56943f Mon Sep 17 00:00:00 2001 From: r00ster91 Date: Sat, 30 Jul 2022 14:46:55 +0200 Subject: [PATCH 2/3] cleanup: inline color constants Originally I just wanted to move these down because they seemed to be in some random position of the file, but these constants look very old with their CASING and pretty unnecessary anyway so I just inlined them. --- lib/std/debug.zig | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 718812961d..da78d4ee95 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -384,14 +384,6 @@ pub fn panicImpl(trace: ?*const std.builtin.StackTrace, first_trace_addr: ?usize os.abort(); } -const RED = "\x1b[31;1m"; -const GREEN = "\x1b[32;1m"; -const CYAN = "\x1b[36;1m"; -const WHITE = "\x1b[37;1m"; -const BOLD = "\x1b[1m"; -const DIM = "\x1b[2m"; -const RESET = "\x1b[0m"; - pub fn writeStackTrace( stack_trace: std.builtin.StackTrace, out_stream: anytype, @@ -615,13 +607,13 @@ pub const TTY = struct { .no_color => return, .escape_codes => { const color_string = switch (color) { - .Red => RED, - .Green => GREEN, - .Cyan => CYAN, - .White => WHITE, - .Dim => DIM, - .Bold => BOLD, - .Reset => RESET, + .Red => "\x1b[31;1m", + .Green => "\x1b[32;1m", + .Cyan => "\x1b[36;1m", + .White => "\x1b[37;1m", + .Bold => "\x1b[1m", + .Dim => "\x1b[2m", + .Reset => "\x1b[0m", }; try out_stream.writeAll(color_string); }, From 7561f63b5d93fb32b39410590625bb16bf2ac0dd Mon Sep 17 00:00:00 2001 From: r00ster91 Date: Mon, 31 Oct 2022 19:43:41 +0100 Subject: [PATCH 3/3] std.debug: use OpenSelfDebugInfoError --- lib/std/debug.zig | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/std/debug.zig b/lib/std/debug.zig index da78d4ee95..c48324422d 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -761,14 +761,12 @@ fn printLineInfo( } } -// TODO use this pub const OpenSelfDebugInfoError = error{ MissingDebugInfo, - OutOfMemory, UnsupportedOperatingSystem, }; -pub fn openSelfDebugInfo(allocator: mem.Allocator) anyerror!DebugInfo { +pub fn openSelfDebugInfo(allocator: mem.Allocator) OpenSelfDebugInfoError!DebugInfo { nosuspend { if (builtin.strip_debug_info) return error.MissingDebugInfo; @@ -785,7 +783,7 @@ pub fn openSelfDebugInfo(allocator: mem.Allocator) anyerror!DebugInfo { .windows, .solaris, => return DebugInfo.init(allocator), - else => return error.UnsupportedDebugInfo, + else => return error.UnsupportedOperatingSystem, } } }