Commit e2b954c273

Martin Wickham <spexguy070@gmail.com>
2021-06-21 20:47:38
Add support for NO_COLOR
1 parent 7bdeda8
Changed files (7)
lib/std/special/build_runner.zig
@@ -63,6 +63,11 @@ pub fn main() !void {
     var install_prefix: ?[]const u8 = null;
     var dir_list = Builder.DirList{};
 
+    // before arg parsing, check for the NO_COLOR environment variable
+    // if it exists, default the color setting to .off
+    // explicit --color arguments will still override this setting.
+    builder.color = if (std.process.hasEnvVarConstant("NO_COLOR")) .off else .auto;
+
     while (nextArg(args, &arg_idx)) |arg| {
         if (mem.startsWith(u8, arg, "-D")) {
             const option_contents = arg[2..];
lib/std/debug.zig
@@ -90,11 +90,11 @@ pub fn getSelfDebugInfo() !*DebugInfo {
 }
 
 pub fn detectTTYConfig() TTY.Config {
-    var bytes: [128]u8 = undefined;
-    const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
-    if (process.getEnvVarOwned(allocator, "ZIG_DEBUG_COLOR")) |_| {
+    if (process.hasEnvVarConstant("ZIG_DEBUG_COLOR")) {
         return .escape_codes;
-    } else |_| {
+    } else if (process.hasEnvVarConstant("NO_COLOR")) {
+        return .no_color;
+    } else {
         const stderr_file = io.getStdErr();
         if (stderr_file.supportsAnsiEscapeCodes()) {
             return .escape_codes;
lib/std/process.zig
@@ -179,6 +179,26 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned
     }
 }
 
+pub fn hasEnvVarConstant(comptime key: []const u8) bool {
+    if (builtin.os.tag == .windows) {
+        const key_w = comptime std.unicode.utf8ToUtf16LeStringLiteral(key);
+        return std.os.getenvW(key_w) != null;
+    } else {
+        return os.getenv(key) != null;
+    }
+}
+
+pub fn hasEnvVar(allocator: *Allocator, key: []const u8) error{OutOfMemory}!bool {
+    if (builtin.os.tag == .windows) {
+        var stack_alloc = std.heap.stackFallback(256 * @sizeOf(u16), allocator);
+        const key_w = try std.unicode.utf8ToUtf16LeWithNull(&stack_alloc.allocator, key);
+        defer stack_alloc.allocator.free(key_w);
+        return std.os.getenvW(key_w) != null;
+    } else {
+        return os.getenv(key) != null;
+    }
+}
+
 test "os.getEnvVarOwned" {
     var ga = std.testing.allocator;
     try testing.expectError(error.EnvironmentVariableNotFound, getEnvVarOwned(ga, "BADENV"));
src/stage1/errmsg.cpp
@@ -16,8 +16,8 @@ enum ErrType {
 };
 
 static void print_err_msg_type(ErrorMsg *err, ErrColor color, ErrType err_type) {
-    bool is_tty = os_stderr_tty();
-    bool use_colors = color == ErrColorOn || (color == ErrColorAuto && is_tty);
+    bool supports_color = os_stderr_supports_color();
+    bool use_colors = color == ErrColorOn || (color == ErrColorAuto && supports_color);
 
     // Show the error location, if available
     if (err->path != nullptr) {
src/stage1/os.cpp
@@ -834,13 +834,14 @@ static bool is_stderr_cyg_pty(void) {
 }
 #endif
 
-bool os_stderr_tty(void) {
+bool os_stderr_supports_color(void) {
+    if (getenv("NO_COLOR") != NULL) return false;
 #if defined(ZIG_OS_WINDOWS)
     return _isatty(_fileno(stderr)) != 0 || is_stderr_cyg_pty();
 #elif defined(ZIG_OS_POSIX)
     return isatty(STDERR_FILENO) != 0;
 #else
-#error "missing os_stderr_tty implementation"
+#error "missing os_stderr_supports_color implementation"
 #endif
 }
 
src/stage1/os.hpp
@@ -99,7 +99,7 @@ Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents);
 
 Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd);
 
-bool os_stderr_tty(void);
+bool os_stderr_supports_color(void);
 void os_stderr_set_color(TermColor color);
 
 Error os_rename(Buf *src_path, Buf *dest_path);
src/main.zig
@@ -503,15 +503,6 @@ const Emit = union(enum) {
     }
 };
 
-fn optionalBoolEnvVar(arena: *Allocator, name: []const u8) !bool {
-    if (std.process.getEnvVarOwned(arena, name)) |_| {
-        return true;
-    } else |err| switch (err) {
-        error.EnvironmentVariableNotFound => return false,
-        else => |e| return e,
-    }
-}
-
 fn optionalStringEnvVar(arena: *Allocator, name: []const u8) !?[]const u8 {
     if (std.process.getEnvVarOwned(arena, name)) |value| {
         return value;
@@ -548,8 +539,8 @@ fn buildOutputType(
     var single_threaded = false;
     var function_sections = false;
     var watch = false;
-    var verbose_link = try optionalBoolEnvVar(arena, "ZIG_VERBOSE_LINK");
-    var verbose_cc = try optionalBoolEnvVar(arena, "ZIG_VERBOSE_CC");
+    var verbose_link = std.process.hasEnvVarConstant("ZIG_VERBOSE_LINK");
+    var verbose_cc = std.process.hasEnvVarConstant("ZIG_VERBOSE_CC");
     var verbose_air = false;
     var verbose_llvm_ir = false;
     var verbose_cimport = false;
@@ -670,6 +661,11 @@ fn buildOutputType(
     defer freePkgTree(gpa, &pkg_tree_root, false);
     var cur_pkg: *Package = &pkg_tree_root;
 
+    // before arg parsing, check for the NO_COLOR environment variable
+    // if it exists, default the color setting to .off
+    // explicit --color arguments will still override this setting.
+    color = if (std.process.hasEnvVarConstant("NO_COLOR")) .off else .auto;
+
     switch (arg_mode) {
         .build, .translate_c, .zig_test, .run => {
             var optimize_mode_string: ?[]const u8 = null;