Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions example.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,38 @@ const spinner = new Ora({
spinner: process.argv[2]
});

spinner.start();
const spinnerDiscardingStdin = new Ora({
discardStdin: true,
text: 'Loading unicorns, discarding stdin',
spinner: process.argv[2]
});

spinnerDiscardingStdin.start();

setTimeout(() => {
spinnerDiscardingStdin.succeed();
spinner.start();
}, 3000);

setTimeout(() => {
spinner.color = 'yellow';
spinner.text = `Loading ${chalk.red('rainbows')}`;
}, 1000);
}, 4000);

setTimeout(() => {
spinner.color = 'green';
spinner.indent = 2;
spinner.text = 'Loading with indent';
}, 2000);
}, 5000);

setTimeout(() => {
spinner.indent = 0;
spinner.spinner = 'moon';
spinner.text = 'Loading with different spinners';
}, 3000);
}, 6000);

setTimeout(() => {
spinner.succeed();
}, 4000);
}, 7000);

// $ node example.js nameOfSpinner
7 changes: 7 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ declare namespace ora {
Note that `{isEnabled: false}` doesn't mean it won't output anything. It just means it won't output the spinner, colors, and other ansi escape codes. It will still log text.
*/
readonly isEnabled?: boolean;

/**
Discard stdin input(except Ctrl+C) while running if it is TTY. Setting it to `true` will prevent spinner from twitching on input, outputting broken lines on `enter` presses, and prevent buffering of input for following reads or commands run after current process exits while spinner is running.

@default false
*/
readonly discardStdin?: boolean;
}

interface PersistOptions {
Expand Down
58 changes: 57 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ const wcwidth = require('wcwidth');
const TEXT = Symbol('text');
const PREFIX_TEXT = Symbol('prefixText');

const noop = () => {};

const ASCII_ETX_CODE = 0x03;

class Ora {
constructor(options) {
if (typeof options === 'string') {
Expand All @@ -20,7 +24,8 @@ class Ora {
this.options = Object.assign({
text: '',
color: 'cyan',
stream: process.stderr
stream: process.stderr,
discardStdin: false
}, options);

this.spinner = this.options.spinner;
Expand All @@ -37,6 +42,7 @@ class Ora {
this.prefixText = this.options.prefixText;
this.linesToClear = 0;
this.indent = this.options.indent;
this.discardStdin = this.options.discardStdin;
}

get indent() {
Expand Down Expand Up @@ -166,6 +172,10 @@ class Ora {
cliCursor.hide(this.stream);
}

if (this.discardStdin && process.stdin.isTTY) {
this.startDiscardingStdin();
}

this.render();
this.id = setInterval(this.render.bind(this), this.interval);

Expand All @@ -185,9 +195,55 @@ class Ora {
cliCursor.show(this.stream);
}

if (this.discardStdin && process.stdin.isTTY) {
this.stopDiscardingStdin();
}

return this;
}

startDiscardingStdin() {
const {stdin} = process;

this._stdinOldRawMode = stdin.isRaw;
this._stdinOldEmit = stdin.emit;
this._stdinOldEmitOwnProperty = Object.prototype.hasOwnProperty.call(stdin, 'emit');

stdin.setRawMode(true);
stdin.on('data', noop);

const self = this;
stdin.emit = function (event, data) {
if (event === 'data') {
if (data.includes(ASCII_ETX_CODE)) {
process.emit('SIGINT');
}
} else {
self._stdinOldEmit.apply(this, arguments); // eslint-disable-line prefer-rest-params
}
};
}

stopDiscardingStdin() {
const {stdin} = process;
stdin.setRawMode(this._stdinOldRawMode);
stdin.removeListener('data', noop);

if (stdin.listenerCount('data') === 0) {
stdin.pause();
}

if (this._stdinOldEmitOwnProperty) {
stdin.emit = this._stdinOldEmit;
} else {
delete stdin.emit;
}

this._stdinOldRawMode = undefined;
this._stdinOldEmit = undefined;
this._stdinOldEmitOwnProperty = undefined;
}

succeed(text) {
return this.stopAndPersist({symbol: logSymbols.success, text});
}
Expand Down
1 change: 1 addition & 0 deletions index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ ora({indent: 1});
ora({interval: 80});
ora({stream: new PassThroughStream()});
ora({isEnabled: true});
ora({discardStdin: true});

spinner.color = 'yellow';
spinner.text = 'Loading rainbows';
Expand Down
7 changes: 7 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,13 @@ Force enable/disable the spinner. If not specified, the spinner will be enabled

Note that `{isEnabled: false}` doesn't mean it won't output anything. It just means it won't output the spinner, colors, and other ansi escape codes. It will still log text.

##### discardStdin

Type: `boolean`<br>
Default: `false`

Discard stdin input(except Ctrl+C) while running if it is TTY. Setting it to `true` will prevent spinner from twitching on input, outputting broken lines on `enter` presses, and prevent buffering of input for following reads or commands run after current process exits while spinner is running.

### Instance

#### .start([text])
Expand Down