0001-Use-colors-by-default.patch

text/plain

Filename: 0001-Use-colors-by-default.patch
Type: text/plain
Part: 0
Message: color by default

Patch

Format: format-patch
Series: patch 0001
Subject: Use colors by default
File+
doc/src/sgml/color.sgml 102 0
doc/src/sgml/filelist.sgml 1 0
doc/src/sgml/postgres.sgml 1 0
src/common/logging.c 41 0
From 58ca7359728959ccc9d7e96d6fbeb324714e9317 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Tue, 31 Dec 2019 11:20:21 +0100
Subject: [PATCH] Use colors by default

Refine the system by which it is decided whether colored output it
used.  Besides the PG_COLOR environment variable previously in use, we
now also observe the NO_COLORS environment variable.  Furthermore, if
neither of these are set, we check whether the terminal supports
colors using the TERM environment variable and use colors
automatically if so.

Also add a documentation appendix that explains who this works and how
the individual colors can be configured.
---
 doc/src/sgml/color.sgml    | 102 +++++++++++++++++++++++++++++++++++++
 doc/src/sgml/filelist.sgml |   1 +
 doc/src/sgml/postgres.sgml |   1 +
 src/common/logging.c       |  41 +++++++++++++++
 4 files changed, 145 insertions(+)
 create mode 100644 doc/src/sgml/color.sgml

diff --git a/doc/src/sgml/color.sgml b/doc/src/sgml/color.sgml
new file mode 100644
index 0000000000..f1697230e5
--- /dev/null
+++ b/doc/src/sgml/color.sgml
@@ -0,0 +1,102 @@
+<!-- doc/src/sgml/color.sgml -->
+
+<appendix id="color">
+ <title>Color Support</title>
+
+ <indexterm zone="color">
+  <primary>color</primary>
+ </indexterm>
+
+ <para>
+  Most programs in the PostgreSQL package can produce colorized console
+  output.  This appendix describes how that is configured.
+ </para>
+
+ <sect1 id="color-when">
+  <title>When Color is Used</title>
+
+  <para>
+   The decision whether to use colorized output is made according to the
+   following procedure:
+
+   <orderedlist>
+    <listitem>
+     <para>
+      If the environment variable
+      <envar>PG_COLOR</envar><indexterm><primary>PG_COLOR</primary></indexterm>
+      is set:
+     </para>
+
+     <orderedlist>
+      <listitem>
+       <para>
+        If the value is <literal>always</literal>, then color is used.
+       </para>
+      </listitem>
+
+      <listitem>
+       <para>
+        If the value is <literal>auto</literal> and the standard error stream
+        is associated with a terminal device, then color is used.
+       </para>
+      </listitem>
+
+      <listitem>
+       <para>
+        Otherwise, color is not used.
+       </para>
+      </listitem>
+     </orderedlist>
+    </listitem>
+
+    <listitem>
+     <para>
+      If the environment variable <envar>NO_COLOR</envar> is set, then color
+      is not used.  See <ulink url="https://no-color.org/"/> for more
+      information about this.
+     </para>
+    </listitem>
+
+    <listitem>
+     <para>
+      If the environment variable <envar>TERM</envar> is set to a terminal
+      type that is recognized to support color and the standard error stream
+      is associated with a terminal device, then color is used.
+     </para>
+    </listitem>
+
+    <listitem>
+     <para>
+      Otherwise, color is not used.
+     </para>
+    </listitem>
+   </orderedlist>
+  </para>
+ </sect1>
+
+ <sect1 id="color-which">
+  <title>Configuring the Colors</title>
+
+  <para>
+   The actual colors to be used are configured using the environment variable
+   <envar>PG_COLORS</envar><indexterm><primary>PG_COLORS</primary></indexterm>
+   (note plural).  The value is a colon-separated list of
+   <literal><replaceable>key</replaceable>=<replaceable>value</replaceable></literal>
+   pairs.  The keys specify what the color is to be used for.  The values are
+   SGR (Select Graphic Rendition) specifications, which are interpreted by the
+   terminal.
+  </para>
+
+  <para>
+   The default value is <literal>error=01;31:warning=01;35:locus=01</literal>.
+  </para>
+
+  <tip>
+   <para>
+    This color specification format is also used by other software packages
+    such as <productname>GCC</productname>, <productname>GNU
+    coreutils</productname>, and <productname>GNU grep</productname>.
+   </para>
+  </tip>
+ </sect1>
+</appendix>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 3da2365ea9..1043d0f7ab 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -170,6 +170,7 @@
 
 <!ENTITY limits     SYSTEM "limits.sgml">
 <!ENTITY acronyms   SYSTEM "acronyms.sgml">
+<!ENTITY color      SYSTEM "color.sgml">
 
 <!ENTITY features-supported   SYSTEM "features-supported.sgml">
 <!ENTITY features-unsupported SYSTEM "features-unsupported.sgml">
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index e59cba7997..1f7bd32878 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -278,6 +278,7 @@ <title>Appendixes</title>
   &docguide;
   &limits;
   &acronyms;
+  &color;
 
  </part>
 
diff --git a/src/common/logging.c b/src/common/logging.c
index 895da7150e..9b0c67046f 100644
--- a/src/common/logging.c
+++ b/src/common/logging.c
@@ -32,6 +32,37 @@ static const char *sgr_locus = NULL;
 #define ANSI_ESCAPE_FMT "\x1b[%sm"
 #define ANSI_ESCAPE_RESET "\x1b[0m"
 
+
+#define str_starts_with(str, substr) (strncmp(str, substr, strlen(substr)) == 0)
+#define str_ends_with(str, substr) (strcmp(str + strlen(str) - strlen(substr), substr) == 0)
+
+static bool
+terminal_supports_color(void)
+{
+	const char *term_env = getenv("TERM");
+
+	if (!term_env)
+		return false;
+	else if (strcmp(term_env, "ansi") == 0)
+		return true;
+	else if (strcmp(term_env, "cygwin") == 0)
+		return true;
+	else if (strcmp(term_env, "linux") == 0)
+		return true;
+	else if (str_starts_with(term_env, "rxvt"))
+		return true;
+	else if (str_starts_with(term_env, "screen"))
+		return true;
+	else if (str_starts_with(term_env, "xterm"))
+		return true;
+	else if (str_starts_with(term_env, "vt100"))
+		return true;
+	else if (str_ends_with(term_env, "color"))
+		return true;
+	else
+		return false;
+}
+
 /*
  * This should be called before any output happens.
  */
@@ -53,6 +84,16 @@ pg_logging_init(const char *argv0)
 			(strcmp(pg_color_env, "auto") == 0 && isatty(fileno(stderr))))
 			log_color = true;
 	}
+	else if (getenv("NO_COLOR"))
+	{
+		/* see https://no-color.org/ */
+		log_color = false;
+	}
+	else
+	{
+		log_color = isatty(fileno(stderr)) &&
+			terminal_supports_color();
+	}
 
 	if (log_color)
 	{
-- 
2.24.1