]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Add ProgressBar class
authorJoel Rosdahl <joel@rosdahl.net>
Wed, 28 Aug 2019 19:58:06 +0000 (21:58 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Thu, 5 Sep 2019 20:04:43 +0000 (22:04 +0200)
The progress bar draws a simple progress bar with percentage to the
console.

Makefile.in
dev.mk.in
src/ProgressBar.cpp [new file with mode: 0644]
src/ProgressBar.hpp [new file with mode: 0644]

index 9ef3aa26ee65e38b342ffdec388593795affd0f6..3c6c721e4fe7e51be34f6f558baad72646371a0f 100644 (file)
@@ -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 \
index 5663ec6e4903c383da334ba6a571604ea660cf32..504f1be2b3f0897fd3b8dafa16644bd132ee219f 100644 (file)
--- 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 (file)
index 0000000..df43052
--- /dev/null
@@ -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 <cstdio>
+#include <fmt/core.h>
+#include <unistd.h>
+
+#ifdef _WIN32
+#  include <windows.h>
+#else
+#  include <sys/ioctl.h>
+#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<int16_t>(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 (file)
index 0000000..f1b43e5
--- /dev/null
@@ -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 <string>
+
+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)
+};