Created
November 3, 2024 00:25
-
-
Save eaton/6608ff283b2a4a54932c103a007fe0c1 to your computer and use it in GitHub Desktop.
Fractional ASCII progress bar
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
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