1 /**
2  * Copyright: Copyright Jason White, 2016
3  * License:   MIT
4  * Authors:   Jason White
5  *
6  * Description:
7  * Helper module for colorizing terminal output.
8  */
9 module button.textcolor;
10 
11 /*
12  * Black        0;30     Dark Gray     1;30
13  * Red          0;31     Light Red     1;31
14  * Green        0;32     Light Green   1;32
15  * Brown/Orange 0;33     Yellow        1;33
16  * Blue         0;34     Light Blue    1;34
17  * Purple       0;35     Light Purple  1;35
18  * Cyan         0;36     Light Cyan    1;36
19  * Light Gray   0;37     White         1;37
20 */
21 
22 private
23 {
24     immutable black     = "\033[0;30m", boldBlack     = "\033[1;30m",
25               red       = "\033[0;31m", boldRed       = "\033[1;31m",
26               green     = "\033[0;32m", boldGreen     = "\033[1;32m",
27               orange    = "\033[0;33m", boldOrange    = "\033[1;33m",
28               blue      = "\033[0;34m", boldBlue      = "\033[1;34m",
29               purple    = "\033[0;35m", boldPurple    = "\033[1;35m",
30               cyan      = "\033[0;36m", boldCyan      = "\033[1;36m",
31               lightGray = "\033[0;37m", boldLightGray = "\033[1;37m";
32 
33     immutable bold  = "\033[1m";
34     immutable reset = "\033[0m";
35 
36     immutable success = boldGreen;
37     immutable error   = boldRed;
38     immutable warning = boldOrange;
39     immutable status  = blue;
40 }
41 
42 struct TextColor
43 {
44     private bool _enabled;
45 
46     this(bool enabled)
47     {
48         _enabled = enabled;
49     }
50 
51     @property
52     immutable(string) opDispatch(string name)() const pure nothrow
53     {
54         if (!_enabled)
55             return "";
56 
57         return mixin(name);
58     }
59 }
60 
61 /**
62  * Returns true if the output is capable of being colorized.
63  */
64 version (Windows)
65 {
66     enum colorizable = false;
67 }
68 else
69 {
70     bool colorizable()
71     {
72         // FIXME: Check on a stream-by-stream basis. If stderr is a terminal,
73         // but stdout isn't, then this fails to do the correct thing.
74         import io.file.stdio : stdout;
75         return stdout.isTerminal;
76     }
77 }
78 
79 /**
80  * Returns true if the output should be colored based on the given option.
81  */
82 bool colorOutput(string option)
83 {
84     switch (option)
85     {
86         case "always":
87             return true;
88         case "never":
89             return false;
90         default:
91             return colorizable;
92     }
93 }