Skip to content

Instantly share code, notes, and snippets.

@trvswgnr
Last active January 8, 2024 01:20
Show Gist options
  • Save trvswgnr/2b5607fd9aadc827f46f48ce979a6864 to your computer and use it in GitHub Desktop.
Save trvswgnr/2b5607fd9aadc827f46f48ce979a6864 to your computer and use it in GitHub Desktop.
spinners.ts - some simple but cool text spinners, mostly taken from https://wiki.tcl-lang.org/page/Text+Spinner

spinners.ts

some simple but cool text spinners, mostly taken from https://wiki.tcl-lang.org/page/Text+Spinner

📦 install

npm i -S gist:2b5607fd9aadc827f46f48ce979a6864

Usage

import { spinner } from "spinners";

const fn = new Promise<string>((resolve) => setTimeout(() => resolve("tr4vvyr00lz"), 3000));
const spin = spinner("doing a thing", "pong");
const text = await fn();
spin.stop();
console.log(text);
{
"version": "0.0.3",
"name": "spinners",
"main": "spinners.ts"
}
/** terminal utilities */
export const term = {
clearLine: () => process.stdout.write("\r\x1b[K"),
hideCursor: () => process.stdout.write("\x1b[?25l"),
showCursor: () => process.stdout.write("\x1b[?25h"),
};
/**
* show a text spinner while `fn` is running
*
* @example
* ```ts
* const obj = spinner("thinking ", "simpleDots");
* const text = await fn();
* obj.stop();
* ```
*
* @param text the text to be printed before the spinner
* @param sequence the name of the spinner sequence, or an array of strings to be used as the spinner
* @returns an object with a `stop` method
*/
export function spinner(text: string, sequence?: SpinnersKey | string[]) {
let spinnerChars = typeof sequence === "string" ? getSpinner(sequence) : sequence;
if (!spinnerChars) {
spinnerChars = spinners.simpleDots;
}
let i = 0;
const spin = () => {
const spinner = spinnerChars![i];
i = (i + 1) % spinnerChars!.length;
return spinner;
};
const stop = (text?: string) => {
term.clearLine();
term.showCursor();
if (text) {
process.stdout.write(text);
}
};
term.hideCursor();
process.stdout.write(text);
const interval = setInterval(() => process.stdout.write("\r" + text + spin()), 100);
return {
/** stop the spinner and clear the line */
stop: (text?: string) => {
clearInterval(interval);
stop(text);
},
};
}
export type Spinners = typeof spinners;
export type SpinnersKey = keyof Spinners;
export function getSpinner(name: SpinnersKey) {
return typeof name === "string" ? spinners[name] : name;
}
/** @see https://wiki.tcl-lang.org/page/Text+Spinner */
const spinners = {
dots: ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"],
line: ["-", "\\", "|", "/"],
line2: ["⠂", "-", "–", "—", "–", "-"],
pipe: ["┤", "┘", "┴", "└", "├", "┌", "┬", "┐"],
simpleDots: [". ", ".. ", "...", " "],
simpleDotsScrolling: [". ", ".. ", "...", " ..", " .", " "],
star: ["✶", "✸", "✹", "✺", "✹", "✷"],
star2: ["+", "x", "*"],
flip: ["_", "_", "_", "-", "`", "`", "'", "´", "-", "_", "_", "_"],
hamburger: ["☱", "☲", "☴"],
growVertical: ["▁", "▃", "▄", "▅", "▆", "▇", "▆", "▅", "▄", "▃"],
growHorizontal: ["▏", "▎", "▍", "▌", "▋", "▊", "▉", "▊", "▋", "▌", "▍", "▎"],
balloon: [" ", ".", "o", "O", "@", "*", " ", " ", " ", " ", " "],
balloon2: [".", "o", "O", "°", "O", "o", "."],
noise: ["▓", "▒", "░"],
bounce: ["⠁", "⠂", "⠄", "⠂"],
boxBounce: ["▖", "▘", "▝", "▗"],
boxBounce2: ["▌", "▀", "▐", "▄"],
triangle: ["◢", "◣", "◤", "◥"],
arc: ["◜", "◠", "◝", "◞", "◡", "◟"],
circle: ["◡", "⊙", "◠"],
squareCorners: ["◰", "◳", "◲", "◱"],
circleQuarters: ["◴", "◷", "◶", "◵"],
circleHalves: ["◐", "◓", "◑", "◒"],
squish: ["╫", "╪"],
toggle: ["⊶", "⊷"],
toggle2: ["□", "■"],
arrow: ["←", "↖", "↑", "↗", "→", "↘", "↓", "↙"],
arrow2: ["▹▹▹▹▹", "▸▹▹▹▹", "▹▸▹▹▹", "▹▹▸▹▹", "▹▹▹▸▹", "▹▹▹▹▸"],
bird: ["︷", "︵", "︹", "︺", "︶", "︸", "︶", "︺", "︹", "︵"],
bouncingBar: [
"[ ]",
"[= ]",
"[== ]",
"[=== ]",
"[ ===]",
"[ ==]",
"[ =]",
"[ ]",
"[ =]",
"[ ==]",
"[ ===]",
"[====]",
"[=== ]",
"[== ]",
"[= ]",
],
bouncingBall: [
"( ● )",
"( ● )",
"( ● )",
"( ● )",
"( ●)",
"( ● )",
"( ● )",
"( ● )",
"( ● )",
"(● )",
],
pong: [
"▐● ▌",
"▐ ● ▌",
"▐ ● ▌",
"▐ ● ▌",
"▐ ● ▌",
"▐ ● ▌",
"▐ ● ▌",
"▐ ●▌",
"▐ ● ▌",
"▐ ● ▌",
"▐ ● ▌",
"▐ ● ▌",
"▐ ● ▌",
"▐ ● ▌",
],
shark: [
"◣˷˷˷˷˷˷˷˷˷˷˷˷",
"˷◣˷˷˷˷˷˷˷˷˷˷˷",
"˷˷◣˷˷˷˷˷˷˷˷˷˷",
"˷˷˷◣˷˷˷˷˷˷˷˷˷",
"˷˷˷˷◣˷˷˷˷˷˷˷˷",
"˷˷˷˷˷◣˷˷˷˷˷˷˷",
"˷˷˷˷˷˷◣˷˷˷˷˷˷",
"˷˷˷˷˷˷˷◣˷˷˷˷˷",
"˷˷˷˷˷˷˷˷◣˷˷˷˷",
"˷˷˷˷˷˷˷˷˷◣˷˷˷",
"˷˷˷˷˷˷˷˷˷˷◣˷˷",
"˷˷˷˷˷˷˷˷˷˷˷◣˷",
"˷˷˷˷˷˷˷˷˷˷˷˷◣",
"˷˷˷˷˷˷˷˷˷˷˷˷◢",
"˷˷˷˷˷˷˷˷˷˷˷◢˷",
"˷˷˷˷˷˷˷˷˷˷◢˷˷",
"˷˷˷˷˷˷˷˷˷◢˷˷˷",
"˷˷˷˷˷˷˷˷◢˷˷˷˷",
"˷˷˷˷˷˷˷◢˷˷˷˷˷",
"˷˷˷˷˷˷◢˷˷˷˷˷˷",
"˷˷˷˷˷◢˷˷˷˷˷˷˷",
"˷˷˷˷◢˷˷˷˷˷˷˷˷",
"˷˷˷◢˷˷˷˷˷˷˷˷˷",
"˷˷◢˷˷˷˷˷˷˷˷˷˷",
"˷◢˷˷˷˷˷˷˷˷˷˷˷",
"◢˷˷˷˷˷˷˷˷˷˷˷˷",
],
dqpb: ["d", "q", "p", "b"],
grenade: [
"، ",
"′ ",
" ´ ",
" ‾ ",
" ⸌",
" ⸊",
" |",
" ⁎",
" ⁕",
" ෴ ",
" ⁓",
" ",
" ",
" ",
],
point: ["∙∙∙", "●∙∙", "∙●∙", "∙∙●", "∙∙∙"],
pointBounce: ["●∙∙∙∙", "∙●∙∙∙", "∙∙●∙∙", "∙∙∙●∙", "∙∙∙∙●", "∙∙∙●∙", "∙∙●∙∙", "∙●∙∙∙"],
layer: ["-", "=", "≡"],
betaWave: ["ρββββββ", "βρβββββ", "ββρββββ", "βββρβββ", "ββββρββ", "βββββρβ", "ββββββρ"],
};
// handle ctrl+c - show the cursor and exit
process.on("SIGINT", () => {
term.showCursor();
process.stdout.write("\n");
process.exit(130);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment