From fbc4f1adc502a1c5bc9f97bb4124df6a352651f4 Mon Sep 17 00:00:00 2001 From: Marcus Holland-Moritz Date: Sun, 29 Nov 2020 17:49:34 +0100 Subject: [PATCH] Neater progress indicator --- include/dwarfs/console_writer.h | 5 +- src/dwarfs/console_writer.cpp | 84 ++++++++++++++++++++++----------- src/mkdwarfs.cpp | 4 +- 3 files changed, 63 insertions(+), 30 deletions(-) diff --git a/include/dwarfs/console_writer.h b/include/dwarfs/console_writer.h index d1f79672..79647eac 100644 --- a/include/dwarfs/console_writer.h +++ b/include/dwarfs/console_writer.h @@ -35,8 +35,10 @@ class progress; class console_writer : public logger { public: + enum display_mode { NORMAL, REWRITE }; + console_writer(std::ostream& os, bool is_terminal, size_t width, - level_type threshold); + level_type threshold, display_mode mode = NORMAL); void write(level_type level, const std::string& output) override; @@ -53,5 +55,6 @@ class console_writer : public logger { std::atomic counter_{0}; const bool show_progress_; const size_t width_; + const display_mode mode_; }; } // namespace dwarfs diff --git a/src/dwarfs/console_writer.cpp b/src/dwarfs/console_writer.cpp index 55edd6f2..d9cc600e 100644 --- a/src/dwarfs/console_writer.cpp +++ b/src/dwarfs/console_writer.cpp @@ -24,6 +24,8 @@ #include +#include + #include "dwarfs/console_writer.h" #include "dwarfs/entry.h" #include "dwarfs/file_interface.h" @@ -34,12 +36,14 @@ namespace dwarfs { console_writer::console_writer(std::ostream& os, bool show_progress, - size_t width, level_type threshold) + size_t width, level_type threshold, + display_mode mode) : os_(os) , threshold_(threshold) , frac_(0.0) , show_progress_(show_progress) - , width_(width) { + , width_(width) + , mode_(mode) { os_.imbue(std::locale(os_.getloc(), new boost::posix_time::time_facet("%H:%M:%S.%f"))); if (threshold > level_type::INFO) { @@ -51,7 +55,14 @@ console_writer::console_writer(std::ostream& os, bool show_progress, void console_writer::rewind() { if (!statebuf_.empty()) { - os_ << "\x1b[A\r\x1b[A\x1b[A\x1b[A\x1b[A\x1b[A\x1b[A"; + switch (mode_) { + case NORMAL: + os_ << "\x1b[A\r\x1b[A\x1b[A\x1b[A\x1b[A\x1b[A\x1b[A"; + break; + case REWRITE: + os_ << "\x1b[A\r\x1b[A\x1b[A\x1b[A"; + break; + } } } @@ -99,57 +110,74 @@ void console_writer::update(const progress& p, bool last) { if (show_progress_) { for (size_t i = 0; i < width_; ++i) { - oss << '-'; + oss << "⎯"; } oss << "\n"; } - oss << p.status(width_) << newline + switch (mode_) { + case NORMAL: + oss << p.status(width_) << newline - << "scanned/found: " << p.dirs_scanned << "/" << p.dirs_found << " dirs, " - << p.links_scanned << "/" << p.links_found << " links, " - << p.files_scanned << "/" << p.files_found << " files" << newline + << "scanned/found: " << p.dirs_scanned << "/" << p.dirs_found + << " dirs, " << p.links_scanned << "/" << p.links_found << " links, " + << p.files_scanned << "/" << p.files_found << " files" << newline - << "original size: " << size_with_unit(p.original_size) - << ", dedupe: " << size_with_unit(p.saved_by_deduplication) << " (" - << p.duplicate_files - << " files), segment: " << size_with_unit(p.saved_by_segmentation) - << newline + << "original size: " << size_with_unit(p.original_size) + << ", dedupe: " << size_with_unit(p.saved_by_deduplication) << " (" + << p.duplicate_files + << " files), segment: " << size_with_unit(p.saved_by_segmentation) + << newline - << "filesystem: " << size_with_unit(p.filesystem_size) << " in " - << p.block_count << " blocks (" << p.chunk_count << " chunks, " - << p.inodes_written << "/" << p.files_found - p.duplicate_files - << " inodes)" << newline + << "filesystem: " << size_with_unit(p.filesystem_size) << " in " + << p.block_count << " blocks (" << p.chunk_count << " chunks, " + << p.inodes_written << "/" << p.files_found - p.duplicate_files + << " inodes)" << newline - << "compressed filesystem: " << p.blocks_written << " blocks/" - << size_with_unit(p.compressed_size) << " written" << newline; + << "compressed filesystem: " << p.blocks_written << " blocks/" + << size_with_unit(p.compressed_size) << " written" << newline; + break; + + case REWRITE: + oss << "filesystem: " << size_with_unit(p.filesystem_size) << " in " + << p.block_count << " blocks (" << p.chunk_count << " chunks, " + << p.inodes_written << " inodes)" << newline + + << "compressed filesystem: " << p.blocks_written << "/" << p.block_count + << " blocks/" << size_with_unit(p.compressed_size) << " written" + << newline; + break; + } if (show_progress_) { - // TODO: this can likely be improved size_t orig = p.original_size - p.saved_by_deduplication; double frac_fs = orig > 0 ? double(p.filesystem_size + p.saved_by_segmentation) / orig : 0.0; double frac_comp = p.block_count > 0 ? double(p.blocks_written) / p.block_count : 0.0; - double frac = (frac_fs + frac_comp) / 2.0; + double frac = mode_ == NORMAL ? (frac_fs + frac_comp) / 2.0 : frac_comp; if (frac > frac_) { frac_ = frac; } - size_t w = width_ * frac_; + size_t barlen = 8 * (width_ - 6) * frac_; + size_t w = barlen / 8; + size_t c = barlen % 8; - for (size_t i = 0; i < width_; ++i) { - if (i == 0 || i == (width_ - 1)) { - oss << "|"; + static const char* bar[8] = {"▏", "▎", "▍", "▌", "▋", "▊", "▉", "█"}; + + for (size_t i = 0; i < width_ - 6; ++i) { + if (i == (width_ - 7)) { + oss << bar[0]; } else if (i == w && !last) { - oss << "/-\\|"[counter_ % 4]; + oss << bar[c]; } else { - oss << (i < w ? "=" : " "); + oss << (i < w ? bar[7] : " "); } } - oss << "\n"; + oss << fmt::format("{:3.0f}% ", 100 * frac_) << "-\\|/"[counter_ % 4] << '\n'; ++counter_; diff --git a/src/mkdwarfs.cpp b/src/mkdwarfs.cpp index 147ae854..af0d255a 100644 --- a/src/mkdwarfs.cpp +++ b/src/mkdwarfs.cpp @@ -443,7 +443,9 @@ int mkdwarfs(int argc, char** argv) { max_scanner_workers); console_writer lgr(std::cerr, !no_progress && ::isatty(::fileno(stderr)), - get_term_width(), logger::parse_level(log_level)); + get_term_width(), logger::parse_level(log_level), + recompress ? console_writer::REWRITE + : console_writer::NORMAL); std::shared_ptr