diff --git a/src/openms/include/OpenMS/APPLICATIONS/ConsoleUtils.h b/src/openms/include/OpenMS/APPLICATIONS/ConsoleUtils.h index a6fcafe42d0..abb81fde9f5 100644 --- a/src/openms/include/OpenMS/APPLICATIONS/ConsoleUtils.h +++ b/src/openms/include/OpenMS/APPLICATIONS/ConsoleUtils.h @@ -35,46 +35,211 @@ #pragma once #include +#include +#include +#include namespace OpenMS { class OPENMS_DLLAPI ConsoleUtils { -public: + public: /// make a string console friendly /// by breaking it into multiple lines according to the console width /// The 'indentation' gives the number of spaces which is prepended beginning at the second (!) /// line, so one gets a left aligned block which has some space to the left. /// An indentation of 0 results in the native console's default behaviour: just break at the end of /// its width and start a new line. - /// but usually one wants nicely intended blocks, which the console does not support - /// 'max_lines' gives the upper limit of lines returned after breaking is finished. + /// but usually one wants nicely indented blocks, which the console does not support + /// 'max_lines' gives the upper limit of lines returned after breaking is finished. /// Excess lines are removed and replaced by '...', BUT the last line will be preserved. /// @param input String to be split /// @param indentation Number of spaces to use for lines 2 until last line. /// @param max_lines Limit of output lines (all others are removed) - static String breakString(const String& input, const Size indentation, const Size max_lines); + /// C'tor + ConsoleUtils(); + + /// Copy C'tor + ConsoleUtils(const ConsoleUtils&); + + /// Destructor + ~ConsoleUtils(); + + static OpenMS::String breakString(const String& input, + const Size indentation, + const Size max_lines, + const Size curser_pos = 0); + + static OpenMS::StringList breakStringList(const String& input, + const Size indentation, + const Size max_lines, + const Size curser_pos = 0); + + int getConsoleSize() //deleted const here + { + return console_width_; + } + + static ConsoleUtils getInstance() + { + return getInstance_(); + } + + +//#ifdef OPENMS_WINDOWSPLATFORM + + // /// reset the color of the windows output handle + // void resetCoutColor(); + // /// reset the color of the windows error handle + // void resetCerrColor(); + + /// reset the color of both output streams + void resetConsoleColor(); -private: - /// width of console we are currently in (if not determinable, set to 80 as default) + void setCoutColor(int color_code); + + void setCerrColor(int color_code); + + int getCoutColor(); + + int getCerrColor(); + +//#endif + + private: + /// width of console we are currently in + ///(if not determinable, set to 80 as default) int console_width_; /// read console settings for output shaping int readConsoleSize_(); + + static ConsoleUtils& getInstance_(); + /// returns a console friendly version of input - String breakString_(const String& input, const Size indentation, const Size max_lines); + OpenMS::StringList breakString_(const String& input, + const Size indentation, + const Size max_lines, + const Size curser_pos); - /// C'tor - ConsoleUtils(); - /// Copy C'tor - ConsoleUtils(const ConsoleUtils &); + + // /// Destructor + // ~ConsoleUtils(); /// Assignment operator void operator=(ConsoleUtils const&); + +//#ifdef OPENMS_WINDOWSPLATFORM + + /// Default console color for output stream + int default_cout_; + + /// Default console color for error stream + int default_cerr_; + + +//#endif }; + class ColorizerMethods: public Colorizer + { + + public: + + ///Constructor + ColorizerMethods(const Color color); + + /// Default destructor + ~ColorizerMethods(); + + void outputToStream_(std::ostream& o_stream){this->outputToStream(o_stream);} + + void colorStream_(std::ostream& stream) const{this->colorStream(stream);} + + void resetColor_(std::ostream& stream){this->resetColor(stream);} + + bool getReset_(){return this->getReset();} + + std::string getDataAsString_(){return this->getDataAsString();} + }; + + class IndentedStringStream + { + public: + IndentedStringStream(std::ostream& stream, + const Size indentation, + const Size max_lines) : stream_(&stream), + indentation_(indentation), + max_lines_(max_lines), + current_column_pos_(0) + { + max_line_width_ = ConsoleUtils::getInstance().getConsoleSize(); + } + + + template + IndentedStringStream& operator<<(const T& data) + { + + std::stringstream s; + s << data; + const std::string& string_to_print = s.str(); + + //wie viele zeilen sind es / viel viele zeichen in letrzter zeile + + OpenMS::StringList result = ConsoleUtils::breakStringList(string_to_print, + indentation_, + max_lines_, + current_column_pos_); + + if (result.size()>=2) + { // we completed the previous line, so start counting from the latest incomplete line + current_column_pos_ = result.back().size(); + } + else + { // only one line; simply forward the column position + current_column_pos_ += result.back().size(); + } + + + + *stream_ << ListUtils::concatenate(result, '\n'); + + return *this; + + } +///741 = offset +///763 = indent + + + // IndentedStringStream& operator<<(ColorizerMethods& colorizer); + + private: + std::ostream* stream_; + int indentation_; + int max_lines_; + int max_line_width_; + int current_column_pos_; + + + IndentedStringStream& operator<<(ColorizerMethods& colorizer) +{ + colorizer.colorStream_(*stream_); + this->operator<<(colorizer.getDataAsString_()); + + if(colorizer.getReset_()) + { + colorizer.resetColor_(*stream_); + + } + + return *this; +} + +}; + } // namespace OpenMS diff --git a/src/openms/include/OpenMS/CONCEPT/Colorizer.h b/src/openms/include/OpenMS/CONCEPT/Colorizer.h new file mode 100644 index 00000000000..51f7e6b6719 --- /dev/null +++ b/src/openms/include/OpenMS/CONCEPT/Colorizer.h @@ -0,0 +1,246 @@ +// -------------------------------------------------------------------------- +// OpenMS -- Open-Source Mass Spectrometry +// -------------------------------------------------------------------------- +// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen, +// ETH Zurich, and Freie Universitaet Berlin 2002-2022. +// +// This software is released under a three-clause BSD license: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of any author or any participating institution +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// For a full list of authors, refer to the file AUTHORS. +// -------------------------------------------------------------------------- +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING +// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// -------------------------------------------------------------------------- +// $Maintainer: Chris Bielow, Moritz Berger, Tetana Krymovska$ +// $Authors: Chris Bielow, Moritz Berger, Tetana Krymovska$ +// -------------------------------------------------------------------------- + +#pragma once + +//#include + +#include +#include +#include +#include + +////// +#include +#include +///// + + +namespace OpenMS +{ + /// Text colors for console output + enum class Color + { // internal note: the order is important here! See Colorizer::colors_ + BLACK, + RED, + GREEN, + YELLOW, + BLUE, + MAGENTA, + CYAN, + WHITE, + RESET, ///< reset the color to the previous (default?) color + }; + + /** + * @brief A class, that provides options for colored output with the "<<" operator for output streams (cout, cerr) + * + */ + + class OPENMS_DLLAPI Colorizer + { + +friend class ConsoleUtils; + +public: + /// Constructor + Colorizer(const Color color); + + /// Constructor + Colorizer(); + + // Copy constructor + Colorizer(const Colorizer &rhs); + + /// Destructor + ~Colorizer(); + + /// insetrion Operator + friend std::ostream& operator<<(std::ostream& o_stream, Colorizer& col); + + + /// Bracket Operator + Colorizer& operator()() + { + reset_ = false; + this->input_.str(""); // clear the stream + return *this; + } + + /// Bracket Operator + template + Colorizer& operator()(T s) + { + this->input_.str(""); // clear the stringstream + this->input_ << s; // add new data + reset_ = true; + return *this; + } + + /// + Colorizer& reset(); + + +protected: + + const int color_; + /// + void outputToStream(std::ostream& o_stream); + + /// + void colorStream(std::ostream& stream) const; + + /// + void resetColor(std::ostream& stream); + + /// + std::string getDataAsString(); + + bool getReset() + { + return this->reset_; + } + + std::string getInput() + { + std::stringstream input_out; + input_out << input_.rdbuf(); + + return input_out.str(); + } + + const char* getColor_() + { + return this->colors_[color_]; + } + + const char* getResetColor_(){ + return this->colors_[int(Color::RESET)]; + } + +private: + + /// input in Colorizer object to be colored + std::stringstream input_; + + /// + bool reset_ = true; + + +/** + * @brief constant string array which saves the Linux color codes. + * 0=black + * 1=red + * 2=green + * 3=yellow + * 4=blue + * 5=magenta + * 6=cyan + * 7=white + * 8=default console color (reset) + * + */ +#if defined(_WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) + /// + inline static constexpr std::array colors_ {16, 12, 10, 14, 9, 13, 11, 15, 15}; + +#elif defined(__linux__) || defined(__OSX__) + /// + inline static constexpr std::array colors_ {"\033[30m", "\033[31m", "\033[32m", "\033[33m", "\033[34m", "\033[35m", "\033[36m", "\033[37m", "\033[0m"}; + +#endif + }; + + // declaration of all colorizer object. + extern OPENMS_DLLAPI Colorizer black; + extern OPENMS_DLLAPI Colorizer red; + extern OPENMS_DLLAPI Colorizer green; + extern OPENMS_DLLAPI Colorizer yellow; + extern OPENMS_DLLAPI Colorizer blue; + extern OPENMS_DLLAPI Colorizer magenta; + extern OPENMS_DLLAPI Colorizer cyan; + extern OPENMS_DLLAPI Colorizer white; + // extern OPENMS_DLLAPI Colorizer reset_color; ///< reset the color to default, alias for 'make_default_color' + //extern /*OPENMS_DLLAPI*/ Colorizer default_color; ///< reset the color to default, alias for 'reset_color' + + //Stream operator declaration + OPENMS_DLLAPI std::ostream& operator<<(std::ostream& o_stream, + OpenMS::Colorizer& col); + + +class OPENMS_DLLAPI ColorizerTester: public Colorizer + + /*only used in Colorizer_test.cpp for testing Colorizer method + functionality. While using Colorizer instances, only cout or cerr + streams are being colorized. + + Methods with underscore "_" at the name end are used to + reveal functionality of protected class functions in the unit test. + + For separate Colorizer method testing, stringstreams are used instead. + This class modified these methods to use Colorizer functionality on + stringstreams instead of cout/cerr streams. Such methods have "Simple" + attached to the method name. + + This class should not be used outside Colorizer_test.cpp + */ +{ + public: + + ///Constructor + ColorizerTester(const Color color) : Colorizer(color){}; + + /// Default destructor + ~ColorizerTester(){}; + + //Colorizer methods encapsulated for unit test + void outputToStream_(std::ostream& o_stream){this->outputToStream(o_stream);} + + void colorStream_(std::ostream& stream) const{this->colorStream(stream);} + + void resetColor_(std::ostream& stream){this->resetColor(stream);} + + std::string getDataAsString_(){return this->getDataAsString();} + + + //modified methods of Colorizer that work for stringstream instead of cerr/cout + void outputToStreamSimple(std::ostream& o_stream); + + void colorStreamSimple(std::ostream& stream); + + void resetColorSimple(std::ostream& stream); + +}; + +} diff --git a/src/openms/source/APPLICATIONS/ConsoleUtils.cpp b/src/openms/source/APPLICATIONS/ConsoleUtils.cpp index 8a3a993c626..dc94b300024 100644 --- a/src/openms/source/APPLICATIONS/ConsoleUtils.cpp +++ b/src/openms/source/APPLICATIONS/ConsoleUtils.cpp @@ -33,11 +33,10 @@ // -------------------------------------------------------------------------- #include - #include #include -#ifdef OPENMS_WINDOWSPLATFORM +#ifdef OPENMS_WINDOWSPLATTFORM #include // for GetConsoleScreenBufferInfo() #undef min #undef max @@ -54,18 +53,54 @@ namespace OpenMS { // initialize the console width readConsoleSize_(); + + //if operating OS is Windows: save default output color for cour and cerr +#ifdef OPENMS_WINDOWSPLATTFORM + CONSOLE_SCREEN_BUFFER_INFO Info; + HANDLE handle_stdout = GetStdHandle(STD_OUTPUT_HANDLE); + HANDLE handle_stderr = GetStdHandle(STD_ERROR_HANDLE); + + GetConsoleScreenBufferInfo(handle_stdout, &Info); + + default_cout_ = Info.wAttributes; + + GetConsoleScreenBufferInfo(handle_stderr, &Info); + + default_cerr_ = Info.wAttributes; + + /// get and remember 2 default colors +#endif + } + + ConsoleUtils::~ConsoleUtils() + { +#ifdef OPENMS_WINDOWSPLATTFORM + resetConsoleColor(); +#endif } - ConsoleUtils::ConsoleUtils(ConsoleUtils const& other) : - console_width_(other.console_width_) + ConsoleUtils::ConsoleUtils(ConsoleUtils const& other) = default; + void ConsoleUtils::operator=(const ConsoleUtils& other) {}; + + OpenMS::String ConsoleUtils::breakString(const String& input, + const Size indentation, + const Size max_lines, + const Size curser_pos) { + return ListUtils::concatenate(ConsoleUtils::getInstance().breakString_(input, indentation, + max_lines, curser_pos),"\n"); } - void ConsoleUtils::operator=(const ConsoleUtils& other) + OpenMS::StringList ConsoleUtils::breakStringList(const String& input, + const Size indentation, + const Size max_lines, + const Size curser_pos) { - console_width_ = other.console_width_; + return ConsoleUtils::getInstance().breakString_(input, indentation, + max_lines, curser_pos); } + int ConsoleUtils::readConsoleSize_() { // avoid calling this function more than once @@ -93,7 +128,7 @@ namespace OpenMS OPENMS_LOG_DEBUG << "output shaping: COLUMNS env does not exist!" << std::endl; } -#ifdef OPENMS_WINDOWSPLATFORM +#ifdef OPENMS_WINDOWSPLATTFORM HANDLE hOut; CONSOLE_SCREEN_BUFFER_INFO SBInfo; hOut = GetStdHandle(STD_OUTPUT_HANDLE); @@ -111,9 +146,10 @@ namespace OpenMS String output(buff); StringList components; output.split(' ', components); - if (components.size() == 2) + if (components.size() == 2){ console_width_ = components[1].toInt(); } + } else { // TODO: throw ? @@ -140,30 +176,43 @@ namespace OpenMS } return console_width_; + } - String ConsoleUtils::breakString(const String& input, const Size indentation, const Size max_lines) + ConsoleUtils& ConsoleUtils::getInstance_() { static ConsoleUtils instance; - return instance.breakString_(input, indentation, max_lines); + return instance; } - String ConsoleUtils::breakString_(const OpenMS::String& input, const Size indentation, const Size max_lines) + OpenMS::StringList ConsoleUtils::breakString_(const OpenMS::String& input, + const Size indentation, + const Size max_lines, + const Size curser_pos) { - + // get the line length - const Int line_len = ConsoleUtils::readConsoleSize_(); + Int line_len = ConsoleUtils::readConsoleSize_(); StringList result; Size short_line_len = line_len - indentation; + + /// hier wird linelen - neuer param curpos + line_len -= curser_pos; + + + if (short_line_len < 1) { std::cerr << "INTERNAL ERROR: cannot split lines into empty strings! see breakString_()"; - return input; + result.push_back(input); + return result; } + for (Size i = 0; i < input.size(); ) { - String line = input.substr(i, result.empty() ? line_len : short_line_len); // first line has full length + String line = input.substr(i, result.empty() ? line_len : short_line_len); + // first line has full length Size advance_size = line.size(); if (line.hasSubstring("\n")) { @@ -193,20 +242,55 @@ namespace OpenMS } i += advance_size; - String s_intend = (result.empty() ? "" : String(indentation, ' ')); // first line no indentation - String r = s_intend + (result.empty() ? line : line.trim()); // intended lines get trimmed + String s_intend = (result.empty() ? "" : String(indentation, ' ')); + // first line no indentation + String r = s_intend + (result.empty() ? line : line.trim()); + // intended lines get trimmed result.push_back(r); //(r.fillRight(' ', (UInt) line_len)); } - if (result.size() > max_lines) // remove lines from end if we get too many (but leave the last one)... + if (result.size() > max_lines) + // remove lines from end if we get too many (but leave the last one)... { String last = result.back(); result.erase(result.begin() + max_lines - 2, result.end()); - result.push_back((String(indentation, ' ') + String("..."))); //.fillRight(' ',(UInt) line_len)); + result.push_back((String(indentation, ' ') + String("..."))); + //.fillRight(' ',(UInt) line_len)); result.push_back(last); } + // remove last " " from last line to prevent automatic line break //if (result.size()>0 && result[result.size()-1].hasSuffix(" ")) result[result.size()-1] = result[result.size()-1].substr(0,result[result.size()-1].size()-1); - return ListUtils::concatenate(result, "\n"); + + return result; + } + +#ifdef OPENMS_WINDOWSPLATTFORM + void ConsoleUtils::resetConsoleColor() + { + setCoutColor(default_cout_); + setCerrColor(default_cerr_); } + void setCoutColor(int color_code) + { + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color_code); + } + + void setCerrColor(int color_code) + { + SetConsoleTextAttribute(GetStdHandle(STD_ERROR_HANDLE), color_code); + } + +int getCoutColor() +{ + return default_cout_; +} + +int getCerrColor() +{ + return default_cerr_; } + +#endif +} + diff --git a/src/openms/source/APPLICATIONS/TOPPBase.cpp b/src/openms/source/APPLICATIONS/TOPPBase.cpp index 7ecd76b4a40..dc4afcb929f 100755 --- a/src/openms/source/APPLICATIONS/TOPPBase.cpp +++ b/src/openms/source/APPLICATIONS/TOPPBase.cpp @@ -38,6 +38,7 @@ #include #include +#include #include #include #include @@ -189,7 +190,7 @@ namespace OpenMS addEmptyLine_(); //common section for all tools if (ToolHandler::getTOPPToolList().count(tool_name_)) - addText_("Common TOPP options:"); + addText_("cd options:"); else addText_("Common UTIL options:"); registerStringOption_("ini", "", "", "Use the given TOPP INI file", false); @@ -251,7 +252,9 @@ namespace OpenMS // test if no options were given if (argc == 1) { + cout << red(); writeLog_("No options given. Aborting!"); + cout << red.reset(); printUsage_(); return ILLEGAL_PARAMETERS; } @@ -555,8 +558,9 @@ namespace OpenMS << "\n"; // print warning regarding not shown parameters - if (!subsections_.empty() && !verbose) - cerr << ConsoleUtils::breakString("This tool has algorithm parameters that are not shown here! Please check the ini file for a detailed description or use the --helphelp option.", 0, 10) + "\n\n"; + if (!subsections_.empty() && !verbose){ + cerr << ConsoleUtils::breakString("This tool has algorithm parameters that are not shown here! Please check the ini file for a detailed description or use the --helphelp option.", 0, 10) << "\n\n"; + } if (verbose) { @@ -572,7 +576,7 @@ namespace OpenMS } } - cerr << "Options (mandatory options marked with '*'):" << "\n"; + cerr << magenta("Options (mandatory options marked with '*'):") << "\n"; //determine max length of parameters (including argument) for indentation UInt max_size = 0; @@ -746,7 +750,7 @@ namespace OpenMS //output cerr << "\n" - << "The following configuration subsections are valid:" << "\n"; + << green("The following configuration subsections are valid:") << "\n"; for (map::const_iterator it = subsections_.begin(); it != subsections_.end(); ++it) { String tmp = String(" - ") + it->first; @@ -754,11 +758,12 @@ namespace OpenMS cerr << ConsoleUtils::breakString(tmp + it->second, indent, 10); cerr << "\n"; } - cerr << "\n" + cerr << blue() << "\n" << ConsoleUtils::breakString("You can write an example INI file using the '-write_ini' option.", 0, 10) << "\n" << ConsoleUtils::breakString("Documentation of subsection parameters can be found in the doxygen documentation or the INIFileEditor.", 0, 10) << "\n" << ConsoleUtils::breakString("For more information, please consult the online documentation for this tool:", 0, 10) << "\n" - << ConsoleUtils::breakString(" - " + docurl, 0, 10) << "\n"; + << ConsoleUtils::breakString(" - " + docurl, 0, 10) << blue.reset() << "\n"; + } cerr << endl; } diff --git a/src/openms/source/CONCEPT/Colorizer.cpp b/src/openms/source/CONCEPT/Colorizer.cpp new file mode 100644 index 00000000000..3604cf9bde5 --- /dev/null +++ b/src/openms/source/CONCEPT/Colorizer.cpp @@ -0,0 +1,219 @@ +// -------------------------------------------------------------------------- +// OpenMS -- Open-Source Mass Spectrometry +// -------------------------------------------------------------------------- +// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen, +// ETH Zurich, and Freie Universitaet Berlin 2002-2022. +// +// This software is released under a three-clause BSD license: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of any author or any participating institution +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// For a full list of authors, refer to the file AUTHORS. +// -------------------------------------------------------------------------- +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING +// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// -------------------------------------------------------------------------- +// $Maintainer: Moritz Berger, Tetana Krymovska $ +// $Authors: Moritz Berger, Tetana Krymovska$ +// -------------------------------------------------------------------------- + +#include +#include + +#ifdef OPENMS_WINDOWSPLATTFORM + #include + #include +#endif + +namespace OpenMS +{ + + // Constructor + Colorizer::Colorizer(const Color color) : color_((int)color) + // color must be in initializer list, because of const keyword + { + } + + /// Default destructor + Colorizer::~Colorizer() + { +// if colorizer object is destroyed, set console color back to def col. +#if defined(__linux__) || defined(__OSX__) + std::cout << colors_[int(Color::RESET)]; +#endif + } + + /// + void Colorizer::colorStream(std::ostream& stream) const + { +#if defined(_WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) + + if (&std::cout == &stream) + { + // set color of output + ConsoleUtils::getInstance().setCoutColor(colors_[color_]); + } + else if (&std::cerr == &stream) + { + ///set color of error stream + ConsoleUtils::getInstance().setCerrColor(colors_[color_]); + } + +#elif defined(__linux__) || defined(__OSX__) + //check if the output is being fed to file or console + //supress output of ANSI codes into the file + + if (&std::cout == &stream) + { + if(isatty(STDOUT_FILENO) || isatty(STDERR_FILENO)) + { + //write coloring escape codes into the string + stream << this->colors_[this->color_]; + } + } + else if (&std::cerr == &stream) + { + // stream << this->colors_[this->color_]; //delete + if(isatty(STDOUT_FILENO) || isatty(STDERR_FILENO)) + { + stream << this->colors_[this->color_]; + // stream << "\033[35m"; //delete + + } + } +#endif + } + + /// + void Colorizer::resetColor(std::ostream& stream) + { +#ifdef OPENMS_WINDOWSPLATTFORM + if (&std::cout == &stream) + { + ///reset color of output + ConsoleUtils::getInstance().resetCoutColor(); + } + else if (&std::cerr == &stream) + { + ///reset color of error stream + ConsoleUtils::getInstance().resetCerrColor(); + } + +#elif defined(__linux__) || defined(__OSX__) + // check if the output is being fed to file or console + // supress output of ANSI codes into the file + + if (&std::cout == &stream) + { + if(isatty(STDOUT_FILENO) || isatty(STDERR_FILENO)) + { + //write RESET ANSI code to string + stream << this->colors_[int(Color::RESET)]; + } + } + else if (&std::cerr == &stream) + { + if(isatty(STDOUT_FILENO) || isatty(STDERR_FILENO)) + { + stream << this->colors_[int(Color::RESET)]; + } + } +#endif + } + + /// + std::string Colorizer::getDataAsString() + { + return input_.str(); + } + + // Helper function, to manipulate the output stream in class. + void Colorizer::outputToStream(std::ostream& o_stream) + { + /// color the stream (or console) + colorStream(o_stream); + + // paste text + o_stream << this->input_.str(); + + // if flag reset is set: reset comand line. else dont reset. + + // std::cout<< " |Col reset is A " << this->reset_; //delete + if (this->reset_) + { + resetColor(o_stream); + // std::cout<< " |Col reset is B " << this->reset_; //delete + } + } + + /// + Colorizer& Colorizer::reset() + { + this->input_.str(""); + reset_ = true; + return *this; + } + + // overload the shift operator (<<) + std::ostream& operator<<(std::ostream& o_stream, + OpenMS::Colorizer& col) + { + // colorize string with color set in the object + col.outputToStream(o_stream); + return o_stream; + } + + + // Objekte des typs colorizer + OpenMS::Colorizer black(Color::BLACK); + OpenMS::Colorizer red(Color::RED); + OpenMS::Colorizer green(Color::GREEN); + OpenMS::Colorizer yellow(Color::YELLOW); + OpenMS::Colorizer blue(Color::BLUE); + OpenMS::Colorizer magenta(Color::MAGENTA); + OpenMS::Colorizer cyan(Color::CYAN); + OpenMS::Colorizer white(Color::WHITE); + + +//ColorizerTester methods for unit test +void ColorizerTester::colorStreamSimple(std::ostream& stream) +{ + stream << this->Colorizer::getColor_(); +} + +void ColorizerTester::resetColorSimple(std::ostream& stream) +{ + stream << this->Colorizer::getResetColor_(); +} + +void ColorizerTester::outputToStreamSimple(std::ostream& o_stream){ + + /// color the stream (or console) + ColorizerTester::colorStreamSimple(o_stream); + + // paste text + o_stream << this->Colorizer::getInput(); + + // if flag reset is set: reset comand line. else dont reset. + if (this->Colorizer::getReset()) + { + ColorizerTester::resetColorSimple(o_stream); + } + +} +} // namespace OpenMS diff --git a/src/openms/source/CONCEPT/sources.cmake b/src/openms/source/CONCEPT/sources.cmake index 56f3acc8ffd..6e39d4ffa46 100644 --- a/src/openms/source/CONCEPT/sources.cmake +++ b/src/openms/source/CONCEPT/sources.cmake @@ -4,6 +4,7 @@ set(directory source/CONCEPT) ### list all filenames of the directory here set(sources_list ClassTest.cpp +Colorizer.cpp CommonEnums.cpp Constants.cpp Exception.cpp diff --git a/src/tests/class_tests/openms/executables.cmake b/src/tests/class_tests/openms/executables.cmake index 69418cac5c3..b98d6784956 100644 --- a/src/tests/class_tests/openms/executables.cmake +++ b/src/tests/class_tests/openms/executables.cmake @@ -1,5 +1,6 @@ set(concept_executables_list ClassTest_test + Colorizer_test Exception_Base_test FactoryBase_test Factory_test diff --git a/src/tests/class_tests/openms/source/Colorizer_test.cpp b/src/tests/class_tests/openms/source/Colorizer_test.cpp new file mode 100644 index 00000000000..14c838f3e53 --- /dev/null +++ b/src/tests/class_tests/openms/source/Colorizer_test.cpp @@ -0,0 +1,287 @@ +// -------------------------------------------------------------------------- +// OpenMS -- Open-Source Mass Spectrometry +// -------------------------------------------------------------------------- +// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen, +// ETH Zurich, and Freie Universitaet Berlin 2002-2021. +// +// This software is released under a three-clause BSD license: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of any author or any participating institution +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// For a full list of authors, refer to the file AUTHORS. +// -------------------------------------------------------------------------- +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING +// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// -------------------------------------------------------------------------- +// $Maintainer: $ +// $Authors: Moritz Berger, Tetana Krymovska$ +// -------------------------------------------------------------------------- + +#include +#include + +/////////////////////////// +#include +/////////////////////////// + +#include +#include +#include +#include +#include + +using namespace OpenMS; +using namespace std; + + +template +//convert any input to string +string convertToString ( T var_input ) +{ + ostringstream ss; + ss << var_input; + return ss.str(); +} + +START_TEST(Colorizer(),"$Id$") + + //Test variables +char test_char = 'a'; +int test_int = 15; +float test_float = 2094.5892; +string test_string = " !#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; + +//ANSI codes + +#ifdef OPENMS_WINDOWSPLATFORM + + string const blackANSI = ""; + string const redANSI = ""; + string const greenANSI = ""; + string const yellowANSI = ""; + string const blueANSI = ""; + string const magentaANSI = ""; + string const cyanANSI = ""; + string const whiteANSI = ""; + string const resetColorANSI = ""; + +#elif defined(__linux__) || defined(__OSX__) + + string const blackANSI = "\e[30m"; + string const redANSI = "\e[31m"; + string const greenANSI = "\e[32m"; + string const yellowANSI = "\e[33m"; + string const blueANSI = "\e[34m"; + string const magentaANSI = "\e[35m"; + string const cyanANSI = "\e[36m";; + string const whiteANSI = "\e[37m"; + string const resetColorANSI = "\e[0m"; + +#endif + + +START_SECTION(Colorizer::colorStream(ostream& stream) const) +{ + /*modified ColorizerTester method used for colorisation + of stringstreams instead of cerr/cour for the purpose of + testing + */ + + //without text + stringstream test_stream; + ColorizerTester c(Color::BLACK); + + c.colorStreamSimple(test_stream); + TEST_EQUAL(test_stream.str(), blackANSI) + + //with text + test_stream.str(string()); + test_stream.clear(); + + test_stream << c(test_string); + c.colorStreamSimple(test_stream); + TEST_EQUAL(test_stream.str(),test_string+blackANSI) +} +END_SECTION + + +START_SECTION(Colorizer::outputToStream(ostream& o_stream)) +{ + /*modified ColorizerTester method used for colorisation + of stringstreams instead of cerr/cour for the purpose of + testing + */ + + //without text + stringstream test_stream; + ColorizerTester c(Color::CYAN); + c.outputToStreamSimple(test_stream); + TEST_EQUAL(test_stream.str(), cyanANSI+resetColorANSI) + + // with text + test_stream.str(string()); + test_stream.clear(); + + test_stream << c(test_string); + c.outputToStreamSimple(test_stream); + + TEST_EQUAL(test_stream.str(),test_string+cyanANSI+test_string+resetColorANSI) +} +END_SECTION + +START_SECTION(Colorizer::resetColor(ostream& stream)) +{ + /*modified ColorizerTester method used for colorisation + of stringstreams instead of cerr/cour for the purpose of + testing + */ + + stringstream test_stream; + ColorizerTester c(Color::GREEN); + + test_stream << c(test_string); + c.resetColorSimple(test_stream); + TEST_EQUAL(test_stream.str(), test_string+resetColorANSI) +} +END_SECTION + +START_SECTION(Colorizer::getDataAsString()) +{ + stringstream test_stream; + ColorizerTester c(Color::RED); + + test_stream << c(test_string); + test_stream << c.getDataAsString_(); + TEST_EQUAL(test_stream.str(), test_string+test_string) +} +END_SECTION + +START_SECTION(Colorizer::reset()) +{ + NOT_TESTABLE + //due to cerr/cout output supression in this test file, colorisation is not working +} +END_SECTION + +START_SECTION("Testing Colorizer instances") + + /*Check that the colorized input contains the original text. + Insertion of ANSI codes is supressed so only test insertion is testable. + */ +{ + stringstream colored_stream; + + colored_stream << black(test_string); + TEST_EQUAL(colored_stream.str(), test_string) + colored_stream.str(string()); + colored_stream.clear(); + + colored_stream << red(test_string); + TEST_EQUAL(colored_stream.str(), test_string) + colored_stream.str(string()); + colored_stream.clear(); + + colored_stream << green(test_string); + TEST_EQUAL(colored_stream.str(), test_string) + colored_stream.str(string()); + colored_stream.clear(); + + colored_stream << yellow(test_string); + TEST_EQUAL(colored_stream.str(), test_string) + colored_stream.str(string()); + colored_stream.clear(); + + colored_stream << blue(test_string); + TEST_EQUAL(colored_stream.str(), test_string) + colored_stream.str(string()); + colored_stream.clear(); + + colored_stream << magenta(test_string); + TEST_EQUAL(colored_stream.str(), test_string) + colored_stream.str(string()); + colored_stream.clear(); + + colored_stream << cyan(test_string); + TEST_EQUAL(colored_stream.str(), test_string) + colored_stream.str(string()); + colored_stream.clear(); + + colored_stream << white(test_string); + TEST_EQUAL(colored_stream.str(), test_string) + colored_stream.str(string()); + colored_stream.clear(); +} +END_SECTION + +START_SECTION("Testing Colorizer inputs") + /* + Testing various inputs for colorizing + Insertion of ANSI codes is supressed so only test insertion is testable. + */ +{ + stringstream colored_stream; + string comparison_string; + + //char//////////////////////////////////// + colored_stream << yellow(test_char); + comparison_string.append(convertToString(test_char)); + TEST_EQUAL(colored_stream.str(), comparison_string) + + //clearing streams + colored_stream.str(string()); + colored_stream.clear(); + comparison_string = ""; + + //int/////////////////////////////// + colored_stream << green(test_int); + comparison_string.append(convertToString(test_int)); + TEST_EQUAL(colored_stream.str(), comparison_string) + + //clearing streams + colored_stream.str(string()); + colored_stream.clear(); + comparison_string = ""; + + //float/////////////////////////////// + colored_stream << red(test_float); + comparison_string.append(convertToString(test_float)); + TEST_EQUAL(colored_stream.str(), comparison_string) + + //clearing streams + colored_stream.str(string()); + colored_stream.clear(); + comparison_string = ""; +} +END_SECTION + +START_SECTION(Colorizer& operator()()) + /* + Testing ()operator for colorising + Insertion of ANSI codes is supressed so only test insertion is testable. + */ +{ + stringstream test_stream; + test_stream << green() + << "green text" + << 123 << "!" + << " "; + TEST_EQUAL(test_stream.str(),"green text123! ") +} +END_SECTION + +END_TEST \ No newline at end of file diff --git a/src/tests/class_tests/openms/source/ConsoleUtils_test.cpp b/src/tests/class_tests/openms/source/ConsoleUtils_test.cpp index 81b0c41a8cf..3b33ae08c17 100644 --- a/src/tests/class_tests/openms/source/ConsoleUtils_test.cpp +++ b/src/tests/class_tests/openms/source/ConsoleUtils_test.cpp @@ -37,7 +37,13 @@ /////////////////////////// #include +#include /////////////////////////// +#include +#include +#include +#include +#include using namespace OpenMS; using namespace std; @@ -47,32 +53,78 @@ START_TEST(ConsoleUtils, "$Id$") ///////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////// -START_SECTION(ConsoleUtils()) +START_SECTION(const int getConsoleSize()) { - // this class is a singleton exposing a single function (breakString) NOT_TESTABLE } END_SECTION -START_SECTION(~ConsoleUtils()) +START_SECTION(ConsoleUtils getInstance()) { NOT_TESTABLE } END_SECTION -START_SECTION((static String breakString(const String &input, const Size indentation, const Size max_lines))) +#ifdef OPENMS_WINDOWSPLATTFORM + +START_SECTION(void resetConsoleColor()) +{ + ConsoleUtils c(ConsoleUtils const); + c.ConsoleUtils::setCoutColor(16); + c.ConsoleUtils::setCerrColor(9); + int def_cout = c.ConsoleUtils::getCoutColor(); + int def_cerr = c.ConsoleUtils::getCerrColor(); + TEST_EQUAL(def_cout,16) + TEST_EQUAL(def_cerr,10) +} +END_SECTION + +START_SECTION(void setCoutColor()) +{ + ConsoleUtils c(ConsoleUtils const); + c.ConsoleUtils::setCoutColor(16); + int def_ = c.ConsoleUtils::getCoutColor(); + TEST_EQUAL(def,16); +} +END_SECTION + +START_SECTION(void setCerrColor()) +{ + ConsoleUtils c(ConsoleUtils const); + c.ConsoleUtils::setCerrColor(11); + int def_ = c.ConsoleUtils::getCoutColor(); + TEST_EQUAL(def,11); +} +END_SECTION +#endif + +START_SECTION((static OpenMS::String breakString(const String& input, + const Size indentation, + const Size max_lines, + const Size curser_pos = 0))) { // we cannot predict which shape the broken string will have, so testing is rather limited String test_string = "This is a test string which should be broken up into multiple lines."; String broken_string = ConsoleUtils::breakString(test_string, 0, 10); TEST_EQUAL(test_string.length() <= broken_string.length(), true) + } END_SECTION +START_SECTION(static OpenMS::StringList breakStringList(const String& input, + const Size indentation, + const Size max_lines, + const Size curser_pos = 0)) +{ + String test_string = "This is a test string which should be broken up into multiple lines."; + OpenMS::StringList broken_string = ConsoleUtils::breakStringList(test_string, 0, 10); + + String broken_string_string = broken_string.StringList::at(0); + TEST_EQUAL(test_string.length() <= broken_string_string.length(), true) +} +END_SECTION -///////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////// END_TEST diff --git a/t b/t new file mode 100644 index 00000000000..126ade0b604 --- /dev/null +++ b/t @@ -0,0 +1,4 @@ + colorizer_testclass +* consoleutils_testclass + master + remotes/openms_tetak94/colorizer_testclass