1 /** 
2  * The custom text transformer that implements the gogga-stylised
3  * logging messages
4  */
5 module gogga.transform;
6 
7 import dlog;
8 import gogga.context;
9 import std.conv : to;
10 
11 /** 
12  * The gogga styles supported
13  */
14 public enum GoggaMode
15 {
16     /** 
17      * TwoKTwenty3 is: `[<file>] (<module>:<lineNumber>) <message>`
18      */
19     TwoKTwenty3,
20 
21     /** 
22      * Simple mode is just: `[<LEVEL>] <message>`
23      */
24     SIMPLE,
25 
26     /** 
27      * Rustacean mode is: `[<LEVEL>] (<filePath>/<functionName>:<lineNumber>) <message>`
28      */
29     RUSTACEAN
30 }
31 
32 /** 
33  * The custom gogga text transformer
34  */
35 public class GoggaTransform : MessageTransform
36 {
37     /** 
38      * Current style
39      */
40     private GoggaMode mode;
41 
42     /** 
43      * Transforms the provided text
44      *
45      * Params:
46      *   text = text to transform
47      *   ctx = the context passed in
48      * Returns: a string of transformed text
49      */
50     public override string transform(string text, Context ctx)
51     {
52         /* The generated output string */
53         string finalOutput;
54 
55 
56         /* Get the GoggaContext */
57         GoggaContext gCtx = cast(GoggaContext)ctx;
58 
59         /* Extract the line information */
60         CompilationInfo compInfo = gCtx.getLineInfo();
61         string[] context = compInfo.toArray();
62 
63         /* Extract the Level */
64         Level level = gCtx.getLevel();
65 
66 
67         /** 
68          * Simple mode is just: `[<LEVEL>] <message>`
69          */
70         if(mode == GoggaMode.SIMPLE)
71         {
72             finalOutput = cast(string)debugColor("["~to!(string)(level)~"] ", level);
73 
74             finalOutput ~= text~"\n";
75         }
76         /** 
77          * TwoKTwenty3 is: `[<file>] (<module>:<lineNumber>) <message>`
78          */
79         else if(mode == GoggaMode.TwoKTwenty3)
80         {
81             /* Module information (and status debugColoring) */
82             string moduleInfo = cast(string)debugColor("["~context[1]~"]", level);
83             
84             /* Function and line number info */
85             string funcInfo = cast(string)(colorSrc("("~context[4]~":"~context[2]~")"));
86 
87             finalOutput =  moduleInfo~" "~funcInfo~" "~text~"\n";
88         }
89         /** 
90          * Rustacean mode is: `[<LEVEL>] (<filePath>/<functionName>:<lineNumber>) <message>`
91          */
92         else
93         {
94             finalOutput = cast(string)debugColor(to!(string)(level)~"\t", level);
95             finalOutput ~= cast(string)(colorSrc(context[1]~"/"~context[4]~":"~context[2]~"  "));
96             finalOutput ~= text~"\n";
97         }
98 
99         return finalOutput;
100     }
101 
102     /** 
103      * Set the gogga style
104      *
105      * Params:
106      *   mode = the GoggaMode to use
107      */
108     public void setMode(GoggaMode mode)
109     {
110         this.mode = mode;
111     }
112 }
113 
114 /** 
115  * Colorise the text provided accoridng to the level and then
116  * reset the colors at the end
117  *
118  * Params:
119  *   text = the text to colorise
120  *   level = the color to use
121  * Returns: the byte sequence of characters and controls
122  */
123 private byte[] debugColor(string text, Level level)
124 {
125     /* The generated message */
126     byte[] messageBytes;
127 
128     /* If INFO, set green */
129     if(level == Level.INFO)
130     {
131         messageBytes = cast(byte[])[27, '[','3','2','m'];
132     }
133     /* If WARNING, set warning */
134     else if(level == Level.WARN)
135     {
136         messageBytes = cast(byte[])[27, '[','3','5','m']; /* TODO: FInd yllow */
137     }
138     /* If ERROR, set error */
139     else if(level == Level.ERROR)
140     {
141         messageBytes = cast(byte[])[27, '[','3','1','m'];
142     }
143 
144     /* Add the message */
145     messageBytes ~= cast(byte[])text;
146 
147     /* Switch back debugColor */
148     messageBytes ~= cast(byte[])[27, '[', '3', '9', 'm'];
149 
150     /* Reset coloring */
151     messageBytes ~= [27, '[', 'm'];
152 
153     return messageBytes;
154 }
155 
156 /** 
157  * Colors the provided text in a gray fashion and then
158  * resets back to normal
159  *
160  * Params:
161  *   text = the text to gray color
162  * Returns: the byte sequence of characters and controls
163  */
164 private byte[] colorSrc(string text)
165 {
166     /* The generated message */
167     byte[] messageBytes;
168 
169     /* Reset coloring */
170     messageBytes ~= [27, '[', 'm'];
171 
172     /* Color gray */
173     messageBytes ~= [27, '[', '3', '9', ';', '2', 'm'];
174 
175     /* Append the message */
176     messageBytes ~= text;
177 
178     /* Reset coloring */
179     messageBytes ~= [27, '[', 'm'];
180 
181     return messageBytes;
182 }