authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-10-02 01:37:05-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-10-02 01:37:05-04:00
log0a4283b38ba40242f8f9302a63e8c4d664a50799
treef3f9fadc7c5683197d0b09abbfd8c58b779db8e9
parentb3f3db46bec83bd467f4e0759ab58965aa3a8459

support terminal colors for cmd.exe and msys pty

See #302

3 files changed, 164 insertions(+), 12 deletions(-)

src/errmsg.cpp+22-11
...@@ -10,12 +10,6 @@...@@ -10,12 +10,6 @@
1010
11#include <stdio.h>11#include <stdio.h>
1212
13#define RED "\x1b[31;1m"
14#define GREEN "\x1b[32;1m"
15#define CYAN "\x1b[36;1m"
16#define WHITE "\x1b[37;1m"
17#define RESET "\x1b[0m"
18
19enum ErrType {13enum ErrType {
20 ErrTypeError,14 ErrTypeError,
21 ErrTypeNote,15 ErrTypeNote,
...@@ -27,12 +21,26 @@ static void print_err_msg_type(ErrorMsg *err, ErrColor color, ErrType err_type)...@@ -27,12 +21,26 @@ static void print_err_msg_type(ErrorMsg *err, ErrColor color, ErrType err_type)
27 size_t col = err->column_start + 1;21 size_t col = err->column_start + 1;
28 const char *text = buf_ptr(err->msg);22 const char *text = buf_ptr(err->msg);
2923
3024 bool is_tty = os_stderr_tty();
31 if (color == ErrColorOn || (color == ErrColorAuto && os_stderr_tty())) {25 if (color == ErrColorOn || (color == ErrColorAuto && is_tty)) {
32 if (err_type == ErrTypeError) {26 if (err_type == ErrTypeError) {
33 fprintf(stderr, WHITE "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ": " RED "error:" WHITE " %s" RESET "\n", path, line, col, text);27 os_stderr_set_color(TermColorWhite);
28 fprintf(stderr, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ": ", path, line, col);
29 os_stderr_set_color(TermColorRed);
30 fprintf(stderr, "error:");
31 os_stderr_set_color(TermColorWhite);
32 fprintf(stderr, " %s", text);
33 os_stderr_set_color(TermColorReset);
34 fprintf(stderr, "\n");
34 } else if (err_type == ErrTypeNote) {35 } else if (err_type == ErrTypeNote) {
35 fprintf(stderr, WHITE "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ": " CYAN "note:" WHITE " %s" RESET "\n", path, line, col, text);36 os_stderr_set_color(TermColorWhite);
37 fprintf(stderr, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ": ", path, line, col);
38 os_stderr_set_color(TermColorCyan);
39 fprintf(stderr, "note:");
40 os_stderr_set_color(TermColorWhite);
41 fprintf(stderr, " %s", text);
42 os_stderr_set_color(TermColorReset);
43 fprintf(stderr, "\n");
36 } else {44 } else {
37 zig_unreachable();45 zig_unreachable();
38 }46 }
...@@ -41,7 +49,10 @@ static void print_err_msg_type(ErrorMsg *err, ErrColor color, ErrType err_type)...@@ -41,7 +49,10 @@ static void print_err_msg_type(ErrorMsg *err, ErrColor color, ErrType err_type)
41 for (size_t i = 0; i < err->column_start; i += 1) {49 for (size_t i = 0; i < err->column_start; i += 1) {
42 fprintf(stderr, " ");50 fprintf(stderr, " ");
43 }51 }
44 fprintf(stderr, GREEN "^" RESET "\n");52 os_stderr_set_color(TermColorGreen);
53 fprintf(stderr, "^");
54 os_stderr_set_color(TermColorReset);
55 fprintf(stderr, "\n");
45 } else {56 } else {
46 if (err_type == ErrTypeError) {57 if (err_type == ErrTypeError) {
47 fprintf(stderr, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ": error: %s\n", path, line, col, text);58 fprintf(stderr, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ": error: %s\n", path, line, col, text);
src/os.cpp+133-1
...@@ -639,9 +639,68 @@ int os_get_cwd(Buf *out_cwd) {...@@ -639,9 +639,68 @@ int os_get_cwd(Buf *out_cwd) {
639#endif639#endif
640}640}
641641
642#if defined(ZIG_OS_WINDOWS)
643#define is_wprefix(s, prefix) \
644 (wcsncmp((s), (prefix), sizeof(prefix) / sizeof(WCHAR) - 1) == 0)
645static bool is_stderr_cyg_pty(void) {
646 HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
647 if (stderr_handle == INVALID_HANDLE_VALUE)
648 return false;
649
650 HANDLE h;
651 int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * MAX_PATH;
652 FILE_NAME_INFO *nameinfo;
653 WCHAR *p = NULL;
654
655 // Cygwin/msys's pty is a pipe.
656 if (GetFileType(stderr_handle) != FILE_TYPE_PIPE) {
657 return 0;
658 }
659 nameinfo = (FILE_NAME_INFO *)allocate<char>(size);
660 if (nameinfo == NULL) {
661 return 0;
662 }
663 // Check the name of the pipe:
664 // '\{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master'
665 if (GetFileInformationByHandleEx(stderr_handle, FileNameInfo, nameinfo, size)) {
666 nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = L'\0';
667 p = nameinfo->FileName;
668 if (is_wprefix(p, L"\\cygwin-")) { /* Cygwin */
669 p += 8;
670 } else if (is_wprefix(p, L"\\msys-")) { /* MSYS and MSYS2 */
671 p += 6;
672 } else {
673 p = NULL;
674 }
675 if (p != NULL) {
676 while (*p && isxdigit(*p)) /* Skip 16-digit hexadecimal. */
677 ++p;
678 if (is_wprefix(p, L"-pty")) {
679 p += 4;
680 } else {
681 p = NULL;
682 }
683 }
684 if (p != NULL) {
685 while (*p && isdigit(*p)) /* Skip pty number. */
686 ++p;
687 if (is_wprefix(p, L"-from-master")) {
688 //p += 12;
689 } else if (is_wprefix(p, L"-to-master")) {
690 //p += 10;
691 } else {
692 p = NULL;
693 }
694 }
695 }
696 free(nameinfo);
697 return (p != NULL);
698}
699#endif
700
642bool os_stderr_tty(void) {701bool os_stderr_tty(void) {
643#if defined(ZIG_OS_WINDOWS)702#if defined(ZIG_OS_WINDOWS)
644 return _isatty(_fileno(stderr)) != 0;703 return _isatty(_fileno(stderr)) != 0 || is_stderr_cyg_pty();
645#elif defined(ZIG_OS_POSIX)704#elif defined(ZIG_OS_POSIX)
646 return isatty(STDERR_FILENO) != 0;705 return isatty(STDERR_FILENO) != 0;
647#else706#else
...@@ -859,3 +918,76 @@ int os_self_exe_path(Buf *out_path) {...@@ -859,3 +918,76 @@ int os_self_exe_path(Buf *out_path) {
859#endif918#endif
860 return ErrorFileNotFound;919 return ErrorFileNotFound;
861}920}
921
922#define VT_RED "\x1b[31;1m"
923#define VT_GREEN "\x1b[32;1m"
924#define VT_CYAN "\x1b[36;1m"
925#define VT_WHITE "\x1b[37;1m"
926#define VT_RESET "\x1b[0m"
927
928static void set_color_posix(TermColor color) {
929 switch (color) {
930 case TermColorRed:
931 fprintf(stderr, VT_RED);
932 break;
933 case TermColorGreen:
934 fprintf(stderr, VT_GREEN);
935 break;
936 case TermColorCyan:
937 fprintf(stderr, VT_CYAN);
938 break;
939 case TermColorWhite:
940 fprintf(stderr, VT_WHITE);
941 break;
942 case TermColorReset:
943 fprintf(stderr, VT_RESET);
944 break;
945 }
946}
947
948void os_stderr_set_color(TermColor color) {
949#if defined(ZIG_OS_WINDOWS)
950 if (is_stderr_cyg_pty()) {
951 set_color_posix(color);
952 return;
953 }
954 HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
955 if (stderr_handle == INVALID_HANDLE_VALUE)
956 zig_panic("unable to get stderr handle");
957 fflush(stderr);
958 DWORD ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
959 if (color != TermColorReset) {
960 DWORD mode_flags = 0;
961 GetConsoleMode(stderr_handle, &mode_flags);
962 mode_flags |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
963 SetConsoleMode(stderr_handle, mode_flags);
964 }
965 DWORD chars_written;
966 switch (color) {
967 case TermColorRed:
968 WriteConsole(stderr_handle, VT_RED, strlen(VT_RED), &chars_written, NULL);
969 break;
970 case TermColorGreen:
971 WriteConsole(stderr_handle, VT_GREEN, strlen(VT_GREEN), &chars_written, NULL);
972 break;
973 case TermColorCyan:
974 WriteConsole(stderr_handle, VT_CYAN, strlen(VT_CYAN), &chars_written, NULL);
975 break;
976 case TermColorWhite:
977 WriteConsole(stderr_handle, VT_WHITE, strlen(VT_WHITE), &chars_written, NULL);
978 break;
979 case TermColorReset:
980 {
981 WriteConsole(stderr_handle, VT_RESET, strlen(VT_RESET), &chars_written, NULL);
982
983 DWORD mode_flags = 0;
984 GetConsoleMode(stderr_handle, &mode_flags);
985 mode_flags &= ~ENABLE_VIRTUAL_TERMINAL_PROCESSING;
986 SetConsoleMode(stderr_handle, mode_flags);
987 break;
988 }
989 }
990#else
991 set_color_posix(color);
992#endif
993}
src/os.hpp+9
...@@ -15,6 +15,14 @@...@@ -15,6 +15,14 @@
15#include <stdio.h>15#include <stdio.h>
16#include <inttypes.h>16#include <inttypes.h>
1717
18enum TermColor {
19 TermColorRed,
20 TermColorGreen,
21 TermColorCyan,
22 TermColorWhite,
23 TermColorReset,
24};
25
18enum TerminationId {26enum TerminationId {
19 TerminationIdClean,27 TerminationIdClean,
20 TerminationIdSignaled,28 TerminationIdSignaled,
...@@ -53,6 +61,7 @@ int os_fetch_file_path(Buf *full_path, Buf *out_contents);...@@ -53,6 +61,7 @@ int os_fetch_file_path(Buf *full_path, Buf *out_contents);
53int os_get_cwd(Buf *out_cwd);61int os_get_cwd(Buf *out_cwd);
5462
55bool os_stderr_tty(void);63bool os_stderr_tty(void);
64void os_stderr_set_color(TermColor color);
5665
57int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path);66int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path);
58int os_delete_file(Buf *path);67int os_delete_file(Buf *path);