Skip to content

Instantly share code, notes, and snippets.

@eaton
Created November 3, 2024 00:25
Show Gist options
  • Save eaton/6608ff283b2a4a54932c103a007fe0c1 to your computer and use it in GitHub Desktop.
Save eaton/6608ff283b2a4a54932c103a007fe0c1 to your computer and use it in GitHub Desktop.
Fractional ASCII progress bar
export const BarThemes = {
fractional: [' ', '▏', '▎', '▍', '▌', '▋', '▊', '▉', '█'],
shaded: [' ', '░', '▒', '▓', '█'],
simple: ['▒', '█'],
ascii: ['-', '#'],
};
// Renders a fixed-length ASCII progress bar that supports
// fractionally-filled characters using Unicode boxes and bars.
export function renderBar(
total = 100,
current = 0,
width = 40,
theme: keyof typeof BarThemes = 'simple',
): string {
// Calculate the progress percentage
const progress = Math.min(current / total, 1); // Cap at 1 to avoid overflow
const totalFilledLength = width * progress; // Full length, including partial segment
const segments = BarThemes[theme];
const full = segments[segments.length - 1] ?? '#';
const empty = segments[0] ?? ' ';
// Determine the integer and fractional parts of the filled length
const filledLength = Math.floor(totalFilledLength); // Complete segments
const partialIndex = Math.floor(
(totalFilledLength - filledLength) * segments.length,
);
// Create the filled, partial, and empty parts of the bar
const filledBar = full.repeat(filledLength);
const partialBar = partialIndex > 0 ? segments[partialIndex] : ''; // Select a partial character if needed
const emptyBar = empty.repeat(width - filledLength - (partialBar ? 1 : 0));
return `${filledBar}${partialBar}${emptyBar}`;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment