Last active
December 21, 2015 17:09
-
-
Save cire3791/6338578 to your computer and use it in GitHub Desktop.
Simple progress indicator for console proof of concept
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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