diff options
| author | Nils Maier <maierman@web.de> | 2013-11-17 09:42:36 +0100 |
|---|---|---|
| committer | Nils Maier <maierman@web.de> | 2013-11-21 15:42:42 +0100 |
| commit | 80528aa9cee07f05cbd536627ca876ddf56b9407 (patch) | |
| tree | c6dddb65c3aa1745476d324cafe2e654e8e2a9f6 /src | |
| parent | 87ea4904a0136564bdb22a95d9fef12282c27624 (diff) | |
Use some colors in progress reports (where available)
Diffstat (limited to 'src')
| -rw-r--r-- | src/ColorizedStream.cc | 106 | ||||
| -rw-r--r-- | src/ColorizedStream.h | 185 | ||||
| -rw-r--r-- | src/ConsoleStatCalc.cc | 71 | ||||
| -rw-r--r-- | src/Makefile.am | 1 |
4 files changed, 334 insertions, 29 deletions
diff --git a/src/ColorizedStream.cc b/src/ColorizedStream.cc new file mode 100644 index 00000000..4388406e --- /dev/null +++ b/src/ColorizedStream.cc @@ -0,0 +1,106 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * Copyright (C) 2013 Nils Maier + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ + +#include "ColorizedStream.h" + + +namespace aria2 { +namespace colors { + +const Color black("30"); +const Color red("31"); +const Color green("32"); +const Color yellow("33"); +const Color blue("34"); +const Color magenta("35"); +const Color cyan("36"); +const Color white("37"); + +const Color lightred("1;31"); +const Color lightgreen("1;32"); +const Color lightyellow("1;33"); +const Color lightblue("1;34"); +const Color lightmagenta("1;35"); +const Color lightcyan("1;36"); +const Color lightwhite("1;37"); + +const Color clear("0"); + +} // namespace colors + +std::string ColorizedStreamBuf::str(bool color) const +{ + std::stringstream rv; + for (const auto& e: elems) { + if (color || e.first != eColor) { + rv << e.second; + } + } + if (color) { + rv << colors::clear.str(); + } + return rv.str(); +} + +std::string ColorizedStreamBuf::str(bool color, size_t max) const +{ + std::stringstream rv; + for (const auto& e: elems) { + if (e.first == eColor) { + if (color) { + rv << e.second; + } + continue; + } + auto size = e.second.size(); + if (size > max) { + auto cut = e.second; + cut.resize(max); + rv << cut; + break; + } + rv << e.second; + max -= size; + if (!max) { + break; + } + } + if (color) { + rv << colors::clear.str(); + } + return rv.str(); +} + +} // namespace aria2 diff --git a/src/ColorizedStream.h b/src/ColorizedStream.h new file mode 100644 index 00000000..431c8149 --- /dev/null +++ b/src/ColorizedStream.h @@ -0,0 +1,185 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * Copyright (C) 2013 Nils Maier + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ + +#ifndef D_COLORIZED_STREAM_H +#define D_COLORIZED_STREAM_H + +#include <string> +#include <sstream> +#include <deque> + +namespace aria2 { + +namespace colors { + +class Color +{ +private: + std::string str_; + +public: + explicit Color(const char* str) + : str_(std::string("\033[") + str + "m") + {} + + const std::string& str() const { + return str_; + } +}; + +extern const Color black; +extern const Color red; +extern const Color green; +extern const Color yellow; +extern const Color blue; +extern const Color magenta; +extern const Color cyan; +extern const Color white; + +extern const Color lightred; +extern const Color lightgreen; +extern const Color lightyellow; +extern const Color lightblue; +extern const Color lightmagenta; +extern const Color lightcyan; +extern const Color lightwhite; + +extern const Color clear; + +} // namespace colors + +typedef std::char_traits<char> traits_t; +class ColorizedStreamBuf + : public std::basic_streambuf<char, traits_t> +{ + enum part_t + { + eColor, + eString + }; + typedef std::pair<part_t, std::string> elem_t; + typedef std::deque<elem_t> elems_t; + elems_t elems; + +public: + ColorizedStreamBuf() + { + elems.push_back(std::make_pair(eString, "")); + } + + void setColor(const colors::Color& color) + { + elems.push_back(std::make_pair(eColor, color.str())); + elems.push_back(std::make_pair(eString, "")); + } + + traits_t::int_type overflow(traits_t::int_type c) + { + elems.back().second.push_back((char)c); + return std::char_traits<char>::not_eof(c); + } + + void append(const std::string& str) + { + elems.back().second += str; + } + + void append(const char* str) + { + elems.back().second += str; + } + + std::string str(bool color) const; + std::string str(bool color, size_t max) const; +}; + +class ColorizedStream: public std::basic_ostream<char, traits_t> +{ +public: + ColorizedStream() + : std::basic_ios<char, traits_t>(&buf), + std::basic_ostream<char, traits_t>(&buf) + { + init(&buf); + } + + void setColor(const colors::Color& color) + { + buf.setColor(color); + } + void append(const std::string& str) { + buf.append(str); + } + void append(const char* str) { + buf.append(str); + } + + std::string str(bool colors) const + { + return buf.str(colors); + } + std::string str(bool colors, size_t max) const + { + return buf.str(colors, max); + } + +private: + ColorizedStreamBuf buf; +}; + +inline +ColorizedStream& operator<<(ColorizedStream& stream, const std::string& str) +{ + stream.append(str); + return stream; +} + +inline +ColorizedStream& operator<<(ColorizedStream& stream, const char* str) +{ + stream.append(str); + return stream; +} + +inline +ColorizedStream& operator<<(ColorizedStream& stream, const colors::Color& c) +{ + stream.setColor(c); + return stream; +} + +} // namespace aria2 + +#endif // D_COLORIZED_STREAM_H diff --git a/src/ConsoleStatCalc.cc b/src/ConsoleStatCalc.cc index 262e8b8f..7e2d351c 100644 --- a/src/ConsoleStatCalc.cc +++ b/src/ConsoleStatCalc.cc @@ -62,6 +62,8 @@ #include "wallclock.h" #include "FileEntry.h" #include "console.h" +#include "ColorizedStream.h" + #ifdef ENABLE_BITTORRENT # include "bittorrent_helper.h" # include "PeerStorage.h" @@ -96,7 +98,8 @@ protected: } // namespace namespace { -void printSizeProgress(std::ostream& o, const std::shared_ptr<RequestGroup>& rg, +void printSizeProgress(ColorizedStream& o, + const std::shared_ptr<RequestGroup>& rg, const TransferStat& stat, const SizeFormatter& sizeFormatter) { @@ -128,14 +131,18 @@ void printSizeProgress(std::ostream& o, const std::shared_ptr<RequestGroup>& rg, } // namespace namespace { -void printProgressCompact(std::ostream& o, const DownloadEngine* e, +void printProgressCompact(ColorizedStream& o, const DownloadEngine* e, const SizeFormatter& sizeFormatter) { - if(!e->getRequestGroupMan()->downloadFinished()) { + if (!e->getRequestGroupMan()->downloadFinished()) { NetStat& netstat = e->getRequestGroupMan()->getNetStat(); int dl = netstat.calculateDownloadSpeed(); int ul = netstat.calculateUploadSpeed(); - o << "[DL:" << sizeFormatter(dl) << "B UL:" << sizeFormatter(ul) << "B]"; + o << "[DL:" << colors::green << sizeFormatter(dl) << "B" << colors::clear; + if (ul) { + o << " UL:" << colors::cyan << sizeFormatter(ul) << "B" << colors::clear; + } + o << "]"; } const RequestGroupList& groups = @@ -157,9 +164,8 @@ void printProgressCompact(std::ostream& o, const DownloadEngine* e, } // namespace namespace { -void printProgress -(std::ostream& o, const std::shared_ptr<RequestGroup>& rg, const DownloadEngine* e, - const SizeFormatter& sizeFormatter) +void printProgress(ColorizedStream& o, const std::shared_ptr<RequestGroup>& rg, + const DownloadEngine* e, const SizeFormatter& sizeFormatter) { TransferStat stat = rg->calculateStat(); int eta = 0; @@ -179,18 +185,18 @@ void printProgress } #endif // ENABLE_BITTORRENT - if(!rg->downloadFinished()) { - o << " DL:" - << sizeFormatter(stat.downloadSpeed) << "B"; + if (!rg->downloadFinished()) { + o << " DL:" << + colors::green << sizeFormatter(stat.downloadSpeed) << "B" << + colors::clear; } - if(stat.sessionUploadLength > 0) { - o << " UL:" - << sizeFormatter(stat.uploadSpeed) << "B" - << "(" << sizeFormatter(stat.allTimeUploadLength) << "B)"; + if (stat.sessionUploadLength > 0) { + o << " UL:" << + colors::cyan << sizeFormatter(stat.uploadSpeed) << "B" << colors::clear; + o << "(" << sizeFormatter(stat.allTimeUploadLength) << "B)"; } - if(eta > 0) { - o << " ETA:" - << util::secfmt(eta); + if (eta > 0) { + o << " ETA:" << colors::yellow << util::secfmt(eta) << colors::clear; } o << "]"; } @@ -212,7 +218,7 @@ public: void operator()(const RequestGroupList::value_type& rg) { const char SEP_CHAR = '-'; - std::stringstream o; + ColorizedStream o; printProgress(o, rg, e_, sizeFormatter_); const std::vector<std::shared_ptr<FileEntry> >& fileEntries = rg->getDownloadContext()->getFileEntries(); @@ -221,15 +227,16 @@ public: o, rg->inMemoryDownload()); o << "\n" << std::setfill(SEP_CHAR) << std::setw(cols_) << SEP_CHAR << "\n"; - global::cout()->write(o.str().c_str()); + auto str = o.str(false); + global::cout()->write(str.c_str()); } }; } // namespace namespace { -void printProgressSummary -(const RequestGroupList& groups, size_t cols, const DownloadEngine* e, - const SizeFormatter& sizeFormatter) +void printProgressSummary(const RequestGroupList& groups, size_t cols, + const DownloadEngine* e, + const SizeFormatter& sizeFormatter) { const char SEP_CHAR = '='; time_t now; @@ -304,7 +311,7 @@ ConsoleStatCalc::calculateStat(const DownloadEngine* e) std::string line(cols, ' '); global::cout()->printf("\r%s\r", line.c_str()); } - std::ostringstream o; + ColorizedStream o; if(e->getRequestGroupMan()->countRequestGroup() > 0) { if((summaryInterval_ > 0) && lastSummaryNotified_.differenceInMillis(global::wallclock())+ @@ -320,6 +327,7 @@ ConsoleStatCalc::calculateStat(const DownloadEngine* e) return; } size_t numGroup = e->getRequestGroupMan()->countRequestGroup(); + const bool color = global::cout()->supportsColor() && isTTY_; if(numGroup == 1) { const std::shared_ptr<RequestGroup>& rg = *e->getRequestGroupMan()->getRequestGroups().begin(); @@ -367,15 +375,20 @@ ConsoleStatCalc::calculateStat(const DownloadEngine* e) } } #endif // ENABLE_MESSAGE_DIGEST - std::string readout = o.str(); if(isTTY_) { - if(truncate_ && readout.size() > cols) { - readout[cols] = '\0'; + if (truncate_) { + auto str = o.str(color, cols); + global::cout()->write(str.c_str()); + } + else { + auto str = o.str(color); + global::cout()->write(str.c_str()); } - global::cout()->write(readout.c_str()); global::cout()->flush(); - } else { - global::cout()->write(readout.c_str()); + } + else { + auto str = o.str(false); + global::cout()->write(str.c_str()); global::cout()->write("\n"); } } diff --git a/src/Makefile.am b/src/Makefile.am index 91146686..a6f5508c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -226,6 +226,7 @@ SRCS = option_processing.cc\ OutputFile.h\ NullOutputFile.h\ console.cc console.h\ + ColorizedStream.cc ColorizedStream.h\ IOFile.cc IOFile.h\ BufferedFile.cc BufferedFile.h\ SegList.h\ |
