pg.ddx.io  pgsql-hackers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Peter Eisentraut <peter.eisentraut@2ndquadrant.com>
To: pgsql-hackers <pgsql-hackers@postgresql.org>
Subject: color by default
Date: Tue, 31 Dec 2019 11:40:28 +0100
Message-ID: <bbdcce43-bd2e-5599-641b-9b44b9e0add4@2ndquadrant.com> (raw)

With the attached patch, I propose to enable the colored output by 
default in PG13.

For those who don't like color output, I also add support for the 
environment variable NO_COLOR, which is an emerging standard for turning 
off color across different software packages (https://no-color.org/). 
Of course, you can also continue to use the PG_COLOR variable.

I have looked around how other packages do the automatic color 
detection.  It's usually a combination of mysterious termcap stuff and 
slightly less mysterious matching of the TERM variable against a list of 
known terminal types.  I figured we can skip the termcap stuff and still 
get really good coverage in practice, so that's what I did.

I have also added a documentation appendix to explain all of this. 
(Perhaps we should now remove the repetitive mention of the PG_COLOR 
variable in each man page, but I haven't done that in this patch.)

I'm aware of the pending patch to improve color support on Windows. 
I'll check that one out as well, but it appears to be orthogonal to this 
one.

-- 
Peter Eisentraut              http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
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



Attachments:

  [text/plain] 0001-Use-colors-by-default.patch (6.1K, ../bbdcce43-bd2e-5599-641b-9b44b9e0add4@2ndquadrant.com/2-0001-Use-colors-by-default.patch)
  download | inline diff:
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



view thread (34+ messages)  latest in thread

Message-ID: <bbdcce43-bd2e-5599-641b-9b44b9e0add4@2ndquadrant.com>
Permalink:  ../bbdcce43-bd2e-5599-641b-9b44b9e0add4@2ndquadrant.com/
Also on:    postgresql.org/message-id/bbdcce43-bd2e-5599-641b-9b44b9e0add4@2ndquadrant.com

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-hackers@postgresql.org
  Cc: peter.eisentraut@2ndquadrant.com
  Subject: Re: color by default
  In-Reply-To: <bbdcce43-bd2e-5599-641b-9b44b9e0add4@2ndquadrant.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox