diff options
| author | Joel Kronqvist <joel.h.kronqvist@gmail.com> | 2022-03-05 19:02:27 +0200 | 
|---|---|---|
| committer | Joel Kronqvist <joel.h.kronqvist@gmail.com> | 2022-03-05 19:02:27 +0200 | 
| commit | 5d309ff52cd399a6b71968a6b9a70c8ac0b98981 (patch) | |
| tree | 360f7eb50f956e2367ef38fa1fc6ac7ac5258042 /node_modules/prompts/lib/elements | |
| parent | b500a50f1b97d93c98b36ed9a980f8188d648147 (diff) | |
| download | LYLLRuoka-5d309ff52cd399a6b71968a6b9a70c8ac0b98981.tar.gz LYLLRuoka-5d309ff52cd399a6b71968a6b9a70c8ac0b98981.zip  | |
Added node_modules for the updating to work properly.
Diffstat (limited to 'node_modules/prompts/lib/elements')
| -rw-r--r-- | node_modules/prompts/lib/elements/autocomplete.js | 264 | ||||
| -rw-r--r-- | node_modules/prompts/lib/elements/autocompleteMultiselect.js | 194 | ||||
| -rw-r--r-- | node_modules/prompts/lib/elements/confirm.js | 89 | ||||
| -rw-r--r-- | node_modules/prompts/lib/elements/date.js | 209 | ||||
| -rw-r--r-- | node_modules/prompts/lib/elements/index.js | 13 | ||||
| -rw-r--r-- | node_modules/prompts/lib/elements/multiselect.js | 271 | ||||
| -rw-r--r-- | node_modules/prompts/lib/elements/number.js | 213 | ||||
| -rw-r--r-- | node_modules/prompts/lib/elements/prompt.js | 68 | ||||
| -rw-r--r-- | node_modules/prompts/lib/elements/select.js | 175 | ||||
| -rw-r--r-- | node_modules/prompts/lib/elements/text.js | 208 | ||||
| -rw-r--r-- | node_modules/prompts/lib/elements/toggle.js | 118 | 
11 files changed, 1822 insertions, 0 deletions
diff --git a/node_modules/prompts/lib/elements/autocomplete.js b/node_modules/prompts/lib/elements/autocomplete.js new file mode 100644 index 0000000..8e06da2 --- /dev/null +++ b/node_modules/prompts/lib/elements/autocomplete.js @@ -0,0 +1,264 @@ +'use strict'; + +const color = require('kleur'); +const Prompt = require('./prompt'); +const { erase, cursor } = require('sisteransi'); +const { style, clear, figures, wrap, entriesToDisplay } = require('../util'); + +const getVal = (arr, i) => arr[i] && (arr[i].value || arr[i].title || arr[i]); +const getTitle = (arr, i) => arr[i] && (arr[i].title || arr[i].value || arr[i]); +const getIndex = (arr, valOrTitle) => { +  const index = arr.findIndex(el => el.value === valOrTitle || el.title === valOrTitle); +  return index > -1 ? index : undefined; +}; + +/** + * TextPrompt Base Element + * @param {Object} opts Options + * @param {String} opts.message Message + * @param {Array} opts.choices Array of auto-complete choices objects + * @param {Function} [opts.suggest] Filter function. Defaults to sort by title + * @param {Number} [opts.limit=10] Max number of results to show + * @param {Number} [opts.cursor=0] Cursor start position + * @param {String} [opts.style='default'] Render style + * @param {String} [opts.fallback] Fallback message - initial to default value + * @param {String} [opts.initial] Index of the default value + * @param {Boolean} [opts.clearFirst] The first ESCAPE keypress will clear the input + * @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.noMatches] The no matches found label + */ +class AutocompletePrompt extends Prompt { +  constructor(opts={}) { +    super(opts); +    this.msg = opts.message; +    this.suggest = opts.suggest; +    this.choices = opts.choices; +    this.initial = typeof opts.initial === 'number' +      ? opts.initial +      : getIndex(opts.choices, opts.initial); +    this.select = this.initial || opts.cursor || 0; +    this.i18n = { noMatches: opts.noMatches || 'no matches found' }; +    this.fallback = opts.fallback || this.initial; +    this.clearFirst = opts.clearFirst || false; +    this.suggestions = []; +    this.input = ''; +    this.limit = opts.limit || 10; +    this.cursor = 0; +    this.transform = style.render(opts.style); +    this.scale = this.transform.scale; +    this.render = this.render.bind(this); +    this.complete = this.complete.bind(this); +    this.clear = clear('', this.out.columns); +    this.complete(this.render); +    this.render(); +  } + +  set fallback(fb) { +    this._fb = Number.isSafeInteger(parseInt(fb)) ? parseInt(fb) : fb; +  } + +  get fallback() { +    let choice; +    if (typeof this._fb === 'number') +      choice = this.choices[this._fb]; +    else if (typeof this._fb === 'string') +      choice = { title: this._fb }; +    return choice || this._fb || { title: this.i18n.noMatches }; +  } + +  moveSelect(i) { +    this.select = i; +    if (this.suggestions.length > 0) +      this.value = getVal(this.suggestions, i); +    else this.value = this.fallback.value; +    this.fire(); +  } + +  async complete(cb) { +    const p = (this.completing = this.suggest(this.input, this.choices)); +    const suggestions = await p; + +    if (this.completing !== p) return; +    this.suggestions = suggestions +      .map((s, i, arr) => ({ title: getTitle(arr, i), value: getVal(arr, i), description: s.description })); +    this.completing = false; +    const l = Math.max(suggestions.length - 1, 0); +    this.moveSelect(Math.min(l, this.select)); + +    cb && cb(); +  } + +  reset() { +    this.input = ''; +    this.complete(() => { +      this.moveSelect(this.initial !== void 0 ? this.initial : 0); +      this.render(); +    }); +    this.render(); +  } + +  exit() { +    if (this.clearFirst && this.input.length > 0) { +      this.reset(); +    } else { +      this.done = this.exited = true;  +      this.aborted = false; +      this.fire(); +      this.render(); +      this.out.write('\n'); +      this.close(); +    } +  } + +  abort() { +    this.done = this.aborted = true; +    this.exited = false; +    this.fire(); +    this.render(); +    this.out.write('\n'); +    this.close(); +  } + +  submit() { +    this.done = true; +    this.aborted = this.exited = false; +    this.fire(); +    this.render(); +    this.out.write('\n'); +    this.close(); +  } + +  _(c, key) { +    let s1 = this.input.slice(0, this.cursor); +    let s2 = this.input.slice(this.cursor); +    this.input = `${s1}${c}${s2}`; +    this.cursor = s1.length+1; +    this.complete(this.render); +    this.render(); +  } + +  delete() { +    if (this.cursor === 0) return this.bell(); +    let s1 = this.input.slice(0, this.cursor-1); +    let s2 = this.input.slice(this.cursor); +    this.input = `${s1}${s2}`; +    this.complete(this.render); +    this.cursor = this.cursor-1; +    this.render(); +  } + +  deleteForward() { +    if(this.cursor*this.scale >= this.rendered.length) return this.bell(); +    let s1 = this.input.slice(0, this.cursor); +    let s2 = this.input.slice(this.cursor+1); +    this.input = `${s1}${s2}`; +    this.complete(this.render); +    this.render(); +  } + +  first() { +    this.moveSelect(0); +    this.render(); +  } + +  last() { +    this.moveSelect(this.suggestions.length - 1); +    this.render(); +  } + +  up() { +    if (this.select === 0) { +      this.moveSelect(this.suggestions.length - 1); +    } else { +      this.moveSelect(this.select - 1); +    } +    this.render(); +  } + +  down() { +    if (this.select === this.suggestions.length - 1) { +      this.moveSelect(0); +    } else { +      this.moveSelect(this.select + 1); +    } +    this.render(); +  } + +  next() { +    if (this.select === this.suggestions.length - 1) { +      this.moveSelect(0); +    } else this.moveSelect(this.select + 1); +    this.render(); +  } + +  nextPage() { +    this.moveSelect(Math.min(this.select + this.limit, this.suggestions.length - 1)); +    this.render(); +  } + +  prevPage() { +    this.moveSelect(Math.max(this.select - this.limit, 0)); +    this.render(); +  } + +  left() { +    if (this.cursor <= 0) return this.bell(); +    this.cursor = this.cursor-1; +    this.render(); +  } + +  right() { +    if (this.cursor*this.scale >= this.rendered.length) return this.bell(); +    this.cursor = this.cursor+1; +    this.render(); +  } + +  renderOption(v, hovered, isStart, isEnd) { +    let desc; +    let prefix = isStart ? figures.arrowUp : isEnd ? figures.arrowDown : ' '; +    let title = hovered ? color.cyan().underline(v.title) : v.title; +    prefix = (hovered ? color.cyan(figures.pointer) + ' ' : '  ') + prefix; +    if (v.description) { +      desc = ` - ${v.description}`; +      if (prefix.length + title.length + desc.length >= this.out.columns +        || v.description.split(/\r?\n/).length > 1) { +        desc = '\n' + wrap(v.description, { margin: 3, width: this.out.columns }) +      } +    } +    return prefix + ' ' + title + color.gray(desc || ''); +  } + +  render() { +    if (this.closed) return; +    if (this.firstRender) this.out.write(cursor.hide); +    else this.out.write(clear(this.outputText, this.out.columns)); +    super.render(); + +    let { startIndex, endIndex } = entriesToDisplay(this.select, this.choices.length, this.limit); + +    this.outputText = [ +      style.symbol(this.done, this.aborted, this.exited), +      color.bold(this.msg), +      style.delimiter(this.completing), +      this.done && this.suggestions[this.select] +        ? this.suggestions[this.select].title +        : this.rendered = this.transform.render(this.input) +    ].join(' '); + +    if (!this.done) { +      const suggestions = this.suggestions +        .slice(startIndex, endIndex) +        .map((item, i) =>  this.renderOption(item, +          this.select === i + startIndex, +          i === 0 && startIndex > 0, +          i + startIndex === endIndex - 1 && endIndex < this.choices.length)) +        .join('\n'); +      this.outputText += `\n` + (suggestions || color.gray(this.fallback.title)); +    } + +    this.out.write(erase.line + cursor.to(0) + this.outputText); +  } +} + +module.exports = AutocompletePrompt; diff --git a/node_modules/prompts/lib/elements/autocompleteMultiselect.js b/node_modules/prompts/lib/elements/autocompleteMultiselect.js new file mode 100644 index 0000000..b64510f --- /dev/null +++ b/node_modules/prompts/lib/elements/autocompleteMultiselect.js @@ -0,0 +1,194 @@ +'use strict'; + +const color = require('kleur'); +const { cursor } = require('sisteransi'); +const MultiselectPrompt = require('./multiselect'); +const { clear, style, figures } = require('../util'); +/** + * MultiselectPrompt Base Element + * @param {Object} opts Options + * @param {String} opts.message Message + * @param {Array} opts.choices Array of choice objects + * @param {String} [opts.hint] Hint to display + * @param {String} [opts.warn] Hint shown for disabled choices + * @param {Number} [opts.max] Max choices + * @param {Number} [opts.cursor=0] Cursor start position + * @param {Stream} [opts.stdin] The Readable stream to listen to + * @param {Stream} [opts.stdout] The Writable stream to write readline data to + */ +class AutocompleteMultiselectPrompt extends MultiselectPrompt { +  constructor(opts={}) { +    opts.overrideRender = true; +    super(opts); +    this.inputValue = ''; +    this.clear = clear('', this.out.columns); +    this.filteredOptions = this.value; +    this.render(); +  } + +  last() { +    this.cursor = this.filteredOptions.length - 1; +    this.render(); +  } +  next() { +    this.cursor = (this.cursor + 1) % this.filteredOptions.length; +    this.render(); +  } + +  up() { +    if (this.cursor === 0) { +      this.cursor = this.filteredOptions.length - 1; +    } else { +      this.cursor--; +    } +    this.render(); +  } + +  down() { +    if (this.cursor === this.filteredOptions.length - 1) { +      this.cursor = 0; +    } else { +      this.cursor++; +    } +    this.render(); +  } + +  left() { +    this.filteredOptions[this.cursor].selected = false; +    this.render(); +  } + +  right() { +    if (this.value.filter(e => e.selected).length >= this.maxChoices) return this.bell(); +    this.filteredOptions[this.cursor].selected = true; +    this.render(); +  } + +  delete() { +    if (this.inputValue.length) { +      this.inputValue = this.inputValue.substr(0, this.inputValue.length - 1); +      this.updateFilteredOptions(); +    } +  } + +  updateFilteredOptions() { +    const currentHighlight = this.filteredOptions[this.cursor]; +    this.filteredOptions = this.value +      .filter(v => { +        if (this.inputValue) { +          if (typeof v.title === 'string') { +            if (v.title.toLowerCase().includes(this.inputValue.toLowerCase())) { +              return true; +            } +          } +          if (typeof v.value === 'string') { +            if (v.value.toLowerCase().includes(this.inputValue.toLowerCase())) { +              return true; +            } +          } +          return false; +        } +        return true; +      }); +    const newHighlightIndex = this.filteredOptions.findIndex(v => v === currentHighlight) +    this.cursor = newHighlightIndex < 0 ? 0 : newHighlightIndex; +    this.render(); +  } + +  handleSpaceToggle() { +    const v = this.filteredOptions[this.cursor]; + +    if (v.selected) { +      v.selected = false; +      this.render(); +    } else if (v.disabled || this.value.filter(e => e.selected).length >= this.maxChoices) { +      return this.bell(); +    } else { +      v.selected = true; +      this.render(); +    } +  } + +  handleInputChange(c) { +    this.inputValue = this.inputValue + c; +    this.updateFilteredOptions(); +  } + +  _(c, key) { +    if (c === ' ') { +      this.handleSpaceToggle(); +    } else { +      this.handleInputChange(c); +    } +  } + +  renderInstructions() { +    if (this.instructions === undefined || this.instructions) { +      if (typeof this.instructions === 'string') { +        return this.instructions; +      } +      return ` +Instructions: +    ${figures.arrowUp}/${figures.arrowDown}: Highlight option +    ${figures.arrowLeft}/${figures.arrowRight}/[space]: Toggle selection +    [a,b,c]/delete: Filter choices +    enter/return: Complete answer +`; +    } +    return ''; +  } + +  renderCurrentInput() { +    return ` +Filtered results for: ${this.inputValue ? this.inputValue : color.gray('Enter something to filter')}\n`; +  } + +  renderOption(cursor, v, i) { +    let title; +    if (v.disabled) title = cursor === i ? color.gray().underline(v.title) : color.strikethrough().gray(v.title); +    else title = cursor === i ? color.cyan().underline(v.title) : v.title; +    return (v.selected ? color.green(figures.radioOn) : figures.radioOff) + '  ' + title +  } + +  renderDoneOrInstructions() { +    if (this.done) { +      return this.value +        .filter(e => e.selected) +        .map(v => v.title) +        .join(', '); +    } + +    const output = [color.gray(this.hint), this.renderInstructions(), this.renderCurrentInput()]; + +    if (this.filteredOptions.length && this.filteredOptions[this.cursor].disabled) { +      output.push(color.yellow(this.warn)); +    } +    return output.join(' '); +  } + +  render() { +    if (this.closed) return; +    if (this.firstRender) this.out.write(cursor.hide); +    super.render(); + +    // print prompt + +    let prompt = [ +      style.symbol(this.done, this.aborted), +      color.bold(this.msg), +      style.delimiter(false), +      this.renderDoneOrInstructions() +    ].join(' '); + +    if (this.showMinError) { +      prompt += color.red(`You must select a minimum of ${this.minSelected} choices.`); +      this.showMinError = false; +    } +    prompt += this.renderOptions(this.filteredOptions); + +    this.out.write(this.clear + prompt); +    this.clear = clear(prompt, this.out.columns); +  } +} + +module.exports = AutocompleteMultiselectPrompt; diff --git a/node_modules/prompts/lib/elements/confirm.js b/node_modules/prompts/lib/elements/confirm.js new file mode 100644 index 0000000..7a9173f --- /dev/null +++ b/node_modules/prompts/lib/elements/confirm.js @@ -0,0 +1,89 @@ +const color = require('kleur'); +const Prompt = require('./prompt'); +const { style, clear } = require('../util'); +const { erase, cursor } = require('sisteransi'); + +/** + * ConfirmPrompt Base Element + * @param {Object} opts Options + * @param {String} opts.message Message + * @param {Boolean} [opts.initial] Default value (true/false) + * @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.yes] The "Yes" label + * @param {String} [opts.yesOption] The "Yes" option when choosing between yes/no + * @param {String} [opts.no] The "No" label + * @param {String} [opts.noOption] The "No" option when choosing between yes/no + */ +class ConfirmPrompt extends Prompt { +  constructor(opts={}) { +    super(opts); +    this.msg = opts.message; +    this.value = opts.initial; +    this.initialValue = !!opts.initial; +    this.yesMsg = opts.yes || 'yes'; +    this.yesOption = opts.yesOption || '(Y/n)'; +    this.noMsg = opts.no || 'no'; +    this.noOption = opts.noOption || '(y/N)'; +    this.render(); +  } + +  reset() { +    this.value = this.initialValue; +    this.fire(); +    this.render(); +  } + +  exit() { +    this.abort(); +  } + +  abort() { +    this.done = this.aborted = true; +    this.fire(); +    this.render(); +    this.out.write('\n'); +    this.close(); +  } + +  submit() { +    this.value = this.value || false; +    this.done = true; +    this.aborted = false; +    this.fire(); +    this.render(); +    this.out.write('\n'); +    this.close(); +  } + +  _(c, key) { +    if (c.toLowerCase() === 'y') { +      this.value = true; +      return this.submit(); +    } +    if (c.toLowerCase() === 'n') { +      this.value = false; +      return this.submit(); +    } +    return this.bell(); +  } + +  render() { +    if (this.closed) return; +    if (this.firstRender) this.out.write(cursor.hide); +    else this.out.write(clear(this.outputText, this.out.columns)); +    super.render(); + +    this.outputText = [ +      style.symbol(this.done, this.aborted), +      color.bold(this.msg), +      style.delimiter(this.done), +      this.done ? (this.value ? this.yesMsg : this.noMsg) +          : color.gray(this.initialValue ? this.yesOption : this.noOption) +    ].join(' '); + +    this.out.write(erase.line + cursor.to(0) + this.outputText); +  } +} + +module.exports = ConfirmPrompt; diff --git a/node_modules/prompts/lib/elements/date.js b/node_modules/prompts/lib/elements/date.js new file mode 100644 index 0000000..71ff608 --- /dev/null +++ b/node_modules/prompts/lib/elements/date.js @@ -0,0 +1,209 @@ +'use strict'; + +const color = require('kleur'); +const Prompt = require('./prompt'); +const { style, clear, figures } = require('../util'); +const { erase, cursor } = require('sisteransi'); +const { DatePart, Meridiem, Day, Hours, Milliseconds, Minutes, Month, Seconds, Year } = require('../dateparts'); + +const regex = /\\(.)|"((?:\\["\\]|[^"])+)"|(D[Do]?|d{3,4}|d)|(M{1,4})|(YY(?:YY)?)|([aA])|([Hh]{1,2})|(m{1,2})|(s{1,2})|(S{1,4})|./g; +const regexGroups = { +  1: ({token}) => token.replace(/\\(.)/g, '$1'), +  2: (opts) => new Day(opts), // Day // TODO +  3: (opts) => new Month(opts), // Month +  4: (opts) => new Year(opts), // Year +  5: (opts) => new Meridiem(opts), // AM/PM // TODO (special) +  6: (opts) => new Hours(opts), // Hours +  7: (opts) => new Minutes(opts), // Minutes +  8: (opts) => new Seconds(opts), // Seconds +  9: (opts) => new Milliseconds(opts), // Fractional seconds +} + +const dfltLocales = { +  months: 'January,February,March,April,May,June,July,August,September,October,November,December'.split(','), +  monthsShort: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','), +  weekdays: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','), +  weekdaysShort: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(',') +} + + +/** + * DatePrompt Base Element + * @param {Object} opts Options + * @param {String} opts.message Message + * @param {Number} [opts.initial] Index of default value + * @param {String} [opts.mask] The format mask + * @param {object} [opts.locales] The date locales + * @param {String} [opts.error] The error message shown on invalid value + * @param {Function} [opts.validate] Function to validate the submitted value + * @param {Stream} [opts.stdin] The Readable stream to listen to + * @param {Stream} [opts.stdout] The Writable stream to write readline data to + */ +class DatePrompt extends Prompt { +  constructor(opts={}) { +    super(opts); +    this.msg = opts.message; +    this.cursor = 0; +    this.typed = ''; +    this.locales = Object.assign(dfltLocales, opts.locales); +    this._date = opts.initial || new Date(); +    this.errorMsg = opts.error || 'Please Enter A Valid Value'; +    this.validator = opts.validate || (() => true); +    this.mask = opts.mask || 'YYYY-MM-DD HH:mm:ss'; +    this.clear = clear('', this.out.columns); +    this.render(); +  } + +  get value() { +    return this.date +  } + +  get date() { +    return this._date; +  } + +  set date(date) { +    if (date) this._date.setTime(date.getTime()); +  } + +  set mask(mask) { +    let result; +    this.parts = []; +    while(result = regex.exec(mask)) { +      let match = result.shift(); +      let idx = result.findIndex(gr => gr != null); +      this.parts.push(idx in regexGroups +        ? regexGroups[idx]({ token: result[idx] || match, date: this.date, parts: this.parts, locales: this.locales }) +        : result[idx] || match); +    } + +    let parts = this.parts.reduce((arr, i) => { +      if (typeof i === 'string' && typeof arr[arr.length - 1] === 'string') +        arr[arr.length - 1] += i; +      else arr.push(i); +      return arr; +    }, []); + +    this.parts.splice(0); +    this.parts.push(...parts); +    this.reset(); +  } + +  moveCursor(n) { +    this.typed = ''; +    this.cursor = n; +    this.fire(); +  } + +  reset() { +    this.moveCursor(this.parts.findIndex(p => p instanceof DatePart)); +    this.fire(); +    this.render(); +  } + +  exit() { +    this.abort(); +  } + +  abort() { +    this.done = this.aborted = true; +    this.error = 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() { +    await this.validate(); +    if (this.error) { +      this.color = 'red'; +      this.fire(); +      this.render(); +      return; +    } +    this.done = true; +    this.aborted = false; +    this.fire(); +    this.render(); +    this.out.write('\n'); +    this.close(); +  } + +  up() { +    this.typed = ''; +    this.parts[this.cursor].up(); +    this.render(); +  } + +  down() { +    this.typed = ''; +    this.parts[this.cursor].down(); +    this.render(); +  } + +  left() { +    let prev = this.parts[this.cursor].prev(); +    if (prev == null) return this.bell(); +    this.moveCursor(this.parts.indexOf(prev)); +    this.render(); +  } + +  right() { +    let next = this.parts[this.cursor].next(); +    if (next == null) return this.bell(); +    this.moveCursor(this.parts.indexOf(next)); +    this.render(); +  } + +  next() { +    let next = this.parts[this.cursor].next(); +    this.moveCursor(next +      ? this.parts.indexOf(next) +      : this.parts.findIndex((part) => part instanceof DatePart)); +    this.render(); +  } + +  _(c) { +    if (/\d/.test(c)) { +      this.typed += c; +      this.parts[this.cursor].setTo(this.typed); +      this.render(); +    } +  } + +  render() { +    if (this.closed) return; +    if (this.firstRender) this.out.write(cursor.hide); +    else this.out.write(clear(this.outputText, this.out.columns)); +    super.render(); + +    // Print prompt +    this.outputText = [ +      style.symbol(this.done, this.aborted), +      color.bold(this.msg), +      style.delimiter(false), +      this.parts.reduce((arr, p, idx) => arr.concat(idx === this.cursor && !this.done ? color.cyan().underline(p.toString()) : p), []) +          .join('') +    ].join(' '); + +    // Print error +    if (this.error) { +      this.outputText += 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); +  } +} + +module.exports = DatePrompt; diff --git a/node_modules/prompts/lib/elements/index.js b/node_modules/prompts/lib/elements/index.js new file mode 100644 index 0000000..2556dd0 --- /dev/null +++ b/node_modules/prompts/lib/elements/index.js @@ -0,0 +1,13 @@ +'use strict'; + +module.exports = { +  TextPrompt: require('./text'), +  SelectPrompt: require('./select'), +  TogglePrompt: require('./toggle'), +  DatePrompt: require('./date'), +  NumberPrompt: require('./number'), +  MultiselectPrompt: require('./multiselect'), +  AutocompletePrompt: require('./autocomplete'), +  AutocompleteMultiselectPrompt: require('./autocompleteMultiselect'), +  ConfirmPrompt: require('./confirm') +}; diff --git a/node_modules/prompts/lib/elements/multiselect.js b/node_modules/prompts/lib/elements/multiselect.js new file mode 100644 index 0000000..99b393f --- /dev/null +++ b/node_modules/prompts/lib/elements/multiselect.js @@ -0,0 +1,271 @@ +'use strict'; + +const color = require('kleur'); +const { cursor } = require('sisteransi'); +const Prompt = require('./prompt'); +const { clear, figures, style, wrap, entriesToDisplay } = require('../util'); + +/** + * MultiselectPrompt Base Element + * @param {Object} opts Options + * @param {String} opts.message Message + * @param {Array} opts.choices Array of choice objects + * @param {String} [opts.hint] Hint to display + * @param {String} [opts.warn] Hint shown for disabled choices + * @param {Number} [opts.max] Max choices + * @param {Number} [opts.cursor=0] Cursor start position + * @param {Number} [opts.optionsPerPage=10] Max options to display at once + * @param {Stream} [opts.stdin] The Readable stream to listen to + * @param {Stream} [opts.stdout] The Writable stream to write readline data to + */ +class MultiselectPrompt extends Prompt { +  constructor(opts={}) { +    super(opts); +    this.msg = opts.message; +    this.cursor = opts.cursor || 0; +    this.scrollIndex = opts.cursor || 0; +    this.hint = opts.hint || ''; +    this.warn = opts.warn || '- This option is disabled -'; +    this.minSelected = opts.min; +    this.showMinError = false; +    this.maxChoices = opts.max; +    this.instructions = opts.instructions; +    this.optionsPerPage = opts.optionsPerPage || 10; +    this.value = opts.choices.map((ch, idx) => { +      if (typeof ch === 'string') +        ch = {title: ch, value: idx}; +      return { +        title: ch && (ch.title || ch.value || ch), +        description: ch && ch.description, +        value: ch && (ch.value === undefined ? idx : ch.value), +        selected: ch && ch.selected, +        disabled: ch && ch.disabled +      }; +    }); +    this.clear = clear('', this.out.columns); +    if (!opts.overrideRender) { +      this.render(); +    } +  } + +  reset() { +    this.value.map(v => !v.selected); +    this.cursor = 0; +    this.fire(); +    this.render(); +  } + +  selected() { +    return this.value.filter(v => v.selected); +  } + +  exit() { +    this.abort(); +  } + +  abort() { +    this.done = this.aborted = true; +    this.fire(); +    this.render(); +    this.out.write('\n'); +    this.close(); +  } + +  submit() { +    const selected = this.value +      .filter(e => e.selected); +    if (this.minSelected && selected.length < this.minSelected) { +      this.showMinError = true; +      this.render(); +    } else { +      this.done = true; +      this.aborted = false; +      this.fire(); +      this.render(); +      this.out.write('\n'); +      this.close(); +    } +  } + +  first() { +    this.cursor = 0; +    this.render(); +  } + +  last() { +    this.cursor = this.value.length - 1; +    this.render(); +  } +  next() { +    this.cursor = (this.cursor + 1) % this.value.length; +    this.render(); +  } + +  up() { +    if (this.cursor === 0) { +      this.cursor = this.value.length - 1; +    } else { +      this.cursor--; +    } +    this.render(); +  } + +  down() { +    if (this.cursor === this.value.length - 1) { +      this.cursor = 0; +    } else { +      this.cursor++; +    } +    this.render(); +  } + +  left() { +    this.value[this.cursor].selected = false; +    this.render(); +  } + +  right() { +    if (this.value.filter(e => e.selected).length >= this.maxChoices) return this.bell(); +    this.value[this.cursor].selected = true; +    this.render(); +  } + +  handleSpaceToggle() { +    const v = this.value[this.cursor]; + +    if (v.selected) { +      v.selected = false; +      this.render(); +    } else if (v.disabled || this.value.filter(e => e.selected).length >= this.maxChoices) { +      return this.bell(); +    } else { +      v.selected = true; +      this.render(); +    } +  } + +  toggleAll() { +    if (this.maxChoices !== undefined || this.value[this.cursor].disabled) { +      return this.bell(); +    } + +    const newSelected = !this.value[this.cursor].selected; +    this.value.filter(v => !v.disabled).forEach(v => v.selected = newSelected); +    this.render(); +  } + +  _(c, key) { +    if (c === ' ') { +      this.handleSpaceToggle(); +    } else if (c === 'a') { +      this.toggleAll(); +    } else { +      return this.bell(); +    } +  } + +  renderInstructions() { +    if (this.instructions === undefined || this.instructions) { +      if (typeof this.instructions === 'string') { +        return this.instructions; +      } +      return '\nInstructions:\n' +        + `    ${figures.arrowUp}/${figures.arrowDown}: Highlight option\n` +        + `    ${figures.arrowLeft}/${figures.arrowRight}/[space]: Toggle selection\n` +        + (this.maxChoices === undefined ? `    a: Toggle all\n` : '') +        + `    enter/return: Complete answer`; +    } +    return ''; +  } + +  renderOption(cursor, v, i, arrowIndicator) { +    const prefix = (v.selected ? color.green(figures.radioOn) : figures.radioOff) + ' ' + arrowIndicator + ' '; +    let title, desc; + +    if (v.disabled) { +      title = cursor === i ? color.gray().underline(v.title) : color.strikethrough().gray(v.title); +    } else { +      title = cursor === i ? color.cyan().underline(v.title) : v.title; +      if (cursor === i && v.description) { +        desc = ` - ${v.description}`; +        if (prefix.length + title.length + desc.length >= this.out.columns +          || v.description.split(/\r?\n/).length > 1) { +          desc = '\n' + wrap(v.description, { margin: prefix.length, width: this.out.columns }); +        } +      } +    } + +    return prefix + title + color.gray(desc || ''); +  } + +  // shared with autocompleteMultiselect +  paginateOptions(options) { +    if (options.length === 0) { +      return color.red('No matches for this query.'); +    } + +    let { startIndex, endIndex } = entriesToDisplay(this.cursor, options.length, this.optionsPerPage); +    let prefix, styledOptions = []; + +    for (let i = startIndex; i < endIndex; i++) { +      if (i === startIndex && startIndex > 0) { +        prefix = figures.arrowUp; +      } else if (i === endIndex - 1 && endIndex < options.length) { +        prefix = figures.arrowDown; +      } else { +        prefix = ' '; +      } +      styledOptions.push(this.renderOption(this.cursor, options[i], i, prefix)); +    } + +    return '\n' + styledOptions.join('\n'); +  } + +  // shared with autocomleteMultiselect +  renderOptions(options) { +    if (!this.done) { +      return this.paginateOptions(options); +    } +    return ''; +  } + +  renderDoneOrInstructions() { +    if (this.done) { +      return this.value +        .filter(e => e.selected) +        .map(v => v.title) +        .join(', '); +    } + +    const output = [color.gray(this.hint), this.renderInstructions()]; + +    if (this.value[this.cursor].disabled) { +      output.push(color.yellow(this.warn)); +    } +    return output.join(' '); +  } + +  render() { +    if (this.closed) return; +    if (this.firstRender) this.out.write(cursor.hide); +    super.render(); + +    // print prompt +    let prompt = [ +      style.symbol(this.done, this.aborted), +      color.bold(this.msg), +      style.delimiter(false), +      this.renderDoneOrInstructions() +    ].join(' '); +    if (this.showMinError) { +      prompt += color.red(`You must select a minimum of ${this.minSelected} choices.`); +      this.showMinError = false; +    } +    prompt += this.renderOptions(this.value); + +    this.out.write(this.clear + prompt); +    this.clear = clear(prompt, this.out.columns); +  } +} + +module.exports = MultiselectPrompt; diff --git a/node_modules/prompts/lib/elements/number.js b/node_modules/prompts/lib/elements/number.js new file mode 100644 index 0000000..dc3efe9 --- /dev/null +++ b/node_modules/prompts/lib/elements/number.js @@ -0,0 +1,213 @@ +const color = require('kleur'); +const Prompt = require('./prompt'); +const { cursor, erase } = require('sisteransi'); +const { style, figures, clear, lines } = require('../util'); + +const isNumber = /[0-9]/; +const isDef = any => any !== undefined; +const round = (number, precision) => { +  let factor = Math.pow(10, precision); +  return Math.round(number * factor) / factor; +} + +/** + * NumberPrompt Base Element + * @param {Object} opts Options + * @param {String} opts.message Message + * @param {String} [opts.style='default'] Render style + * @param {Number} [opts.initial] Default value + * @param {Number} [opts.max=+Infinity] Max value + * @param {Number} [opts.min=-Infinity] Min value + * @param {Boolean} [opts.float=false] Parse input as floats + * @param {Number} [opts.round=2] Round floats to x decimals + * @param {Number} [opts.increment=1] Number to increment by when using arrow-keys + * @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 NumberPrompt extends Prompt { +  constructor(opts={}) { +    super(opts); +    this.transform = style.render(opts.style); +    this.msg = opts.message; +    this.initial = isDef(opts.initial) ? opts.initial : ''; +    this.float = !!opts.float; +    this.round = opts.round || 2; +    this.inc = opts.increment || 1; +    this.min = isDef(opts.min) ? opts.min : -Infinity; +    this.max = isDef(opts.max) ? opts.max : Infinity; +    this.errorMsg = opts.error || `Please Enter A Valid Value`; +    this.validator = opts.validate || (() => true); +    this.color = `cyan`; +    this.value = ``; +    this.typed = ``; +    this.lastHit = 0; +    this.render(); +  } + +  set value(v) { +    if (!v && v !== 0) { +      this.placeholder = true; +      this.rendered = color.gray(this.transform.render(`${this.initial}`)); +      this._value = ``; +    } else { +      this.placeholder = false; +      this.rendered = this.transform.render(`${round(v, this.round)}`); +      this._value = round(v, this.round); +    } +    this.fire(); +  } + +  get value() { +    return this._value; +  } + +  parse(x) { +    return this.float ? parseFloat(x) : parseInt(x); +  } + +  valid(c) { +    return c === `-` || c === `.` && this.float || isNumber.test(c) +  } + +  reset() { +    this.typed = ``; +    this.value = ``; +    this.fire(); +    this.render(); +  } + +  exit() { +    this.abort(); +  } + +  abort() { +    let x = this.value; +    this.value = x !== `` ? x : this.initial; +    this.done = this.aborted = true; +    this.error = 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() { +    await this.validate(); +    if (this.error) { +      this.color = `red`; +      this.fire(); +      this.render(); +      return; +    } +    let x = this.value; +    this.value = x !== `` ? x : this.initial; +    this.done = true; +    this.aborted = false; +    this.error = false; +    this.fire(); +    this.render(); +    this.out.write(`\n`); +    this.close(); +  } + +  up() { +    this.typed = ``; +    if(this.value === '') { +      this.value = this.min - this.inc; +    } +    if (this.value >= this.max) return this.bell(); +    this.value += this.inc; +    this.color = `cyan`; +    this.fire(); +    this.render(); +  } + +  down() { +    this.typed = ``; +    if(this.value === '') { +      this.value = this.min + this.inc; +    } +    if (this.value <= this.min) return this.bell(); +    this.value -= this.inc; +    this.color = `cyan`; +    this.fire(); +    this.render(); +  } + +  delete() { +    let val = this.value.toString(); +    if (val.length === 0) return this.bell(); +    this.value = this.parse((val = val.slice(0, -1))) || ``; +    if (this.value !== '' && this.value < this.min) { +      this.value = this.min; +    } +    this.color = `cyan`; +    this.fire(); +    this.render(); +  } + +  next() { +    this.value = this.initial; +    this.fire(); +    this.render(); +  } + +  _(c, key) { +    if (!this.valid(c)) return this.bell(); + +    const now = Date.now(); +    if (now - this.lastHit > 1000) this.typed = ``; // 1s elapsed +    this.typed += c; +    this.lastHit = now; +    this.color = `cyan`; + +    if (c === `.`) return this.fire(); + +    this.value = Math.min(this.parse(this.typed), this.max); +    if (this.value > this.max) this.value = this.max; +    if (this.value < this.min) this.value = this.min; +    this.fire(); +    this.render(); +  } + +  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 = ''; + +    // Print prompt +    this.outputText = [ +      style.symbol(this.done, this.aborted), +      color.bold(this.msg), +      style.delimiter(this.done), +      !this.done || (!this.done && !this.placeholder) +          ? color[this.color]().underline(this.rendered) : this.rendered +    ].join(` `); + +    // Print error +    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); +  } +} + +module.exports = NumberPrompt; diff --git a/node_modules/prompts/lib/elements/prompt.js b/node_modules/prompts/lib/elements/prompt.js new file mode 100644 index 0000000..b793330 --- /dev/null +++ b/node_modules/prompts/lib/elements/prompt.js @@ -0,0 +1,68 @@ +'use strict'; + +const readline = require('readline'); +const { action } = require('../util'); +const EventEmitter = require('events'); +const { beep, cursor } = require('sisteransi'); +const color = require('kleur'); + +/** + * Base prompt skeleton + * @param {Stream} [opts.stdin] The Readable stream to listen to + * @param {Stream} [opts.stdout] The Writable stream to write readline data to + */ +class Prompt extends EventEmitter { +  constructor(opts={}) { +    super(); + +    this.firstRender = true; +    this.in = opts.stdin || process.stdin; +    this.out = opts.stdout || process.stdout; +    this.onRender = (opts.onRender || (() => void 0)).bind(this); +    const rl = readline.createInterface({ input:this.in, escapeCodeTimeout:50 }); +    readline.emitKeypressEvents(this.in, rl); + +    if (this.in.isTTY) this.in.setRawMode(true); +    const isSelect = [ 'SelectPrompt', 'MultiselectPrompt' ].indexOf(this.constructor.name) > -1; +    const keypress = (str, key) => { +      let a = action(key, isSelect); +      if (a === false) { +        this._ && this._(str, key); +      } else if (typeof this[a] === 'function') { +        this[a](key); +      } else { +        this.bell(); +      } +    }; + +    this.close = () => { +      this.out.write(cursor.show); +      this.in.removeListener('keypress', keypress); +      if (this.in.isTTY) this.in.setRawMode(false); +      rl.close(); +      this.emit(this.aborted ? 'abort' : this.exited ? 'exit' : 'submit', this.value); +      this.closed = true; +    }; + +    this.in.on('keypress', keypress); +  } + +  fire() { +    this.emit('state', { +      value: this.value, +      aborted: !!this.aborted, +      exited: !!this.exited +    }); +  } + +  bell() { +    this.out.write(beep); +  } + +  render() { +    this.onRender(color); +    if (this.firstRender) this.firstRender = false; +  } +} + +module.exports = Prompt; diff --git a/node_modules/prompts/lib/elements/select.js b/node_modules/prompts/lib/elements/select.js new file mode 100644 index 0000000..6d6727f --- /dev/null +++ b/node_modules/prompts/lib/elements/select.js @@ -0,0 +1,175 @@ +'use strict'; + +const color = require('kleur'); +const Prompt = require('./prompt'); +const { style, clear, figures, wrap, entriesToDisplay } = require('../util'); +const { cursor } = require('sisteransi'); + +/** + * SelectPrompt Base Element + * @param {Object} opts Options + * @param {String} opts.message Message + * @param {Array} opts.choices Array of choice objects + * @param {String} [opts.hint] Hint to display + * @param {Number} [opts.initial] Index of default value + * @param {Stream} [opts.stdin] The Readable stream to listen to + * @param {Stream} [opts.stdout] The Writable stream to write readline data to + * @param {Number} [opts.optionsPerPage=10] Max options to display at once + */ +class SelectPrompt extends Prompt { +  constructor(opts={}) { +    super(opts); +    this.msg = opts.message; +    this.hint = opts.hint || '- Use arrow-keys. Return to submit.'; +    this.warn = opts.warn || '- This option is disabled'; +    this.cursor = opts.initial || 0; +    this.choices = opts.choices.map((ch, idx) => { +      if (typeof ch === 'string') +        ch = {title: ch, value: idx}; +      return { +        title: ch && (ch.title || ch.value || ch), +        value: ch && (ch.value === undefined ? idx : ch.value), +        description: ch && ch.description, +        selected: ch && ch.selected, +        disabled: ch && ch.disabled +      }; +    }); +    this.optionsPerPage = opts.optionsPerPage || 10; +    this.value = (this.choices[this.cursor] || {}).value; +    this.clear = clear('', this.out.columns); +    this.render(); +  } + +  moveCursor(n) { +    this.cursor = n; +    this.value = this.choices[n].value; +    this.fire(); +  } + +  reset() { +    this.moveCursor(0); +    this.fire(); +    this.render(); +  } + +  exit() { +    this.abort(); +  } + +  abort() { +    this.done = this.aborted = true; +    this.fire(); +    this.render(); +    this.out.write('\n'); +    this.close(); +  } + +  submit() { +    if (!this.selection.disabled) { +      this.done = true; +      this.aborted = false; +      this.fire(); +      this.render(); +      this.out.write('\n'); +      this.close(); +    } else +      this.bell(); +  } + +  first() { +    this.moveCursor(0); +    this.render(); +  } + +  last() { +    this.moveCursor(this.choices.length - 1); +    this.render(); +  } + +  up() { +    if (this.cursor === 0) { +      this.moveCursor(this.choices.length - 1); +    } else { +      this.moveCursor(this.cursor - 1); +    } +    this.render(); +  } + +  down() { +    if (this.cursor === this.choices.length - 1) { +      this.moveCursor(0); +    } else { +      this.moveCursor(this.cursor + 1); +    } +    this.render(); +  } + +  next() { +    this.moveCursor((this.cursor + 1) % this.choices.length); +    this.render(); +  } + +  _(c, key) { +    if (c === ' ') return this.submit(); +  } + +  get selection() { +    return this.choices[this.cursor]; +  } + +  render() { +    if (this.closed) return; +    if (this.firstRender) this.out.write(cursor.hide); +    else this.out.write(clear(this.outputText, this.out.columns)); +    super.render(); + +    let { startIndex, endIndex } = entriesToDisplay(this.cursor, this.choices.length, this.optionsPerPage); + +    // Print prompt +    this.outputText = [ +      style.symbol(this.done, this.aborted), +      color.bold(this.msg), +      style.delimiter(false), +      this.done ? this.selection.title : this.selection.disabled +          ? color.yellow(this.warn) : color.gray(this.hint) +    ].join(' '); + +    // Print choices +    if (!this.done) { +      this.outputText += '\n'; +      for (let i = startIndex; i < endIndex; i++) { +        let title, prefix, desc = '', v = this.choices[i]; + +        // Determine whether to display "more choices" indicators +        if (i === startIndex && startIndex > 0) { +          prefix = figures.arrowUp; +        } else if (i === endIndex - 1 && endIndex < this.choices.length) { +          prefix = figures.arrowDown; +        } else { +          prefix = ' '; +        } + +        if (v.disabled) { +          title = this.cursor === i ? color.gray().underline(v.title) : color.strikethrough().gray(v.title); +          prefix = (this.cursor === i ? color.bold().gray(figures.pointer) + ' ' : '  ') + prefix; +        } else { +          title = this.cursor === i ? color.cyan().underline(v.title) : v.title; +          prefix = (this.cursor === i ? color.cyan(figures.pointer) + ' ' : '  ') + prefix; +          if (v.description && this.cursor === i) { +            desc = ` - ${v.description}`; +            if (prefix.length + title.length + desc.length >= this.out.columns +                || v.description.split(/\r?\n/).length > 1) { +              desc = '\n' + wrap(v.description, { margin: 3, width: this.out.columns }); +            } +          } +        } + +        this.outputText += `${prefix} ${title}${color.gray(desc)}\n`; +      } +    } + +    this.out.write(this.outputText); +  } +} + +module.exports = SelectPrompt; diff --git a/node_modules/prompts/lib/elements/text.js b/node_modules/prompts/lib/elements/text.js new file mode 100644 index 0000000..ee78181 --- /dev/null +++ b/node_modules/prompts/lib/elements/text.js @@ -0,0 +1,208 @@ +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;
\ No newline at end of file diff --git a/node_modules/prompts/lib/elements/toggle.js b/node_modules/prompts/lib/elements/toggle.js new file mode 100644 index 0000000..bad612c --- /dev/null +++ b/node_modules/prompts/lib/elements/toggle.js @@ -0,0 +1,118 @@ +const color = require('kleur'); +const Prompt = require('./prompt'); +const { style, clear } = require('../util'); +const { cursor, erase } = require('sisteransi'); + +/** + * TogglePrompt Base Element + * @param {Object} opts Options + * @param {String} opts.message Message + * @param {Boolean} [opts.initial=false] Default value + * @param {String} [opts.active='no'] Active label + * @param {String} [opts.inactive='off'] Inactive label + * @param {Stream} [opts.stdin] The Readable stream to listen to + * @param {Stream} [opts.stdout] The Writable stream to write readline data to + */ +class TogglePrompt extends Prompt { +  constructor(opts={}) { +    super(opts); +    this.msg = opts.message; +    this.value = !!opts.initial; +    this.active = opts.active || 'on'; +    this.inactive = opts.inactive || 'off'; +    this.initialValue = this.value; +    this.render(); +  } + +  reset() { +    this.value = this.initialValue; +    this.fire(); +    this.render(); +  } + +  exit() { +    this.abort(); +  } + +  abort() { +    this.done = this.aborted = true; +    this.fire(); +    this.render(); +    this.out.write('\n'); +    this.close(); +  } + +  submit() { +    this.done = true; +    this.aborted = false; +    this.fire(); +    this.render(); +    this.out.write('\n'); +    this.close(); +  } + +  deactivate() { +    if (this.value === false) return this.bell(); +    this.value = false; +    this.render(); +  } + +  activate() { +    if (this.value === true) return this.bell(); +    this.value = true; +    this.render(); +  } + +  delete() { +    this.deactivate(); +  } +  left() { +    this.deactivate(); +  } +  right() { +    this.activate(); +  } +  down() { +    this.deactivate(); +  } +  up() { +    this.activate(); +  } + +  next() { +    this.value = !this.value; +    this.fire(); +    this.render(); +  } + +  _(c, key) { +    if (c === ' ') { +      this.value = !this.value; +    } else if (c === '1') { +      this.value = true; +    } else if (c === '0') { +      this.value = false; +    } else return this.bell(); +    this.render(); +  } + +  render() { +    if (this.closed) return; +    if (this.firstRender) this.out.write(cursor.hide); +    else this.out.write(clear(this.outputText, this.out.columns)); +    super.render(); + +    this.outputText = [ +      style.symbol(this.done, this.aborted), +      color.bold(this.msg), +      style.delimiter(this.done), +      this.value ? this.inactive : color.cyan().underline(this.inactive), +      color.gray('/'), +      this.value ? color.cyan().underline(this.active) : this.active +    ].join(' '); + +    this.out.write(erase.line + cursor.to(0) + this.outputText); +  } +} + +module.exports = TogglePrompt;  | 
