| ... | ... | @@ -639,9 +639,68 @@ int os_get_cwd(Buf *out_cwd) { |
| 639 | 639 | #endif |
| 640 | 640 | } |
| 641 | 641 | |
| 642 | #if defined(ZIG_OS_WINDOWS) |
| 643 | #define is_wprefix(s, prefix) \ |
| 644 | (wcsncmp((s), (prefix), sizeof(prefix) / sizeof(WCHAR) - 1) == 0) |
| 645 | static 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 | |
| 642 | 701 | bool os_stderr_tty(void) { |
| 643 | 702 | #if defined(ZIG_OS_WINDOWS) |
| 644 | | return _isatty(_fileno(stderr)) != 0; |
| 703 | return _isatty(_fileno(stderr)) != 0 || is_stderr_cyg_pty(); |
| 645 | 704 | #elif defined(ZIG_OS_POSIX) |
| 646 | 705 | return isatty(STDERR_FILENO) != 0; |
| 647 | 706 | #else |
| ... | ... | @@ -859,3 +918,76 @@ int os_self_exe_path(Buf *out_path) { |
| 859 | 918 | #endif |
| 860 | 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 | |
| 928 | static 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 | |
| 948 | void 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 | } |