MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Commentator.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <source_location>
4#include <string_view>
5
6#ifdef MAYAFLUX_PLATFORM_WINDOWS
7#include <windows.h>
8#ifdef ERROR
9#undef ERROR
10#endif // ERROR
11#endif // MAYAFLUX_PLATFORM_WINDOWS
12
13namespace Lila {
14
15/**
16 * @namespace Colors
17 * @brief ANSI color codes for terminal output.
18 *
19 * Provides color codes for use in log messages. Automatically enabled on supported platforms.
20 */
21namespace Colors {
22 constexpr std::string_view Reset = "\033[0m";
23 constexpr std::string_view Red = "\033[31m";
24 constexpr std::string_view Green = "\033[32m";
25 constexpr std::string_view Yellow = "\033[33m";
26 constexpr std::string_view Blue = "\033[34m";
27 constexpr std::string_view Magenta = "\033[35m";
28 constexpr std::string_view Cyan = "\033[36m";
29 constexpr std::string_view BrightRed = "\033[91m";
30 constexpr std::string_view BrightBlue = "\033[94m";
31}
32
33/**
34 * @enum LogLevel
35 * @brief Log severity levels for Commentator.
36 *
37 * Controls filtering and formatting of log output.
38 */
39enum class LogLevel : uint8_t {
40 TRACE, ///< Fine-grained debug information
41 DEBUG, ///< Debug-level information
42 INFO, ///< Informational messages
43 WARN, ///< Warnings
44 ERROR, ///< Errors
45 FATAL ///< Fatal errors
46};
47
48/**
49 * @enum Emitter
50 * @brief Source category for log messages.
51 *
52 * Used to indicate which subsystem emitted the log.
53 */
54enum class Emitter : uint8_t {
55 SERVER, ///< TCP server, connection handling
56 INTERPRETER, ///< Clang interpreter, compilation, symbol resolution
57 SYSTEM, ///< System-level operations, initialization
58 GENERAL ///< General/uncategorized
59};
60
61/**
62 * @class Commentator
63 * @brief Centralized, thread-safe logging and announcement system for Lila.
64 *
65 * The Commentator class provides formatted, colorized, and categorized logging for all Lila subsystems.
66 * It supports log levels, verbosity, and source tagging, and is designed for both interactive and automated use.
67 *
68 * ## Core Features
69 * - Singleton access via Commentator::instance()
70 * - Log level filtering and verbosity control
71 * - Colorized output (ANSI codes, auto-enabled on supported platforms)
72 * - Source location reporting (file, line) for verbose/error/fatal logs
73 * - Thread-safe logging (mutex-protected)
74 * - Macros for convenient logging (LILA_INFO, LILA_ERROR, etc.)
75 *
76 * ## Usage Example
77 * ```cpp
78 * LILA_INFO(Lila::Emitter::SYSTEM, "Server started");
79 * LILA_ERROR(Lila::Emitter::INTERPRETER, "Compilation failed");
80 * Lila::Commentator::instance().set_level(Lila::LogLevel::DEBUG);
81 * Lila::Commentator::instance().set_verbose(true);
82 * ```
83 *
84 * Commentator is intended for internal use by Lila and its binaries.
85 */
86class LILA_API Commentator {
87public:
89 {
90 static Commentator commentary;
91 return commentary;
92 }
93
94 void set_level(LogLevel level)
95 {
96 std::lock_guard lock(m_mutex);
97 m_min_level = level;
98 }
99
100 /**
101 * @brief Enables or disables verbose output (shows source location).
102 * @param verbose True to enable verbose mode.
103 */
104 void set_verbose(bool verbose)
105 {
106 m_verbose = verbose;
107 }
108
109 /**
110 * @brief Announces a log message with full control.
111 * @param level Log severity.
112 * @param source Emitter subsystem.
113 * @param message Log message.
114 * @param location Source location (auto-filled).
115 */
116 void announce(LogLevel level, Emitter source, std::string_view message,
117 std::source_location location = std::source_location::current())
118 {
119 if (level < m_min_level)
120 return;
121
122 std::lock_guard lock(m_mutex);
123
124 auto use_color = [this](std::string_view color_code) {
125 return m_colors_enabled ? color_code : "";
126 };
127
128 std::cout << " "; // 8 spaces indent
129
130 std::cout << use_color(Colors::BrightBlue)
131 << "▶ LILA "
132 << use_color(Colors::Reset);
133
134 std::cout << use_color(level_color(level))
135 << "|" << level_string(level) << "| "
136 << use_color(Colors::Reset);
137
138 std::cout << use_color(Colors::Cyan)
139 << emitter_string(source) << " → "
140 << use_color(Colors::Reset);
141
142 std::cout << message;
143
144 if (m_verbose || level >= LogLevel::ERROR) {
145 if (location.file_name() != nullptr) {
146 std::cout << use_color(Colors::BrightBlue)
147 << " (" << extract_filename(location.file_name())
148 << ":" << location.line() << ")"
149 << use_color(Colors::Reset);
150 }
151 }
152
153 std::cout << "\n";
154 }
155
156 /**
157 * @brief Logs a TRACE-level message.
158 * @param source Emitter subsystem.
159 * @param message Log message.
160 * @param location Source location (auto-filled).
161 */
162 void trace(Emitter source, std::string_view message,
163 std::source_location location = std::source_location::current())
164 {
165 announce(LogLevel::TRACE, source, message, location);
166 }
167
168 /**
169 * @brief Logs a DEBUG-level message.
170 * @param source Emitter subsystem.
171 * @param message Log message.
172 * @param location Source location (auto-filled).
173 */
174 void debug(Emitter source, std::string_view message,
175 std::source_location location = std::source_location::current())
176 {
177 announce(LogLevel::DEBUG, source, message, location);
178 }
179
180 /**
181 * @brief Logs an INFO-level message.
182 * @param source Emitter subsystem.
183 * @param message Log message.
184 * @param location Source location (auto-filled).
185 */
186 void info(Emitter source, std::string_view message,
187 std::source_location location = std::source_location::current())
188 {
189 announce(LogLevel::INFO, source, message, location);
190 }
191
192 /**
193 * @brief Logs a WARN-level message.
194 * @param source Emitter subsystem.
195 * @param message Log message.
196 * @param location Source location (auto-filled).
197 */
198 void warn(Emitter source, std::string_view message,
199 std::source_location location = std::source_location::current())
200 {
201 announce(LogLevel::WARN, source, message, location);
202 }
203
204 /**
205 * @brief Logs an ERROR-level message.
206 * @param source Emitter subsystem.
207 * @param message Log message.
208 * @param location Source location (auto-filled).
209 */
210 void error(Emitter source, std::string_view message,
211 std::source_location location = std::source_location::current())
212 {
213 announce(LogLevel::ERROR, source, message, location);
214 }
215
216 /**
217 * @brief Logs a FATAL-level message.
218 * @param source Emitter subsystem.
219 * @param message Log message.
220 * @param location Source location (auto-filled).
221 */
222 void fatal(Emitter source, std::string_view message,
223 std::source_location location = std::source_location::current())
224 {
225 announce(LogLevel::FATAL, source, message, location);
226 }
227
228 Commentator(const Commentator&) = delete;
230
231private:
232 /**
233 * @brief Initializes console color support (platform-specific).
234 * @return True if colors are enabled.
235 */
237 : m_colors_enabled(initialize_console_colors())
238 {
239 }
240
241 std::mutex m_mutex;
242 LogLevel m_min_level = LogLevel::INFO;
243 bool m_verbose = false;
245
247 {
248#ifdef _WIN32
249 // Enable ANSI escape sequences on Windows 10+
250 HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
251 if (hOut == INVALID_HANDLE_VALUE) {
252 return false;
253 }
254
255 DWORD dwMode = 0;
256 if (!GetConsoleMode(hOut, &dwMode)) {
257 return false;
258 }
259
260 dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
261 if (!SetConsoleMode(hOut, dwMode)) {
262 // Fallback: colors not supported on this Windows version
263 return false;
264 }
265 return true;
266#else
267 // Unix/Linux/macOS: ANSI colors always supported
268 return true;
269#endif
270 }
271
272 /**
273 * @brief Gets the ANSI color code for a log level.
274 * @param level LogLevel value.
275 * @return Color code string.
276 */
277 static constexpr std::string_view level_color(LogLevel level)
278 {
279 switch (level) {
280 case LogLevel::TRACE:
281 return Colors::Cyan;
282 case LogLevel::DEBUG:
283 return Colors::Blue;
284 case LogLevel::INFO:
285 return Colors::Green;
286 case LogLevel::WARN:
287 return Colors::Yellow;
288 case LogLevel::ERROR:
289 case LogLevel::FATAL:
290 return Colors::BrightRed;
291 default:
292 return Colors::Reset;
293 }
294 }
295
296 /**
297 * @brief Gets the string representation of a log level.
298 * @param level LogLevel value.
299 * @return Log level string.
300 */
301 static constexpr std::string_view level_string(LogLevel level)
302 {
303 switch (level) {
304 case LogLevel::TRACE:
305 return "TRACE";
306 case LogLevel::DEBUG:
307 return "DEBUG";
308 case LogLevel::INFO:
309 return "INFO";
310 case LogLevel::WARN:
311 return "WARN";
312 case LogLevel::ERROR:
313 return "ERROR";
314 case LogLevel::FATAL:
315 return "FATAL";
316 default:
317 return "UNKNOWN";
318 }
319 }
320
321 /**
322 * @brief Gets the string representation of an emitter.
323 * @param source Emitter value.
324 * @return Emitter string.
325 */
326 static constexpr std::string_view emitter_string(Emitter source)
327 {
328 switch (source) {
329 case Emitter::SERVER:
330 return "SERVER";
331 case Emitter::INTERPRETER:
332 return "INTERP";
333 case Emitter::SYSTEM:
334 return "SYSTEM";
335 case Emitter::GENERAL:
336 return "GENERAL";
337 default:
338 return "UNKNOWN";
339 }
340 }
341
342 /**
343 * @brief Extracts the filename from a file path.
344 * @param path File path.
345 * @return Filename string view.
346 */
347 static std::string_view extract_filename(const char* path)
348 {
349 std::string_view sv(path);
350 auto pos = sv.find_last_of("/\\");
351 return (pos == std::string_view::npos) ? sv : sv.substr(pos + 1);
352 }
353};
354
355} // namespace Lila
356
357#define LILA_TRACE(emitter, msg) ::Lila::Commentator::instance().trace(emitter, msg)
358#define LILA_DEBUG(emitter, msg) ::Lila::Commentator::instance().debug(emitter, msg)
359#define LILA_INFO(emitter, msg) ::Lila::Commentator::instance().info(emitter, msg)
360#define LILA_WARN(emitter, msg) ::Lila::Commentator::instance().warn(emitter, msg)
361#define LILA_ERROR(emitter, msg) ::Lila::Commentator::instance().error(emitter, msg)
362#define LILA_FATAL(emitter, msg) ::Lila::Commentator::instance().fatal(emitter, msg)
static std::string_view extract_filename(const char *path)
Extracts the filename from a file path.
void set_verbose(bool verbose)
Enables or disables verbose output (shows source location).
Commentator & operator=(const Commentator &)=delete
void announce(LogLevel level, Emitter source, std::string_view message, std::source_location location=std::source_location::current())
Announces a log message with full control.
void trace(Emitter source, std::string_view message, std::source_location location=std::source_location::current())
Logs a TRACE-level message.
void info(Emitter source, std::string_view message, std::source_location location=std::source_location::current())
Logs an INFO-level message.
static bool initialize_console_colors()
static constexpr std::string_view emitter_string(Emitter source)
Gets the string representation of an emitter.
void set_level(LogLevel level)
static constexpr std::string_view level_string(LogLevel level)
Gets the string representation of a log level.
static Commentator & instance()
void warn(Emitter source, std::string_view message, std::source_location location=std::source_location::current())
Logs a WARN-level message.
Commentator(const Commentator &)=delete
void error(Emitter source, std::string_view message, std::source_location location=std::source_location::current())
Logs an ERROR-level message.
Commentator()
Initializes console color support (platform-specific).
void debug(Emitter source, std::string_view message, std::source_location location=std::source_location::current())
Logs a DEBUG-level message.
static constexpr std::string_view level_color(LogLevel level)
Gets the ANSI color code for a log level.
void fatal(Emitter source, std::string_view message, std::source_location location=std::source_location::current())
Logs a FATAL-level message.
Centralized, thread-safe logging and announcement system for Lila.
Emitter
Source category for log messages.
LogLevel
Log severity levels for Commentator.
ANSI color codes for terminal output.
constexpr std::string_view Red
constexpr std::string_view Cyan
constexpr std::string_view BrightRed
constexpr std::string_view Green
constexpr std::string_view Blue
constexpr std::string_view BrightBlue
constexpr std::string_view Magenta
constexpr std::string_view Yellow
constexpr std::string_view Reset