/*
Ousía
Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
This program 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.
This program 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 this program. If not, see .
*/
#include
#include
#include "Logger.hpp"
namespace ousia {
/* Class Terminal */
class Terminal {
private:
/**
* If set to false, no control codes are generated.
*/
bool active;
public:
static const int BLACK = 30;
static const int RED = 31;
static const int GREEN = 32;
static const int YELLOW = 33;
static const int BLUE = 34;
static const int MAGENTA = 35;
static const int CYAN = 36;
static const int WHITE = 37;
Terminal(bool active) : active(active) {}
std::string color(int color, bool bright = true) const
{
if (!active) {
return std::string{};
}
std::stringstream ss;
ss << "\x1b[";
if (bright) {
ss << "1;";
}
ss << color << "m";
return ss.str();
}
std::string reset() const
{
if (!active) {
return std::string{};
}
return "\x1b[0m";
}
};
/* Class TerminalLogger */
/**
* Small class used internally for formated terminal output using ANSI/VT100
* escape codes on supported terminals.
*
* TODO: Deactivate if using windows or use the corresponding API function.
*/
std::string TerminalLogger::currentFilename()
{
if (!files.empty()) {
return files.top().file;
}
return std::string{};
}
void TerminalLogger::processMessage(Message msg)
{
Terminal t(useColor);
// Print the file name
std::string filename = currentFilename();
bool hasFile = !filename.empty();
if (hasFile) {
os << t.color(Terminal::WHITE, true) << filename << t.reset();
}
// Print line and column number
if (msg.pos.hasLine()) {
if (hasFile) {
os << ':';
}
os << t.color(Terminal::WHITE, true) << msg.pos.line
<< t.reset();
if (msg.pos.hasColumn()) {
os << ':' << msg.pos.column;
}
}
// Print the optional seperator
if (hasFile || msg.pos.hasLine()) {
os << ": ";
}
// Print the severity
switch (msg.severity) {
case Severity::DEBUG:
break;
case Severity::NOTE:
os << t.color(Terminal::CYAN, true) << "note: ";
break;
case Severity::WARNING:
os << t.color(Terminal::MAGENTA, true) << "warning: ";
break;
case Severity::ERROR:
os << t.color(Terminal::RED, true) << "error: ";
break;
case Severity::FATAL_ERROR:
os << t.color(Terminal::RED, true) << "fatal: ";
break;
}
os << t.reset();
// Print the actual message
os << msg.msg << std::endl;
// Print the error message context if available
if (msg.ctx.valid()) {
size_t relPos = msg.ctx.relPos;
if (msg.ctx.truncatedStart) {
os << "[...] ";
relPos += 6;
}
os << msg.ctx.text;
if (msg.ctx.truncatedEnd) {
os << " [...]";
}
os << std::endl;
for (size_t i = 0; i < relPos; i++) {
os << ' ';
}
os << t.color(Terminal::GREEN) << '^' << t.reset() << std::endl;
}
}
size_t TerminalLogger::processPushFile(File file)
{
files.push(file);
return files.size();
}
size_t TerminalLogger::processPopFile()
{
files.pop();
return files.size();
}
}