Skip to content

Commit

Permalink
feat(cli): add spinner.message prop
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewthauer committed May 21, 2024
1 parent 39c2a4c commit 21c9b8e
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 10 deletions.
70 changes: 60 additions & 10 deletions cli/spinner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export interface SpinnerOptions {
export class Spinner {
#spinner: string[];
/** The message to display next to the spinner. */
message: string;
#message: string = "";
#interval: number;
#color?: Color;
#intervalId: number | undefined;
Expand All @@ -92,30 +92,74 @@ export class Spinner {
* import { Spinner } from "@std/cli/spinner";
*
* const spinner = new Spinner({ message: "Loading..." });
* spinner.stop();
* ```
*/
constructor(
{
spinner = DEFAULT_SPINNER,
message = "",
interval = DEFAULT_INTERVAL,
color,
}: SpinnerOptions = {},
) {
constructor({
spinner = DEFAULT_SPINNER,
message = "",
interval = DEFAULT_INTERVAL,
color,
}: SpinnerOptions = {}) {
this.#spinner = spinner;
this.message = message;
this.#interval = interval;
this.color = color;
}

/**
* Set the message of the spinner.
* This can be changed while the spinner is active.
*
* @example
* ```ts
* import { Spinner } from "@std/cli/spinner";
*
* const spinner = new Spinner({ message: "Working..." });
* spinner.start();
*
* for (let step = 0; step < 5; step++) {
* await doWork();
* spinner.message = `Finished Step #${step}`;
* }
*
* spinner.stop();
* spinner.message = "Done!";
* ```
*/
set message(message: string) {
this.#message = message;
}

/**
* Get the current message of the spinner.
*/
get message(): string {
return this.#message;
}

/**
* Set the color of the spinner. This defaults to the default terminal color.
* This can be changed while the spinner is active.
*
* @example
* ```ts
* import { Spinner } from "@std/cli/spinner";
*
* const spinner = new Spinner({ message: "Loading...", color: "yellow" });
* spinner.start();
*
* await doStep1();
* spinner.color = "magenta";
* ```
*/
set color(value: Color | undefined) {
this.#color = value ? COLORS[value] : undefined;
}

/**
* Get the current color of the spinner.
*/
get color(): Color | undefined {
return this.#color;
}
Expand All @@ -132,10 +176,14 @@ export class Spinner {
* ```
*/
start() {
if (this.#active || Deno.stdout.writable.locked) return;
if (this.#active || Deno.stdout.writable.locked) {
return;
}

this.#active = true;
let i = 0;
const noColor = Deno.noColor;

// Updates the spinner after the given interval.
const updateFrame = () => {
const color = this.#color ?? "";
Expand All @@ -148,8 +196,10 @@ export class Spinner {
Deno.stdout.writeSync(frame);
i = (i + 1) % this.#spinner.length;
};

this.#intervalId = setInterval(updateFrame, this.#interval);
}

/**
* Stops the spinner.
*
Expand Down
13 changes: 13 additions & 0 deletions cli/spinner_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,3 +191,16 @@ Deno.test("Spinner.message can be updated", async () => {
const expected = "⠋ ⠙ One dino 🦕⠹ Two dinos 🦕🦕⠸ Three dinos 🦕🦕🦕";
assertEquals(actual, expected);
});

Deno.test("Spinner.message returns the current value when updated", () => {
const spinner = new Spinner();

spinner.message = "Step 1";
assertEquals(spinner.message, "Step 1");

spinner.message = "Step 2";
assertEquals(spinner.message, "Step 2");

spinner.message = "Step 3";
assertEquals(spinner.message, "Step 3");
});

0 comments on commit 21c9b8e

Please sign in to comment.