Reputation: 3934
I wrote a header for a progress bar. It contains the following function:
/**
* @brief advances the progress bar every time an interval of x
* function calls has been completed
* @param current the current iteration
* @param o the stream to write to
*/
inline void run(step current, sost& o=std::cerr)
{
if(current%interval == 0 && !(current > max))
{
// do away with the cursor
#ifdef UNIXLIKE
printf("\e[?25l");
#endif
// fill line with background symbol
for (int i = 0; i < PSD+lbracketSize; ++i) o << " ";
for (unsigned i = 0; i < pres; ++i) o << pre;
o << rbracket << "\r";
o.flush();
// calculate percentage and make a string of it
float prct = ((float)current/max)*100;
sstr strprct = helper::to_string((int)prct);
// get percantge to length of three
if (helper::utf8_size(strprct) < 2) strprct = " "+strprct;
if (helper::utf8_size(strprct) < 3) strprct = " "+strprct;
// print percentage and bar
o << "[" << strprct << "% ] " << lbracket;
for (auto i = pbar.begin(); i != pbar.end(); ++i) o << *i;
o << "\r";
o.flush();
pbar.push_back(bar);
}
if(current>=max-1)
{
cancel();
}
}
It works fine. As you can see I send the progress bar to stderr. The idea behind that was, that I can pipe the output of my program, which goes to stdout, without catching the progress bar on stderr. But in practice it does not quite work. While the progress bar does not get catched by the pipe as intended, the \r
command seems to not take effect, as the bar is written with ever new lines, rather than stay on the same line, as it does, when I don't pipe stdout. Why is that? Doesn't make any sense to me.
so, normally the bar looks like this:
[ 37% ] ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
When I pipe stdout to a file, I get this all over my terminal for countless lines:
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
Upvotes: 3
Views: 294
Reputation: 2629
Please, check if the following code does not work fine for you if stdout is redirected:
#include <iostream>
int main(int argc, char ** argv)
{
std::cerr << "Hello,\rWorld!\n";
return 0;
}
I have some suggestions for your code:
The line printf("\e[?25l");
should be changed to o << "\e[?25l"
. You should not mix stdio.h
with iostream
and you should output the control sequence to stderr.
stderr
can be redirected too. You need to check if the stream is terminal and detect the capabilities of the terminal. The implementation is system specific. One of the solutions can be found here. Also this link may be helpful.
You can forcibly output to the terminal by getting the name of the terminal using tty
command and writing to it.
Upvotes: 3