1 /**
2  * Logger module.
3  *
4  * License:
5  *     MIT. See LICENSE for full details.
6  */
7 module tkd.interpreter.logger;
8 
9 /**
10  * Imports.
11  */
12 import std.datetime;
13 import std.process;
14 import std.stdio;
15 import std.string;
16 
17 /**
18  * A simple class to provide logging support.
19  */
20 class Logger
21 {
22 	/**
23 	 * Level of importance of the text to write to the logger.
24 	 */
25 	private enum Level
26 	{
27 		/**
28 		 * The eval level is for evaluated commands.
29 		 */
30 		eval,
31 
32 		/**
33 		 * The information level used for info messages.
34 		 */
35 		information,
36 
37 		/**
38 		 * The warning level used for warning messages.
39 		 */
40 		warning,
41 
42 		/**
43 		 * The error level used for error messages.
44 		 */
45 		error,
46 	}
47 
48 	/**
49 	 * The open log file.
50 	 */
51 	private File _log;
52 
53 	/**
54 	 * Constructor.
55 	 *
56 	 * If a log file is not passed, log instead to stdout.
57 	 *
58 	 * Params:
59 	 *     logFile = The log file for logging.
60 	 */
61 	public this(string logFile = null) nothrow
62 	{
63 		try
64 		{
65 			if (logFile is null)
66 			{
67 				this._log = stdout;
68 			}
69 			else
70 			{
71 				this._log = File(logFile, "w");
72 			}
73 		}
74 		catch (Exception ex)
75 		{
76 			assert(false, ex.msg);
77 		}
78 	}
79 
80 	/**
81 	 * Get the current timestamp for the log.
82 	 *
83 	 * Returns:
84 	 *     The current timestamp.
85 	 */
86 	private string getTimestamp() nothrow
87 	{
88 		try
89 		{
90 			auto time = Clock.currTime();
91 			return format("%d/%02d/%02d %d:%02d:%02d", time.year, time.month, time.day, time.hour, time.minute, time.second);
92 		}
93 		catch (Exception ex)
94 		{
95 			assert(false, ex.msg);
96 		}
97 	}
98 
99 	/**
100 	 * Write text to the log.
101 	 *
102 	 * Params:
103 	 *     text = The text to write to the log.
104 	 *     level = The level of the text.
105 	 */
106 	private void log(string text, Level level) nothrow
107 	{
108 		string levelText;
109 
110 		switch(level)
111 		{
112 			case Level.eval:
113 				levelText = "EVAL";
114 				break;
115 
116 			case Level.warning:
117 				levelText = "WARN";
118 				break;
119 
120 			case Level.error:
121 				levelText = "ERROR";
122 				break;
123 
124 			default:
125 				levelText = "INFO";
126 				break;
127 		}
128 
129 		try
130 		{
131 			this._log.writefln("%s %s: %s", this.getTimestamp(), levelText, text);
132 			this._log.flush();
133 		}
134 		catch (Exception ex)
135 		{
136 			assert(false, ex.msg);
137 		}
138 	}
139 
140 	/**
141 	 * Write eval text to the log.
142 	 *
143 	 * Params:
144 	 *     text = The format of the text to write to the log.
145 	 *     args = The arguments that the format defines (if any).
146 	 */
147 	public void eval(A...)(string text, A args) nothrow
148 	{
149 		try
150 		{
151 			this.log(format(text, args), Level.eval);
152 		}
153 		catch (Exception ex)
154 		{
155 			assert(false, ex.msg);
156 		}
157 	}
158 
159 	/**
160 	 * Write info text to the log.
161 	 *
162 	 * Params:
163 	 *     text = The format of the text to write to the log.
164 	 *     args = The arguments that the format defines (if any).
165 	 */
166 	public void info(A...)(string text, A args) nothrow
167 	{
168 		try
169 		{
170 			this.log(format(text, args), Level.information);
171 		}
172 		catch (Exception ex)
173 		{
174 			assert(false, ex.msg);
175 		}
176 	}
177 
178 	/**
179 	 * Write warning text to the log.
180 	 *
181 	 * Params:
182 	 *     text = The format of the text to write to the log.
183 	 *     args = The arguments that the format defines (if any).
184 	 */
185 	public void warning(A...)(string text, A args) nothrow
186 	{
187 		try
188 		{
189 			this.log(format(text, args), Level.warning);
190 		}
191 		catch (Exception ex)
192 		{
193 			assert(false, ex.msg);
194 		}
195 	}
196 
197 	/**
198 	 * Write error text to the log.
199 	 *
200 	 * Params:
201 	 *     text = The format of the text to write to the log.
202 	 *     args = The arguments that the format defines (if any).
203 	 */
204 	public void error(A...)(string text, A args) nothrow
205 	{
206 		try
207 		{
208 			this.log(format(text, args), Level.error);
209 		}
210 		catch (Exception ex)
211 		{
212 			assert(false, ex.msg);
213 		}
214 	}
215 
216 }