diff --git a/CMakeLists.txt b/CMakeLists.txt index b9a7268..69221d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20) include(cmake/color.cmake) -set(BLT_VERSION 5.2.14) +set(BLT_VERSION 5.2.15) set(BLT_TARGET BLT) diff --git a/include/blt/logging/status.h b/include/blt/logging/status.h index 8ce363d..b6d2fe2 100644 --- a/include/blt/logging/status.h +++ b/include/blt/logging/status.h @@ -19,42 +19,85 @@ #ifndef BLT_LOGGING_STATUS_H #define BLT_LOGGING_STATUS_H +#include #include #include -#include #include +#include namespace blt::logging { + class status_bar_t; class status_item_t { public: virtual ~status_item_t() = default; + void assign(status_bar_t* bar) + { + m_status = bar; + } + [[nodiscard]] virtual i32 lines_used() const { return 1; } - virtual std::string print() = 0; + [[nodiscard]] virtual std::string print(vec2i screen_size, i32 max_printed_length) const = 0; + protected: + status_bar_t* m_status = nullptr; + }; + + class status_progress_bar_t final : public status_item_t + { + public: + [[nodiscard]] std::string print(vec2i screen_size, i32 max_printed_length) const override; + + void set_progress(double progress); + + void add_progress(const double progress) + { + set_progress(get_progress() + progress); + } + + [[nodiscard]] double get_progress() const + { + return m_progress; + } + private: + double m_progress = 0.0; }; class status_bar_t final : public injector_t { public: - explicit status_bar_t(i32 status_size); + explicit status_bar_t(); injector_output_t inject(const std::string& input) override; - void redraw(); + status_bar_t& add(status_item_t& item) + { + item.assign(this); + m_status_items.push_back(&item); + compute_size(); + return *this; + } + + void redraw() const; ~status_bar_t() override; private: - i32 m_status_size; + void compute_size(); + + std::vector m_status_items; + i32 m_status_size = 0; + i32 m_max_printed_length = 0; vec2i m_screen_size; vec2i m_last_log_position; vec2i m_begin_position; + + std::mutex m_print_mutex; }; } diff --git a/libraries/parallel-hashmap b/libraries/parallel-hashmap index 93201da..7ef2e73 160000 --- a/libraries/parallel-hashmap +++ b/libraries/parallel-hashmap @@ -1 +1 @@ -Subproject commit 93201da2ba5a6aba0a6e57ada64973555629b3e3 +Subproject commit 7ef2e733416953b222851f9a360d7fc72d068ee5 diff --git a/src/blt/logging/status.cpp b/src/blt/logging/status.cpp index f114911..258dbbb 100644 --- a/src/blt/logging/status.cpp +++ b/src/blt/logging/status.cpp @@ -89,7 +89,7 @@ namespace blt::logging changed.c_cc[VTIME] = 0; tcsetattr( STDIN_FILENO, TCSANOW, &changed); - // printf ( "\033[2J"); //clear screen + printf ( "\033[2J"); //clear screen printf ( "\033[9999;9999H"); // cursor should move as far as it can @@ -115,7 +115,53 @@ namespace blt::logging throw std::runtime_error("Could not get screen size"); } - status_bar_t::status_bar_t(const i32 status_size): m_status_size(status_size) + i32 get_size_no_ansi(const std::string& str) + { + i32 size = 0; + for (size_t i = 0; i < str.size(); i++) + { + if (str[i] == BLT_ANSI_ESCAPE[0]) + { + while (i < str.size()) + { + if (std::isalpha(str[i++])) + break; + } + } + ++size; + } + return size; + } + + std::string status_progress_bar_t::print(const vec2i screen_size, const i32 max_printed_length) const + { + std::string output = "["; + output.reserve(max_printed_length); + const auto amount_filled = (max_printed_length - 2) * m_progress; + auto amount_filled_int = static_cast(amount_filled); + const auto frac = amount_filled - static_cast(amount_filled_int); + + for (i64 i = 0; i < amount_filled_int; i++) + output += '#'; + if (frac >= 0.5) + { + output += '|'; + ++amount_filled_int; + } + for (i64 i = amount_filled_int; i < max_printed_length - 2; i++) + output += ' '; + + output += ']'; + return output; + } + + void status_progress_bar_t::set_progress(const double progress) + { + m_progress = progress; + // m_status->redraw(); + } + + status_bar_t::status_bar_t() { m_screen_size = get_screen_size(); std::cout << ansi::cursor::home << std::flush; @@ -126,6 +172,7 @@ namespace blt::logging injector_output_t status_bar_t::inject(const std::string& input) { + std::scoped_lock lock{m_print_mutex}; injector_output_t output{input, false, false}; if (output.new_logging_output.back() != '\n') output.new_logging_output += '\n'; @@ -137,19 +184,25 @@ namespace blt::logging } std::cout << ansi::erase::entire_line << std::flush; std::cout << output.new_logging_output << std::flush; + m_max_printed_length = std::max(get_size_no_ansi(output.new_logging_output), m_max_printed_length); m_last_log_position = get_cursor_position(); redraw(); return output; } - void status_bar_t::redraw() + void status_bar_t::compute_size() + { + m_status_size = 0; + for (const auto* ptr : m_status_items) + m_status_size += ptr->lines_used(); + } + + void status_bar_t::redraw() const { std::cout << ansi::cursor::move_to(m_last_log_position.x(), m_last_log_position.y()); - std::cout << ansi::erase::entire_line << std::flush; - std::cout << "[----status----]" << std::endl; - std::cout << ansi::erase::entire_line << std::flush; - std::cout << "[----Second Line----]" << std::endl; + for (const auto* ptr : m_status_items) + std::cout << ansi::erase::entire_line << ptr->print(m_screen_size, m_max_printed_length) << std::endl; std::cout << std::flush; } diff --git a/tests/logger_tests.cpp b/tests/logger_tests.cpp index d18ef60..c00d01d 100644 --- a/tests/logger_tests.cpp +++ b/tests/logger_tests.cpp @@ -185,17 +185,23 @@ int main() // // BLT_TRACE("Now time to test the logger status box"); - blt::logging::status_bar_t status{2}; + blt::logging::status_progress_bar_t progress; + blt::logging::status_bar_t status; + status.add(progress); blt::logging::get_global_config().add_injector(status); + progress.set_progress(1.0 / 103.0); BLT_TRACE("Hello There!"); std::this_thread::sleep_for(std::chrono::milliseconds(1500)); + progress.set_progress(2.0 / 103.0); BLT_TRACE("I am printing stuff!"); std::this_thread::sleep_for(std::chrono::milliseconds(1500)); + progress.set_progress(3.0 / 103.0); BLT_TRACE("How are you!?"); for (int i = 0; i < 100; i++) { + progress.set_progress((4.0 + i) / 103.0); BLT_INFO("I am printing some output {} times!", i + 1); std::this_thread::sleep_for(std::chrono::milliseconds(100)); }