diff --git a/include/indicators/cursor_control.hpp b/include/indicators/cursor_control.hpp new file mode 100755 index 0000000..d962f5c --- /dev/null +++ b/include/indicators/cursor_control.hpp @@ -0,0 +1,43 @@ +#pragma once + +#if defined(_MSC_VER) +#if !defined(NOMINMAX) +#define NOMINMAX +#endif +#include +#include +#else +#include +#endif + +namespace indicators { + +#if defined(_MSC_VER) + +void enable_cursor_movement() { + auto hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleMode(hStdout, + ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING); +} + +void show_console_cursor(bool const show) { + HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); + + CONSOLE_CURSOR_INFO cursorInfo; + + GetConsoleCursorInfo(out, &cursorInfo); + cursorInfo.bVisible = show; // set the cursor visibility + SetConsoleCursorInfo(out, &cursorInfo); +} + +#else + +void enable_cursor_movement() {} + +void show_console_cursor(bool const show) { + std::fputs(show ? "\e[?25h" : "\e[?25l", stdout); +} + +#endif + +} // namespace indicators \ No newline at end of file diff --git a/include/indicators/cursor_movement.hpp b/include/indicators/cursor_movement.hpp new file mode 100755 index 0000000..51bab30 --- /dev/null +++ b/include/indicators/cursor_movement.hpp @@ -0,0 +1,46 @@ +#pragma once + +#if defined(_MSC_VER) +#if !defined(NOMINMAX) +#define NOMINMAX +#endif +#include +#include +#else +#include +#endif + +namespace indicators { + +#ifdef _MSC_VER + +void move(int x, int y) { + auto hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + if (!hStdout) + return; + + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo(hStdout, &csbiInfo); + + COORD cursor; + + cursor.X = csbiInfo.dwCursorPosition.X + x; + cursor.Y = csbiInfo.dwCursorPosition.Y + y; + SetConsoleCursorPosition(hStdout, cursor); +} + +void move_up(int lines) { move(0, -lines); } +void move_down(int lines) { move(0, -lines); } +void move_right(int cols) { move(cols, 0); } +void move_left(int cols) { move(-cols, 0); } + +#else + +void move_up(int lines) { std::cout << "x1b[" << lines << "A"; } +void move_down(int lines) { std::cout << "x1b[" << lines << "B"; } +void move_right(int cols) { std::cout << "x1b[" << cols << "C"; } +void move_left(int cols) { std::cout << "x1b[" << cols << "D"; } + +#endif + +} // namespace indicators \ No newline at end of file diff --git a/include/indicators/multi_progress.hpp b/include/indicators/multi_progress.hpp index 41c4e86..d2a210e 100644 --- a/include/indicators/multi_progress.hpp +++ b/include/indicators/multi_progress.hpp @@ -27,11 +27,13 @@ SOFTWARE. #pragma once #include #include -#include #include #include #include +#include +#include + namespace indicators { template class MultiProgress { @@ -86,8 +88,7 @@ private: void print_progress() { std::lock_guard lock{mutex_}; if (started_) - for (size_t i = 0; i < count; ++i) - std::cout << "\x1b[A"; + move_up(count); for (auto &bar : bars_) { bar.get().print_progress(true); std::cout << "\n"; diff --git a/samples/multi_progress_bar.cpp b/samples/multi_progress_bar.cpp index a457cab..4f8da20 100644 --- a/samples/multi_progress_bar.cpp +++ b/samples/multi_progress_bar.cpp @@ -1,7 +1,10 @@ #include #include +#include int main() { + indicators::enable_cursor_movement(); + indicators::show_console_cursor(false); indicators::ProgressBar bar1{indicators::option::BarWidth{50}, indicators::option::Start{"["}, @@ -81,5 +84,7 @@ int main() { second_job.join(); third_job.join(); + indicators::show_console_cursor(true); + return 0; }