From ac8fe4b030754584cda9cb1707fc3d9f0d792366 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Sat, 13 Apr 2024 23:59:41 +0200 Subject: 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. --- apt-pkg/install-progress.cc | 12 +++++++++++- test/libapt/install_progress_test.cc | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) 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 #include #include +#include #include #include @@ -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(std::floor(Percent * BarSize)))); + double dummy; + double const BarDoneFractional = std::modf(Percent * BarSize, &dummy); + const char *const BarDoneFractionalChar = (const char *[]){ + " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉"}[static_cast(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 +#include #include #include @@ -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); } -- cgit v1.2.3-70-g09d2