I was trying out the example code from this answer.
#include <iostream>
#include <thread>
#include <chrono>
void drawProgressBar(int, double);
int main() {
drawProgressBar(30, .25);
std::this_thread::sleep_for(std::chrono::seconds(1));
drawProgressBar(30, .50);
std::this_thread::sleep_for(std::chrono::seconds(1));
drawProgressBar(30, .75);
std::this_thread::sleep_for(std::chrono::seconds(1));
drawProgressBar(30, 1);
return 0;
}
void drawProgressBar(int len, double percent) {
std::cout << "\x1B[2K"; // Erase the entire current line.
std::cout << "\x1B[0E"; // Move to the beginning of the current line.
std::string progress;
for (int i = 0; i < len; ++i) {
if (i < static_cast<int>(len * percent)) {
progress += "=";
} else {
progress += " ";
}
}
std::cout << "[" << progress << "] " << (static_cast<int>(100 * percent)) << "%" << std::flush;
}
The expected behavior was a progress bar like so:
[======= ] 25%
which would update three times on the same line, ending up as:
[==============================] 100%
after 3 seconds.
While each progress bar gets erased as expected, the next progress bar is drawn one line down, not on the same line as I was expecting it to.
The documentation linked in the answer (Wikipedia) says that CSI n E
(ESC[nE
) where n
is an integer:
Moves cursor to beginning of the line n (default 1) lines down.
So I would expect CSI 0 E
(ESC[0E
) to move the cursor to the beginning of the current line (the line 0
lines down).
Why doesn't it? Also, how can I achieve the intended behavior?
I'm using Terminal.app
on OS X to run this program.