From: Joel Rosdahl Date: Wed, 28 Aug 2019 19:58:06 +0000 (+0200) Subject: Add ProgressBar class X-Git-Tag: v4.0~805 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d74ca5da634dcb89ce6f5a772dd99032e7fae87c;p=thirdparty%2Fccache.git Add ProgressBar class The progress bar draws a simple progress bar with percentage to the console. --- diff --git a/Makefile.in b/Makefile.in index 9ef3aa26e..3c6c721e4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -33,6 +33,7 @@ Q=$(if $(quiet),@) non_third_party_sources = \ src/AtomicFile.cpp \ src/Config.cpp \ + src/ProgressBar.cpp \ src/args.cpp \ src/ccache.cpp \ src/cleanup.cpp \ diff --git a/dev.mk.in b/dev.mk.in index 5663ec6e4..504f1be2b 100644 --- a/dev.mk.in +++ b/dev.mk.in @@ -38,6 +38,7 @@ non_third_party_headers = \ src/AtomicFile.hpp \ src/Config.hpp \ src/Error.hpp \ + src/ProgressBar.hpp \ src/ccache.hpp \ src/common_header.hpp \ src/compopt.hpp \ diff --git a/src/ProgressBar.cpp b/src/ProgressBar.cpp new file mode 100644 index 000000000..df430529c --- /dev/null +++ b/src/ProgressBar.cpp @@ -0,0 +1,91 @@ +// Copyright (C) 2019 Joel Rosdahl and other contributors +// +// See doc/AUTHORS.adoc for a complete list of contributors. +// +// 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 3 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 + +#include "ProgressBar.hpp" + +#include +#include +#include + +#ifdef _WIN32 +# include +#else +# include +#endif + +namespace { + +const size_t k_max_width = 120; + +size_t +get_terminal_width() +{ +#ifdef _WIN32 + CONSOLE_SCREEN_BUFFER_INFO info; + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info); + return info.srWindow.Right - info.srWindow.Left; +#else + struct winsize winsize; + ioctl(0, TIOCGWINSZ, &winsize); + return winsize.ws_col; +#endif +} + +} // namespace + +ProgressBar::ProgressBar(const std::string& header) + : m_header(header), + m_width(std::min(k_max_width, get_terminal_width())), + m_stdout_is_a_terminal(isatty(STDOUT_FILENO)) +{ + update(0.0); +} + +void +ProgressBar::update(double value) +{ + if (!m_stdout_is_a_terminal) { + return; + } + + int16_t new_value = static_cast(1000 * value); + if (new_value == m_current_value) { + return; + } + m_current_value = new_value; + + size_t first_part_width = m_header.size() + 10; + if (first_part_width + 10 > m_width) { + // The progress bar would be less than 10 characters, so just print the + // percentage. + fmt::print("\r{} {:5.1f}%", m_header, 100 * value); + } else { + size_t total_bar_width = m_width - first_part_width; + size_t filled_bar_width = value * total_bar_width; + size_t unfilled_bar_width = total_bar_width - filled_bar_width; + fmt::print("\r{} {:5.1f}% [{:=<{}}{: <{}}]", + m_header, + 100 * value, + "", + filled_bar_width, + "", + unfilled_bar_width); + } + + fflush(stdout); +} diff --git a/src/ProgressBar.hpp b/src/ProgressBar.hpp new file mode 100644 index 000000000..f1b43e517 --- /dev/null +++ b/src/ProgressBar.hpp @@ -0,0 +1,37 @@ +// Copyright (C) 2019 Joel Rosdahl and other contributors +// +// See doc/AUTHORS.adoc for a complete list of contributors. +// +// 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 3 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 + +#include + +class ProgressBar +{ +public: + explicit ProgressBar(const std::string& header); + + // Update progress bar. + // + // Parameters: + // - value: A value between 0.0 (nothing completed) to 1.0 (all completed). + void update(double value); + +private: + const std::string m_header; + const size_t m_width; + const bool m_stdout_is_a_terminal; + int16_t m_current_value = -1; // trunc(1000 * value) +};