From 99c6f5df144d0530fe43225d353dee881cfdf26a Mon Sep 17 00:00:00 2001 From: Andreas Stöckel Date: Sat, 24 Jan 2015 13:23:55 +0100 Subject: Moved Terminal and TerminalLogger to own classes in new frontent folder --- src/core/common/Logger.cpp | 143 ++------------------------------ src/core/common/Logger.hpp | 61 +++----------- src/core/common/Terminal.cpp | 58 ------------- src/core/common/Terminal.hpp | 124 ---------------------------- src/core/frontend/Terminal.cpp | 58 +++++++++++++ src/core/frontend/Terminal.hpp | 124 ++++++++++++++++++++++++++++ src/core/frontend/TerminalLogger.cpp | 151 ++++++++++++++++++++++++++++++++++ src/core/frontend/TerminalLogger.hpp | 79 ++++++++++++++++++ src/core/resource/ResourceManager.cpp | 2 +- 9 files changed, 432 insertions(+), 368 deletions(-) delete mode 100644 src/core/common/Terminal.cpp delete mode 100644 src/core/common/Terminal.hpp create mode 100644 src/core/frontend/Terminal.cpp create mode 100644 src/core/frontend/Terminal.hpp create mode 100644 src/core/frontend/TerminalLogger.cpp create mode 100644 src/core/frontend/TerminalLogger.hpp (limited to 'src') diff --git a/src/core/common/Logger.cpp b/src/core/common/Logger.cpp index aa61e6a..54156f2 100644 --- a/src/core/common/Logger.cpp +++ b/src/core/common/Logger.cpp @@ -20,8 +20,6 @@ #include #include "Logger.hpp" -#include "Terminal.hpp" -#include "Utils.hpp" namespace ousia { @@ -118,49 +116,49 @@ void LoggerFork::commit() purge(); } -/* Class ScopedLogger */ +/* Class GuardedLogger */ -ScopedLogger::ScopedLogger(Logger &parent, SourceLocation loc) +GuardedLogger::GuardedLogger(Logger &parent, SourceLocation loc) : parent(parent), depth(0) { pushDefaultLocation(loc); } -ScopedLogger::~ScopedLogger() +GuardedLogger::~GuardedLogger() { while (depth > 0) { popDefaultLocation(); } } -void ScopedLogger::processMessage(const Message &msg) +void GuardedLogger::processMessage(const Message &msg) { parent.processMessage(msg); } -bool ScopedLogger::filterMessage(const Message &msg) +bool GuardedLogger::filterMessage(const Message &msg) { return parent.filterMessage(msg); } -void ScopedLogger::processPushDefaultLocation(const SourceLocation &loc) +void GuardedLogger::processPushDefaultLocation(const SourceLocation &loc) { parent.processPushDefaultLocation(loc); depth++; } -void ScopedLogger::processPopDefaultLocation() +void GuardedLogger::processPopDefaultLocation() { depth--; parent.processPopDefaultLocation(); } -void ScopedLogger::processSetDefaultLocation(const SourceLocation &loc) +void GuardedLogger::processSetDefaultLocation(const SourceLocation &loc) { parent.processSetDefaultLocation(loc); } -void ScopedLogger::processSetSourceContextCallback( +void GuardedLogger::processSetSourceContextCallback( SourceContextCallback sourceContextCallback) { parent.processSetSourceContextCallback(sourceContextCallback); @@ -265,128 +263,5 @@ bool ConcreteLogger::hasFatalError() return getSeverityCount(Severity::FATAL_ERROR) > 0; } -/* Class TerminalLogger */ - -void TerminalLogger::processMessage(const Message &msg) -{ - Terminal t(useColor); - - // Fetch filename, position and context - const SourceContext ctx = messageContext(msg); - - // Print the file name - if (ctx.hasFile()) { - os << t.bright() << ctx.filename << t.reset(); - } - - // Print line and column number - if (ctx.hasLine()) { - if (ctx.hasFile()) { - os << ':'; - } - os << t.bright() << ctx.startLine << t.reset(); - if (ctx.hasColumn()) { - os << ':' << ctx.startColumn; - } - } - - // Print the optional seperator - if (ctx.hasFile() || ctx.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 error: "; - break; - } - os << t.reset(); - - // Print the actual message - os << msg.msg << std::endl; - - // Print the error message context if available - if (ctx.hasText()) { - // Iterate over each line in the text - std::vector lines = Utils::split(ctx.text, '\n'); - - const size_t relLen = ctx.relLen ? ctx.relLen : 1; - const size_t relPos = ctx.relPos; - const size_t pstart = relPos; - const size_t pend = relPos + relLen; - - size_t lstart = 0; - size_t lend = 0; - for (size_t n = 0; n < lines.size(); n++) { - bool firstLine = n == 0; - bool lastLine = n == lines.size() - 1; - - // Indicate truncation and indent non-first lines - if (ctx.truncatedStart && firstLine) { - os << "[...] "; - } - if (!firstLine) { - os << "\t"; - } - - // Print the actual line - os << lines[n]; - - // Indicate truncation - if (ctx.truncatedEnd && lastLine) { - os << " [...]"; - } - os << std::endl; - - // Repeat truncation or indendation space in the next line - if (ctx.truncatedStart && firstLine) { - os << " "; - } - if (!firstLine) { - os << "\t"; - } - - // Print the position indicators - lend = lastLine ? pend : lstart + lines[n].size(); - for (size_t i = lstart; i < lend; i++) { - if (i >= pstart && i < pend) { - os << t.color(Terminal::GREEN); - for (; i < std::min(lend, pend); i++) { - if (relLen == 1) { - os << '^'; - } else { - os << '~'; - } - if (i < ctx.text.size() && ctx.text[i] == '\t') { - os << '\t'; - } - } - os << t.reset(); - } else { - if (i < ctx.text.size() && ctx.text[i] == '\t') { - os << '\t'; - } else { - os << ' '; - } - } - } - os << std::endl; - - lstart = lend; - } - } -} } diff --git a/src/core/common/Logger.hpp b/src/core/common/Logger.hpp index 85b1bb1..afe58be 100644 --- a/src/core/common/Logger.hpp +++ b/src/core/common/Logger.hpp @@ -19,9 +19,8 @@ /** * @file Logger.hpp * - * Contains classes for logging messages in Ousía. Provides a generic Logger - * class, and TerminalLogger, an extension of Logger which logs do an output - * stream. + * Contains classes for logging messages in Ousía. Provides various base Logger + * classes that allow to Fork logger instances or to create a GuardedLogger. * * @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de) */ @@ -30,7 +29,6 @@ #define _OUSIA_LOGGER_HPP_ #include -#include #include #include @@ -109,7 +107,7 @@ inline MessageMode operator|(MessageMode a, MessageMode b) // Forward declaration class LoggerFork; -class ScopedLogger; +class GuardedLogger; /** * The Logger class is the base class the individual logging systems should @@ -123,7 +121,7 @@ class ScopedLogger; class Logger { public: friend LoggerFork; - friend ScopedLogger; + friend GuardedLogger; /** * The message struct represents a single log message and all information @@ -611,12 +609,12 @@ public: }; /** - * The ScopedLogger class can be used to automatically pop any pushed file from + * The GuardedLogger class can be used to automatically pop any pushed file from * the File stack maintained by a Logger class (in a RAII manner). This * simplifies managing pushing and popping files in case there are multiple * return calls or exceptions thrown. */ -class ScopedLogger : public Logger { +class GuardedLogger : public Logger { private: /** * Reference to the parent logger instance. @@ -668,20 +666,20 @@ protected: public: /** - * Constructor of the ScopedLogger class, pushes a first file instance onto + * Constructor of the GuardedLogger class, pushes a first file instance onto * the file stack. * * @param parent is the parent logger instance to which all calls should * be relayed. * @param loc specifies the first source location. */ - ScopedLogger(Logger &parent, SourceLocation loc = SourceLocation{}); + GuardedLogger(Logger &parent, SourceLocation loc = SourceLocation{}); /** - * Destructor of the ScopedLogger class, automatically unwinds the file + * Destructor of the GuardedLogger class, automatically unwinds the file * stack. */ - ~ScopedLogger(); + ~GuardedLogger(); }; /** @@ -818,45 +816,6 @@ public: bool hasFatalError(); }; -/** - * Class extending the Logger class and printing the log messages to the - * given - * stream. - */ -class TerminalLogger : public ConcreteLogger { -private: - /** - * Reference to the target output stream. - */ - std::ostream &os; - - /** - * If true, the TerminalLogger will use colors to make the log messages - * prettier. - */ - bool useColor; - -protected: - void processMessage(const Message &msg) override; - -public: - /** - * Constructor of the TerminalLogger class. - * - * @param os is the output stream the log messages should be logged to. - * Should be set to std::cerr in most cases. - * @param useColor if true, the TerminalLogger class will do its best to - * use ANSI/VT100 control sequences for colored log messages. - * @param minSeverity is the minimum severity below which log messages - *are - * discarded. - */ - TerminalLogger(std::ostream &os, bool useColor = false, - Severity minSeverity = DEFAULT_MIN_SEVERITY) - : ConcreteLogger(minSeverity), os(os), useColor(useColor) - { - } -}; } #endif /* _OUSIA_LOGGER_HPP_ */ diff --git a/src/core/common/Terminal.cpp b/src/core/common/Terminal.cpp deleted file mode 100644 index 447e595..0000000 --- a/src/core/common/Terminal.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - Ousía - Copyright (C) 2014 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 "Terminal.hpp" - -namespace ousia { - -std::string Terminal::color(int color, bool bright) const -{ - if (!useColor) { - return std::string{}; - } - std::stringstream ss; - ss << "\x1b["; - if (bright) { - ss << "1;"; - } - ss << color << "m"; - return ss.str(); -} - -std::string Terminal::bright() const -{ - if (!useColor) { - return std::string{}; - } - std::stringstream ss; - ss << "\x1b[1m"; - return ss.str(); -} - -std::string Terminal::reset() const -{ - if (!useColor) { - return std::string{}; - } - return "\x1b[0m"; -} - -} - diff --git a/src/core/common/Terminal.hpp b/src/core/common/Terminal.hpp deleted file mode 100644 index 730853d..0000000 --- a/src/core/common/Terminal.hpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - Ousía - Copyright (C) 2014 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 . -*/ - -/** - * @file Terminal.hpp - * - * Classes for printing colored output to a terminal. - * - * @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de) - */ - -#ifndef _OUSIA_TERMINAL_HPP_ -#define _OUSIA_TERMINAL_HPP_ - -#include - -namespace ousia { - -/** - * The Terminal class contains some helper functions used to interact with the - * terminal as used for colorful output when logging error messages. - * - * TODO: Disable on Windows or use corresponding API-functions for setting the - * color. - * TODO: Give output stream to terminal/use terminal as output stream - */ -class Terminal { -private: - /** - * If set to false, no control codes are generated. - */ - bool useColor; - -public: - /** - * ANSI color code for black. - */ - static const int BLACK = 30; - - /** - * ANSI color code for red. - */ - static const int RED = 31; - - /** - * ANSI color code for green. - */ - static const int GREEN = 32; - - /** - * ANSI color code for yellow. - */ - static const int YELLOW = 33; - - /** - * ANSI color code for blue. - */ - static const int BLUE = 34; - - /** - * ANSI color code for magenta. - */ - static const int MAGENTA = 35; - - /** - * ANSI color code for cyan. - */ - static const int CYAN = 36; - - /** - * ANSI color code for white. - */ - static const int WHITE = 37; - - /** - * Creates a new instance of the Terminal class. - * - * @param useColor specifies whether color codes should be generated. - */ - Terminal(bool useColor) : useColor(useColor) {} - - /** - * Returns a control string for switching to the given color. - * - * @param color is the color the terminal should switch to. - * @param bright specifies whether the terminal should switch to the bright - * mode. - * @return a control string to be included in the output stream. - */ - std::string color(int color, bool bright = true) const; - - /** - * Returns a control string for switching to the bright mode. - * - * @return a control string to be included in the output stream. - */ - std::string bright() const; - - /** - * Returns a control string for switching to the default mode. - * - * @return a control string to be included in the output stream. - */ - std::string reset() const; -}; -} - -#endif /* _OUSIA_TERMINAL_HPP_ */ - diff --git a/src/core/frontend/Terminal.cpp b/src/core/frontend/Terminal.cpp new file mode 100644 index 0000000..447e595 --- /dev/null +++ b/src/core/frontend/Terminal.cpp @@ -0,0 +1,58 @@ +/* + Ousía + Copyright (C) 2014 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 "Terminal.hpp" + +namespace ousia { + +std::string Terminal::color(int color, bool bright) const +{ + if (!useColor) { + return std::string{}; + } + std::stringstream ss; + ss << "\x1b["; + if (bright) { + ss << "1;"; + } + ss << color << "m"; + return ss.str(); +} + +std::string Terminal::bright() const +{ + if (!useColor) { + return std::string{}; + } + std::stringstream ss; + ss << "\x1b[1m"; + return ss.str(); +} + +std::string Terminal::reset() const +{ + if (!useColor) { + return std::string{}; + } + return "\x1b[0m"; +} + +} + diff --git a/src/core/frontend/Terminal.hpp b/src/core/frontend/Terminal.hpp new file mode 100644 index 0000000..730853d --- /dev/null +++ b/src/core/frontend/Terminal.hpp @@ -0,0 +1,124 @@ +/* + Ousía + Copyright (C) 2014 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 . +*/ + +/** + * @file Terminal.hpp + * + * Classes for printing colored output to a terminal. + * + * @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de) + */ + +#ifndef _OUSIA_TERMINAL_HPP_ +#define _OUSIA_TERMINAL_HPP_ + +#include + +namespace ousia { + +/** + * The Terminal class contains some helper functions used to interact with the + * terminal as used for colorful output when logging error messages. + * + * TODO: Disable on Windows or use corresponding API-functions for setting the + * color. + * TODO: Give output stream to terminal/use terminal as output stream + */ +class Terminal { +private: + /** + * If set to false, no control codes are generated. + */ + bool useColor; + +public: + /** + * ANSI color code for black. + */ + static const int BLACK = 30; + + /** + * ANSI color code for red. + */ + static const int RED = 31; + + /** + * ANSI color code for green. + */ + static const int GREEN = 32; + + /** + * ANSI color code for yellow. + */ + static const int YELLOW = 33; + + /** + * ANSI color code for blue. + */ + static const int BLUE = 34; + + /** + * ANSI color code for magenta. + */ + static const int MAGENTA = 35; + + /** + * ANSI color code for cyan. + */ + static const int CYAN = 36; + + /** + * ANSI color code for white. + */ + static const int WHITE = 37; + + /** + * Creates a new instance of the Terminal class. + * + * @param useColor specifies whether color codes should be generated. + */ + Terminal(bool useColor) : useColor(useColor) {} + + /** + * Returns a control string for switching to the given color. + * + * @param color is the color the terminal should switch to. + * @param bright specifies whether the terminal should switch to the bright + * mode. + * @return a control string to be included in the output stream. + */ + std::string color(int color, bool bright = true) const; + + /** + * Returns a control string for switching to the bright mode. + * + * @return a control string to be included in the output stream. + */ + std::string bright() const; + + /** + * Returns a control string for switching to the default mode. + * + * @return a control string to be included in the output stream. + */ + std::string reset() const; +}; +} + +#endif /* _OUSIA_TERMINAL_HPP_ */ + diff --git a/src/core/frontend/TerminalLogger.cpp b/src/core/frontend/TerminalLogger.cpp new file mode 100644 index 0000000..fdb7c8f --- /dev/null +++ b/src/core/frontend/TerminalLogger.cpp @@ -0,0 +1,151 @@ +/* + 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 "Terminal.hpp" +#include "TerminalLogger.hpp" + +namespace ousia { + +/* Class TerminalLogger */ + +void TerminalLogger::processMessage(const Message &msg) +{ + Terminal t(useColor); + + // Fetch filename, position and context + const SourceContext ctx = messageContext(msg); + + // Print the file name + if (ctx.hasFile()) { + os << t.bright() << ctx.filename << t.reset(); + } + + // Print line and column number + if (ctx.hasLine()) { + if (ctx.hasFile()) { + os << ':'; + } + os << t.bright() << ctx.startLine << t.reset(); + if (ctx.hasColumn()) { + os << ':' << ctx.startColumn; + } + } + + // Print the optional seperator + if (ctx.hasFile() || ctx.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 error: "; + break; + } + os << t.reset(); + + // Print the actual message + os << msg.msg << std::endl; + + // Print the error message context if available + if (ctx.hasText()) { + // Iterate over each line in the text + std::vector lines = Utils::split(ctx.text, '\n'); + + const size_t relLen = ctx.relLen ? ctx.relLen : 1; + const size_t relPos = ctx.relPos; + const size_t pstart = relPos; + const size_t pend = relPos + relLen; + + size_t lstart = 0; + size_t lend = 0; + for (size_t n = 0; n < lines.size(); n++) { + bool firstLine = n == 0; + bool lastLine = n == lines.size() - 1; + + // Indicate truncation and indent non-first lines + if (ctx.truncatedStart && firstLine) { + os << "[...] "; + } + if (!firstLine) { + os << "\t"; + } + + // Print the actual line + os << lines[n]; + + // Indicate truncation + if (ctx.truncatedEnd && lastLine) { + os << " [...]"; + } + os << std::endl; + + // Repeat truncation or indendation space in the next line + if (ctx.truncatedStart && firstLine) { + os << " "; + } + if (!firstLine) { + os << "\t"; + } + + // Print the position indicators + lend = lastLine ? pend : lstart + lines[n].size(); + for (size_t i = lstart; i < lend; i++) { + if (i >= pstart && i < pend) { + os << t.color(Terminal::GREEN); + for (; i < std::min(lend, pend); i++) { + if (relLen == 1) { + os << '^'; + } else { + os << '~'; + } + if (i < ctx.text.size() && ctx.text[i] == '\t') { + os << '\t'; + } + } + os << t.reset(); + } else { + if (i < ctx.text.size() && ctx.text[i] == '\t') { + os << '\t'; + } else { + os << ' '; + } + } + } + os << std::endl; + + lstart = lend; + } + } +} + +} + diff --git a/src/core/frontend/TerminalLogger.hpp b/src/core/frontend/TerminalLogger.hpp new file mode 100644 index 0000000..03930e9 --- /dev/null +++ b/src/core/frontend/TerminalLogger.hpp @@ -0,0 +1,79 @@ +/* + 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 . +*/ + +/** + * @file TerminalLogger.hpp + * + * Provides the TerminalLogger class, which is used to log messages to an output + * stream, possibly a Terminal. + * + * @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de) + */ + +#ifndef _OUSIA_TERMINAL_LOGGER_HPP_ +#define _OUSIA_TERMINAL_LOGGER_HPP_ + +#include + +#include + +namespace ousia { + +/** + * Class extending the Logger class and printing (possibly colored) log messages + * to the given stream. + */ +class TerminalLogger : public ConcreteLogger { +private: + /** + * Reference to the target output stream. + */ + std::ostream &os; + + /** + * If true, the TerminalLogger will use colors to make the log messages + * prettier. + */ + bool useColor; + +protected: + void processMessage(const Message &msg) override; + +public: + /** + * Constructor of the TerminalLogger class. + * + * @param os is the output stream the log messages should be logged to. + * Should be set to std::cerr in most cases. + * @param useColor if true, the TerminalLogger class will do its best to + * use ANSI/VT100 control sequences for colored log messages. + * @param minSeverity is the minimum severity below which log messages + * are discarded. + */ + TerminalLogger(std::ostream &os, bool useColor = false, + Severity minSeverity = DEFAULT_MIN_SEVERITY) + : ConcreteLogger(minSeverity), os(os), useColor(useColor) + { + } +}; + +} + +#endif /* _OUSIA_TERMINAL_LOGGER_HPP_ */ + + diff --git a/src/core/resource/ResourceManager.cpp b/src/core/resource/ResourceManager.cpp index a5e76b0..059da41 100644 --- a/src/core/resource/ResourceManager.cpp +++ b/src/core/resource/ResourceManager.cpp @@ -128,7 +128,7 @@ Rooted ResourceManager::parse(ParserContext &ctx, Resource &resource, Rooted node; try { // Set the current source id in the logger instance - ScopedLogger logger(ctx.logger, SourceLocation{sourceId}); + GuardedLogger logger(ctx.logger, SourceLocation{sourceId}); // Fetch the input stream and create a char reader std::unique_ptr is = resource.stream(); -- cgit v1.2.3 From 7e722fdd45496e6c8dd115faa7fab265e13b2e93 Mon Sep 17 00:00:00 2001 From: Andreas Stöckel Date: Sat, 24 Jan 2015 14:23:24 +0100 Subject: Support for italic and underline in logger (yay, toys!) --- src/core/frontend/Terminal.cpp | 20 +++++++++++++++++--- src/core/frontend/Terminal.hpp | 14 ++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/frontend/Terminal.cpp b/src/core/frontend/Terminal.cpp index 447e595..5664564 100644 --- a/src/core/frontend/Terminal.cpp +++ b/src/core/frontend/Terminal.cpp @@ -41,9 +41,23 @@ std::string Terminal::bright() const if (!useColor) { return std::string{}; } - std::stringstream ss; - ss << "\x1b[1m"; - return ss.str(); + return "\x1b[1m"; +} + +std::string Terminal::italic() const +{ + if (!useColor) { + return std::string{}; + } + return "\x1b[3m"; +} + +std::string Terminal::underline() const +{ + if (!useColor) { + return std::string{}; + } + return "\x1b[4m"; } std::string Terminal::reset() const diff --git a/src/core/frontend/Terminal.hpp b/src/core/frontend/Terminal.hpp index 730853d..90a2e6f 100644 --- a/src/core/frontend/Terminal.hpp +++ b/src/core/frontend/Terminal.hpp @@ -111,6 +111,20 @@ public: */ std::string bright() const; + /** + * Makes the text italic. + * + * @return a control string to be included in the output stream. + */ + std::string italic() const; + + /** + * Underlines the text. + * + * @return a control string to be included in the output stream. + */ + std::string underline() const; + /** * Returns a control string for switching to the default mode. * -- cgit v1.2.3 From 2e8432a2fd10f4cf5519628c7ab6e7c6e270ca15 Mon Sep 17 00:00:00 2001 From: Andreas Stöckel Date: Sat, 24 Jan 2015 14:24:19 +0100 Subject: Vastly improved terminal logger context output routine (code is still and will forever be a mess, but it is PREEEEETYYYY!) --- src/core/frontend/TerminalLogger.cpp | 60 ++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/core/frontend/TerminalLogger.cpp b/src/core/frontend/TerminalLogger.cpp index fdb7c8f..3bead06 100644 --- a/src/core/frontend/TerminalLogger.cpp +++ b/src/core/frontend/TerminalLogger.cpp @@ -93,18 +93,27 @@ void TerminalLogger::processMessage(const Message &msg) // Indicate truncation and indent non-first lines if (ctx.truncatedStart && firstLine) { - os << "[...] "; + os << t.italic() << "[...] " << t.reset(); } if (!firstLine) { os << "\t"; } - // Print the actual line - os << lines[n]; + // Print the actual line, replace tabs + for (char c: lines[n]) { + if (c == '\t') { + os << " "; + } else { + os << c; + } + } + if (!lastLine) { + os << t.color(Terminal::BLACK) << "¶" << t.reset(); + } // Indicate truncation if (ctx.truncatedEnd && lastLine) { - os << " [...]"; + os << t.italic() << " [...]" << t.reset(); } os << std::endl; @@ -118,31 +127,48 @@ void TerminalLogger::processMessage(const Message &msg) // Print the position indicators lend = lastLine ? pend : lstart + lines[n].size(); - for (size_t i = lstart; i < lend; i++) { + bool inRegion = false; + for (size_t i = lstart; i < lend + 1; i++) { if (i >= pstart && i < pend) { - os << t.color(Terminal::GREEN); - for (; i < std::min(lend, pend); i++) { + if (!inRegion) { + os << t.color(Terminal::GREEN); + inRegion = true; + } + } else { + if (inRegion) { + os << t.reset(); + inRegion = false; + } + } + char c = i < ctx.text.size() ? ctx.text[i] : ' '; + if (c == '\t') { + if (inRegion) { if (relLen == 1) { - os << '^'; + os << "^ "; } else { - os << '~'; - } - if (i < ctx.text.size() && ctx.text[i] == '\t') { - os << '\t'; + os << "~~~~"; } + } else { + os << " "; } - os << t.reset(); } else { - if (i < ctx.text.size() && ctx.text[i] == '\t') { - os << '\t'; + if (inRegion) { + if (relLen == 1) { + os << "^"; + } else { + os << "~"; + } } else { - os << ' '; + os << " "; } } } + if (inRegion) { + os << t.reset(); + } os << std::endl; - lstart = lend; + lstart = lend + 1; // skip newline } } } -- cgit v1.2.3 From 6cb52deaad36f59738b6b4d203457a7f8d2d13e9 Mon Sep 17 00:00:00 2001 From: Andreas Stöckel Date: Sat, 24 Jan 2015 14:24:59 +0100 Subject: Fixed integer overflow bug in SourceContextReader, adapted TerminaLoggerTest --- src/core/common/SourceContextReader.cpp | 18 ++++--- src/core/common/SourceContextReader.hpp | 20 +++++++- src/core/resource/ResourceManager.cpp | 7 +++ src/core/resource/ResourceManager.hpp | 20 ++++++-- test/core/frontend/TerminalLoggerTest.cpp | 78 ++++++++++++++++++++----------- 5 files changed, 106 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/core/common/SourceContextReader.cpp b/src/core/common/SourceContextReader.cpp index 65a6281..d5d379c 100644 --- a/src/core/common/SourceContextReader.cpp +++ b/src/core/common/SourceContextReader.cpp @@ -56,8 +56,8 @@ SourceContext SourceContextReader::readContext(CharReader &reader, size_t offs = 0; auto it = std::lower_bound(cache.begin(), cache.end(), start); if (it != cache.begin()) { - it--; // Go to the previous entry - offs = *it; // Read the corresponding byte offset + it--; // Go to the previous entry + offs = *it; // Read the corresponding byte offset size_t line = it - cache.begin() + 1; ctx.startLine = line; ctx.endLine = line; @@ -182,17 +182,23 @@ SourceContext SourceContextReader::readContext(CharReader &reader, } // Update the relative position and length, set the "truncated" flags - size_t us = static_cast(s), ue = static_cast(e); - ctx.relPos = start - lineBufStart - us; - ctx.relLen = std::min(ctx.relLen, ue - us); + ctx.relPos = std::max(0, start - lineBufStart - s); + ctx.relLen = std::min(ctx.relLen, e - s); ctx.truncatedStart = s > ts || lastLineStart < lineBufStart; ctx.truncatedEnd = e < te; // Copy the selected area to the output string - ctx.text = std::string{&lineBuf[s], ue - us}; + ctx.text = std::string{&lineBuf[s], static_cast(e - s)}; } return ctx; } + +SourceContext SourceContextReader::readContext(CharReader &reader, + const SourceRange &range, + const std::string &filename) +{ + return readContext(reader, range, MAX_MAX_CONTEXT_LENGTH, filename); +} } diff --git a/src/core/common/SourceContextReader.hpp b/src/core/common/SourceContextReader.hpp index 35e71b3..cd29880 100644 --- a/src/core/common/SourceContextReader.hpp +++ b/src/core/common/SourceContextReader.hpp @@ -82,7 +82,25 @@ public: * @return a SourceContext instance describing the */ SourceContext readContext(CharReader &reader, const SourceRange &range, - size_t maxContextLength = MAX_MAX_CONTEXT_LENGTH, + size_t maxContextLength, + const std::string &filename = ""); + + /** + * Returns the context for the char reader and the given SourceRange. + * Returns an invalid source context if either the given range is invalid + * or the byte offset described in the SourceRange cannot be reached because + * the CharReader cannot be seeked back to this position. Does not limit + * the output context. + * + * @param reader is the CharReader instance from which the context should be + * read. + * @param range describes the Range within the source file for which the + * context should be extraced. + * @param filename is the filename that should be stored in the returned + * context. + * @return a SourceContext instance describing the + */ + SourceContext readContext(CharReader &reader, const SourceRange &range, const std::string &filename = ""); }; } diff --git a/src/core/resource/ResourceManager.cpp b/src/core/resource/ResourceManager.cpp index 059da41..184a16d 100644 --- a/src/core/resource/ResourceManager.cpp +++ b/src/core/resource/ResourceManager.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -280,5 +281,11 @@ SourceContext ResourceManager::readContext(const SourceLocation &location, } return SourceContext{}; } + +SourceContext ResourceManager::readContext(const SourceLocation &location) +{ + return readContext(location, SourceContextReader::MAX_MAX_CONTEXT_LENGTH); +} + } diff --git a/src/core/resource/ResourceManager.hpp b/src/core/resource/ResourceManager.hpp index d5381b9..221e2cc 100644 --- a/src/core/resource/ResourceManager.hpp +++ b/src/core/resource/ResourceManager.hpp @@ -34,7 +34,6 @@ #include #include -#include #include #include "Resource.hpp" @@ -230,9 +229,22 @@ public: * @return a valid SourceContext if a valid SourceLocation was given or an * invalid SourceContext if the location is invalid. */ - SourceContext readContext( - const SourceLocation &location, - size_t maxContextLength = SourceContextReader::MAX_MAX_CONTEXT_LENGTH); + SourceContext readContext(const SourceLocation &location, + size_t maxContextLength); + /** + * Creates and returns a SourceContext structure containing information + * about the given SourceLocation (such as line and column number). Throws + * a LoggableException if an irrecoverable error occurs while looking up the + * context (such as a no longer existing resource). Does not limit the + * context length. + * + * @param location is the SourceLocation for which context information + * should be retrieved. This method is used by the Logger class to print + * pretty messages. + * @return a valid SourceContext if a valid SourceLocation was given or an + * invalid SourceContext if the location is invalid. + */ + SourceContext readContext(const SourceLocation &location); }; } diff --git a/test/core/frontend/TerminalLoggerTest.cpp b/test/core/frontend/TerminalLoggerTest.cpp index b0e769d..99e8f29 100644 --- a/test/core/frontend/TerminalLoggerTest.cpp +++ b/test/core/frontend/TerminalLoggerTest.cpp @@ -35,32 +35,39 @@ struct Pos { }; static const std::string testStr = - "\\link[domain]{book}\n" // 1 - "\\link[domain]{meta}\n" // 2 - "\n" // 3 - "\\meta{\n" // 4 - "\t\\title{The Adventures Of Tom Sawyer}\n" // 5 - "\t\\author{Mark Twain}\n" // 6 - "}\n" // 7 - "\n" // 8 - "\\book{\n" // 9 - "\n" // 10 - "\n" // 11 - "\\chapter\n" // 12 - "<>\n" // 13 - "\n" // 14 - "No answer.\n" // 15 - "\n" // 16 - "<>\n" // 17 - "\n" // 18 - "No answer.\n" // 19 - "\n" // 20 - "<>\n" // 21 - "}\n"; // 22 + "\\link[domain]{book}\n" // 1 + "\\link[domain]{meta}\n" // 2 + "\n" // 3 + "\\meta{\n" // 4 + "\t\\title{The Adventures Of Tom Sawyer}\n" // 5 + "\t\\author{Mark Twain}\n" // 6 + "}\n" // 7 + "\n" // 8 + "\\book{\n" // 9 + "\n" // 10 + "\n" // 11 + "\\chapter\n" // 12 + "<>\n" // 13 + "\n" // 14 + "No answer.\n" // 15 + "\n" // 16 + "<>\n" // 17 + "\n" // 18 + "No answer.\n" // 19 + "\n" // 20 + "<>\n" // 21 + "}\n"; // 22 static SourceContextReader contextReader{}; static SourceContext contextCallback(const SourceLocation &location) +{ + CharReader reader{testStr, 0}; + return contextReader.readContext(reader, location, + "the_adventures_of_tom_sawyer.opd"); +} + +static SourceContext truncatedContextCallback(const SourceLocation &location) { CharReader reader{testStr, 0}; return contextReader.readContext(reader, location, 60, @@ -75,9 +82,18 @@ TEST(TerminalLogger, log) logger.debug("This is a test debug message"); logger.note("This is a test note"); - logger.note("This is a test note with point context", SourceLocation{0, 49}); - logger.note("This is a test note with range context", SourceLocation{0, 49, 55}); - logger.note("This is a test note with multiline context", SourceLocation{0, 49, 150}); + logger.note("This is a test note with point context", + SourceLocation{0, 49}); + logger.note("This is a test note with range context", + SourceLocation{0, 49, 55}); + logger.note("This is a test note with multiline context", + SourceLocation{0, 49, 150}); + + logger.setSourceContextCallback(truncatedContextCallback); + logger.note("This is a test note with truncated multiline context", + SourceLocation{0, 49, 150}); + logger.setSourceContextCallback(contextCallback); + logger.warning("This is a test warning"); logger.error("This is a test error"); logger.fatalError("This is a test fatal error!"); @@ -90,6 +106,14 @@ TEST(TerminalLogger, log) catch (const LoggableException &ex) { logger.log(ex); } + + try { + throw LoggableException{"An exception with context", + SourceLocation{0, 41, 46}}; + } + catch (const LoggableException &ex) { + logger.log(ex); + } } TEST(TerminalLogger, fork) @@ -101,7 +125,9 @@ TEST(TerminalLogger, fork) LoggerFork fork = logger.fork(); - fork.error("This is a test error with context"); + fork.error("This is a test error without"); + + fork.error("This is a test error with context", SourceLocation{0, 6, 12}); // Print all error messages fork.commit(); -- cgit v1.2.3