public
Last active

Simple progress indicator for console proof of concept

  • Download Gist
ProgressIndicator.cpp
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
// Code written by cire, hereby released into the public domain.
 
#include <sstream>
#include <iomanip>
#include <iostream>
#include <thread>
#include <atomic>
#include <chrono>
#include <array>
 
class ProgressIndicator
{
public:
typedef std::chrono::milliseconds duration_type;
 
ProgressIndicator(duration_type delay = duration_type(500))
: _percent(0), _delay(delay), _animationFrame(0) {}
 
void update(unsigned percent) { _percent = percent ; }
void display( std::ostream& os ) const;
bool done() const { return _percent == 100; }
 
private:
void _sleep() const { std::this_thread::sleep_for(_delay); }
 
std::atomic<unsigned> _percent;
const std::chrono::milliseconds _delay;
 
mutable std::size_t _animationFrame;
static std::array<char, 4> cursorAnimation ;
};
 
std::array<char, 4> ProgressIndicator::cursorAnimation = { '\\', '|', '/', '-' };
 
void fill(std::ostream& os, char ch, unsigned length, const char* str = "")
{
os << std::setfill(ch) << std::setw(length) << str;
}
 
void ProgressIndicator::display(std::ostream& out) const
{
const std::size_t indicatorLength(40);
const std::size_t separatorLength(2);
const std::size_t digitalLength(3); // 3 digits to accomodate 100.
const unsigned percent = _percent;
 
std::ostringstream os;
 
unsigned solidLen = static_cast<unsigned>(indicatorLength * (percent / 100.0));
fill(os, '*', solidLen);
 
if (solidLen < indicatorLength)
{
os << cursorAnimation[_animationFrame];
fill(os, '.', indicatorLength - (solidLen + 1));
}
 
fill(os, ' ', separatorLength);
os << std::setw(digitalLength) << std::to_string(percent) << '%';
 
_animationFrame = (_animationFrame + 1) % cursorAnimation.size();
 
fill(out, '\b', os.str().length());
out << os.str() << std::flush;
 
_sleep();
}
 
void spindicator(const ProgressIndicator* indicator)
{
while (!indicator->done())
indicator->display(std::cout);
 
indicator->display(std::cout);
}
 
int main()
{
ProgressIndicator indicator(std::chrono::milliseconds(200));
std::thread indicatorThread(spindicator, &indicator);
 
for (unsigned i = 0; i < 26; ++i)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
indicator.update(i * 4);
}
indicatorThread.join();
std::cout << '\n';
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.