| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 | const color = require('kleur');const Prompt = require('./prompt');const { erase, cursor } = require('sisteransi');const { style, clear, lines, figures } = require('../util');/** * TextPrompt Base Element * @param {Object} opts Options * @param {String} opts.message Message * @param {String} [opts.style='default'] Render style * @param {String} [opts.initial] Default value * @param {Function} [opts.validate] Validate function * @param {Stream} [opts.stdin] The Readable stream to listen to * @param {Stream} [opts.stdout] The Writable stream to write readline data to * @param {String} [opts.error] The invalid error label */class TextPrompt extends Prompt {  constructor(opts={}) {    super(opts);    this.transform = style.render(opts.style);    this.scale = this.transform.scale;    this.msg = opts.message;    this.initial = opts.initial || ``;    this.validator = opts.validate || (() => true);    this.value = ``;    this.errorMsg = opts.error || `Please Enter A Valid Value`;    this.cursor = Number(!!this.initial);    this.cursorOffset = 0;    this.clear = clear(``, this.out.columns);    this.render();  }  set value(v) {    if (!v && this.initial) {      this.placeholder = true;      this.rendered = color.gray(this.transform.render(this.initial));    } else {      this.placeholder = false;      this.rendered = this.transform.render(v);    }    this._value = v;    this.fire();  }  get value() {    return this._value;  }  reset() {    this.value = ``;    this.cursor = Number(!!this.initial);    this.cursorOffset = 0;    this.fire();    this.render();  }  exit() {    this.abort();  }  abort() {    this.value = this.value || this.initial;    this.done = this.aborted = true;    this.error = false;    this.red = false;    this.fire();    this.render();    this.out.write('\n');    this.close();  }  async validate() {    let valid = await this.validator(this.value);    if (typeof valid === `string`) {      this.errorMsg = valid;      valid = false;    }    this.error = !valid;  }  async submit() {    this.value = this.value || this.initial;    this.cursorOffset = 0;    this.cursor = this.rendered.length;    await this.validate();    if (this.error) {      this.red = true;      this.fire();      this.render();      return;    }    this.done = true;    this.aborted = false;    this.fire();    this.render();    this.out.write('\n');    this.close();  }  next() {    if (!this.placeholder) return this.bell();    this.value = this.initial;    this.cursor = this.rendered.length;    this.fire();    this.render();  }  moveCursor(n) {    if (this.placeholder) return;    this.cursor = this.cursor+n;    this.cursorOffset += n;  }  _(c, key) {    let s1 = this.value.slice(0, this.cursor);    let s2 = this.value.slice(this.cursor);    this.value = `${s1}${c}${s2}`;    this.red = false;    this.cursor = this.placeholder ? 0 : s1.length+1;    this.render();  }  delete() {    if (this.isCursorAtStart()) return this.bell();    let s1 = this.value.slice(0, this.cursor-1);    let s2 = this.value.slice(this.cursor);    this.value = `${s1}${s2}`;    this.red = false;    if (this.isCursorAtStart()) {      this.cursorOffset = 0    } else {      this.cursorOffset++;      this.moveCursor(-1);    }    this.render();  }  deleteForward() {    if(this.cursor*this.scale >= this.rendered.length || this.placeholder) return this.bell();    let s1 = this.value.slice(0, this.cursor);    let s2 = this.value.slice(this.cursor+1);    this.value = `${s1}${s2}`;    this.red = false;    if (this.isCursorAtEnd()) {      this.cursorOffset = 0;    } else {      this.cursorOffset++;    }    this.render();  }  first() {    this.cursor = 0;    this.render();  }  last() {    this.cursor = this.value.length;    this.render();  }  left() {    if (this.cursor <= 0 || this.placeholder) return this.bell();    this.moveCursor(-1);    this.render();  }  right() {    if (this.cursor*this.scale >= this.rendered.length || this.placeholder) return this.bell();    this.moveCursor(1);    this.render();  }  isCursorAtStart() {    return this.cursor === 0 || (this.placeholder && this.cursor === 1);  }  isCursorAtEnd() {    return this.cursor === this.rendered.length || (this.placeholder && this.cursor === this.rendered.length + 1)  }  render() {    if (this.closed) return;    if (!this.firstRender) {      if (this.outputError)        this.out.write(cursor.down(lines(this.outputError, this.out.columns) - 1) + clear(this.outputError, this.out.columns));      this.out.write(clear(this.outputText, this.out.columns));    }    super.render();    this.outputError = '';    this.outputText = [      style.symbol(this.done, this.aborted),      color.bold(this.msg),      style.delimiter(this.done),      this.red ? color.red(this.rendered) : this.rendered    ].join(` `);    if (this.error) {      this.outputError += this.errorMsg.split(`\n`)          .reduce((a, l, i) => a + `\n${i ? ' ' : figures.pointerSmall} ${color.red().italic(l)}`, ``);    }    this.out.write(erase.line + cursor.to(0) + this.outputText + cursor.save + this.outputError + cursor.restore + cursor.move(this.cursorOffset, 0));  }}module.exports = TextPrompt;
 |