mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
Add File.getOrEnableAnsiEscapeSupport and use it
On Windows, the console mode flag `ENABLE_VIRTUAL_TERMINAL_PROCESSING` determines whether or not ANSI escape codes are parsed/acted on. On the newer Windows Terminal, this flag is set by default, but on the older Windows Console, it is not set by default, but *can* be enabled (since Windows 10 RS1 from June 2016). The new `File.getOrEnableAnsiEscapeSupport` function will get the current status of ANSI escape code support, but will also attempt to enable `ENABLE_VIRTUAL_TERMINAL_PROCESSING` on Windows if necessary which will provide better/more consistent results for things like `std.Progress` and `std.io.tty`. This type of change was not done previously due to a mistaken assumption (on my part) that the console mode would persist after the run of a program. However, it turns out that the console mode is always reset to the default for each program run in a console session.
This commit is contained in:
parent
17dc939346
commit
337f09e932
@ -377,7 +377,7 @@ pub fn start(options: Options) Node {
|
|||||||
}
|
}
|
||||||
const stderr = std.io.getStdErr();
|
const stderr = std.io.getStdErr();
|
||||||
global_progress.terminal = stderr;
|
global_progress.terminal = stderr;
|
||||||
if (stderr.supportsAnsiEscapeCodes()) {
|
if (stderr.getOrEnableAnsiEscapeSupport()) {
|
||||||
global_progress.terminal_mode = .ansi_escape_codes;
|
global_progress.terminal_mode = .ansi_escape_codes;
|
||||||
} else if (is_windows and stderr.isTty()) {
|
} else if (is_windows and stderr.isTty()) {
|
||||||
global_progress.terminal_mode = TerminalMode{ .windows_api = .{
|
global_progress.terminal_mode = TerminalMode{ .windows_api = .{
|
||||||
|
|||||||
@ -188,7 +188,7 @@ pub fn sync(self: File) SyncError!void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Test whether the file refers to a terminal.
|
/// Test whether the file refers to a terminal.
|
||||||
/// See also `supportsAnsiEscapeCodes`.
|
/// See also `getOrEnableAnsiEscapeSupport` and `supportsAnsiEscapeCodes`.
|
||||||
pub fn isTty(self: File) bool {
|
pub fn isTty(self: File) bool {
|
||||||
return posix.isatty(self.handle);
|
return posix.isatty(self.handle);
|
||||||
}
|
}
|
||||||
@ -245,8 +245,16 @@ pub fn isCygwinPty(file: File) bool {
|
|||||||
std.mem.indexOf(u16, name_wide, &[_]u16{ '-', 'p', 't', 'y' }) != null;
|
std.mem.indexOf(u16, name_wide, &[_]u16{ '-', 'p', 't', 'y' }) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test whether ANSI escape codes will be treated as such.
|
/// Returns whether or not ANSI escape codes will be treated as such,
|
||||||
pub fn supportsAnsiEscapeCodes(self: File) bool {
|
/// and attempts to enable support for ANSI escape codes if necessary
|
||||||
|
/// (on Windows).
|
||||||
|
///
|
||||||
|
/// Returns `true` if ANSI escape codes are supported or support was
|
||||||
|
/// successfully enabled. Returns false if ANSI escape codes are not
|
||||||
|
/// supported or support was unable to be enabled.
|
||||||
|
///
|
||||||
|
/// See also `supportsAnsiEscapeCodes`.
|
||||||
|
pub fn getOrEnableAnsiEscapeSupport(self: File) bool {
|
||||||
if (builtin.os.tag == .windows) {
|
if (builtin.os.tag == .windows) {
|
||||||
var original_console_mode: windows.DWORD = 0;
|
var original_console_mode: windows.DWORD = 0;
|
||||||
|
|
||||||
@ -262,7 +270,8 @@ pub fn supportsAnsiEscapeCodes(self: File) bool {
|
|||||||
var console_mode = original_console_mode | requested_console_modes;
|
var console_mode = original_console_mode | requested_console_modes;
|
||||||
if (windows.kernel32.SetConsoleMode(self.handle, console_mode) != 0) return true;
|
if (windows.kernel32.SetConsoleMode(self.handle, console_mode) != 0) return true;
|
||||||
|
|
||||||
// An application receiving ERROR_INVALID_PARAMETER with one of the newer console mode flags in the bit field should gracefully degrade behavior and try again.
|
// An application receiving ERROR_INVALID_PARAMETER with one of the newer console mode
|
||||||
|
// flags in the bit field should gracefully degrade behavior and try again.
|
||||||
requested_console_modes = windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
requested_console_modes = windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||||
console_mode = original_console_mode | requested_console_modes;
|
console_mode = original_console_mode | requested_console_modes;
|
||||||
if (windows.kernel32.SetConsoleMode(self.handle, console_mode) != 0) return true;
|
if (windows.kernel32.SetConsoleMode(self.handle, console_mode) != 0) return true;
|
||||||
@ -270,6 +279,22 @@ pub fn supportsAnsiEscapeCodes(self: File) bool {
|
|||||||
|
|
||||||
return self.isCygwinPty();
|
return self.isCygwinPty();
|
||||||
}
|
}
|
||||||
|
return self.supportsAnsiEscapeCodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test whether ANSI escape codes will be treated as such without
|
||||||
|
/// attempting to enable support for ANSI escape codes.
|
||||||
|
///
|
||||||
|
/// See also `getOrEnableAnsiEscapeSupport`.
|
||||||
|
pub fn supportsAnsiEscapeCodes(self: File) bool {
|
||||||
|
if (builtin.os.tag == .windows) {
|
||||||
|
var console_mode: windows.DWORD = 0;
|
||||||
|
if (windows.kernel32.GetConsoleMode(self.handle, &console_mode) != 0) {
|
||||||
|
if (console_mode & windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING != 0) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.isCygwinPty();
|
||||||
|
}
|
||||||
if (builtin.os.tag == .wasi) {
|
if (builtin.os.tag == .wasi) {
|
||||||
// WASI sanitizes stdout when fd is a tty so ANSI escape codes
|
// WASI sanitizes stdout when fd is a tty so ANSI escape codes
|
||||||
// will not be interpreted as actual cursor commands, and
|
// will not be interpreted as actual cursor commands, and
|
||||||
|
|||||||
@ -8,6 +8,7 @@ const native_os = builtin.os.tag;
|
|||||||
/// Detect suitable TTY configuration options for the given file (commonly stdout/stderr).
|
/// Detect suitable TTY configuration options for the given file (commonly stdout/stderr).
|
||||||
/// This includes feature checks for ANSI escape codes and the Windows console API, as well as
|
/// This includes feature checks for ANSI escape codes and the Windows console API, as well as
|
||||||
/// respecting the `NO_COLOR` and `CLICOLOR_FORCE` environment variables to override the default.
|
/// respecting the `NO_COLOR` and `CLICOLOR_FORCE` environment variables to override the default.
|
||||||
|
/// Will attempt to enable ANSI escape code support if necessary/possible.
|
||||||
pub fn detectConfig(file: File) Config {
|
pub fn detectConfig(file: File) Config {
|
||||||
const force_color: ?bool = if (builtin.os.tag == .wasi)
|
const force_color: ?bool = if (builtin.os.tag == .wasi)
|
||||||
null // wasi does not support environment variables
|
null // wasi does not support environment variables
|
||||||
@ -20,7 +21,7 @@ pub fn detectConfig(file: File) Config {
|
|||||||
|
|
||||||
if (force_color == false) return .no_color;
|
if (force_color == false) return .no_color;
|
||||||
|
|
||||||
if (file.supportsAnsiEscapeCodes()) return .escape_codes;
|
if (file.getOrEnableAnsiEscapeSupport()) return .escape_codes;
|
||||||
|
|
||||||
if (native_os == .windows and file.isTty()) {
|
if (native_os == .windows and file.isTty()) {
|
||||||
var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
|
var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user