diff --git a/index.d.ts b/index.d.ts
index f2006f3..c7fba81 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -24,6 +24,11 @@ export type Options = Readonly<{
*/
text?: string;
+ /**
+ * Text to display before the spinner.
+ */
+ prefixText?: string;
+
/**
* Name of one of the provided spinners. See [`example.js`](https://github.com/BendingBender/ora/blob/master/example.js) in this repo if you want to test out different spinners. On Windows, it will always use the line spinner as the Windows command-line doesn't have proper Unicode support.
*
@@ -114,9 +119,14 @@ export type PersistOptions = Readonly<{
symbol?: string;
/**
- * Text to be persisted. Default: Current text.
+ * Text to be persisted after the symbol. Default: Current `text`.
*/
text?: string;
+
+ /**
+ * Text to be persisted before the symbol. Default: Current `prefixText`.
+ */
+ prefixText?: string;
}>;
export interface Ora {
@@ -126,9 +136,14 @@ export interface Ora {
readonly isSpinning: boolean;
/**
- * Change the text.
+ * Change the text after the spinner.
*/
text: string;
+
+ /**
+ * Change the text before the spinner.
+ */
+ prefixText: string;
/**
* Change the spinner color.
diff --git a/index.js b/index.js
index 3cbfe5f..ba1da41 100644
--- a/index.js
+++ b/index.js
@@ -7,6 +7,7 @@ const stripAnsi = require('strip-ansi');
const wcwidth = require('wcwidth');
const TEXT = Symbol('text');
+const PREFIX_TEXT = Symbol('prefixText');
class Ora {
constructor(options) {
@@ -33,6 +34,7 @@ class Ora {
// Set *after* `this.stream`
this.text = this.options.text;
+ this.prefixText = this.options.prefixText;
this.linesToClear = 0;
this.indent = this.options.indent;
}
@@ -78,18 +80,32 @@ class Ora {
return this[TEXT];
}
+ get prefixText() {
+ return this[PREFIX_TEXT];
+ }
+
get isSpinning() {
return this.id !== null;
}
- set text(value) {
- this[TEXT] = value;
+ updateLineCount() {
const columns = this.stream.columns || 80;
- this.lineCount = stripAnsi('--' + value).split('\n').reduce((count, line) => {
+ const fullPrefixText = (typeof this[PREFIX_TEXT] === 'string') ? this[PREFIX_TEXT] + '-' : '';
+ this.lineCount = stripAnsi(fullPrefixText + '--' + this[TEXT]).split('\n').reduce((count, line) => {
return count + Math.max(1, Math.ceil(wcwidth(line) / columns));
}, 0);
}
+ set text(value) {
+ this[TEXT] = value;
+ this.updateLineCount();
+ }
+
+ set prefixText(value) {
+ this[PREFIX_TEXT] = value;
+ this.updateLineCount();
+ }
+
frame() {
const {frames} = this.spinner;
let frame = frames[this.frameIndex];
@@ -99,8 +115,10 @@ class Ora {
}
this.frameIndex = ++this.frameIndex % frames.length;
+ const fullPrefixText = typeof this.prefixText === 'string' ? this.prefixText + ' ' : '';
+ const fullText = typeof this.text === 'string' ? ' ' + this.text : '';
- return frame + ' ' + this.text;
+ return fullPrefixText + frame + fullText;
}
clear() {
@@ -187,8 +205,13 @@ class Ora {
}
stopAndPersist(options = {}) {
+ const prefixText = options.prefixText || this.prefixText;
+ const fullPrefixText = (typeof prefixText === 'string') ? prefixText + ' ' : '';
+ const text = options.text || this.text;
+ const fullText = (typeof text === 'string') ? ' ' + text : '';
+
this.stop();
- this.stream.write(`${options.symbol || ' '} ${options.text || this.text}\n`);
+ this.stream.write(`${fullPrefixText}${options.symbol || ' '}${fullText}n`);
return this;
}
diff --git a/index.test-d.ts b/index.test-d.ts
index 21468b1..af7f1f8 100644
--- a/index.test-d.ts
+++ b/index.test-d.ts
@@ -4,6 +4,7 @@ import ora, {promise} from '.';
const spinner = ora('Loading unicorns');
ora({text: 'Loading unicorns'});
+ora({prefixText: 'Loading unicorns'});
ora({spinner: 'squish'});
ora({spinner: {frames: ['-', '+', '-']}});
ora({spinner: {interval: 80, frames: ['-', '+', '-']}});
@@ -34,6 +35,7 @@ spinner.info('info foo');
spinner.stopAndPersist();
spinner.stopAndPersist({text: 'all done'});
spinner.stopAndPersist({symbol: '@', text: 'all done'});
+spinner.stopAndPersist({prefixText: 'all done'});
spinner.clear();
spinner.render();
spinner.frame();
diff --git a/readme.md b/readme.md
index e0353ec..154b112 100644
--- a/readme.md
+++ b/readme.md
@@ -50,6 +50,12 @@ Type: `string`
Text to display after the spinner.
+##### prefixText
+
+Type: `string`
+
+Text to display before the spinner.
+
##### spinner
Type: `string` `Object`
@@ -162,9 +168,16 @@ Symbol to replace the spinner with.
###### text
Type: `string`
-Default: Current text
+Default: Current `text`
+
+Text to be persisted after the symbol
+
+###### prefixText
+
+Type: `string`
+Default: Current `prefixText`
-Text to be persisted.
+Text to be persisted before the symbol.
@@ -182,7 +195,11 @@ Get a new frame.
#### .text
-Change the text.
+Change the text after the spinner.
+
+#### .prefixText
+
+Change the text before the spinner.
#### .color
diff --git a/test.js b/test.js
index 579b4aa..4ccab15 100644
--- a/test.js
+++ b/test.js
@@ -235,6 +235,15 @@ test('erases wrapped lines', t => {
t.is(clearedLines, 3);
t.is(cursorAtRow, -2);
+ spinner.clear();
+ reset();
+ spinner.prefixText = 'foo\n';
+ spinner.text = '\nbar';
+ spinner.render();
+ spinner.render();
+ t.is(clearedLines, 3); // Cleared 'foo\n\nbar'
+ t.is(cursorAtRow, -2);
+
spinner.stop();
});
@@ -304,3 +313,11 @@ test('indent option throws', t => {
spinner.indent = -1;
}, 'The `indent` option must be an integer from 0 and up');
});
+
+test('.stopAndPersist() with prefixText', macro, spinner => {
+ spinner.stopAndPersist({symbol: '@', text: 'foo'});
+}, /bar @ foo/, {prefixText: 'bar'});
+
+test('.stopAndPersist() with manual prefixText', macro, spinner => {
+ spinner.stopAndPersist({symbol: '@', prefixText: 'baz', text: 'foo'});
+}, /baz @ foo/, {prefixText: 'bar'});