Skip to content

Instantly share code, notes, and snippets.

@zaphodikus
Created February 8, 2026 17:49
Show Gist options
  • Select an option

  • Save zaphodikus/6698c0a1d6477351184536f3974fe388 to your computer and use it in GitHub Desktop.

Select an option

Save zaphodikus/6698c0a1d6477351184536f3974fe388 to your computer and use it in GitHub Desktop.
Console Progress bar
// ProgressBar.h
#pragma once
#include <iostream>
#include <fstream>
#include <cstdint>
#include <cassert>
#include <cmath>
#include <chrono>
#include <thread>
constexpr char ASCII_START_CH = (char)204;
constexpr char ASCII_MIDDLE_CH = (char)205;
constexpr char ASCII_END_CH = (char)185;
constexpr char ASCII_LOWDENSITY_CH = (char)176;
constexpr char ASCII_SOLID_CH = (char)219;
/// <summary>
///
/// </summary>
/// <param name="stream&">stream to write to</param>
/// <param name="width"></param>
/// <param name="fillto"></param>
static std::ostream& DrawBar(std::ostream &stream,
uint32_t const width,
uint32_t const fillto
)
{
uint32_t startlen = 0, endlen = 0;
uint32_t middlelen = 0, index = 0;
assert(width >= fillto);
if (fillto <= 0) startlen = 1;
if (fillto < width) endlen = width;
if (width > 2) middlelen = width -1;
for (; index < startlen; index++)
stream << ASCII_START_CH;
for (; index < fillto; index++)
stream << ASCII_SOLID_CH;
for (; index < middlelen; index++)
stream << ASCII_MIDDLE_CH;
for (; index < endlen; index++)
stream << ASCII_END_CH;
return stream;
}
/// <summary>
/// A progress bar for test mode console apps
/// </summary>
class ProgressBar {
private:
char start_char, middle_char, end_char, fill_char;
uint32_t bar_width;
std::string message;
std::ostream& PaintBar(std::ostream& stream, float percentage) {
uint32_t startlen = 0, endlen = 0;
uint32_t middlelen = 0, index = 0;
uint32_t fillto = (uint32_t)std::ceil(percentage * bar_width);
assert(bar_width >= fillto);
if (fillto <= 0) startlen = 1;
if (fillto < bar_width) endlen = bar_width;
if (bar_width > 2) middlelen = bar_width - 1;
for (; index < startlen; index++)
stream << start_char;
for (; index < fillto; index++)
stream << fill_char;
for (; index < middlelen; index++)
stream << middle_char;
for (; index < endlen; index++)
stream << end_char;
stream << " " << message << "\r";
return stream;
}
uint32_t startlen = 0, endlen = 0;
uint32_t middlelen = 0, index = 0;
void _constr(uint32_t width) {
_constr(width, 0.0f, "");
}
void _constr(uint32_t width,
float start_percent,
std::string const pre_message)
{
_constr(width, start_percent, pre_message);
}
void _constr(uint32_t width,
float start_percent,
std::string const pre_message,
char start,
char end,
char middle,
char fill
) {
bar_width = width;
message = pre_message;
start_char = start;
end_char = end;
middle_char = middle;
fill_char = fill;
PaintBar(std::cout, 0.0f);
}
public:
ProgressBar(uint32_t width) {
_constr(width);
}
ProgressBar(uint32_t width, float start_percent, std::string const pre_message) {
_constr(width, start_percent, pre_message, ASCII_START_CH, ASCII_END_CH, ASCII_MIDDLE_CH, ASCII_SOLID_CH);
}
ProgressBar(
uint32_t width,
float start_percent,
std::string const pre_message,
char start,
char end,
char middle,
char fill
) {
_constr(width, start_percent, pre_message, start, end, middle, fill);
}
std::ostream& UpdateBar(std::ostream& stream, float percentage) {
return PaintBar(stream, percentage);
}
void UpdateMessage(std::string const new_message) { message = new_message; }
};
// example usage
int main() {
{
ProgressBar bar = ProgressBar(50, 0.0f, "");
for (uint16_t full = 0; full <= 50; full++) {
float percent = (float)(full / (float)50);
std::string msg = std::to_string((uint32_t)(percent * 100)) + "%";
bar.UpdateMessage(msg);
bar.UpdateBar(std::cout, percent);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
std::cout << std::endl;
} {
ProgressBar bar = ProgressBar(80, 0.0f, "", ASCII_LOWDENSITY_CH, ASCII_LOWDENSITY_CH, ASCII_LOWDENSITY_CH, ASCII_SOLID_CH);
for (uint16_t full = 0; full <= 50; full++) {
float percent = (float)(full / (float)50);
std::string msg = std::to_string((uint32_t)(percent * 100)) + "%";
bar.UpdateMessage(msg);
bar.UpdateBar(std::cout, percent);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment