summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNils Maier <maierman@web.de>2013-11-17 09:42:36 +0100
committerNils Maier <maierman@web.de>2013-11-21 15:42:42 +0100
commit80528aa9cee07f05cbd536627ca876ddf56b9407 (patch)
treec6dddb65c3aa1745476d324cafe2e654e8e2a9f6 /src
parent87ea4904a0136564bdb22a95d9fef12282c27624 (diff)
Use some colors in progress reports (where available)
Diffstat (limited to 'src')
-rw-r--r--src/ColorizedStream.cc106
-rw-r--r--src/ColorizedStream.h185
-rw-r--r--src/ConsoleStatCalc.cc71
-rw-r--r--src/Makefile.am1
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\