From 629676217f2a0daeff34e034b9a13992fe49ed1d Mon Sep 17 00:00:00 2001 From: mo Date: Thu, 30 Jul 2026 11:39:56 +1200 Subject: [PATCH 1/3] Respect TERM=dumb in test runner to prevent ANSI sequences, color Fixes: #7137 --- core/testing/runner.odin | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/testing/runner.odin b/core/testing/runner.odin index 9033d078e..ef5d03864 100644 --- a/core/testing/runner.odin +++ b/core/testing/runner.odin @@ -281,6 +281,15 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { global_log_colors_disabled = !terminal.color_enabled || !terminal.is_terminal(os.stderr) global_ansi_disabled = !terminal.is_terminal(os.stdout) + buf: [128]u8 + if term, err := os.lookup_env(buf[:], "TERM"); err == nil { + // "dumb" terminal overrides all other color and ansi capabilities logic + if term == "dumb" { + global_ansi_disabled = true + global_log_colors_disabled = true + } + } + should_show_animations := FANCY_OUTPUT && terminal.color_enabled && !global_ansi_disabled // -- Parse CLI options From 70507796430f3d48f2bebe3556dcfa351787ce6c Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Thu, 30 Jul 2026 11:46:06 +0200 Subject: [PATCH 2/3] Move TERM == "dumb" test to `core:terminal` --- core/terminal/internal_os.odin | 9 +++++++++ core/terminal/terminal.odin | 5 +++++ core/terminal/terminal_js.odin | 1 + core/terminal/terminal_posix.odin | 1 + core/terminal/terminal_windows.odin | 2 ++ core/testing/runner.odin | 14 ++------------ 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/core/terminal/internal_os.odin b/core/terminal/internal_os.odin index 127cbae54..dc466e7b0 100644 --- a/core/terminal/internal_os.odin +++ b/core/terminal/internal_os.odin @@ -21,6 +21,15 @@ get_no_color :: proc() -> bool { return false } +get_is_dumb :: proc() -> bool { + buf: [128]u8 + if term, err := os.lookup_env(buf[:], "TERM"); err == nil { + // "dumb" terminal overrides all other color and ansi capabilities logic + return term == "dumb" + } + return false +} + get_environment_color :: proc() -> Color_Depth { buf: [128]u8 // `COLORTERM` is non-standard but widespread and unambiguous. diff --git a/core/terminal/terminal.odin b/core/terminal/terminal.odin index 86d928649..0f882b296 100644 --- a/core/terminal/terminal.odin +++ b/core/terminal/terminal.odin @@ -23,6 +23,11 @@ is_terminal :: proc(f: $T) -> bool { return _is_terminal(f) } +/* +This is true if the terminal is dumb, i.e. cannot process ANSI control sequences. +*/ +is_dumb: bool + /* This is true if the terminal is accepting any form of colored text output. */ diff --git a/core/terminal/terminal_js.odin b/core/terminal/terminal_js.odin index 78c6c240f..aafb3223a 100644 --- a/core/terminal/terminal_js.odin +++ b/core/terminal/terminal_js.odin @@ -8,6 +8,7 @@ _is_terminal :: proc "contextless" (handle: any) -> bool { _init_terminal :: proc "contextless" () { color_depth = .None + is_dumb = true } _fini_terminal :: proc "contextless" () { } \ No newline at end of file diff --git a/core/terminal/terminal_posix.odin b/core/terminal/terminal_posix.odin index 62a79797b..3b6701722 100644 --- a/core/terminal/terminal_posix.odin +++ b/core/terminal/terminal_posix.odin @@ -12,6 +12,7 @@ _is_terminal :: proc "contextless" (f: ^os.File) -> bool { _init_terminal :: proc "contextless" () { context = runtime.default_context() color_depth = get_environment_color() + is_dumb = get_is_dumb() } _fini_terminal :: proc "contextless" () { } diff --git a/core/terminal/terminal_windows.odin b/core/terminal/terminal_windows.odin index 64244e1ac..f5d19e3b3 100644 --- a/core/terminal/terminal_windows.odin +++ b/core/terminal/terminal_windows.odin @@ -46,6 +46,8 @@ _init_terminal :: proc "contextless" () { // The user may be on a non-default terminal emulator. color_depth = get_environment_color() } + + is_dumb = get_is_dumb() } _fini_terminal :: proc "contextless" () { diff --git a/core/testing/runner.odin b/core/testing/runner.odin index ef5d03864..e298cf47c 100644 --- a/core/testing/runner.odin +++ b/core/testing/runner.odin @@ -278,18 +278,8 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { // The animations are only ever shown through STDOUT; // STDERR is used exclusively for logging regardless of error level. - global_log_colors_disabled = !terminal.color_enabled || !terminal.is_terminal(os.stderr) - global_ansi_disabled = !terminal.is_terminal(os.stdout) - - buf: [128]u8 - if term, err := os.lookup_env(buf[:], "TERM"); err == nil { - // "dumb" terminal overrides all other color and ansi capabilities logic - if term == "dumb" { - global_ansi_disabled = true - global_log_colors_disabled = true - } - } - + global_log_colors_disabled = terminal.is_dumb || !terminal.color_enabled || !terminal.is_terminal(os.stderr) + global_ansi_disabled = terminal.is_dumb || !terminal.is_terminal(os.stdout) should_show_animations := FANCY_OUTPUT && terminal.color_enabled && !global_ansi_disabled // -- Parse CLI options From d272bfb9cac5f581dd77ad7c40ec7e3b46c59452 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Thu, 30 Jul 2026 12:03:08 +0200 Subject: [PATCH 3/3] context --- core/terminal/internal_os.odin | 4 ++-- core/terminal/terminal_windows.odin | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/terminal/internal_os.odin b/core/terminal/internal_os.odin index dc466e7b0..f4be4480b 100644 --- a/core/terminal/internal_os.odin +++ b/core/terminal/internal_os.odin @@ -72,10 +72,10 @@ get_environment_color :: proc() -> Color_Depth { @(init) init_terminal :: proc "contextless" () { - _init_terminal() - context = runtime.default_context() + _init_terminal() + // We respect `NO_COLOR` specifically as a color-disabler but not as a // blanket ban on any terminal manipulation codes, hence why this comes // after `_init_terminal` which will allow Windows to enable Virtual diff --git a/core/terminal/terminal_windows.odin b/core/terminal/terminal_windows.odin index f5d19e3b3..aff71b362 100644 --- a/core/terminal/terminal_windows.odin +++ b/core/terminal/terminal_windows.odin @@ -18,6 +18,8 @@ old_modes: [2]struct{ } _init_terminal :: proc "contextless" () { + context = runtime.default_context() + vtp_enabled: bool for &v in old_modes { @@ -41,8 +43,6 @@ _init_terminal :: proc "contextless" () { // This color depth is available on Windows 10 since build 10586. color_depth = .Four_Bit } else { - context = runtime.default_context() - // The user may be on a non-default terminal emulator. color_depth = get_environment_color() }