So I was trying to crate a little procedure that would create a progress bar based on a float that was passed to it, and it would return a string.
Of course, if I used echo, it would print put the progress bar in a different line, which is not really what I wanted to do.
So I'd have to print out the carriage return character (\\r) after printing the bar to go back to the star of the line.
The problem is that I tried to use stdout.write(bar & '\\r') from within a thread and... nothing! So I tried importing C's printf function from the "stdio.h" header, and... nothing either!
The funny thing is that the progress bar does get printed out with both, but only after I've killed the program.
Is this intended behavior or is there something weird going on here?
I'm not sure how to do it the carriage return way, but you can do it with stdout.eraseLine() - from https://github.com/Yardanico/adbscan/blob/master/src/adbscan.nim#L156 :
proc updateBar() =
stdout.eraseLine()
let perc = (100 * done / allLen).formatFloat(ffDecimal, 1)
stdout.write &"{done} / {allLen} ({perc}%), found {results.len}"
stdout.flushFile()
Also, the reason why your second way didn't output anything is because you need to call stdout.flushFile()
Oh, that works!
It's odd that the \\r doesn't work, but this is a good workaround.
Thanks for your help!
\r does work though: https://github.com/mratsim/trace-of-radiance/blob/99f7d85/trace_of_radiance_animation.nim#L88
You don't need to wrap printf yourself, you can import system/ansi_c by the way:
https://github.com/mratsim/weave/blob/5034793/weave/instrumentation/loggers.nim#L8-L14
import system/ansi_c
template log*(args: varargs[untyped]): untyped =
c_printf(args)
flushFile(stdout)
stderr.write ..; stderr.flushFile()
Since stderr is already unbuffered by default, flushFile is unnecessary. But this would do the trick for stdout.
If want every stdout write to be unbuffered just like stderr, then you can also do:
include system/io
discard c_setvbuf(stdout, nil, IONBF, 0)
import os
stdout.write "hi\r"
sleep 1000
stdout.write "there\r"
sleep 1000
You can also turn buffering back on with
discard c_setvbuf(stdout, nil, IOFBF, cast[csize_t](8192))
Which approach you use is more or less up to your convenience. Why, you could even activate buffering for stderr, though this might break assumptions of a great deal of library code.