Skip to content

Commit

Permalink
Support ProgressBar messages with wide characters
Browse files Browse the repository at this point in the history
  • Loading branch information
evan-goode committed Dec 10, 2024
1 parent d20e63d commit 92ab80c
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 8 deletions.
16 changes: 11 additions & 5 deletions libdnf5-cli/progressbar/download_progress_bar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.

#include "libdnf5-cli/progressbar/download_progress_bar.hpp"

#include "../utils/utf8.hpp"

#include "libdnf5-cli/tty.hpp"

#include <algorithm>
Expand Down Expand Up @@ -181,8 +183,10 @@ void DownloadProgressBar::to_stream(std::ostream & stream) {
auto message_type = msg.first;
auto message = msg.second;

const auto & prefix = ">>> ";

stream << std::endl;
stream << ">>> ";
stream << prefix;

color_used = false;
if (tty::is_interactive()) {
Expand All @@ -208,12 +212,14 @@ void DownloadProgressBar::to_stream(std::ostream & stream) {
// Add padding to fully fill the terminal_width, this is because MultiProgressBar
// overrides its own messages, it doesn't clear the lines.
// If the message is short some leftover characters could be still present after it.
if (message.length() < terminal_width - 4) {
message.append(terminal_width - message.length() - 4, ' ');
const auto prefix_width = libdnf5::cli::utils::utf8::width(prefix);
const auto message_width = libdnf5::cli::utils::utf8::width(message);
if (message_width < terminal_width - prefix_width) {
message.append(terminal_width - message_width - prefix_width, ' ');
}

// print only part of the message that fits the terminal width
// subtracted '4' relates to the '>>> ' prefix
stream << message.substr(0, terminal_width - 4);
stream << libdnf5::cli::utils::utf8::substr_width(message, 0, terminal_width - prefix_width);

if (color_used) {
stream << tty::reset;
Expand Down
20 changes: 17 additions & 3 deletions test/libdnf5-cli/test_progressbar_interactive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ void ProgressbarInteractiveTest::setUp() {
setenv("DNF5_FORCE_INTERACTIVE", "1", 1);
// Force columns to 70 to make output independ of where it is run
setenv("FORCE_COLUMNS", "70", 1);
// Wide characters do not work at all until we set locales in the code
setlocale(LC_ALL, "C.UTF-8");
}

void ProgressbarInteractiveTest::tearDown() {
Expand Down Expand Up @@ -175,15 +177,18 @@ void ProgressbarInteractiveTest::test_download_progress_bar_with_messages() {
download_progress_bar->set_state(libdnf5::cli::progressbar::ProgressBarState::STARTED);
download_progress_bar->add_message(libdnf5::cli::progressbar::MessageType::INFO, "test message1");
download_progress_bar->add_message(libdnf5::cli::progressbar::MessageType::INFO, "test message2");
download_progress_bar->add_message(libdnf5::cli::progressbar::MessageType::INFO, "test もで 諤奯ゞ");

std::ostringstream oss;
(*download_progress_bar.*get(to_stream{}))(oss);
Pattern expected =
"\\[0/0\\] test 40% | ????? ??B\\/s | 4.0 B | ???????\n"
">>> test message1 \n"
">>> test message2 ";
">>> test message2 \n"
">>> test もで 諤奯ゞ ";
ASSERT_MATCHES(expected, oss.str());

download_progress_bar->pop_message();
download_progress_bar->pop_message();
download_progress_bar->pop_message();

Expand Down Expand Up @@ -270,7 +275,7 @@ void ProgressbarInteractiveTest::test_multi_progress_bar_with_messages_with_tota

download_progress_bar_raw->add_message(libdnf5::cli::progressbar::MessageType::INFO, "test message1");
download_progress_bar_raw->add_message(libdnf5::cli::progressbar::MessageType::INFO, "test message2");
download_progress_bar_raw->add_message(libdnf5::cli::progressbar::MessageType::INFO, "test message3");
download_progress_bar_raw->add_message(libdnf5::cli::progressbar::MessageType::INFO, "test もで 諤奯ゞ");
oss << multi_progress_bar;
download_progress_bar_raw->pop_message();
download_progress_bar_raw->pop_message();
Expand Down Expand Up @@ -312,6 +317,7 @@ void ProgressbarInteractiveTest::test_multi_progress_bars_with_messages_with_tot
download_progress_bar2_raw->set_state(libdnf5::cli::progressbar::ProgressBarState::STARTED);
download_progress_bar2_raw->add_message(libdnf5::cli::progressbar::MessageType::INFO, "test message1");
download_progress_bar2_raw->add_message(libdnf5::cli::progressbar::MessageType::INFO, "test message2");
download_progress_bar2_raw->add_message(libdnf5::cli::progressbar::MessageType::INFO, "test もで 諤奯ゞ");

std::ostringstream oss;
oss << multi_progress_bar;
Expand All @@ -320,11 +326,13 @@ void ProgressbarInteractiveTest::test_multi_progress_bars_with_messages_with_tot
"\\[2/2\\] test2 40% | ????? ??B\\/s | 4.0 B | ???????\n"
">>> test message1 \n"
">>> test message2 \n"
">>> test もで 諤奯ゞ \n"
"----------------------------------------------------------------------\n"
"\\[1/2\\] Total 70% | ????? ??B\\/s | 14.0 B | ???????";

ASSERT_MATCHES(expected, perform_control_sequences(oss.str()));

download_progress_bar2_raw->pop_message();
download_progress_bar2_raw->pop_message();
download_progress_bar2_raw->pop_message();
oss << multi_progress_bar;
Expand All @@ -333,6 +341,7 @@ void ProgressbarInteractiveTest::test_multi_progress_bars_with_messages_with_tot
"\\[2/2\\] test2 40% | ????? ??B\\/s | 4.0 B | ???????\n"
"----------------------------------------------------------------------\n"
"\\[1/2\\] Total 70% | ????? ??B\\/s | 14.0 B | ???????\n"
"\n"
"\n";
ASSERT_MATCHES(expected, perform_control_sequences(oss.str()));

Expand Down Expand Up @@ -411,24 +420,28 @@ void ProgressbarInteractiveTest::test_multi_progress_bars_with_messages() {
download_progress_bar2_raw->set_state(libdnf5::cli::progressbar::ProgressBarState::STARTED);
download_progress_bar2_raw->add_message(libdnf5::cli::progressbar::MessageType::INFO, "test message1");
download_progress_bar2_raw->add_message(libdnf5::cli::progressbar::MessageType::INFO, "test message2");
download_progress_bar2_raw->add_message(libdnf5::cli::progressbar::MessageType::INFO, "test こんにちは世界!");

std::ostringstream oss;
oss << multi_progress_bar;
Pattern expected =
"\\[1/2\\] test1 100% | ????? ??B\\/s | 10.0 B | ???????\n"
"\\[2/2\\] test2 40% | ????? ??B\\/s | 4.0 B | ???????\n"
">>> test message1 \n"
">>> test message2 ";
">>> test message2 \n"
">>> test こんにちは世界! ";

ASSERT_MATCHES(expected, perform_control_sequences(oss.str()));

download_progress_bar2_raw->pop_message();
download_progress_bar2_raw->pop_message();
download_progress_bar2_raw->pop_message();
oss << multi_progress_bar;

expected =
"\\[1/2\\] test1 100% | ????? ??B\\/s | 10.0 B | ???????\n"
"\\[2/2\\] test2 40% | ????? ??B\\/s | 4.0 B | ???????\n"
"\n"
"\n";
ASSERT_MATCHES(expected, perform_control_sequences(oss.str()));

Expand All @@ -441,6 +454,7 @@ void ProgressbarInteractiveTest::test_multi_progress_bars_with_messages() {
expected =
"\\[1/2\\] test1 100% | ????? ??B\\/s | 10.0 B | ???????\n"
"\\[2/2\\] test2 40% | ????? ??B\\/s | 4.0 B | ???????\n"
"\n"
"\n";

ASSERT_MATCHES(expected, perform_control_sequences(oss.str()));
Expand Down

0 comments on commit 92ab80c

Please sign in to comment.