| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 | 'use strict';const colors = require('ansi-colors');const SelectPrompt = require('./select');const placeholder = require('../placeholder');class FormPrompt extends SelectPrompt {  constructor(options) {    super({ ...options, multiple: true });    this.type = 'form';    this.initial = this.options.initial;    this.align = [this.options.align, 'right'].find(v => v != null);    this.emptyError = '';    this.values = {};  }  async reset(first) {    await super.reset();    if (first === true) this._index = this.index;    this.index = this._index;    this.values = {};    this.choices.forEach(choice => choice.reset && choice.reset());    return this.render();  }  dispatch(char) {    return !!char && this.append(char);  }  append(char) {    let choice = this.focused;    if (!choice) return this.alert();    let { cursor, input } = choice;    choice.value = choice.input = input.slice(0, cursor) + char + input.slice(cursor);    choice.cursor++;    return this.render();  }  delete() {    let choice = this.focused;    if (!choice || choice.cursor <= 0) return this.alert();    let { cursor, input } = choice;    choice.value = choice.input = input.slice(0, cursor - 1) + input.slice(cursor);    choice.cursor--;    return this.render();  }  deleteForward() {    let choice = this.focused;    if (!choice) return this.alert();    let { cursor, input } = choice;    if (input[cursor] === void 0) return this.alert();    let str = `${input}`.slice(0, cursor) + `${input}`.slice(cursor + 1);    choice.value = choice.input = str;    return this.render();  }  right() {    let choice = this.focused;    if (!choice) return this.alert();    if (choice.cursor >= choice.input.length) return this.alert();    choice.cursor++;    return this.render();  }  left() {    let choice = this.focused;    if (!choice) return this.alert();    if (choice.cursor <= 0) return this.alert();    choice.cursor--;    return this.render();  }  space(ch, key) {    return this.dispatch(ch, key);  }  number(ch, key) {    return this.dispatch(ch, key);  }  next() {    let ch = this.focused;    if (!ch) return this.alert();    let { initial, input } = ch;    if (initial && initial.startsWith(input) && input !== initial) {      ch.value = ch.input = initial;      ch.cursor = ch.value.length;      return this.render();    }    return super.next();  }  prev() {    let ch = this.focused;    if (!ch) return this.alert();    if (ch.cursor === 0) return super.prev();    ch.value = ch.input = '';    ch.cursor = 0;    return this.render();  }  separator() {    return '';  }  format(value) {    return !this.state.submitted ? super.format(value) : '';  }  pointer() {    return '';  }  indicator(choice) {    return choice.input ? '⦿' : '⊙';  }  async choiceSeparator(choice, i) {    let sep = await this.resolve(choice.separator, this.state, choice, i) || ':';    return sep ? ' ' + this.styles.disabled(sep) : '';  }  async renderChoice(choice, i) {    await this.onChoice(choice, i);    let { state, styles } = this;    let { cursor, initial = '', name, hint, input = '' } = choice;    let { muted, submitted, primary, danger } = styles;    let help = hint;    let focused = this.index === i;    let validate = choice.validate || (() => true);    let sep = await this.choiceSeparator(choice, i);    let msg = choice.message;    if (this.align === 'right') msg = msg.padStart(this.longest + 1, ' ');    if (this.align === 'left') msg = msg.padEnd(this.longest + 1, ' ');    // re-populate the form values (answers) object    let value = this.values[name] = (input || initial);    let color = input ? 'success' : 'dark';    if ((await validate.call(choice, value, this.state)) !== true) {      color = 'danger';    }    let style = styles[color];    let indicator = style(await this.indicator(choice, i)) + (choice.pad || '');    let indent = this.indent(choice);    let line = () => [indent, indicator, msg + sep, input, help].filter(Boolean).join(' ');    if (state.submitted) {      msg = colors.unstyle(msg);      input = submitted(input);      help = '';      return line();    }    if (choice.format) {      input = await choice.format.call(this, input, choice, i);    } else {      let color = this.styles.muted;      let options = { input, initial, pos: cursor, showCursor: focused, color };      input = placeholder(this, options);    }    if (!this.isValue(input)) {      input = this.styles.muted(this.symbols.ellipsis);    }    if (choice.result) {      this.values[name] = await choice.result.call(this, value, choice, i);    }    if (focused) {      msg = primary(msg);    }    if (choice.error) {      input += (input ? ' ' : '') + danger(choice.error.trim());    } else if (choice.hint) {      input += (input ? ' ' : '') + muted(choice.hint.trim());    }    return line();  }  async submit() {    this.value = this.values;    return super.base.submit.call(this);  }}module.exports = FormPrompt;
 |