Support the NO_COLOR environment variable
authorTom Tromey <tom@tromey.com>
Fri, 15 Sep 2023 23:24:26 +0000 (17:24 -0600)
committerTom Tromey <tom@tromey.com>
Fri, 29 Sep 2023 16:55:43 +0000 (10:55 -0600)
I ran across this site:

    https://no-color.org/

... which lobbies for tools to recognize the NO_COLOR environment
variable and disable any terminal styling when it is seen.

This patch implements this for gdb.

Regression tested on x86-64 Fedora 38.

Co-Authored-By: Andrew Burgess <aburgess@redhat.com>
Reviewed-by: Kevin Buettner <kevinb@redhat.com>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Andrew Burgess <aburgess@redhat.com>
17 files changed:
gdb/NEWS
gdb/doc/gdb.texinfo
gdb/main.c
gdb/testsuite/gdb.base/early-init-file.exp
gdb/testsuite/gdb.base/readline-ask.exp
gdb/testsuite/gdb.base/style-interp-exec-mi.exp
gdb/testsuite/gdb.base/style-logging.exp
gdb/testsuite/gdb.base/style.exp
gdb/testsuite/gdb.debuginfod/build-id-no-debug-warning.exp
gdb/testsuite/gdb.debuginfod/crc_mismatch.exp
gdb/testsuite/gdb.python/py-format-string.exp
gdb/testsuite/gdb.python/py-source-styling.exp
gdb/testsuite/gdb.python/py-startup-opt.exp
gdb/testsuite/gdb.rust/rust-style.exp
gdb/testsuite/gdb.tui/tui-layout.exp
gdb/testsuite/lib/gdb.exp
gdb/testsuite/lib/tuiterm.exp

index fd7ab282f6956f067b0f4c8871249ddf4a9a4f43..6523ad1d6aa37efafdae43e5c468e14b54d3e60f 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,10 @@
 
 *** Changes since GDB 13
 
+* GDB now recognizes the NO_COLOR environment variable and disables
+  styling according to the spec.  See https://no-color.org/.
+  Styling can be re-enabled with "set style enabled on".
+
 * The AArch64 'org.gnu.gdb.aarch64.pauth' Pointer Authentication feature string
   has been deprecated in favor of the 'org.gnu.gdb.aarch64.pauth_v2' feature
   string.
index f9c2f955ef63da2a0c71c6af81a77e51ab8ae60a..c962222bac0bcd94b730c2f0bfb6241c2a085b2f 100644 (file)
@@ -27272,6 +27272,9 @@ and styles can also be disabled entirely.
 Enable or disable all styling.  The default is host-dependent, with
 most hosts defaulting to @samp{on}.
 
+If the @env{NO_COLOR} environment variable is set to a non-empty
+value, then @value{GDBN} will change this to @samp{off} at startup.
+
 @item show style enabled
 Show the current state of styling.
 
index cf46f6acb208fbabbc55db7ac06ed26ca5c53ad8..97e04f5b5d8edb0218165e5d597c1a375bbab801 100644 (file)
@@ -654,6 +654,10 @@ captured_main_1 (struct captured_main_args *context)
   int save_auto_load;
   int ret = 1;
 
+  const char *no_color = getenv ("NO_COLOR");
+  if (no_color != nullptr && *no_color != '\0')
+    cli_styling = false;
+
 #ifdef HAVE_USEFUL_SBRK
   /* Set this before constructing scoped_command_stats.  */
   lim_at_start = (char *) sbrk (0);
index 237439f9db762921b98dc0fed9f10222ae512458..6426da8dacfe64b28bfc9324703ecffe4485ff72 100644 (file)
@@ -99,9 +99,7 @@ proc check_gdb_startups_up_quietly { message } {
     }
 }
 
-save_vars { env(TERM) } {
-    # We need an ANSI-capable terminal to get the output.
-    setenv TERM ansi
+with_ansi_styling_terminal {
 
     # Start GDB and confirm that the version string is styled.
     save_vars { INTERNAL_GDBFLAGS env(HOME) env(XDG_CONFIG_HOME) } {
index 51bf6424a026a5c46161693b6e28773765d50a7f..ff33c83c422a3825b86945f24a5c6618f2a6bd68 100644 (file)
@@ -21,6 +21,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" object {debug}]
     return -1
 }
 
+setenv TERM dumb
+
 # INPUTRC gets reset for the next testfile.
 setenv INPUTRC $inputrc
 clean_restart ${binfile}
index 9b2ed87513fd767271ac57e09aa81954dc01af0e..b99e767a034b8809d16fdfa38bd0f776a4af6c57 100644 (file)
 
 standard_testfile
 
-save_vars { env(TERM) } {
-    # We need an ANSI-capable terminal to get the output.
-    setenv TERM ansi
-
+with_ansi_styling_terminal {
     if { [prepare_for_testing "failed to prepare" \
            ${testfile} ${srcfile}] } {
        return
index a156c39146f211b16af04e72bc66a31bf4fd9d2c..c21c3321bdeda26537e50f28a5495465153e9acf 100644 (file)
@@ -22,10 +22,7 @@ require {!is_remote host}
 
 standard_testfile style.c
 
-save_vars { env(TERM) } {
-    # We need an ANSI-capable terminal to get the output.
-    setenv TERM ansi
-
+with_ansi_styling_terminal {
     if {[prepare_for_testing "failed to prepare" $testfile $srcfile debug]} {
        return -1
     }
index 60f909e2402523b15256b0eceabc4f203693d30d..7ee1b44177f756a86609497e4137d8c8e11a6838 100644 (file)
@@ -69,10 +69,7 @@ proc run_style_tests { } {
     global testfile srcfile hex binfile
     global currently_disabled_style decimal hex
 
-    save_vars { env(TERM) } {
-       # We need an ANSI-capable terminal to get the output.
-       setenv TERM ansi
-
+    with_ansi_styling_terminal {
        # Restart GDB with the correct TERM variable setting, this
        # means that GDB will enable styling.
        clean_restart_and_disable "restart 1" ${binfile}
@@ -319,9 +316,10 @@ proc run_style_tests { } {
 # Python pygments module is not available, so, when we disable
 # disassembler styling, we should always see a change in output.
 proc test_disable_disassembler_styling { } {
-    save_vars { env(TERM) } {
+    save_vars { env(TERM) env(NO_COLOR) } {
        # We need an ANSI-capable terminal to get the output.
        setenv TERM ansi
+       setenv NO_COLOR ""
 
        # Restart GDB with the correct TERM variable setting, this
        # means that GDB will enable styling.
@@ -427,9 +425,10 @@ proc test_disassembler_error_handling { } {
        return
     }
 
-    save_vars { env(TERM) } {
+    save_vars { env(TERM) env(NO_COLOR) } {
        # We need an ANSI-capable terminal to get the output.
        setenv TERM ansi
+       setenv NO_COLOR ""
 
        # Restart GDB with the correct TERM variable setting, this
        # means that GDB will enable styling.
index 148363a7c0504772de09652aa72a2de9938d2496..8ee3bb0e78c548bd130ade176698454d236797e4 100644 (file)
@@ -98,10 +98,7 @@ gdb_test "file ${build_id_debug_file}" \
 # Do the same thing again, but this time check that the styling is
 # correct.
 with_test_prefix "check styling" {
-    save_vars { env(TERM) } {
-       # We need an ANSI-capable terminal to get styled output.
-       setenv TERM ansi
-
+    with_ansi_styling_terminal {
        clean_restart
 
        gdb_test_no_output "set debug-file-directory ${debug_file_directory}" \
index 074028eadfd8b5b3298cb78f2ec057e16df58493..e88c4b3c65332c8cd6aaf5f737bef6830b15d48e 100644 (file)
@@ -71,10 +71,7 @@ if {[build_executable crc_mismatch.exp crc_mismatch-2 crc_mismatch-2.c debug] !=
     # Do the same thing again, but this time check that the styling is
     # correct.
     with_test_prefix "check styling" {
-       save_vars { env(TERM) } {
-           # We need an ANSI-capable terminal to get styled output.
-           setenv TERM ansi
-
+       with_ansi_styling_terminal {
            clean_restart
 
            set debug_file_re [style "${escapedobjdirsubdir}/crc_mismatch-2\\.debug" file]
index 55a37766bffa9f039803bb71efb966d52593407c..04d19e483d9ef711c37a4f70d3e7990b0ae36389 100644 (file)
@@ -1184,11 +1184,10 @@ with_test_prefix "format_string" {
   # Perform C Tests.
   if { [build_inferior "${binfile}" "c"] == 0 } {
     with_test_prefix "lang_c" {
-      save_vars { env(TERM) } {
+      with_ansi_styling_terminal {
        # We run all of these tests in an environment where styling
        # could work, but we only expect the final call to
        # test_styling to actually produce any styled output.
-       setenv TERM ansi
        set current_lang "c"
        prepare_gdb "${binfile}"
        test_all_common
index f92d6f7a7064aafb2d685456e4e02be5ab14d936..d3ae339661cc1b265d5c54e742dacf8f4bbdd8d8 100644 (file)
@@ -20,13 +20,11 @@ load_lib gdb-python.exp
 
 standard_testfile
 
-save_vars { env(TERM) } {
+with_ansi_styling_terminal {
     # We need an ANSI-capable terminal to get the output, additionally
     # we need to set LC_ALL so GDB knows the terminal is UTF-8
     # capable, otherwise we'll get a UnicodeEncodeError trying to
     # encode the output.
-    setenv TERM ansi
-
     if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
        return -1
     }
index 08d1c79eee38585a1222cd71a5c61bd762ed3713..729b1c13cb96709221a8ae29554ecffbd67d5582 100644 (file)
@@ -97,10 +97,7 @@ proc test_python_settings { exp_state } {
     gdb_exit
 }
 
-save_vars { env(TERM) } {
-    # We need an ANSI-capable terminal to get the output.
-    setenv TERM ansi
-
+with_ansi_styling_terminal {
     # Check the features are off by default.
     test_python_settings "off"
 
index 0555ea4b8a464c0432c6c62422e5e8a0d8691661..b4ea05ca8ff0610de33d86362755ebb25031a687 100644 (file)
@@ -19,10 +19,7 @@ load_lib rust-support.exp
 require allow_rust_tests
 require {can_compile rust}
 
-save_vars { env(TERM) } {
-    # We need an ANSI-capable terminal to get the output.
-    setenv TERM ansi
-
+with_ansi_styling_terminal {
     standard_testfile .rs
     if {[prepare_for_testing "failed to prepare" $testfile $srcfile \
             {debug rust}]} {
index 13823387e7247cd0caea59bff1e2fde2136f975f..90f27c5eac1ce87654c12af64155076b48473c5e 100644 (file)
@@ -44,13 +44,17 @@ proc test_layout_or_focus {layout_name terminal execution} {
 
     set dumb_terminal [string equal $terminal "dumb"]
 
-    if {$dumb_terminal} {
-       clean_restart $binfile
-    } else {
-       Term::clean_restart 24 80 $binfile
-       if {![Term::prepare_for_tui]} {
-           unsupported "TUI not supported"
-           return
+    global env
+    save_vars { env(TERM) } {
+       setenv TERM $terminal
+       if {$dumb_terminal} {
+           clean_restart $binfile
+       } else {
+           Term::clean_restart 24 80 $binfile
+           if {![Term::prepare_for_tui]} {
+               unsupported "TUI not supported"
+               return
+           }
        }
     }
 
index 1b9179401c456d07263afad0615a686efa761f7b..de22da8d8a8c6bb7f5486a03e9c52ebe25b189ad 100644 (file)
@@ -6468,7 +6468,7 @@ proc default_gdb_init { test_file_name } {
 
     # This disables style output, which would interfere with many
     # tests.
-    setenv TERM "dumb"
+    setenv NO_COLOR sorry
 
     # This setting helps detect bugs in the Python code and doesn't
     # seem to have a significant downside for the tests.
@@ -9238,6 +9238,25 @@ proc with_override { name override body } {
     return $result
 }
 
+# Run BODY after setting the TERM environment variable to 'ansi', and
+# unsetting the NO_COLOR environment variable.
+proc with_ansi_styling_terminal { body } {
+    save_vars { ::env(TERM) ::env(NO_COLOR) } {
+       # Set environment variables to allow styling.
+       setenv TERM ansi
+       unset -nocomplain ::env(NO_COLOR)
+
+       set code [catch {uplevel 1 $body} result]
+    }
+
+    if {$code == 1} {
+       global errorInfo errorCode
+       return -code $code -errorinfo $errorInfo -errorcode $errorCode $result
+    } else {
+       return -code $code $result
+    }
+}
+
 # Setup tuiterm.exp environment.  To be used in test-cases instead of
 # "load_lib tuiterm.exp".  Calls initialization function and schedules
 # finalization function.
index 598c1f8cbdf6ba46333599fbc6d3fc52d399c51f..854fde563932a0eb083e1c6ad5f6d0abe5907326 100644 (file)
@@ -844,8 +844,9 @@ namespace eval Term {
     # BODY.
     proc with_tuiterm {rows cols body} {
        global env stty_init
-       save_vars {env(TERM) stty_init} {
+       save_vars {env(TERM) env(NO_COLOR) stty_init} {
            setenv TERM ansi
+           setenv NO_COLOR ""
            _setup $rows $cols
 
            uplevel $body