summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <jak@debian.org>2024-04-13 23:59:41 +0200
committerJulian Andres Klode <jak@debian.org>2024-04-13 23:59:41 +0200
commitac8fe4b030754584cda9cb1707fc3d9f0d792366 (patch)
tree3cf746da51507a24d49779f5eaf2326dc2c09f75
parentffe5a25fdb0dd178ba36b9f72c5213565adf19f0 (diff)
apt: Use unicode install progress bar on UTF-8 locales
This produces a much more appealing progress bar and it can even show parts of the progress being done.
-rw-r--r--apt-pkg/install-progress.cc12
-rw-r--r--test/libapt/install_progress_test.cc20
2 files changed, 31 insertions, 1 deletions
diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc
index 2b0dc21ea..fe3324426 100644
--- a/apt-pkg/install-progress.cc
+++ b/apt-pkg/install-progress.cc
@@ -13,6 +13,7 @@
#include <sstream>
#include <vector>
#include <fcntl.h>
+#include <langinfo.h>
#include <sys/ioctl.h>
#include <unistd.h>
@@ -344,14 +345,23 @@ void PackageManagerFancy::Stop()
std::string
PackageManagerFancy::GetTextProgressStr(float Percent, int OutputSize)
{
+ bool Unicode = strcmp(nl_langinfo(CODESET), "UTF-8") == 0;
std::string output;
if (unlikely(OutputSize < 3))
return output;
int const BarSize = OutputSize - 2; // bar without the leading "[" and trailing "]"
int const BarDone = std::max(0, std::min(BarSize, static_cast<int>(std::floor(Percent * BarSize))));
+ double dummy;
+ double const BarDoneFractional = std::modf(Percent * BarSize, &dummy);
+ const char *const BarDoneFractionalChar = (const char *[]){
+ " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉"}[static_cast<int>(std::floor(BarDoneFractional * 8))];
output.append("[");
- std::fill_n(std::fill_n(std::back_inserter(output), BarDone, '#'), BarSize - BarDone, '.');
+ for (int i = 0; i < BarDone; i++)
+ output.append(Unicode ? "█" : "#");
+ if (BarDone + 1 <= BarSize)
+ output.append(Unicode ? BarDoneFractionalChar : ".");
+ std::fill_n(std::back_inserter(output), BarSize - BarDone - 1, Unicode ? ' ' : '.');
output.append("]");
return output;
}
diff --git a/test/libapt/install_progress_test.cc b/test/libapt/install_progress_test.cc
index 68101af9b..7015c619c 100644
--- a/test/libapt/install_progress_test.cc
+++ b/test/libapt/install_progress_test.cc
@@ -2,6 +2,7 @@
#include <apt-pkg/install-progress.h>
+#include <locale>
#include <string>
#include <gtest/gtest.h>
@@ -10,6 +11,7 @@ TEST(InstallProgressTest, FancyGetTextProgressStr)
{
APT::Progress::PackageManagerFancy p;
+ char *originalLocale = setlocale(LC_ALL, "C");
EXPECT_EQ(60u, p.GetTextProgressStr(0.5, 60).size());
EXPECT_EQ("[#.]", p.GetTextProgressStr(0.5, 4));
EXPECT_EQ("[..........]", p.GetTextProgressStr(0.0, 12));
@@ -22,4 +24,22 @@ TEST(InstallProgressTest, FancyGetTextProgressStr)
// deal with incorrect inputs gracefully (or should we die instead?)
EXPECT_EQ("[..........]", p.GetTextProgressStr(-1.0, 12));
EXPECT_EQ("[##########]", p.GetTextProgressStr(2.0, 12));
+
+ setlocale(LC_ALL, "C.UTF-8");
+
+ EXPECT_EQ("[█ ]", p.GetTextProgressStr(0.5, 4));
+ EXPECT_EQ("[ ]", p.GetTextProgressStr(0.0, 12));
+ EXPECT_EQ("[█ ]", p.GetTextProgressStr(0.1, 12));
+ EXPECT_EQ("[████ ]", p.GetTextProgressStr(0.4, 12));
+ EXPECT_EQ("[████▉ ]", p.GetTextProgressStr(0.4999, 12));
+ EXPECT_EQ("[█████ ]", p.GetTextProgressStr(0.5000, 12));
+ EXPECT_EQ("[█████ ]", p.GetTextProgressStr(0.5001, 12));
+ EXPECT_EQ("[█████████ ]", p.GetTextProgressStr(0.9001, 12));
+ EXPECT_EQ("[██████████]", p.GetTextProgressStr(1.0, 12));
+
+ // deal with incorrect inputs gracefully (or should we die instead?)
+ EXPECT_EQ("[ ]", p.GetTextProgressStr(-1.0, 12));
+ EXPECT_EQ("[██████████]", p.GetTextProgressStr(2.0, 12));
+
+ setlocale(LC_ALL, originalLocale);
}