| author | |
| committer | |
| log | 88d927a511922efd82c4ec862c8e2aa83df84391 |
| tree | 16449de5465989e1e3f8ae7894b5544cd9491109 |
| parent | 83e0e23f8aa2d90495bbf9c3649aa68f7c55c926 |
This fixes a regression introduced in #12298 where colors would never reset in a Windows console because the attributes would be queried on every `setColor` call, and then try to 'reset' the attributes to what it just queried (i.e. it was essentially doing a complicated no-op on .Reset).
This fixes the problem while (I think) keeping with the spirit of the changes in #12298--that is, `TTY.Config` is not specifically tied to stderr like it was before #12298. To that end, detectTTYConfig now takes a `File` and that's what gets used to query the initial attributes to reset to.
(for context, before #12298, the first `setColor` call is where the reset attributes would get queried and it would always use stderr to do it)4 files changed, 35 insertions(+), 26 deletions(-)
lib/std/builtin.zig+1-1| ... | @@ -51,7 +51,7 @@ pub const StackTrace = struct { | ... | @@ -51,7 +51,7 @@ pub const StackTrace = struct { |
| 51 | const debug_info = std.debug.getSelfDebugInfo() catch |err| { | 51 | const debug_info = std.debug.getSelfDebugInfo() catch |err| { |
| 52 | return writer.print("\nUnable to print stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}); | 52 | return writer.print("\nUnable to print stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}); |
| 53 | }; | 53 | }; |
| 54 | const tty_config = std.debug.detectTTYConfig(); | 54 | const tty_config = std.debug.detectTTYConfig(std.io.getStdErr()); |
| 55 | try writer.writeAll("\n"); | 55 | try writer.writeAll("\n"); |
| 56 | std.debug.writeStackTrace(self, writer, arena.allocator(), debug_info, tty_config) catch |err| { | 56 | std.debug.writeStackTrace(self, writer, arena.allocator(), debug_info, tty_config) catch |err| { |
| 57 | try writer.print("Unable to print stack trace: {s}\n", .{@errorName(err)}); | 57 | try writer.print("Unable to print stack trace: {s}\n", .{@errorName(err)}); |
lib/std/debug.zig+26-17| ... | @@ -109,17 +109,24 @@ pub fn getSelfDebugInfo() !*DebugInfo { | ... | @@ -109,17 +109,24 @@ pub fn getSelfDebugInfo() !*DebugInfo { |
| 109 | } | 109 | } |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | pub fn detectTTYConfig() TTY.Config { | 112 | pub fn detectTTYConfig(file: std.fs.File) TTY.Config { |
| 113 | if (process.hasEnvVarConstant("ZIG_DEBUG_COLOR")) { | 113 | if (process.hasEnvVarConstant("ZIG_DEBUG_COLOR")) { |
| 114 | return .escape_codes; | 114 | return .escape_codes; |
| 115 | } else if (process.hasEnvVarConstant("NO_COLOR")) { | 115 | } else if (process.hasEnvVarConstant("NO_COLOR")) { |
| 116 | return .no_color; | 116 | return .no_color; |
| 117 | } else { | 117 | } else { |
| 118 | const stderr_file = io.getStdErr(); | 118 | if (file.supportsAnsiEscapeCodes()) { |
| 119 | if (stderr_file.supportsAnsiEscapeCodes()) { | ||
| 120 | return .escape_codes; | 119 | return .escape_codes; |
| 121 | } else if (native_os == .windows and stderr_file.isTty()) { | 120 | } else if (native_os == .windows and file.isTty()) { |
| 122 | return .{ .windows_api = stderr_file }; | 121 | var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; |
| 122 | if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE) { | ||
| 123 | // TODO: Should this return an error instead? | ||
| 124 | return .no_color; | ||
| 125 | } | ||
| 126 | return .{ .windows_api = .{ | ||
| 127 | .handle = file.handle, | ||
| 128 | .reset_attributes = info.wAttributes, | ||
| 129 | } }; | ||
| 123 | } else { | 130 | } else { |
| 124 | return .no_color; | 131 | return .no_color; |
| 125 | } | 132 | } |
| ... | @@ -146,7 +153,7 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void { | ... | @@ -146,7 +153,7 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void { |
| 146 | stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return; | 153 | stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return; |
| 147 | return; | 154 | return; |
| 148 | }; | 155 | }; |
| 149 | writeCurrentStackTrace(stderr, debug_info, detectTTYConfig(), start_addr) catch |err| { | 156 | writeCurrentStackTrace(stderr, debug_info, detectTTYConfig(io.getStdErr()), start_addr) catch |err| { |
| 150 | stderr.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return; | 157 | stderr.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return; |
| 151 | return; | 158 | return; |
| 152 | }; | 159 | }; |
| ... | @@ -174,7 +181,7 @@ pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void { | ... | @@ -174,7 +181,7 @@ pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void { |
| 174 | stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return; | 181 | stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return; |
| 175 | return; | 182 | return; |
| 176 | }; | 183 | }; |
| 177 | const tty_config = detectTTYConfig(); | 184 | const tty_config = detectTTYConfig(io.getStdErr()); |
| 178 | printSourceAtAddress(debug_info, stderr, ip, tty_config) catch return; | 185 | printSourceAtAddress(debug_info, stderr, ip, tty_config) catch return; |
| 179 | var it = StackIterator.init(null, bp); | 186 | var it = StackIterator.init(null, bp); |
| 180 | while (it.next()) |return_address| { | 187 | while (it.next()) |return_address| { |
| ... | @@ -257,7 +264,7 @@ pub fn dumpStackTrace(stack_trace: std.builtin.StackTrace) void { | ... | @@ -257,7 +264,7 @@ pub fn dumpStackTrace(stack_trace: std.builtin.StackTrace) void { |
| 257 | stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return; | 264 | stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return; |
| 258 | return; | 265 | return; |
| 259 | }; | 266 | }; |
| 260 | writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, detectTTYConfig()) catch |err| { | 267 | writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, detectTTYConfig(io.getStdErr())) catch |err| { |
| 261 | stderr.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return; | 268 | stderr.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return; |
| 262 | return; | 269 | return; |
| 263 | }; | 270 | }; |
| ... | @@ -600,7 +607,12 @@ pub const TTY = struct { | ... | @@ -600,7 +607,12 @@ pub const TTY = struct { |
| 600 | pub const Config = union(enum) { | 607 | pub const Config = union(enum) { |
| 601 | no_color, | 608 | no_color, |
| 602 | escape_codes, | 609 | escape_codes, |
| 603 | windows_api: File, | 610 | windows_api: if (native_os == .windows) WindowsContext else void, |
| 611 | |||
| 612 | pub const WindowsContext = struct { | ||
| 613 | handle: File.Handle, | ||
| 614 | reset_attributes: u16, | ||
| 615 | }; | ||
| 604 | 616 | ||
| 605 | pub fn setColor(conf: Config, out_stream: anytype, color: Color) !void { | 617 | pub fn setColor(conf: Config, out_stream: anytype, color: Color) !void { |
| 606 | nosuspend switch (conf) { | 618 | nosuspend switch (conf) { |
| ... | @@ -617,19 +629,16 @@ pub const TTY = struct { | ... | @@ -617,19 +629,16 @@ pub const TTY = struct { |
| 617 | }; | 629 | }; |
| 618 | try out_stream.writeAll(color_string); | 630 | try out_stream.writeAll(color_string); |
| 619 | }, | 631 | }, |
| 620 | .windows_api => |file| if (native_os == .windows) { | 632 | .windows_api => |ctx| if (native_os == .windows) { |
| 621 | var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; | ||
| 622 | if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE) | ||
| 623 | return error.FailedRetrievingTerminalInfo; | ||
| 624 | const attributes = switch (color) { | 633 | const attributes = switch (color) { |
| 625 | .Red => windows.FOREGROUND_RED | windows.FOREGROUND_INTENSITY, | 634 | .Red => windows.FOREGROUND_RED | windows.FOREGROUND_INTENSITY, |
| 626 | .Green => windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY, | 635 | .Green => windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY, |
| 627 | .Cyan => windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY, | 636 | .Cyan => windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY, |
| 628 | .White, .Bold => windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY, | 637 | .White, .Bold => windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY, |
| 629 | .Dim => windows.FOREGROUND_INTENSITY, | 638 | .Dim => windows.FOREGROUND_INTENSITY, |
| 630 | .Reset => info.wAttributes, | 639 | .Reset => ctx.reset_attributes, |
| 631 | }; | 640 | }; |
| 632 | try windows.SetConsoleTextAttribute(file.handle, attributes); | 641 | try windows.SetConsoleTextAttribute(ctx.handle, attributes); |
| 633 | } else { | 642 | } else { |
| 634 | unreachable; | 643 | unreachable; |
| 635 | }, | 644 | }, |
| ... | @@ -2005,7 +2014,7 @@ test "#4353: std.debug should manage resources correctly" { | ... | @@ -2005,7 +2014,7 @@ test "#4353: std.debug should manage resources correctly" { |
| 2005 | const writer = std.io.null_writer; | 2014 | const writer = std.io.null_writer; |
| 2006 | var di = try openSelfDebugInfo(testing.allocator); | 2015 | var di = try openSelfDebugInfo(testing.allocator); |
| 2007 | defer di.deinit(); | 2016 | defer di.deinit(); |
| 2008 | try printSourceAtAddress(&di, writer, showMyTrace(), detectTTYConfig()); | 2017 | try printSourceAtAddress(&di, writer, showMyTrace(), detectTTYConfig(std.io.getStdErr())); |
| 2009 | } | 2018 | } |
| 2010 | 2019 | ||
| 2011 | noinline fn showMyTrace() usize { | 2020 | noinline fn showMyTrace() usize { |
| ... | @@ -2065,7 +2074,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize | ... | @@ -2065,7 +2074,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize |
| 2065 | pub fn dump(t: @This()) void { | 2074 | pub fn dump(t: @This()) void { |
| 2066 | if (!enabled) return; | 2075 | if (!enabled) return; |
| 2067 | 2076 | ||
| 2068 | const tty_config = detectTTYConfig(); | 2077 | const tty_config = detectTTYConfig(std.io.getStdErr()); |
| 2069 | const stderr = io.getStdErr().writer(); | 2078 | const stderr = io.getStdErr().writer(); |
| 2070 | const end = @min(t.index, size); | 2079 | const end = @min(t.index, size); |
| 2071 | const debug_info = getSelfDebugInfo() catch |err| { | 2080 | const debug_info = getSelfDebugInfo() catch |err| { |
lib/std/testing.zig+1-1| ... | @@ -312,7 +312,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const | ... | @@ -312,7 +312,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const |
| 312 | const actual_window = actual[window_start..@min(actual.len, window_start + max_window_size)]; | 312 | const actual_window = actual[window_start..@min(actual.len, window_start + max_window_size)]; |
| 313 | const actual_truncated = window_start + actual_window.len < actual.len; | 313 | const actual_truncated = window_start + actual_window.len < actual.len; |
| 314 | 314 | ||
| 315 | const ttyconf = std.debug.detectTTYConfig(); | 315 | const ttyconf = std.debug.detectTTYConfig(std.io.getStdErr()); |
| 316 | var differ = if (T == u8) BytesDiffer{ | 316 | var differ = if (T == u8) BytesDiffer{ |
| 317 | .expected = expected_window, | 317 | .expected = expected_window, |
| 318 | .actual = actual_window, | 318 | .actual = actual_window, |
src/main.zig+7-7| ... | @@ -3431,7 +3431,7 @@ fn updateModule(gpa: Allocator, comp: *Compilation, hook: AfterUpdateHook) !void | ... | @@ -3431,7 +3431,7 @@ fn updateModule(gpa: Allocator, comp: *Compilation, hook: AfterUpdateHook) !void |
| 3431 | 3431 | ||
| 3432 | if (errors.list.len != 0) { | 3432 | if (errors.list.len != 0) { |
| 3433 | const ttyconf: std.debug.TTY.Config = switch (comp.color) { | 3433 | const ttyconf: std.debug.TTY.Config = switch (comp.color) { |
| 3434 | .auto => std.debug.detectTTYConfig(), | 3434 | .auto => std.debug.detectTTYConfig(std.io.getStdErr()), |
| 3435 | .on => .escape_codes, | 3435 | .on => .escape_codes, |
| 3436 | .off => .no_color, | 3436 | .off => .no_color, |
| 3437 | }; | 3437 | }; |
| ... | @@ -4252,7 +4252,7 @@ pub fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void | ... | @@ -4252,7 +4252,7 @@ pub fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void |
| 4252 | 4252 | ||
| 4253 | try Compilation.AllErrors.addZir(arena_instance.allocator(), &errors, &file); | 4253 | try Compilation.AllErrors.addZir(arena_instance.allocator(), &errors, &file); |
| 4254 | const ttyconf: std.debug.TTY.Config = switch (color) { | 4254 | const ttyconf: std.debug.TTY.Config = switch (color) { |
| 4255 | .auto => std.debug.detectTTYConfig(), | 4255 | .auto => std.debug.detectTTYConfig(std.io.getStdErr()), |
| 4256 | .on => .escape_codes, | 4256 | .on => .escape_codes, |
| 4257 | .off => .no_color, | 4257 | .off => .no_color, |
| 4258 | }; | 4258 | }; |
| ... | @@ -4465,7 +4465,7 @@ fn fmtPathFile( | ... | @@ -4465,7 +4465,7 @@ fn fmtPathFile( |
| 4465 | 4465 | ||
| 4466 | try Compilation.AllErrors.addZir(arena_instance.allocator(), &errors, &file); | 4466 | try Compilation.AllErrors.addZir(arena_instance.allocator(), &errors, &file); |
| 4467 | const ttyconf: std.debug.TTY.Config = switch (fmt.color) { | 4467 | const ttyconf: std.debug.TTY.Config = switch (fmt.color) { |
| 4468 | .auto => std.debug.detectTTYConfig(), | 4468 | .auto => std.debug.detectTTYConfig(std.io.getStdErr()), |
| 4469 | .on => .escape_codes, | 4469 | .on => .escape_codes, |
| 4470 | .off => .no_color, | 4470 | .off => .no_color, |
| 4471 | }; | 4471 | }; |
| ... | @@ -4586,7 +4586,7 @@ fn printErrsMsgToStdErr( | ... | @@ -4586,7 +4586,7 @@ fn printErrsMsgToStdErr( |
| 4586 | }; | 4586 | }; |
| 4587 | 4587 | ||
| 4588 | const ttyconf: std.debug.TTY.Config = switch (color) { | 4588 | const ttyconf: std.debug.TTY.Config = switch (color) { |
| 4589 | .auto => std.debug.detectTTYConfig(), | 4589 | .auto => std.debug.detectTTYConfig(std.io.getStdErr()), |
| 4590 | .on => .escape_codes, | 4590 | .on => .escape_codes, |
| 4591 | .off => .no_color, | 4591 | .off => .no_color, |
| 4592 | }; | 4592 | }; |
| ... | @@ -5176,7 +5176,7 @@ pub fn cmdAstCheck( | ... | @@ -5176,7 +5176,7 @@ pub fn cmdAstCheck( |
| 5176 | var errors = std.ArrayList(Compilation.AllErrors.Message).init(arena); | 5176 | var errors = std.ArrayList(Compilation.AllErrors.Message).init(arena); |
| 5177 | try Compilation.AllErrors.addZir(arena, &errors, &file); | 5177 | try Compilation.AllErrors.addZir(arena, &errors, &file); |
| 5178 | const ttyconf: std.debug.TTY.Config = switch (color) { | 5178 | const ttyconf: std.debug.TTY.Config = switch (color) { |
| 5179 | .auto => std.debug.detectTTYConfig(), | 5179 | .auto => std.debug.detectTTYConfig(std.io.getStdErr()), |
| 5180 | .on => .escape_codes, | 5180 | .on => .escape_codes, |
| 5181 | .off => .no_color, | 5181 | .off => .no_color, |
| 5182 | }; | 5182 | }; |
| ... | @@ -5301,7 +5301,7 @@ pub fn cmdChangelist( | ... | @@ -5301,7 +5301,7 @@ pub fn cmdChangelist( |
| 5301 | if (file.zir.hasCompileErrors()) { | 5301 | if (file.zir.hasCompileErrors()) { |
| 5302 | var errors = std.ArrayList(Compilation.AllErrors.Message).init(arena); | 5302 | var errors = std.ArrayList(Compilation.AllErrors.Message).init(arena); |
| 5303 | try Compilation.AllErrors.addZir(arena, &errors, &file); | 5303 | try Compilation.AllErrors.addZir(arena, &errors, &file); |
| 5304 | const ttyconf = std.debug.detectTTYConfig(); | 5304 | const ttyconf = std.debug.detectTTYConfig(std.io.getStdErr()); |
| 5305 | for (errors.items) |full_err_msg| { | 5305 | for (errors.items) |full_err_msg| { |
| 5306 | full_err_msg.renderToStdErr(ttyconf); | 5306 | full_err_msg.renderToStdErr(ttyconf); |
| 5307 | } | 5307 | } |
| ... | @@ -5340,7 +5340,7 @@ pub fn cmdChangelist( | ... | @@ -5340,7 +5340,7 @@ pub fn cmdChangelist( |
| 5340 | if (file.zir.hasCompileErrors()) { | 5340 | if (file.zir.hasCompileErrors()) { |
| 5341 | var errors = std.ArrayList(Compilation.AllErrors.Message).init(arena); | 5341 | var errors = std.ArrayList(Compilation.AllErrors.Message).init(arena); |
| 5342 | try Compilation.AllErrors.addZir(arena, &errors, &file); | 5342 | try Compilation.AllErrors.addZir(arena, &errors, &file); |
| 5343 | const ttyconf = std.debug.detectTTYConfig(); | 5343 | const ttyconf = std.debug.detectTTYConfig(std.io.getStdErr()); |
| 5344 | for (errors.items) |full_err_msg| { | 5344 | for (errors.items) |full_err_msg| { |
| 5345 | full_err_msg.renderToStdErr(ttyconf); | 5345 | full_err_msg.renderToStdErr(ttyconf); |
| 5346 | } | 5346 | } |