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