Skip to content

Instantly share code, notes, and snippets.

@cire3791
Last active December 21, 2015 17:09
Show Gist options
  • Save cire3791/6338578 to your computer and use it in GitHub Desktop.
Save cire3791/6338578 to your computer and use it in GitHub Desktop.
Simple progress indicator for console proof of concept
// 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';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment