From 80b22b0d339ab57ed82f30fa58811fe28e0ba829 Mon Sep 17 00:00:00 2001 From: Joey Perrott Date: Wed, 25 Aug 2021 09:56:57 -0700 Subject: [PATCH] feat(ng-dev): create a spinner utility (#183) PR Close #183 --- ng-dev/utils/spinner.ts | 55 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 ng-dev/utils/spinner.ts diff --git a/ng-dev/utils/spinner.ts b/ng-dev/utils/spinner.ts new file mode 100644 index 000000000..6ffdcc5fb --- /dev/null +++ b/ng-dev/utils/spinner.ts @@ -0,0 +1,55 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {cursorTo, clearLine} from 'readline'; + +/** ANSI escape code to hide cursor in terminal. */ +const hideCursor = '\x1b[?25l'; +/** ANSI escape code to show cursor in terminal. */ +const showCursor = '\x1b[?25h'; + +export class Spinner { + /** The id of the interval being used to trigger frame printing. */ + private intervalId = setInterval(() => this.printFrame(), 125); + /** The characters to iterate through to create the appearance of spinning in the spinner. */ + private spinnerCharacters = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']; + /** The index of the spinner character used in the frame. */ + private currentSpinnerCharacterIndex = 0; + + constructor(private text: string) { + process.stdout.write(hideCursor); + } + + /** Get the next spinner character. */ + private getNextSpinnerCharacter() { + this.currentSpinnerCharacterIndex = + (this.currentSpinnerCharacterIndex % this.spinnerCharacters.length) + 1; + return this.spinnerCharacters[this.currentSpinnerCharacterIndex - 1]; + } + + /** Print the current text for the spinner to the */ + private printFrame(prefix = this.getNextSpinnerCharacter(), text = this.text) { + cursorTo(process.stdout, 0); + process.stdout.write(` ${prefix} ${text}`); + // Clear to the right of the cursor location in case the new frame is shorter than the previous. + clearLine(process.stdout, 1); + cursorTo(process.stdout, 0); + } + + /** Updates the spinner text with the provided text. */ + update(text: string) { + this.text = text; + } + + /** Completes the spinner. */ + complete() { + clearInterval(this.intervalId); + process.stdout.write('\n'); + process.stdout.write(showCursor); + } +}