diff --git a/libdnf5-cli/progressbar/download_progress_bar.cpp b/libdnf5-cli/progressbar/download_progress_bar.cpp
index 03416ee59..12b398ba3 100644
--- a/libdnf5-cli/progressbar/download_progress_bar.cpp
+++ b/libdnf5-cli/progressbar/download_progress_bar.cpp
@@ -20,6 +20,8 @@ along with libdnf. If not, see .
#include "libdnf5-cli/progressbar/download_progress_bar.hpp"
+#include "../utils/utf8.hpp"
+
#include "libdnf5-cli/tty.hpp"
#include
@@ -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()) {
@@ -205,9 +209,17 @@ 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.
+ 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;
diff --git a/test/libdnf5-cli/test_progressbar_interactive.cpp b/test/libdnf5-cli/test_progressbar_interactive.cpp
index 40b52af67..016a6a3c2 100644
--- a/test/libdnf5-cli/test_progressbar_interactive.cpp
+++ b/test/libdnf5-cli/test_progressbar_interactive.cpp
@@ -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() {
@@ -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 message1 \n"
+ ">>> test message2 \n"
+ ">>> test もで 諤奯ゞ ";
ASSERT_MATCHES(expected, oss.str());
+ download_progress_bar->pop_message();
download_progress_bar->pop_message();
download_progress_bar->pop_message();
@@ -238,7 +243,7 @@ void ProgressbarInteractiveTest::test_multi_progress_bar_with_messages_with_tota
oss << multi_progress_bar;
Pattern expected =
"\\[1/1\\] test 40% | ????? ??B\\/s | 4.0 B | ???????\n"
- ">>> test message1\n"
+ ">>> test message1 \n"
"----------------------------------------------------------------------\n"
"\\[0/1\\] Total 40% | ????? ??B\\/s | 4.0 B | ???????";
@@ -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();
@@ -312,19 +317,22 @@ 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;
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\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;
@@ -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()));
@@ -363,7 +372,7 @@ void ProgressbarInteractiveTest::test_multi_progress_bar_with_messages() {
oss << multi_progress_bar;
Pattern expected =
"\\[1/1\\] test 40% | ????? ??B\\/s | 4.0 B | ???????\n"
- ">>> test message1";
+ ">>> test message1 ";
ASSERT_MATCHES(expected, perform_control_sequences(oss.str()));
@@ -411,17 +420,20 @@ 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 message1 \n"
+ ">>> 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;
@@ -429,6 +441,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()));
@@ -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()));
@@ -467,3 +481,39 @@ void ProgressbarInteractiveTest::test_multi_progress_bars_with_messages() {
ASSERT_MATCHES(expected, perform_control_sequences(oss.str()));
}
+
+void ProgressbarInteractiveTest::test_multi_progress_bar_with_short_messages() {
+ // With single bar and Total disabled
+ // First print long message and remove it (successful scriptlet for package with long name),
+ // then print short msg (different package that prints something to the log and the message stays).
+
+ auto download_progress_bar = std::make_unique(10, "test");
+
+ libdnf5::cli::progressbar::MultiProgressBar multi_progress_bar;
+ multi_progress_bar.set_total_bar_visible_limit(libdnf5::cli::progressbar::MultiProgressBar::NEVER_VISIBLE_LIMIT);
+ auto download_progress_bar_raw = download_progress_bar.get();
+ multi_progress_bar.add_bar(std::move(download_progress_bar));
+
+ download_progress_bar_raw->set_ticks(4);
+ download_progress_bar_raw->set_state(libdnf5::cli::progressbar::ProgressBarState::STARTED);
+ download_progress_bar_raw->add_message(
+ libdnf5::cli::progressbar::MessageType::INFO, "test loooooooooooooooooooooooooooooooooooooooooong message");
+
+ std::ostringstream oss;
+ oss << multi_progress_bar;
+ Pattern expected =
+ "\\[1/1\\] test 40% | ????? ??B\\/s | 4.0 B | ???????\n"
+ ">>> test loooooooooooooooooooooooooooooooooooooooooong message ";
+
+ ASSERT_MATCHES(expected, perform_control_sequences(oss.str()));
+
+ download_progress_bar_raw->pop_message();
+ download_progress_bar_raw->add_message(libdnf5::cli::progressbar::MessageType::INFO, "test short message");
+
+ oss << multi_progress_bar;
+ expected =
+ "\\[1/1\\] test 40% | ????? ??B\\/s | 4.0 B | ???????\n"
+ ">>> test short message ";
+
+ ASSERT_MATCHES(expected, perform_control_sequences(oss.str()));
+}
diff --git a/test/libdnf5-cli/test_progressbar_interactive.hpp b/test/libdnf5-cli/test_progressbar_interactive.hpp
index 2f55338f2..676ac938f 100644
--- a/test/libdnf5-cli/test_progressbar_interactive.hpp
+++ b/test/libdnf5-cli/test_progressbar_interactive.hpp
@@ -34,6 +34,7 @@ class ProgressbarInteractiveTest : public CppUnit::TestCase {
CPPUNIT_TEST(test_multi_progress_bar_with_messages_with_total);
CPPUNIT_TEST(test_multi_progress_bars_with_messages_with_total);
CPPUNIT_TEST(test_multi_progress_bar_with_messages);
+ CPPUNIT_TEST(test_multi_progress_bar_with_short_messages);
CPPUNIT_TEST(test_multi_progress_bars_with_messages);
CPPUNIT_TEST_SUITE_END();
@@ -49,6 +50,7 @@ class ProgressbarInteractiveTest : public CppUnit::TestCase {
void test_multi_progress_bar_with_messages_with_total();
void test_multi_progress_bars_with_messages_with_total();
void test_multi_progress_bar_with_messages();
+ void test_multi_progress_bar_with_short_messages();
void test_multi_progress_bars_with_messages();
};