1 /** 2 * Consoleur: a package for interaction with character-oriented terminal emulators 3 * 4 * Copyright: Maxim Freck, 2017. 5 * Authors: Maxim Freck <maxim@freck.pp.ru> 6 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 7 */ 8 module consoleur.style.posix; 9 version(Posix) { 10 11 /// Color list 12 enum Color: uint 13 { 14 //default 8 colors 15 black = 0, 16 maroon, 17 green, 18 olive, 19 navy, 20 purple, 21 teal, 22 silver, 23 24 //light 8 colors 25 grey = 8, 26 red, 27 lime, 28 yellow, 29 blue, 30 fuchsia, 31 aqua, 32 white, 33 34 grayscale1 = 232, 35 grayscale2, 36 grayscale3, 37 grayscale4, 38 grayscale5, 39 grayscale6, 40 grayscale7, 41 grayscale8, 42 grayscale9, 43 grayscale10, 44 grayscale11, 45 grayscale12, 46 grayscale13, 47 grayscale14, 48 grayscale15, 49 grayscale16, 50 grayscale17, 51 grayscale18, 52 grayscale19, 53 grayscale20, 54 grayscale21, 55 grayscale22, 56 grayscale23, 57 grayscale24 58 } 59 60 /// Font styles 61 enum Style: uint { 62 none = 0, 63 bold = 0b00000000_00000000_00000000_00000001, 64 italic = 0b00000000_00000000_00000000_00000010, 65 underline = 0b00000000_00000000_00000000_00000100, 66 blink = 0b00000000_00000000_00000000_00001000, 67 inverted = 0b00000000_00000000_00000000_00010000, 68 linethrough = 0b00000000_00000000_00000000_00100000, 69 } 70 71 72 private Style style; 73 private uint fgColor = Color.white; 74 private uint bgColor = Color.black; 75 76 /******* 77 * Sets default colors 78 */ 79 void setDefaultColors() @safe 80 { 81 import std.stdio: write; 82 write("\x1b[39m\x1b[49m"); 83 } 84 85 /******* 86 * Sets foreground color 87 * Returns: true in case of success, otherwise false 88 * 89 * Params: 90 * c = The color (0-7 — default colors, 8-15 — bright colors) 91 */ 92 bool setFg(Color c) @safe 93 { 94 import std.stdio: writef; 95 96 if (c > 15) return false; 97 fgColor = c; 98 99 if (c > 7) { 100 writef("\033[%u;1m", c+30-8); 101 } else { 102 writef("\033[%um", c+30); 103 } 104 105 return true; 106 } 107 108 /******* 109 * Sets background color 110 * Returns: true in case of success, otherwise false 111 * 112 * Params: 113 * c = The color (0-7 — default colors, 8-15 — bright colors) 114 */ 115 bool setBg(Color c) @safe 116 { 117 import std.stdio: writef; 118 119 if (c > 15) return false; 120 bgColor = c; 121 122 if (c > 7) { 123 writef("\x1b[%u;1m", c+40-8); 124 } else { 125 writef("\x1b[%um", c+40); 126 } 127 128 return true; 129 } 130 131 /******* 132 * Sets terminal colors 133 * Returns: true in case of success, otherwise false 134 * 135 * Params: 136 * fgC = The foreground color 137 * bgC = The background color 138 */ 139 bool setColors(Color fgC, Color bgC) @safe 140 { 141 return (setFg(fgC) && setBg(bgC)); 142 } 143 144 145 /******* 146 * Sets foreground color in a 256 color mode 147 * Returns: true in case of success, otherwise false 148 * 149 * Params: 150 * c = The color 151 */ 152 bool setFg256(uint c) @safe 153 { 154 import std.stdio: writef; 155 156 if (c > 255) return false; 157 158 fgColor = c; 159 writef("\x1b[38;05;%um", c); 160 161 return true; 162 } 163 164 /******* 165 * Sets background color in a 256 color mode 166 * Returns: true in case of success, otherwise false 167 * 168 * Params: 169 * c = The color 170 */ 171 bool setBg256(uint c) @safe 172 { 173 import std.stdio: writef; 174 175 if (c > 255) return false; 176 177 bgColor = c; 178 writef("\x1b[48;05;%um", c); 179 180 return true; 181 } 182 183 /******* 184 * Sets colors in a 256 color mode 185 * Returns: true in case of success, otherwise false 186 * 187 * Params: 188 * fgC = The foreground color 189 * bgC = The background color 190 */ 191 bool setColors256(int fgC, int bgC) @safe 192 { 193 return (setFg256(fgC) && setBg256(bgC)); 194 } 195 196 /******* 197 * Sets foreground color in a TrueColor mode 198 * Returns: true in case of success, otherwise false 199 * 200 * Params: 201 * c = The color 202 */ 203 bool setFg24bit(uint c) @safe 204 { 205 import std.stdio: writef; 206 207 fgColor = c; 208 writef("\x1b[38;2;%u;%u;%um", c.r, c.g, c.b); 209 210 return true; 211 } 212 213 /******* 214 * Sets background color in a TrueColor mode 215 * Returns: true in case of success, otherwise false 216 * 217 * Params: 218 * c = The color 219 */ 220 bool setBg24bit(uint c) @safe 221 { 222 import std.stdio: writef; 223 224 bgColor = c; 225 writef("\x1b[48;2;%u;%u;%um", c.r, c.g, c.b); 226 227 return true; 228 } 229 230 /******* 231 * Sets colors in a TrueColor mode 232 * Returns: true in case of success, otherwise false 233 * 234 * Params: 235 * fgC = The foreground color 236 * bgC = The background color 237 */ 238 void setColors24bit(int fgC, int bgC) @safe 239 { 240 setFg24bit(fgC); 241 setBg24bit(bgC); 242 } 243 244 245 /******* 246 * Builds color code for a TrueColor functions 247 * Returns: uint representing the color code 248 * 249 * Params: 250 * r = red component 251 * g = green component 252 * b = blue component 253 */ 254 pragma(inline) nothrow uint rgb(uint r, uint g, uint b) @safe @nogc 255 { 256 return ((r & 0xff) << 24 | (g & 0xff) << 16 | (b & 0xff) << 8); 257 } 258 259 pragma(inline) private nothrow uint r(uint src) @safe @nogc 260 { 261 return (src & 0xff000000) >> 24; 262 } 263 264 pragma(inline) private nothrow uint g(uint src) @safe @nogc 265 { 266 return (src & 0x00ff0000) >> 16; 267 } 268 269 pragma(inline) private nothrow uint b(uint src) @safe @nogc 270 { 271 return (src & 0x0000ff00) >> 8; 272 } 273 274 275 /******* 276 * Sets text styles (see enum Style) 277 * 278 * Params: 279 * s = The style 280 */ 281 void setStyle(Style s) 282 { 283 import std.stdio: write; 284 string esc; 285 286 if (s == style) return; 287 288 esc.check(s, Style.bold, "\x1b[1m", "\x1b[22m"); 289 esc.check(s, Style.italic, "\x1b[3m", "\x1b[23m"); 290 esc.check(s, Style.underline, "\x1b[4m", "\x1b[24m"); 291 esc.check(s, Style.blink, "\x1b[5m", "\x1b[25m"); 292 esc.check(s, Style.inverted, "\x1b[7m", "\x1b[27m"); 293 esc.check(s, Style.linethrough, "\x1b[9m", "\x1b[29m"); 294 295 style = s; 296 297 write(esc); 298 } 299 300 pragma(inline) private void check(ref string str, Style s, Style st, string on, string off) @safe 301 { 302 if ( (s & st) && !(style & st)) { 303 str ~= on; 304 style |= st; 305 } else if (!(s & st) && (style & st)) { 306 str ~=off; 307 style &= ~st; 308 } 309 } 310 311 }