Skip to content

Commit 3b77dce

Browse files
committed
Fix command-line colorization on Windows with VT100-compatible environments
When setting PG_COLOR to "always" or "auto" in a Windows terminal VT100-compatible, the colorization output was not showing up correctly because it is necessary to update the console's output handling mode. This fix allows to detect automatically if the environment is compatible with VT100. Hence, PG_COLOR=auto is able to detect and handle both compatible and non-compatible environments. The behavior of PG_COLOR=always remains unchanged, as it enforces the use of colorized output even if the environment does not allow it. This fix is based on an initial suggestion from Thomas Munro. Reported-by: Haiying Tang Author: Juan José Santamaría Flecha Reviewed-by: Michail Nikolaev, Michael Paquier, Haiying Tang Discussion: https://postgr.es/m/16108-134692e97146b7bc@postgresql.org Backpatch-through: 12
1 parent 12c5cad commit 3b77dce

File tree

1 file changed

+49
-1
lines changed

1 file changed

+49
-1
lines changed

src/common/logging.c

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,43 @@ static const char *sgr_locus = NULL;
3232
#define ANSI_ESCAPE_FMT "\x1b[%sm"
3333
#define ANSI_ESCAPE_RESET "\x1b[0m"
3434

35+
#ifdef WIN32
36+
37+
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
38+
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
39+
#endif
40+
41+
/*
42+
* Attempt to enable VT100 sequence processing for colorization on Windows.
43+
* If current environment is not VT100-compatible or if this mode could not
44+
* be enabled, return false.
45+
*/
46+
static bool
47+
enable_vt_processing(void)
48+
{
49+
/* Check stderr */
50+
HANDLE hOut = GetStdHandle(STD_ERROR_HANDLE);
51+
DWORD dwMode = 0;
52+
53+
if (hOut == INVALID_HANDLE_VALUE)
54+
return false;
55+
56+
/*
57+
* Look for the current console settings and check if VT100 is already
58+
* enabled.
59+
*/
60+
if (!GetConsoleMode(hOut, &dwMode))
61+
return false;
62+
if ((dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) != 0)
63+
return true;
64+
65+
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
66+
if (!SetConsoleMode(hOut, dwMode))
67+
return false;
68+
return true;
69+
}
70+
#endif /* WIN32 */
71+
3572
/*
3673
* This should be called before any output happens.
3774
*/
@@ -40,6 +77,17 @@ pg_logging_init(const char *argv0)
4077
{
4178
const char *pg_color_env = getenv("PG_COLOR");
4279
bool log_color = false;
80+
bool color_terminal = isatty(fileno(stderr));
81+
82+
#ifdef WIN32
83+
84+
/*
85+
* On Windows, check if environment is VT100-compatible if using a
86+
* terminal.
87+
*/
88+
if (color_terminal)
89+
color_terminal = enable_vt_processing();
90+
#endif
4391

4492
/* usually the default, but not on Windows */
4593
setvbuf(stderr, NULL, _IONBF, 0);
@@ -50,7 +98,7 @@ pg_logging_init(const char *argv0)
5098
if (pg_color_env)
5199
{
52100
if (strcmp(pg_color_env, "always") == 0 ||
53-
(strcmp(pg_color_env, "auto") == 0 && isatty(fileno(stderr))))
101+
(strcmp(pg_color_env, "auto") == 0 && color_terminal))
54102
log_color = true;
55103
}
56104

0 commit comments

Comments
 (0)