1 // Copyright Mario Kröplin 2013. 2 // Distributed under the Boost Software License, Version 1.0. 3 // (See accompanying file LICENSE_1_0.txt or copy at 4 // http://www.boost.org/LICENSE_1_0.txt) 5 6 module dunit.color; 7 8 import std.stdio; 9 10 enum Color { red, green, yellow, onRed, onGreen, onYellow } 11 12 version (Posix) 13 { 14 /** 15 * Writes the text in the given color, if possible. 16 */ 17 public void writec(Color color, string text) 18 { 19 if (canUseColor()) 20 { 21 const string CSI = "\x1B["; 22 23 final switch (color) with (Color) 24 { 25 case red: 26 stdout.write(CSI, "37;31;1m"); 27 break; 28 case green: 29 stdout.write(CSI, "37;32;1m"); 30 break; 31 case yellow: 32 stdout.write(CSI, "37;33;1m"); 33 break; 34 case onRed: 35 stdout.write(CSI, "37;41;1m"); 36 break; 37 case onGreen: 38 stdout.write(CSI, "37;42;1m"); 39 break; 40 case onYellow: 41 stdout.write(CSI, "37;43;1m"); 42 break; 43 } 44 stdout.write(text); 45 stdout.write(CSI, "0m"); 46 stdout.flush(); 47 } 48 else 49 { 50 stdout.write(text); 51 stdout.flush(); 52 } 53 } 54 55 private static bool canUseColor() 56 { 57 static bool useColor = false; 58 static bool computed = false; 59 60 if (!computed) 61 { 62 // disable colors if the output is written to a file or pipe instead of a tty 63 import core.sys.posix.unistd : isatty; 64 65 useColor = isatty(stdout.fileno()) != 0; 66 computed = true; 67 } 68 return useColor; 69 } 70 } 71 72 version (Windows) 73 { 74 /** 75 * Writes the text in the given color, if possible. 76 */ 77 public void writec(Color color, string text) 78 { 79 if (canUseColor()) 80 { 81 import core.sys.windows.windows; 82 83 HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); 84 CONSOLE_SCREEN_BUFFER_INFO info; 85 86 GetConsoleScreenBufferInfo(handle, &info); 87 final switch (color) with (Color) 88 { 89 case red: 90 SetConsoleTextAttribute(handle, 91 FOREGROUND_RED | FOREGROUND_INTENSITY); 92 break; 93 case green: 94 SetConsoleTextAttribute(handle, 95 FOREGROUND_GREEN | FOREGROUND_INTENSITY); 96 break; 97 case yellow: 98 SetConsoleTextAttribute(handle, 99 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); 100 break; 101 case onRed: 102 SetConsoleTextAttribute(handle, 103 BACKGROUND_RED | BACKGROUND_INTENSITY); 104 break; 105 case onGreen: 106 SetConsoleTextAttribute(handle, 107 BACKGROUND_GREEN | BACKGROUND_INTENSITY); 108 break; 109 case onYellow: 110 SetConsoleTextAttribute(handle, 111 BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_INTENSITY); 112 break; 113 } 114 stdout.write(text); 115 stdout.flush(); 116 SetConsoleTextAttribute(handle, info.wAttributes); 117 } 118 else 119 { 120 stdout.write(text); 121 stdout.flush(); 122 } 123 } 124 125 private static bool canUseColor() 126 { 127 static bool useColor = false; 128 static bool computed = false; 129 130 if (!computed) 131 { 132 // disable colors if the results output is written to a file or pipe instead of a tty 133 import core.sys.windows.windows; 134 135 CONSOLE_SCREEN_BUFFER_INFO info; 136 137 useColor = GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info) > 0; 138 computed = true; 139 } 140 return useColor; 141 } 142 }