From 49c8663304bac19282b8f801cfc298cb25719a8a Mon Sep 17 00:00:00 2001 From: Andrew Thauer <6507159+andrewthauer@users.noreply.github.com> Date: Sat, 18 Jan 2025 16:10:36 -0500 Subject: [PATCH 1/5] feat(cli): support stderr on spinner --- cli/unstable_spinner.ts | 14 +++++++++++--- cli/unstable_spinner_test.ts | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/cli/unstable_spinner.ts b/cli/unstable_spinner.ts index 178a5b14965c..c034b1ef8292 100644 --- a/cli/unstable_spinner.ts +++ b/cli/unstable_spinner.ts @@ -75,6 +75,12 @@ export interface SpinnerOptions { * This can be changed while the spinner is active. */ color?: Color; + /** + * The stream to write the spinner to. + * + * @default {Deno.stdout} + */ + stream?: typeof Deno.stderr | typeof Deno.stdout; } /** @@ -126,6 +132,7 @@ export class Spinner { #color: Color | undefined; #intervalId: number | undefined; #active = false; + #stream: typeof Deno.stdout | typeof Deno.stderr; /** * Creates a new spinner. @@ -142,6 +149,7 @@ export class Spinner { this.#spinner = spinner; this.message = message; this.#interval = interval; + this.#stream = options?.stream ?? Deno.stdout; this.color = color; } @@ -199,7 +207,7 @@ export class Spinner { * ``` */ start() { - if (this.#active || Deno.stdout.writable.locked) { + if (this.#active || this.#stream.writable.locked) { return; } @@ -219,7 +227,7 @@ export class Spinner { const writeData = new Uint8Array(LINE_CLEAR.length + frame.length); writeData.set(LINE_CLEAR); writeData.set(frame, LINE_CLEAR.length); - Deno.stdout.writeSync(writeData); + this.#stream.writeSync(writeData); i = (i + 1) % this.#spinner.length; }; @@ -245,7 +253,7 @@ export class Spinner { stop() { if (this.#intervalId && this.#active) { clearInterval(this.#intervalId); - Deno.stdout.writeSync(LINE_CLEAR); // Clear the current line + this.#stream.writeSync(LINE_CLEAR); // Clear the current line this.#active = false; } } diff --git a/cli/unstable_spinner_test.ts b/cli/unstable_spinner_test.ts index a1833c2cbef7..4ae1bd15bf9f 100644 --- a/cli/unstable_spinner_test.ts +++ b/cli/unstable_spinner_test.ts @@ -166,6 +166,39 @@ Deno.test("Spinner constructor accepts interval", async () => { } }); +Deno.test("Spinner constructor accepts stream", async () => { + try { + stub(Deno.stdin, "setRaw"); + + const expectedOutput = [ + "\r\x1b[K⠋\x1b[0m ", + "\r\x1b[K⠙\x1b[0m ", + "\r\x1b[K⠹\x1b[0m ", + "\r\x1b[K", + ]; + + const actualOutput: string[] = []; + + stub( + Deno.stderr, + "writeSync", + (data: Uint8Array) => { + const output = decoder.decode(data); + actualOutput.push(output); + return data.length; + }, + ); + + const spinner = new Spinner({ interval: 300, stream: Deno.stderr }); + spinner.start(); + await delay(1000); // 100ms buffer + spinner.stop(); + assertEquals(actualOutput, expectedOutput); + } finally { + restore(); + } +}); + Deno.test("Spinner constructor accepts each color", async (t) => { await t.step("black", async () => { try { From 6e0b5c732971fa3a787357caf295c4e5d585807d Mon Sep 17 00:00:00 2001 From: Andrew Thauer <6507159+andrewthauer@users.noreply.github.com> Date: Mon, 20 Jan 2025 09:13:27 -0500 Subject: [PATCH 2/5] add stderr example to spinner class --- cli/unstable_spinner.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/cli/unstable_spinner.ts b/cli/unstable_spinner.ts index c034b1ef8292..d8dee8617feb 100644 --- a/cli/unstable_spinner.ts +++ b/cli/unstable_spinner.ts @@ -83,7 +83,8 @@ export interface SpinnerOptions { stream?: typeof Deno.stderr | typeof Deno.stdout; } -/** +/**nnnn + * that * A spinner that can be used to indicate that something is loading. * * @experimental **UNSTABLE**: New API, yet to be vetted. @@ -99,6 +100,15 @@ export interface SpinnerOptions { * spinner.stop(); * console.log("Finished loading!"); * }, 3_000); + * + * // You can also use the spinner with `Deno.stderr` + * const spinner2 = new Spinner({ message: "Loading...", color: "yellow", stream: Deno.stderr }); + * spinner.start(); + * + * setTimeout(() => { + * spinner.stop(); + * console.error"Finished loading!"); + * }, 3_000); * ``` */ export class Spinner { From 03d94da82eadacd1f100106d454c650ead39dc91 Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa Date: Tue, 21 Jan 2025 13:10:40 +0900 Subject: [PATCH 3/5] Apply suggestions from code review --- cli/unstable_spinner.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cli/unstable_spinner.ts b/cli/unstable_spinner.ts index d8dee8617feb..e76c4faaa4cc 100644 --- a/cli/unstable_spinner.ts +++ b/cli/unstable_spinner.ts @@ -83,8 +83,7 @@ export interface SpinnerOptions { stream?: typeof Deno.stderr | typeof Deno.stdout; } -/**nnnn - * that +/** * A spinner that can be used to indicate that something is loading. * * @experimental **UNSTABLE**: New API, yet to be vetted. From b5110a46452d06c92555d38a60daed2534a32d6d Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa Date: Tue, 21 Jan 2025 13:13:29 +0900 Subject: [PATCH 4/5] fix lint --- async/unstable_wait_for.ts | 2 +- async/unstable_wait_for_test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/async/unstable_wait_for.ts b/async/unstable_wait_for.ts index ca71dafd638e..c6f20e245ae4 100644 --- a/async/unstable_wait_for.ts +++ b/async/unstable_wait_for.ts @@ -1,4 +1,4 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2025 the Deno authors. All rights reserved. MIT license. // This module is browser compatible. import { deadline } from "./deadline.ts"; diff --git a/async/unstable_wait_for_test.ts b/async/unstable_wait_for_test.ts index 2c286413d074..39e35d827a74 100644 --- a/async/unstable_wait_for_test.ts +++ b/async/unstable_wait_for_test.ts @@ -1,4 +1,4 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2025 the Deno authors. All rights reserved. MIT license. import { assertAlmostEquals, assertEquals, assertRejects } from "@std/assert"; import { waitFor } from "./unstable_wait_for.ts"; From 364e4a3bc8573a1994dff2be1dca76fa79ef9723 Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa Date: Tue, 21 Jan 2025 13:14:31 +0900 Subject: [PATCH 5/5] fix lint --- async/unstable_wait_for.ts | 2 +- async/unstable_wait_for_test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/async/unstable_wait_for.ts b/async/unstable_wait_for.ts index c6f20e245ae4..d776342b035c 100644 --- a/async/unstable_wait_for.ts +++ b/async/unstable_wait_for.ts @@ -1,4 +1,4 @@ -// Copyright 2018-2025 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2025 the Deno authors. MIT license. // This module is browser compatible. import { deadline } from "./deadline.ts"; diff --git a/async/unstable_wait_for_test.ts b/async/unstable_wait_for_test.ts index 39e35d827a74..d8b3156ebed7 100644 --- a/async/unstable_wait_for_test.ts +++ b/async/unstable_wait_for_test.ts @@ -1,4 +1,4 @@ -// Copyright 2018-2025 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2025 the Deno authors. MIT license. import { assertAlmostEquals, assertEquals, assertRejects } from "@std/assert"; import { waitFor } from "./unstable_wait_for.ts";