[READ-ONLY] Mirror of https://github.com/bombshell-dev/clack. Effortlessly build beautiful command-line apps bomb.sh/docs/clack/basics/getting-started/
cli command-line command-line-app node prompt prompts
5

Configure Feed

Select the types of activity you want to include in your feed.

fix(#106): spinner conflict with terminal on error

Bruno Rocha (Mar 29, 2023, 1:57 PM -0300) 52183c45 f43807f6

+68 -25
+5
.changeset/ninety-ravens-smoke.md
··· 1 + --- 2 + '@clack/prompts': patch 3 + --- 4 + 5 + Fix `spinner` conflict with terminal on error between `spinner.start()` and `spinner.stop()`
+63 -25
packages/prompts/src/index.ts
··· 607 607 export const spinner = () => { 608 608 let unblock: () => void; 609 609 let loop: NodeJS.Timer; 610 + let isSpinnerActive: boolean = false; 610 611 const delay = unicode ? 80 : 120; 612 + 613 + const start = (message: string = ''): void => { 614 + isSpinnerActive = true; 615 + message = message.replace(/\.?\.?\.$/, ''); 616 + unblock = block(); 617 + process.stdout.write(`${color.gray(S_BAR)}\n${color.magenta('○')} ${message}\n`); 618 + let i = 0; 619 + let dot = 0; 620 + loop = setInterval(() => { 621 + let frame = frames[i]; 622 + process.stdout.write(cursor.move(-999, -1)); 623 + process.stdout.write( 624 + `${color.magenta(frame)} ${message}${ 625 + Math.floor(dot) >= 1 ? '.'.repeat(Math.floor(dot)).slice(0, 3) : '' 626 + } \n` 627 + ); 628 + i = i === frames.length - 1 ? 0 : i + 1; 629 + dot = dot === frames.length ? 0 : dot + 0.125; 630 + }, delay); 631 + }; 632 + 633 + const stop = (message: string = '', code: number = 0): void => { 634 + isSpinnerActive = false; 635 + process.stdout.write(cursor.move(-999, -2)); 636 + process.stdout.write(erase.down(2)); 637 + clearInterval(loop); 638 + const bar = color.gray(S_BAR); 639 + const step = 640 + code === 0 641 + ? color.green(S_STEP_SUBMIT) 642 + : code === 1 643 + ? color.red(S_STEP_CANCEL) 644 + : color.red(S_STEP_ERROR); 645 + process.stdout.write(`${bar}\n${step} ${message}\n`); 646 + unblock(); 647 + }; 648 + 649 + const handleCancel = () => { 650 + if (isSpinnerActive) { 651 + stop('Canceled', 1); 652 + } 653 + }; 654 + 655 + const handleError = () => { 656 + if (isSpinnerActive) { 657 + stop('Something went wrong', 2); 658 + } 659 + }; 660 + 661 + // Trigger on code exception 662 + process.on('uncaughtException', handleError); 663 + // Trigger on promise rejection 664 + process.on('unhandledRejection', handleError); 665 + // Trigger on Ctrl + C -> multi platform 666 + process.on('SIGINT', handleCancel); 667 + // Trigger on kill process 668 + process.on('SIGTERM', handleCancel); 669 + // Trigger on system shutdown 670 + process.on('exit', handleCancel); 671 + 611 672 return { 612 - start(message = '') { 613 - message = message.replace(/\.?\.?\.$/, ''); 614 - unblock = block(); 615 - process.stdout.write(`${color.gray(S_BAR)}\n${color.magenta('○')} ${message}\n`); 616 - let i = 0; 617 - let dot = 0; 618 - loop = setInterval(() => { 619 - let frame = frames[i]; 620 - process.stdout.write(cursor.move(-999, -1)); 621 - process.stdout.write( 622 - `${color.magenta(frame)} ${message}${ 623 - Math.floor(dot) >= 1 ? '.'.repeat(Math.floor(dot)).slice(0, 3) : '' 624 - } \n` 625 - ); 626 - i = i === frames.length - 1 ? 0 : i + 1; 627 - dot = dot === frames.length ? 0 : dot + 0.125; 628 - }, delay); 629 - }, 630 - stop(message = '') { 631 - process.stdout.write(cursor.move(-999, -2)); 632 - process.stdout.write(erase.down(2)); 633 - clearInterval(loop); 634 - process.stdout.write(`${color.gray(S_BAR)}\n${color.green(S_STEP_SUBMIT)} ${message}\n`); 635 - unblock(); 636 - }, 673 + start, 674 + stop, 637 675 }; 638 676 }; 639 677