-
Notifications
You must be signed in to change notification settings - Fork 630
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(cli): command line spinner #3968
Changes from 9 commits
5ad1730
c6c441a
dff1a8a
e61c225
47e482e
70bc64c
f0943da
0a02309
5a05f3e
1b22a75
ab957cb
ffb621c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,3 +8,4 @@ | |
|
||
export * from "./parse_args.ts"; | ||
export * from "./prompt_secret.ts"; | ||
export * from "./spinner.ts"; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. | ||
|
||
const encoder = new TextEncoder(); | ||
|
||
const LINE_CLEAR = encoder.encode("\r\u001b[K"); // From cli/prompt_secret.ts | ||
const COLOR_RESET = "\u001b[0m"; | ||
const DEFAULT_SPEED = 75; | ||
const DEFAULT_SPINNER = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]; | ||
|
||
/** Options for {@linkcode Spinner}. */ | ||
export interface SpinnerOptions { | ||
/** | ||
* The sequence of characters to be iterated through for animation. | ||
* | ||
* @default {["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]} | ||
*/ | ||
spinner?: string[]; | ||
/** The message to display next to the spinner. */ | ||
message?: string; | ||
/** The speed of the spinner. | ||
* | ||
* @default {75} | ||
*/ | ||
speed?: number; | ||
/** The color of the spinner. Defaults to the default terminal color. */ | ||
color?: string; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems this needs to be ANSI color code. On the other hand, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it definitely makes it easier to read and write quickly. I'll make it support both 👍 |
||
} | ||
|
||
/** | ||
* A spinner that can be used to indicate that something is loading. | ||
*/ | ||
export class Spinner { | ||
#spinner: string[]; | ||
#message: string; | ||
#speed: number; | ||
#color?: string; | ||
#intervalId: number | undefined; | ||
#active = false; | ||
|
||
/** | ||
* Creates a new spinner. | ||
* | ||
* @example | ||
* ```ts | ||
* import { Spinner } from "https://deno.land/std@$STD_VERSION/cli/spinner.ts"; | ||
* | ||
* const spinner = new Spinner({ message: "Loading..." }); | ||
iuioiua marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* ``` | ||
*/ | ||
constructor(options?: SpinnerOptions) { | ||
this.#spinner = options?.spinner ?? DEFAULT_SPINNER; | ||
this.#message = options?.message ?? ""; | ||
this.#speed = options?.speed ?? DEFAULT_SPEED; | ||
this.#color = options?.color; | ||
} | ||
|
||
/** | ||
* Starts the spinner. | ||
* | ||
* @example | ||
* ```ts | ||
* import { Spinner } from "https://deno.land/std@$STD_VERSION/cli/spinner.ts"; | ||
* | ||
* const spinner = new Spinner({ message: "Loading..." }); | ||
* spinner.start(); | ||
* ``` | ||
*/ | ||
start() { | ||
iuioiua marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (this.#active || Deno.stdout.writable.locked) return; | ||
this.#active = true; | ||
let i = 0; | ||
const color = this.#color ?? ""; | ||
|
||
// Updates the spinner after the given interval. | ||
const updateFrame = () => { | ||
Deno.stdout.writeSync(LINE_CLEAR); | ||
const frame = encoder.encode( | ||
color + this.#spinner[i] + COLOR_RESET + " " + this.#message, | ||
); | ||
Deno.stdout.writeSync(frame); | ||
i = (i + 1) % this.#spinner.length; | ||
}; | ||
this.#intervalId = setInterval(updateFrame, this.#speed); | ||
} | ||
/** | ||
* Stops the spinner. | ||
* | ||
* @example | ||
* ```ts | ||
* import { Spinner } from "https://deno.land/std@$STD_VERSION/cli/spinner.ts"; | ||
* | ||
* const spinner = new Spinner({ message: "Loading..." }); | ||
* spinner.start(); | ||
* | ||
* setTimeout(() => { | ||
* spinner.stop(); | ||
* console.log("Finished loading!"); | ||
* }, 3000); | ||
* ``` | ||
*/ | ||
stop() { | ||
iuioiua marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (this.#intervalId && this.#active) { | ||
clearInterval(this.#intervalId); | ||
Deno.stdout.writeSync(LINE_CLEAR); // Clear the current line | ||
Deno.removeSignalListener("SIGINT", this.stop.bind(this)); | ||
this.#active = false; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
speed
sounds strange to me as lower number gives faster speed of spinner. How aboutinternal
? ref: https://github.com/sindresorhus/ora?tab=readme-ov-file#interval