diff --git a/src/debug/ansi-escape-codes.cpp b/src/debug/ansi-escape-codes.cpp
new file mode 100644
index 0000000..fcb5c99
--- /dev/null
+++ b/src/debug/ansi-escape-codes.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2017-2019 Christopher J. Howard
+ *
+ * This file is part of Antkeeper Source Code.
+ *
+ * Antkeeper Source Code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Antkeeper Source Code is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Antkeeper Source Code. If not, see .
+ */
+
+#include "ansi-escape-codes.hpp"
+
+const char* ANSI_CODE_RESET = "\u001b[0m";
+
+const char* ANSI_CODE_BLACK = "\u001b[30m";
+const char* ANSI_CODE_RED = "\u001b[31m";
+const char* ANSI_CODE_GREEN = "\u001b[32m";
+const char* ANSI_CODE_YELLOW = "\u001b[33m";
+const char* ANSI_CODE_BLUE = "\u001b[34m";
+const char* ANSI_CODE_MAGENTA = "\u001b[35m";
+const char* ANSI_CODE_CYAN = "\u001b[36m";
+const char* ANSI_CODE_WHITE = "\u001b[37m";
+
+const char* ANSI_CODE_BRIGHT_BLACK = "\u001b[30;1m";
+const char* ANSI_CODE_BRIGHT_RED = "\u001b[31;1m";
+const char* ANSI_CODE_BRIGHT_GREEN = "\u001b[32;1m";
+const char* ANSI_CODE_BRIGHT_YELLOW = "\u001b[33;1m";
+const char* ANSI_CODE_BRIGHT_BLUE = "\u001b[34;1m";
+const char* ANSI_CODE_BRIGHT_MAGENTA = "\u001b[35;1m";
+const char* ANSI_CODE_BRIGHT_CYAN = "\u001b[36;1m";
+const char* ANSI_CODE_BRIGHT_WHITE = "\u001b[37;1m";
+
+const char* ANSI_CODE_BACKGROUND_BLACK = "\u001b[40m";
+const char* ANSI_CODE_BACKGROUND_RED = "\u001b[41m";
+const char* ANSI_CODE_BACKGROUND_GREEN = "\u001b[42m";
+const char* ANSI_CODE_BACKGROUND_YELLOW = "\u001b[43m";
+const char* ANSI_CODE_BACKGROUND_BLUE = "\u001b[44m";
+const char* ANSI_CODE_BACKGROUND_MAGENTA = "\u001b[45m";
+const char* ANSI_CODE_BACKGROUND_CYAN = "\u001b[46m";
+const char* ANSI_CODE_BACKGROUND_WHITE = "\u001b[47m";
+
+const char* ANSI_CODE_BACKGROUND_BRIGHT_BLACK = "\u001b[40;1m";
+const char* ANSI_CODE_BACKGROUND_BRIGHT_RED = "\u001b[41;1m";
+const char* ANSI_CODE_BACKGROUND_BRIGHT_GREEN = "\u001b[42;1m";
+const char* ANSI_CODE_BACKGROUND_BRIGHT_YELLOW = "\u001b[43;1m";
+const char* ANSI_CODE_BACKGROUND_BRIGHT_BLUE = "\u001b[44;1m";
+const char* ANSI_CODE_BACKGROUND_BRIGHT_MAGENTA = "\u001b[45;1m";
+const char* ANSI_CODE_BACKGROUND_BRIGHT_CYAN = "\u001b[46;1m";
+const char* ANSI_CODE_BACKGROUND_BRIGHT_WHITE = "\u001b[47;1m";
+
+const char* ANSI_CODE_BOLD = "\u001b[1m";
+const char* ANSI_CODE_UNDERLINE = "\u001b[4m";
+const char* ANSI_CODE_REVERSED = "\u001b[7m";
+
+
+
+
diff --git a/src/debug/ansi-escape-codes.hpp b/src/debug/ansi-escape-codes.hpp
new file mode 100644
index 0000000..ae92768
--- /dev/null
+++ b/src/debug/ansi-escape-codes.hpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2017-2019 Christopher J. Howard
+ *
+ * This file is part of Antkeeper Source Code.
+ *
+ * Antkeeper Source Code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Antkeeper Source Code is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Antkeeper Source Code. If not, see .
+ */
+
+#ifndef ANSI_ESCAPE_CODES_HPP
+#define ANSI_ESCAPE_CODES_HPP
+
+// Reset code
+extern const char* ANSI_CODE_RESET;
+
+// Standard colors
+extern const char* ANSI_CODE_BLACK;
+extern const char* ANSI_CODE_RED;
+extern const char* ANSI_CODE_GREEN;
+extern const char* ANSI_CODE_YELLOW;
+extern const char* ANSI_CODE_BLUE;
+extern const char* ANSI_CODE_MAGENTA;
+extern const char* ANSI_CODE_CYAN;
+extern const char* ANSI_CODE_WHITE;
+
+// Bright colors
+extern const char* ANSI_CODE_BRIGHT_BLACK;
+extern const char* ANSI_CODE_BRIGHT_RED;
+extern const char* ANSI_CODE_BRIGHT_GREEN;
+extern const char* ANSI_CODE_BRIGHT_YELLOW;
+extern const char* ANSI_CODE_BRIGHT_BLUE;
+extern const char* ANSI_CODE_BRIGHT_MAGENTA;
+extern const char* ANSI_CODE_BRIGHT_CYAN;
+extern const char* ANSI_CODE_BRIGHT_WHITE;
+
+// Standard background colors
+extern const char* ANSI_CODE_BACKGROUND_BLACK;
+extern const char* ANSI_CODE_BACKGROUND_RED;
+extern const char* ANSI_CODE_BACKGROUND_GREEN;
+extern const char* ANSI_CODE_BACKGROUND_YELLOW;
+extern const char* ANSI_CODE_BACKGROUND_BLUE;
+extern const char* ANSI_CODE_BACKGROUND_MAGENTA;
+extern const char* ANSI_CODE_BACKGROUND_CYAN;
+extern const char* ANSI_CODE_BACKGROUND_WHITE;
+
+// Bright background colors
+extern const char* ANSI_CODE_BACKGROUND_BRIGHT_BLACK;
+extern const char* ANSI_CODE_BACKGROUND_BRIGHT_RED;
+extern const char* ANSI_CODE_BACKGROUND_BRIGHT_GREEN;
+extern const char* ANSI_CODE_BACKGROUND_BRIGHT_YELLOW;
+extern const char* ANSI_CODE_BACKGROUND_BRIGHT_BLUE;
+extern const char* ANSI_CODE_BACKGROUND_BRIGHT_MAGENTA;
+extern const char* ANSI_CODE_BACKGROUND_BRIGHT_CYAN;
+extern const char* ANSI_CODE_BACKGROUND_BRIGHT_WHITE;
+
+// Decorations
+extern const char* ANSI_CODE_BOLD;
+extern const char* ANSI_CODE_UNDERLINE;
+extern const char* ANSI_CODE_REVERSED;
+
+#endif // ANSI_ESCAPE_CODES_HPP
+
diff --git a/src/debug/logger.cpp b/src/debug/logger.cpp
index b0817ef..0498c7e 100644
--- a/src/debug/logger.cpp
+++ b/src/debug/logger.cpp
@@ -18,10 +18,19 @@
*/
#include "logger.hpp"
+#include "ansi-escape-codes.hpp"
#include
Logger::Logger():
- os(&std::cout)
+ os(&std::cout),
+ logPrefix(std::string()),
+ logPostfix("\n"),
+ warningPrefix(ANSI_CODE_YELLOW + std::string("Warning: ")),
+ warningPostfix(ANSI_CODE_RESET),
+ errorPrefix(ANSI_CODE_RED + std::string("Error: ")),
+ errorPostfix(ANSI_CODE_RESET),
+ successPrefix(ANSI_CODE_GREEN + std::string("Success: ")),
+ successPostfix(ANSI_CODE_RESET)
{}
Logger::~Logger()
@@ -36,8 +45,63 @@ void Logger::log(const std::string& text)
{
if (os)
{
- (*os) << text;
+ (*os) << (logPrefix + text + logPostfix);
os->flush();
}
}
+void Logger::warning(const std::string& text)
+{
+ log(warningPrefix + text + warningPostfix);
+}
+
+void Logger::error(const std::string& text)
+{
+ log(errorPrefix + text + errorPostfix);
+}
+
+void Logger::success(const std::string& text)
+{
+ log(successPrefix + text + successPostfix);
+}
+
+void Logger::setLogPrefix(const std::string& prefix)
+{
+ logPrefix = prefix;
+}
+
+void Logger::setLogPostfix(const std::string& postfix)
+{
+ logPostfix = postfix;
+}
+
+void Logger::setWarningPrefix(const std::string& prefix)
+{
+ warningPrefix = prefix;
+}
+
+void Logger::setWarningPostfix(const std::string& postfix)
+{
+ warningPostfix = postfix;
+}
+
+void Logger::setErrorPrefix(const std::string& prefix)
+{
+ errorPrefix = prefix;
+}
+
+void Logger::setErrorPostfix(const std::string& postfix)
+{
+ errorPostfix = postfix;
+}
+
+void Logger::setSuccessPrefix(const std::string& prefix)
+{
+ successPrefix = prefix;
+}
+
+void Logger::setSuccessPostfix(const std::string& postfix)
+{
+ successPostfix = postfix;
+}
+
diff --git a/src/debug/logger.hpp b/src/debug/logger.hpp
index 3529568..d343e3e 100644
--- a/src/debug/logger.hpp
+++ b/src/debug/logger.hpp
@@ -40,8 +40,29 @@ public:
*/
void log(const std::string& text);
+ void warning(const std::string& text);
+ void error(const std::string& text);
+ void success(const std::string& text);
+
+ void setLogPrefix(const std::string& prefix);
+ void setLogPostfix(const std::string& postfix);
+ void setWarningPrefix(const std::string& prefix);
+ void setWarningPostfix(const std::string& postfix);
+ void setErrorPrefix(const std::string& prefix);
+ void setErrorPostfix(const std::string& postfix);
+ void setSuccessPrefix(const std::string& prefix);
+ void setSuccessPostfix(const std::string& postfix);
+
private:
std::ostream* os;
+ std::string logPrefix;
+ std::string logPostfix;
+ std::string warningPrefix;
+ std::string warningPostfix;
+ std::string errorPrefix;
+ std::string errorPostfix;
+ std::string successPrefix;
+ std::string successPostfix;
};
#endif // LOGGER_HPP
diff --git a/src/game.cpp b/src/game.cpp
index 527bce2..95ff21e 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -66,6 +66,7 @@
#include "debug/command-interpreter.hpp"
#include "debug/logger.hpp"
+#include "debug/ansi-escape-codes.hpp"
template <>
bool Game::readSetting(const std::string& name, std::string* value) const
@@ -506,7 +507,7 @@ void Game::setup()
}
catch (const std::exception& e)
{
- logger->log("Failed to load one or more models: \"" + std::string(e.what()) + "\"\n");
+ logger->error("Failed to load one or more models: \"" + std::string(e.what()) + "\"\n");
close(EXIT_FAILURE);
}
@@ -746,10 +747,45 @@ void Game::handleEvent(const ScheduledFunctionEvent& event)
void Game::setupDebugging()
{
// Setup logging
- logger = new Logger();
- std::string logFilename = configPath + "log.txt";
- logFileStream.open(logFilename.c_str());
- logger->redirect(&logFileStream);
+ {
+ logger = new Logger();
+
+ // Style log format
+ std::string logPrefix = std::string();
+ std::string logPostfix = "\n";
+ std::string warningPrefix = "Warning: ";
+ std::string warningPostfix = std::string();
+ std::string errorPrefix = "Error: ";
+ std::string errorPostfix = std::string();
+ std::string successPrefix = std::string();
+ std::string successPostfix = std::string();
+
+ // Enable colored messages on debug builds
+ #if defined(DEBUG)
+ warningPrefix = std::string(ANSI_CODE_BOLD) + std::string(ANSI_CODE_YELLOW) + std::string("Warning: ") + std::string(ANSI_CODE_RESET) + std::string(ANSI_CODE_YELLOW);
+ warningPostfix.append(ANSI_CODE_RESET);
+ errorPrefix = std::string(ANSI_CODE_BOLD) + std::string(ANSI_CODE_RED) + std::string("Error: ") + std::string(ANSI_CODE_RESET) + std::string(ANSI_CODE_RED);
+ errorPostfix.append(ANSI_CODE_RESET);
+ successPrefix.insert(0, ANSI_CODE_GREEN);
+ successPostfix.append(ANSI_CODE_RESET);
+ #endif
+
+ logger->setLogPrefix(logPrefix);
+ logger->setLogPostfix(logPostfix);
+ logger->setWarningPrefix(warningPrefix);
+ logger->setWarningPostfix(warningPostfix);
+ logger->setErrorPrefix(errorPrefix);
+ logger->setErrorPostfix(errorPostfix);
+ logger->setSuccessPrefix(successPrefix);
+ logger->setSuccessPostfix(successPostfix);
+
+ // Redirect logger output to log file on release builds
+ #if !defined(DEBUG)
+ std::string logFilename = configPath + "log.txt";
+ logFileStream.open(logFilename.c_str());
+ logger->redirect(&logFileStream);
+ #endif
+ }
// Create CLI
cli = new CommandInterpreter();
@@ -2034,7 +2070,7 @@ void Game::loadControlProfile(const std::string& profileName)
auto it = controlNameMap.find(controlName);
if (it == controlNameMap.end())
{
- logger->log("Game::loadControlProfile(): Unknown control name \"" + controlName + "\"\n");
+ logger->warning("Game::loadControlProfile(): Unknown control name \"" + controlName + "\"\n");
continue;
}
@@ -2078,7 +2114,7 @@ void Game::loadControlProfile(const std::string& profileName)
}
else
{
- logger->log("Game::loadControlProfile(): Unknown mouse motion axis \"" + axisName + "\"\n");
+ logger->warning("Game::loadControlProfile(): Unknown mouse motion axis \"" + axisName + "\"\n");
continue;
}
@@ -2102,7 +2138,7 @@ void Game::loadControlProfile(const std::string& profileName)
}
else
{
- logger->log("Game::loadControlProfile(): Unknown mouse wheel axis \"" + axisName + "\"\n");
+ logger->warning("Game::loadControlProfile(): Unknown mouse wheel axis \"" + axisName + "\"\n");
continue;
}
@@ -2124,7 +2160,7 @@ void Game::loadControlProfile(const std::string& profileName)
}
else
{
- logger->log("Game::loadControlProfile(): Unknown mouse event type \"" + eventType + "\"\n");
+ logger->warning("Game::loadControlProfile(): Unknown mouse event type \"" + eventType + "\"\n");
continue;
}
}
@@ -2182,13 +2218,13 @@ void Game::loadControlProfile(const std::string& profileName)
}
else
{
- logger->log("Game::loadControlProfile(): Unknown gamepad event type \"" + eventType + "\"\n");
+ logger->warning("Game::loadControlProfile(): Unknown gamepad event type \"" + eventType + "\"\n");
continue;
}
}
else
{
- logger->log("Game::loadControlProfile(): Unknown input device type \"" + deviceType + "\"\n");
+ logger->warning("Game::loadControlProfile(): Unknown input device type \"" + deviceType + "\"\n");
continue;
}
}