mirror of https://github.com/aria2/aria2
Use some colors in progress reports (where available)
parent
87ea4904a0
commit
80528aa9ce
|
@ -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
|
|
@ -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
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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\
|
||||
|
|
Loading…
Reference in New Issue