[
  {
    "path": ".editorconfig",
    "content": "# http://editorconfig.org\nroot = true\n\n[*]\nindent_size = 2\nindent_style = tab\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[*.{js,json,yml,md}]\nindent_style = space\n\n[example.js]\nindent_size = 4\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n### Describe the bug\nA clear and concise description of what the bug is.\n\n### To Reproduce\nSteps to reproduce the behavior:\n\n1. Step 1\n2. Step 2\n3. ...\n\n### Expected behavior\nA clear and concise description of what you expected to happen.\n\n### System\n\n- OS: [e.g. MacOS 10.14.3]\n- Terminal: [e.g. iTerm, PowerShell]\n- Node version: `node -v`\n\n### Additional context\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n### Is your feature request related to a problem?\nPlease describe. A clear and concise description of what the problem is.  \nEx. I'm always frustrated when [...]\n\n### Describe the solution you'd like\nA clear and concise description of what you want to happen.\n\n### Describe alternatives you've considered\nA clear and concise description of any alternative solutions or features you've considered.\n\n### Additional context\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/funding.yml",
    "content": "# These are supported funding model platforms\n\ngithub: terkelg\n"
  },
  {
    "path": ".github/workflows/size.yml",
    "content": "name: \"Size\"\n\non:\n  pull_request:\n    types: [synchronize, opened]\n\njobs:\n  size:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n        with:\n          fetch-depth: 1\n      - uses: preactjs/compressed-size-action@v2\n        continue-on-error: true\n        with:\n          repo-token: \"${{ secrets.GITHUB_TOKEN }}\"\n          pattern: \"**/lib/*.js\"\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: Test\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\njobs:\n  build:\n\n    runs-on: ubuntu-latest\n\n    strategy:\n      matrix:\n        node-version: [14.x, 16.x, 18.x, 19.x]\n\n    steps:\n      - uses: actions/checkout@v3\n      - name: Use Node.js ${{ matrix.node-version }}\n        uses: actions/setup-node@v3\n        with:\n          node-version: ${{ matrix.node-version }}\n      - run: npm ci\n      - run: npm test\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\n.DS_Store\ndist\n\n\\.idea/\n"
  },
  {
    "path": "example.js",
    "content": "'use strict';\n\nconst { prompt } = require('./');\n\nlet interval;\n\n(async function(){\n    const questions = [\n        {\n            type: 'text',\n            name: 'twitter',\n            message: `What's your twitter handle?`,\n            initial: `terkelg`,\n            format: v => `@${v}`\n        },\n        {\n            type: 'number',\n            name: 'age',\n            message: 'How old are you?',\n            validate: value => value < 18 ? `Sorry, you have to be 18` : true\n        },\n        {\n            type: 'password',\n            name: 'secret',\n            message: 'Tell me a secret'\n        },\n        {\n            type: 'confirm',\n            name: 'confirmed',\n            message: 'Can you confirm?'\n        },\n        {\n            type: prev => prev && 'toggle',\n            name: 'confirmtoggle',\n            message: 'Can you confirm again?',\n            active: 'yes',\n            inactive: 'no'\n        },\n        {\n            type: 'list',\n            name: 'keywords',\n            message: 'Enter keywords'\n        },\n        {\n            type: 'select',\n            name: 'color',\n            message: 'Pick a color',\n            choices: [\n                { title: 'Red', description: 'This option has a description.', value: '#ff0000' },\n                { title: 'Green', value: '#00ff00' },\n                { title: 'Yellow', value: '#ffff00', disabled: true },\n                { title: 'Blue', value: '#0000ff' }\n            ]\n        },\n        {\n            type: 'multiselect',\n            name: 'multicolor',\n            message: 'Pick colors',\n            hint: false,\n            choices: [\n                { title: 'Red', description: 'This option has a description.', value: '#ff0000' },\n                { title: 'Green', value: '#00ff00' },\n                { title: 'Yellow', value: '#ffff00', disabled: true },\n                { title: 'Blue', value: '#0000ff' }\n            ]\n        },\n        {\n            type: 'autocomplete',\n            name: 'actor',\n            message: 'Pick your favorite actor',\n            initial: 1,\n            limit: 3,\n            suggest: (input, choices) => choices.filter(i => i.title.toLowerCase().includes(input.toLowerCase())),\n            choices: [\n                { title: 'Cage' },\n                { title: 'Clooney', value: 'silver-fox' },\n                { title: 'Gyllenhaal' },\n                { title: 'Gibson' },\n                { title: 'Grant', description: 'This option has a description.' },\n                { title: 'Hanks' },\n                { title: 'Downey Jr.' }\n            ],\n            fallback: {\n                title: `This is the fallback. Its value is 'fallback'`,\n                value: 'fallback'\n            }\n        },\n        {\n            type: 'date',\n            name: 'birthday',\n            message: `What's your birthday?`,\n            validate: date => date > Date.now() ? `Your birth day can't be in the future` : true\n        },\n        {\n            type: 'number',\n            name: 'prompt',\n            message: 'This will be overridden',\n            onRender(color) {\n                this.no = (this.no || 1);\n                this.msg = `Enter a number (e.g. ${color.cyan(this.no)})`;\n                if (!interval) interval = setInterval(() => {\n                    this.no += 1;\n                    this.render();\n                }, 1000);\n            }\n        }\n    ];\n\n    const answers = await prompt(questions, {onCancel:cleanup, onSubmit:cleanup});\n    console.log(answers);\n})();\n\nfunction cleanup() {\n    clearInterval(interval);\n}\n\n"
  },
  {
    "path": "index.d.ts",
    "content": "// Definitions migrated from DefinitelyTyped.\n//\n// Special Thanks to: Berkay GURSOY <https://github.com/Berkays>\n//                    Daniel Perez Alvarez <https://github.com/unindented>\n//                    Kamontat Chantrachirathumrong <https://github.com/kamontat>\n//                    theweirdone <https://github.com/theweirdone>\n//                    whoaa512 <https://github.com/whoaa512>\n//                    John Reilly <https://github.com/johnnyreilly>\n//                    Christopher Hiller <https://github.com/boneskull>\n\n\nexport = prompts;\n\nimport { Readable, Writable } from 'stream';\nimport { Kleur } from 'kleur';\n\ndeclare function prompts<T extends string = string>(\n\tquestions: prompts.PromptObject<T> | Array<prompts.PromptObject<T>>,\n\toptions?: prompts.Options\n): Promise<prompts.Answers<T>>;\n\ndeclare namespace prompts {\n\t// Circular reference from prompts\n\tconst prompt: any;\n\n\tfunction inject(arr: ReadonlyArray<any>): void;\n\n\tnamespace inject {\n\t\tconst prototype: {};\n\t}\n\n\tfunction override(obj: { [key: string]: any }): void;\n\n\tnamespace override {\n\t\tconst prototype: {};\n\t}\n\n\tnamespace prompts {\n\t\tfunction autocomplete(args: PromptObject): any;\n\n\t\tfunction confirm(args: PromptObject): void;\n\n\t\tfunction date(args: PromptObject): any;\n\n\t\tfunction invisible(args: PromptObject): any;\n\n\t\tfunction list(args: PromptObject): any;\n\n\t\tfunction multiselect(args: PromptObject): any;\n\n\t\tfunction number(args: PromptObject): void;\n\n\t\tfunction password(args: PromptObject): any;\n\n\t\tfunction select(args: PromptObject): void;\n\n\t\tfunction text(args: PromptObject): void;\n\n\t\tfunction toggle(args: PromptObject): void;\n\t}\n\n\t// Based upon: https://github.com/terkelg/prompts/blob/d7d2c37a0009e3235b2e88a7d5cdbb114ac271b2/lib/elements/select.js#L29\n\tinterface Choice {\n\t\ttitle: string;\n\t\tvalue?: any;\n\t\tdisabled?: boolean | undefined;\n\t\tselected?: boolean | undefined;\n\t\tdescription?: string | undefined;\n\t}\n\n\tinterface Options {\n\t\tonSubmit?: ((prompt: PromptObject, answer: any, answers: any[]) => void) | undefined;\n\t\tonCancel?: ((prompt: PromptObject, answers: any) => void) | undefined;\n\t}\n\n\tinterface PromptObject<T extends string = string> {\n\t\ttype: PromptType | Falsy | PrevCaller<T, PromptType | Falsy>;\n\t\tname: ValueOrFunc<T>;\n\t\tmessage?: ValueOrFunc<string> | undefined;\n\t\tinitial?: InitialReturnValue | PrevCaller<T, InitialReturnValue | Promise<InitialReturnValue>> | undefined;\n\t\tstyle?: string | PrevCaller<T, string | Falsy> | undefined;\n\t\tformat?: PrevCaller<T, void> | undefined;\n\t\tvalidate?: PrevCaller<T, boolean | string | Promise<boolean | string>> | undefined;\n\t\tonState?: PrevCaller<T, void> | undefined;\n\t\tonRender?: ((kleur: Kleur) => void) | undefined;\n\t\tmin?: number | PrevCaller<T, number | Falsy> | undefined;\n\t\tmax?: number | PrevCaller<T, number | Falsy> | undefined;\n\t\tfloat?: boolean | PrevCaller<T, boolean | Falsy> | undefined;\n\t\tround?: number | PrevCaller<T, number | Falsy> | undefined;\n\t\tinstructions?: string | boolean | undefined;\n\t\tincrement?: number | PrevCaller<T, number | Falsy> | undefined;\n\t\tseparator?: string | PrevCaller<T, string | Falsy> | undefined;\n\t\tactive?: string | PrevCaller<T, string | Falsy> | undefined;\n\t\tinactive?: string | PrevCaller<T, string | Falsy> | undefined;\n\t\tchoices?: Choice[] | PrevCaller<T, Choice[] | Falsy> | undefined;\n\t\thint?: string | PrevCaller<T, string | Falsy> | undefined;\n\t\twarn?: string | PrevCaller<T, string | Falsy> | undefined;\n\t\tsuggest?: ((input: any, choices: Choice[]) => Promise<any>) | undefined;\n\t\tlimit?: number | PrevCaller<T, number | Falsy> | undefined;\n\t\tmask?: string | PrevCaller<T, string | Falsy> | undefined;\n\t\tstdout?: Writable | undefined;\n\t\tstdin?: Readable | undefined;\n\t}\n\n\ttype Answers<T extends string> = { [id in T]: any };\n\n\ttype PrevCaller<T extends string, R = T> = (\n\t\tprev: any,\n\t\tvalues: Answers<T>,\n\t\tprompt: PromptObject\n\t) => R;\n\n\ttype Falsy = false | null | undefined;\n\n\ttype PromptType = \"text\" | \"password\" | \"invisible\" | \"number\" | \"confirm\" | \"list\" | \"toggle\" | \"select\" | \"multiselect\" | \"autocomplete\" | \"date\" | \"autocompleteMultiselect\";\n\n\ttype ValueOrFunc<T extends string> = T | PrevCaller<T>;\n\n\ttype InitialReturnValue = string | number | boolean | Date;\n}\n"
  },
  {
    "path": "index.js",
    "content": "module.exports = require('./lib/index.js');\n"
  },
  {
    "path": "lib/dateparts/datepart.js",
    "content": "'use strict';\n\nclass DatePart {\n  constructor({token, date, parts, locales}) {\n    this.token = token;\n    this.date = date || new Date();\n    this.parts = parts || [this];\n    this.locales = locales || {};\n  }\n\n  up() {}\n\n  down() {}\n\n  next() {\n    const currentIdx = this.parts.indexOf(this);\n    return this.parts.find((part, idx) => idx > currentIdx && part instanceof DatePart);\n  }\n\n  setTo(val) {}\n\n  prev() {\n    let parts = [].concat(this.parts).reverse();\n    const currentIdx = parts.indexOf(this);\n    return parts.find((part, idx) => idx > currentIdx && part instanceof DatePart);\n  }\n\n  toString() {\n    return String(this.date);\n  }\n}\n\nmodule.exports = DatePart;\n\n\n"
  },
  {
    "path": "lib/dateparts/day.js",
    "content": "'use strict';\n\nconst DatePart = require('./datepart');\n\nconst pos = n => {\n  n = n % 10;\n  return n === 1 ? 'st'\n       : n === 2 ? 'nd'\n       : n === 3 ? 'rd'\n       : 'th';\n}\n\nclass Day extends DatePart {\n  constructor(opts={}) {\n    super(opts);\n  }\n\n  up() {\n    this.date.setDate(this.date.getDate() + 1);\n  }\n\n  down() {\n    this.date.setDate(this.date.getDate() - 1);\n  }\n\n  setTo(val) {\n    this.date.setDate(parseInt(val.substr(-2)));\n  }\n\n  toString() {\n    let date = this.date.getDate();\n    let day = this.date.getDay();\n    return this.token === 'DD' ? String(date).padStart(2, '0')\n         : this.token === 'Do' ? date + pos(date)\n         : this.token === 'd' ? day + 1\n         : this.token === 'ddd' ? this.locales.weekdaysShort[day]\n         : this.token === 'dddd' ? this.locales.weekdays[day]\n         : date;\n  }\n}\n\nmodule.exports = Day;\n"
  },
  {
    "path": "lib/dateparts/hours.js",
    "content": "'use strict';\n\nconst DatePart = require('./datepart');\n\nclass Hours extends DatePart {\n  constructor(opts={}) {\n    super(opts);\n  }\n\n  up() {\n    this.date.setHours(this.date.getHours() + 1);\n  }\n\n  down() {\n    this.date.setHours(this.date.getHours() - 1);\n  }\n\n  setTo(val) {\n    this.date.setHours(parseInt(val.substr(-2)));\n  }\n\n  toString() {\n    let hours = this.date.getHours();\n    if (/h/.test(this.token))\n      hours = (hours % 12) || 12;\n    return this.token.length > 1 ? String(hours).padStart(2, '0') : hours;\n  }\n}\n\nmodule.exports = Hours;\n"
  },
  {
    "path": "lib/dateparts/index.js",
    "content": "'use strict';\n\nmodule.exports = {\n  DatePart: require('./datepart'),\n  Meridiem: require('./meridiem'),\n  Day: require('./day'),\n  Hours: require('./hours'),\n  Milliseconds: require('./milliseconds'),\n  Minutes: require('./minutes'),\n  Month: require('./month'),\n  Seconds: require('./seconds'),\n  Year: require('./year'),\n}\n"
  },
  {
    "path": "lib/dateparts/meridiem.js",
    "content": "'use strict';\n\nconst DatePart = require('./datepart');\n\nclass Meridiem extends DatePart {\n  constructor(opts={}) {\n    super(opts);\n  }\n\n  up() {\n    this.date.setHours((this.date.getHours() + 12) % 24);\n  }\n\n  down() {\n    this.up();\n  }\n\n  toString() {\n    let meridiem = this.date.getHours() > 12 ? 'pm' : 'am';\n    return /\\A/.test(this.token) ? meridiem.toUpperCase() : meridiem;\n  }\n}\n\nmodule.exports = Meridiem;\n"
  },
  {
    "path": "lib/dateparts/milliseconds.js",
    "content": "'use strict';\n\nconst DatePart = require('./datepart');\n\nclass Milliseconds extends DatePart {\n  constructor(opts={}) {\n    super(opts);\n  }\n\n  up() {\n    this.date.setMilliseconds(this.date.getMilliseconds() + 1);\n  }\n\n  down() {\n    this.date.setMilliseconds(this.date.getMilliseconds() - 1);\n  }\n\n  setTo(val) {\n    this.date.setMilliseconds(parseInt(val.substr(-(this.token.length))));\n  }\n\n  toString() {\n    return String(this.date.getMilliseconds()).padStart(4, '0')\n                                              .substr(0, this.token.length);\n  }\n}\n\nmodule.exports = Milliseconds;\n"
  },
  {
    "path": "lib/dateparts/minutes.js",
    "content": "'use strict';\n\nconst DatePart = require('./datepart');\n\nclass Minutes extends DatePart {\n  constructor(opts={}) {\n    super(opts);\n  }\n\n  up() {\n    this.date.setMinutes(this.date.getMinutes() + 1);\n  }\n\n  down() {\n    this.date.setMinutes(this.date.getMinutes() - 1);\n  }\n\n  setTo(val) {\n    this.date.setMinutes(parseInt(val.substr(-2)));\n  }\n\n  toString() {\n    let m = this.date.getMinutes();\n    return this.token.length > 1 ? String(m).padStart(2, '0') : m;\n  }\n}\n\nmodule.exports = Minutes;\n"
  },
  {
    "path": "lib/dateparts/month.js",
    "content": "'use strict';\n\nconst DatePart = require('./datepart');\n\nclass Month extends DatePart {\n  constructor(opts={}) {\n    super(opts);\n  }\n\n  up() {\n    this.date.setMonth(this.date.getMonth() + 1);\n  }\n\n  down() {\n    this.date.setMonth(this.date.getMonth() - 1);\n  }\n\n  setTo(val) {\n    val = parseInt(val.substr(-2)) - 1;\n    this.date.setMonth(val < 0 ? 0 : val);\n  }\n\n  toString() {\n    let month = this.date.getMonth();\n    let tl = this.token.length;\n    return tl === 2 ? String(month + 1).padStart(2, '0')\n           : tl === 3 ? this.locales.monthsShort[month]\n             : tl === 4 ? this.locales.months[month]\n               : String(month + 1);\n  }\n}\n\nmodule.exports = Month;\n"
  },
  {
    "path": "lib/dateparts/seconds.js",
    "content": "'use strict';\n\nconst DatePart = require('./datepart');\n\nclass Seconds extends DatePart {\n  constructor(opts={}) {\n    super(opts);\n  }\n\n  up() {\n    this.date.setSeconds(this.date.getSeconds() + 1);\n  }\n\n  down() {\n    this.date.setSeconds(this.date.getSeconds() - 1);\n  }\n\n  setTo(val) {\n    this.date.setSeconds(parseInt(val.substr(-2)));\n  }\n\n  toString() {\n    let s = this.date.getSeconds();\n    return this.token.length > 1 ? String(s).padStart(2, '0') : s;\n  }\n}\n\nmodule.exports = Seconds;\n"
  },
  {
    "path": "lib/dateparts/year.js",
    "content": "'use strict';\n\nconst DatePart = require('./datepart');\n\nclass Year extends DatePart {\n  constructor(opts={}) {\n    super(opts);\n  }\n\n  up() {\n    this.date.setFullYear(this.date.getFullYear() + 1);\n  }\n\n  down() {\n    this.date.setFullYear(this.date.getFullYear() - 1);\n  }\n\n  setTo(val) {\n    this.date.setFullYear(val.substr(-4));\n  }\n\n  toString() {\n    let year = String(this.date.getFullYear()).padStart(4, '0');\n    return this.token.length === 2 ? year.substr(-2) : year;\n  }\n}\n\nmodule.exports = Year;\n"
  },
  {
    "path": "lib/elements/autocomplete.js",
    "content": "'use strict';\n\nconst color = require('kleur');\nconst Prompt = require('./prompt');\nconst { erase, cursor } = require('sisteransi');\nconst { style, clear, figures, wrap, entriesToDisplay } = require('../util');\n\nconst getVal = (arr, i) => arr[i] && (arr[i].value || arr[i].title || arr[i]);\nconst getTitle = (arr, i) => arr[i] && (arr[i].title || arr[i].value || arr[i]);\nconst getIndex = (arr, valOrTitle) => {\n  const index = arr.findIndex(el => el.value === valOrTitle || el.title === valOrTitle);\n  return index > -1 ? index : undefined;\n};\n\n/**\n * TextPrompt Base Element\n * @param {Object} opts Options\n * @param {String} opts.message Message\n * @param {Array} opts.choices Array of auto-complete choices objects\n * @param {Function} [opts.suggest] Filter function. Defaults to sort by title\n * @param {Number} [opts.limit=10] Max number of results to show\n * @param {Number} [opts.cursor=0] Cursor start position\n * @param {String} [opts.style='default'] Render style\n * @param {String} [opts.fallback] Fallback message - initial to default value\n * @param {String} [opts.initial] Index of the default value\n * @param {Boolean} [opts.clearFirst] The first ESCAPE keypress will clear the input\n * @param {Stream} [opts.stdin] The Readable stream to listen to\n * @param {Stream} [opts.stdout] The Writable stream to write readline data to\n * @param {String} [opts.noMatches] The no matches found label\n */\nclass AutocompletePrompt extends Prompt {\n  constructor(opts={}) {\n    super(opts);\n    this.msg = opts.message;\n    this.suggest = opts.suggest;\n    this.choices = opts.choices;\n    this.initial = typeof opts.initial === 'number'\n      ? opts.initial\n      : getIndex(opts.choices, opts.initial);\n    this.select = this.initial || opts.cursor || 0;\n    this.i18n = { noMatches: opts.noMatches || 'no matches found' };\n    this.fallback = opts.fallback || this.initial;\n    this.clearFirst = opts.clearFirst || false;\n    this.suggestions = [];\n    this.input = '';\n    this.limit = opts.limit || 10;\n    this.cursor = 0;\n    this.transform = style.render(opts.style);\n    this.scale = this.transform.scale;\n    this.render = this.render.bind(this);\n    this.complete = this.complete.bind(this);\n    this.clear = clear('', this.out.columns);\n    this.complete(this.render);\n    this.render();\n  }\n\n  set fallback(fb) {\n    this._fb = Number.isSafeInteger(parseInt(fb)) ? parseInt(fb) : fb;\n  }\n\n  get fallback() {\n    let choice;\n    if (typeof this._fb === 'number')\n      choice = this.choices[this._fb];\n    else if (typeof this._fb === 'string')\n      choice = { title: this._fb };\n    return choice || this._fb || { title: this.i18n.noMatches };\n  }\n\n  moveSelect(i) {\n    this.select = i;\n    if (this.suggestions.length > 0)\n      this.value = getVal(this.suggestions, i);\n    else this.value = this.fallback.value;\n    this.fire();\n  }\n\n  async complete(cb) {\n    const p = (this.completing = this.suggest(this.input, this.choices));\n    const suggestions = await p;\n\n    if (this.completing !== p) return;\n    this.suggestions = suggestions\n      .map((s, i, arr) => ({ title: getTitle(arr, i), value: getVal(arr, i), description: s.description }));\n    this.completing = false;\n    const l = Math.max(suggestions.length - 1, 0);\n    this.moveSelect(Math.min(l, this.select));\n\n    cb && cb();\n  }\n\n  reset() {\n    this.input = '';\n    this.complete(() => {\n      this.moveSelect(this.initial !== void 0 ? this.initial : 0);\n      this.render();\n    });\n    this.render();\n  }\n\n  exit() {\n    if (this.clearFirst && this.input.length > 0) {\n      this.reset();\n    } else {\n      this.done = this.exited = true; \n      this.aborted = false;\n      this.fire();\n      this.render();\n      this.out.write('\\n');\n      this.close();\n    }\n  }\n\n  abort() {\n    this.done = this.aborted = true;\n    this.exited = false;\n    this.fire();\n    this.render();\n    this.out.write('\\n');\n    this.close();\n  }\n\n  submit() {\n    this.done = true;\n    this.aborted = this.exited = false;\n    this.fire();\n    this.render();\n    this.out.write('\\n');\n    this.close();\n  }\n\n  _(c, key) {\n    let s1 = this.input.slice(0, this.cursor);\n    let s2 = this.input.slice(this.cursor);\n    this.input = `${s1}${c}${s2}`;\n    this.cursor = s1.length+1;\n    this.complete(this.render);\n    this.render();\n  }\n\n  delete() {\n    if (this.cursor === 0) return this.bell();\n    let s1 = this.input.slice(0, this.cursor-1);\n    let s2 = this.input.slice(this.cursor);\n    this.input = `${s1}${s2}`;\n    this.complete(this.render);\n    this.cursor = this.cursor-1;\n    this.render();\n  }\n\n  deleteForward() {\n    if(this.cursor*this.scale >= this.rendered.length) return this.bell();\n    let s1 = this.input.slice(0, this.cursor);\n    let s2 = this.input.slice(this.cursor+1);\n    this.input = `${s1}${s2}`;\n    this.complete(this.render);\n    this.render();\n  }\n\n  first() {\n    this.moveSelect(0);\n    this.render();\n  }\n\n  last() {\n    this.moveSelect(this.suggestions.length - 1);\n    this.render();\n  }\n\n  up() {\n    if (this.select === 0) {\n      this.moveSelect(this.suggestions.length - 1);\n    } else {\n      this.moveSelect(this.select - 1);\n    }\n    this.render();\n  }\n\n  down() {\n    if (this.select === this.suggestions.length - 1) {\n      this.moveSelect(0);\n    } else {\n      this.moveSelect(this.select + 1);\n    }\n    this.render();\n  }\n\n  next() {\n    if (this.select === this.suggestions.length - 1) {\n      this.moveSelect(0);\n    } else this.moveSelect(this.select + 1);\n    this.render();\n  }\n\n  nextPage() {\n    this.moveSelect(Math.min(this.select + this.limit, this.suggestions.length - 1));\n    this.render();\n  }\n\n  prevPage() {\n    this.moveSelect(Math.max(this.select - this.limit, 0));\n    this.render();\n  }\n\n  left() {\n    if (this.cursor <= 0) return this.bell();\n    this.cursor = this.cursor-1;\n    this.render();\n  }\n\n  right() {\n    if (this.cursor*this.scale >= this.rendered.length) return this.bell();\n    this.cursor = this.cursor+1;\n    this.render();\n  }\n\n  renderOption(v, hovered, isStart, isEnd) {\n    let desc;\n    let prefix = isStart ? figures.arrowUp : isEnd ? figures.arrowDown : ' ';\n    let title = hovered ? color.cyan().underline(v.title) : v.title;\n    prefix = (hovered ? color.cyan(figures.pointer) + ' ' : '  ') + prefix;\n    if (v.description) {\n      desc = ` - ${v.description}`;\n      if (prefix.length + title.length + desc.length >= this.out.columns\n        || v.description.split(/\\r?\\n/).length > 1) {\n        desc = '\\n' + wrap(v.description, { margin: 3, width: this.out.columns })\n      }\n    }\n    return prefix + ' ' + title + color.gray(desc || '');\n  }\n\n  render() {\n    if (this.closed) return;\n    if (this.firstRender) this.out.write(cursor.hide);\n    else this.out.write(clear(this.outputText, this.out.columns));\n    super.render();\n\n    let { startIndex, endIndex } = entriesToDisplay(this.select, this.choices.length, this.limit);\n\n    this.outputText = [\n      style.symbol(this.done, this.aborted, this.exited),\n      color.bold(this.msg),\n      style.delimiter(this.completing),\n      this.done && this.suggestions[this.select]\n        ? this.suggestions[this.select].title\n        : this.rendered = this.transform.render(this.input)\n    ].join(' ');\n\n    if (!this.done) {\n      const suggestions = this.suggestions\n        .slice(startIndex, endIndex)\n        .map((item, i) =>  this.renderOption(item,\n          this.select === i + startIndex,\n          i === 0 && startIndex > 0,\n          i + startIndex === endIndex - 1 && endIndex < this.choices.length))\n        .join('\\n');\n      this.outputText += `\\n` + (suggestions || color.gray(this.fallback.title));\n    }\n\n    this.out.write(erase.line + cursor.to(0) + this.outputText);\n  }\n}\n\nmodule.exports = AutocompletePrompt;\n"
  },
  {
    "path": "lib/elements/autocompleteMultiselect.js",
    "content": "'use strict';\n\nconst color = require('kleur');\nconst { cursor } = require('sisteransi');\nconst MultiselectPrompt = require('./multiselect');\nconst { clear, style, figures } = require('../util');\n/**\n * MultiselectPrompt Base Element\n * @param {Object} opts Options\n * @param {String} opts.message Message\n * @param {Array} opts.choices Array of choice objects\n * @param {String} [opts.hint] Hint to display\n * @param {String} [opts.warn] Hint shown for disabled choices\n * @param {Number} [opts.max] Max choices\n * @param {Number} [opts.cursor=0] Cursor start position\n * @param {Stream} [opts.stdin] The Readable stream to listen to\n * @param {Stream} [opts.stdout] The Writable stream to write readline data to\n */\nclass AutocompleteMultiselectPrompt extends MultiselectPrompt {\n  constructor(opts={}) {\n    opts.overrideRender = true;\n    super(opts);\n    this.inputValue = '';\n    this.clear = clear('', this.out.columns);\n    this.filteredOptions = this.value;\n    this.render();\n  }\n\n  last() {\n    this.cursor = this.filteredOptions.length - 1;\n    this.render();\n  }\n  next() {\n    this.cursor = (this.cursor + 1) % this.filteredOptions.length;\n    this.render();\n  }\n\n  up() {\n    if (this.cursor === 0) {\n      this.cursor = this.filteredOptions.length - 1;\n    } else {\n      this.cursor--;\n    }\n    this.render();\n  }\n\n  down() {\n    if (this.cursor === this.filteredOptions.length - 1) {\n      this.cursor = 0;\n    } else {\n      this.cursor++;\n    }\n    this.render();\n  }\n\n  left() {\n    this.filteredOptions[this.cursor].selected = false;\n    this.render();\n  }\n\n  right() {\n    if (this.value.filter(e => e.selected).length >= this.maxChoices) return this.bell();\n    this.filteredOptions[this.cursor].selected = true;\n    this.render();\n  }\n\n  delete() {\n    if (this.inputValue.length) {\n      this.inputValue = this.inputValue.substr(0, this.inputValue.length - 1);\n      this.updateFilteredOptions();\n    }\n  }\n\n  updateFilteredOptions() {\n    const currentHighlight = this.filteredOptions[this.cursor];\n    this.filteredOptions = this.value\n      .filter(v => {\n        if (this.inputValue) {\n          if (typeof v.title === 'string') {\n            if (v.title.toLowerCase().includes(this.inputValue.toLowerCase())) {\n              return true;\n            }\n          }\n          if (typeof v.value === 'string') {\n            if (v.value.toLowerCase().includes(this.inputValue.toLowerCase())) {\n              return true;\n            }\n          }\n          return false;\n        }\n        return true;\n      });\n    const newHighlightIndex = this.filteredOptions.findIndex(v => v === currentHighlight)\n    this.cursor = newHighlightIndex < 0 ? 0 : newHighlightIndex;\n    this.render();\n  }\n\n  handleSpaceToggle() {\n    const v = this.filteredOptions[this.cursor];\n\n    if (v.selected) {\n      v.selected = false;\n      this.render();\n    } else if (v.disabled || this.value.filter(e => e.selected).length >= this.maxChoices) {\n      return this.bell();\n    } else {\n      v.selected = true;\n      this.render();\n    }\n  }\n\n  handleInputChange(c) {\n    this.inputValue = this.inputValue + c;\n    this.updateFilteredOptions();\n  }\n\n  _(c, key) {\n    if (c === ' ') {\n      this.handleSpaceToggle();\n    } else {\n      this.handleInputChange(c);\n    }\n  }\n\n  renderInstructions() {\n    if (this.instructions === undefined || this.instructions) {\n      if (typeof this.instructions === 'string') {\n        return this.instructions;\n      }\n      return `\nInstructions:\n    ${figures.arrowUp}/${figures.arrowDown}: Highlight option\n    ${figures.arrowLeft}/${figures.arrowRight}/[space]: Toggle selection\n    [a,b,c]/delete: Filter choices\n    enter/return: Complete answer\n`;\n    }\n    return '';\n  }\n\n  renderCurrentInput() {\n    return `\nFiltered results for: ${this.inputValue ? this.inputValue : color.gray('Enter something to filter')}\\n`;\n  }\n\n  renderOption(cursor, v, i, arrowIndicator) {\n    const prefix = (v.selected ? color.green(figures.radioOn) : figures.radioOff) + ' ' + arrowIndicator + ' ';\n    let title;\n    if (v.disabled) title = cursor === i ? color.gray().underline(v.title) : color.strikethrough().gray(v.title);\n    else title = cursor === i ? color.cyan().underline(v.title) : v.title;\n    return prefix + title;\n  }\n\n  renderDoneOrInstructions() {\n    if (this.done) {\n      return this.value\n        .filter(e => e.selected)\n        .map(v => v.title)\n        .join(', ');\n    }\n\n    const output = [color.gray(this.hint), this.renderInstructions(), this.renderCurrentInput()];\n\n    if (this.filteredOptions.length && this.filteredOptions[this.cursor].disabled) {\n      output.push(color.yellow(this.warn));\n    }\n    return output.join(' ');\n  }\n\n  render() {\n    if (this.closed) return;\n    if (this.firstRender) this.out.write(cursor.hide);\n    super.render();\n\n    // print prompt\n\n    let prompt = [\n      style.symbol(this.done, this.aborted),\n      color.bold(this.msg),\n      style.delimiter(false),\n      this.renderDoneOrInstructions()\n    ].join(' ');\n\n    if (this.showMinError) {\n      prompt += color.red(`You must select a minimum of ${this.minSelected} choices.`);\n      this.showMinError = false;\n    }\n    prompt += this.renderOptions(this.filteredOptions);\n\n    this.out.write(this.clear + prompt);\n    this.clear = clear(prompt, this.out.columns);\n  }\n}\n\nmodule.exports = AutocompleteMultiselectPrompt;\n"
  },
  {
    "path": "lib/elements/confirm.js",
    "content": "const color = require('kleur');\nconst Prompt = require('./prompt');\nconst { style, clear } = require('../util');\nconst { erase, cursor } = require('sisteransi');\n\n/**\n * ConfirmPrompt Base Element\n * @param {Object} opts Options\n * @param {String} opts.message Message\n * @param {Boolean} [opts.initial] Default value (true/false)\n * @param {Stream} [opts.stdin] The Readable stream to listen to\n * @param {Stream} [opts.stdout] The Writable stream to write readline data to\n * @param {String} [opts.yes] The \"Yes\" label\n * @param {String} [opts.yesOption] The \"Yes\" option when choosing between yes/no\n * @param {String} [opts.no] The \"No\" label\n * @param {String} [opts.noOption] The \"No\" option when choosing between yes/no\n */\nclass ConfirmPrompt extends Prompt {\n  constructor(opts={}) {\n    super(opts);\n    this.msg = opts.message;\n    this.value = opts.initial;\n    this.initialValue = !!opts.initial;\n    this.yesMsg = opts.yes || 'yes';\n    this.yesOption = opts.yesOption || '(Y/n)';\n    this.noMsg = opts.no || 'no';\n    this.noOption = opts.noOption || '(y/N)';\n    this.render();\n  }\n\n  reset() {\n    this.value = this.initialValue;\n    this.fire();\n    this.render();\n  }\n\n  exit() {\n    this.abort();\n  }\n\n  abort() {\n    this.done = this.aborted = true;\n    this.fire();\n    this.render();\n    this.out.write('\\n');\n    this.close();\n  }\n\n  submit() {\n    this.value = this.value || false;\n    this.done = true;\n    this.aborted = false;\n    this.fire();\n    this.render();\n    this.out.write('\\n');\n    this.close();\n  }\n\n  _(c, key) {\n    if (c.toLowerCase() === 'y') {\n      this.value = true;\n      return this.submit();\n    }\n    if (c.toLowerCase() === 'n') {\n      this.value = false;\n      return this.submit();\n    }\n    return this.bell();\n  }\n\n  render() {\n    if (this.closed) return;\n    if (this.firstRender) this.out.write(cursor.hide);\n    else this.out.write(clear(this.outputText, this.out.columns));\n    super.render();\n\n    this.outputText = [\n      style.symbol(this.done, this.aborted),\n      color.bold(this.msg),\n      style.delimiter(this.done),\n      this.done ? (this.value ? this.yesMsg : this.noMsg)\n          : color.gray(this.initialValue ? this.yesOption : this.noOption)\n    ].join(' ');\n\n    this.out.write(erase.line + cursor.to(0) + this.outputText);\n  }\n}\n\nmodule.exports = ConfirmPrompt;\n"
  },
  {
    "path": "lib/elements/date.js",
    "content": "'use strict';\n\nconst color = require('kleur');\nconst Prompt = require('./prompt');\nconst { style, clear, figures } = require('../util');\nconst { erase, cursor } = require('sisteransi');\nconst { DatePart, Meridiem, Day, Hours, Milliseconds, Minutes, Month, Seconds, Year } = require('../dateparts');\n\nconst 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;\nconst regexGroups = {\n  1: ({token}) => token.replace(/\\\\(.)/g, '$1'),\n  2: (opts) => new Day(opts), // Day // TODO\n  3: (opts) => new Month(opts), // Month\n  4: (opts) => new Year(opts), // Year\n  5: (opts) => new Meridiem(opts), // AM/PM // TODO (special)\n  6: (opts) => new Hours(opts), // Hours\n  7: (opts) => new Minutes(opts), // Minutes\n  8: (opts) => new Seconds(opts), // Seconds\n  9: (opts) => new Milliseconds(opts), // Fractional seconds\n}\n\nconst dfltLocales = {\n  months: 'January,February,March,April,May,June,July,August,September,October,November,December'.split(','),\n  monthsShort: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n  weekdays: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n  weekdaysShort: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(',')\n}\n\n\n/**\n * DatePrompt Base Element\n * @param {Object} opts Options\n * @param {String} opts.message Message\n * @param {Number} [opts.initial] Index of default value\n * @param {String} [opts.mask] The format mask\n * @param {object} [opts.locales] The date locales\n * @param {String} [opts.error] The error message shown on invalid value\n * @param {Function} [opts.validate] Function to validate the submitted value\n * @param {Stream} [opts.stdin] The Readable stream to listen to\n * @param {Stream} [opts.stdout] The Writable stream to write readline data to\n */\nclass DatePrompt extends Prompt {\n  constructor(opts={}) {\n    super(opts);\n    this.msg = opts.message;\n    this.cursor = 0;\n    this.typed = '';\n    this.locales = Object.assign(dfltLocales, opts.locales);\n    this._date = opts.initial || new Date();\n    this.errorMsg = opts.error || 'Please Enter A Valid Value';\n    this.validator = opts.validate || (() => true);\n    this.mask = opts.mask || 'YYYY-MM-DD HH:mm:ss';\n    this.clear = clear('', this.out.columns);\n    this.render();\n  }\n\n  get value() {\n    return this.date\n  }\n\n  get date() {\n    return this._date;\n  }\n\n  set date(date) {\n    if (date) this._date.setTime(date.getTime());\n  }\n\n  set mask(mask) {\n    let result;\n    this.parts = [];\n    while(result = regex.exec(mask)) {\n      let match = result.shift();\n      let idx = result.findIndex(gr => gr != null);\n      this.parts.push(idx in regexGroups\n        ? regexGroups[idx]({ token: result[idx] || match, date: this.date, parts: this.parts, locales: this.locales })\n        : result[idx] || match);\n    }\n\n    let parts = this.parts.reduce((arr, i) => {\n      if (typeof i === 'string' && typeof arr[arr.length - 1] === 'string')\n        arr[arr.length - 1] += i;\n      else arr.push(i);\n      return arr;\n    }, []);\n\n    this.parts.splice(0);\n    this.parts.push(...parts);\n    this.reset();\n  }\n\n  moveCursor(n) {\n    this.typed = '';\n    this.cursor = n;\n    this.fire();\n  }\n\n  reset() {\n    this.moveCursor(this.parts.findIndex(p => p instanceof DatePart));\n    this.fire();\n    this.render();\n  }\n\n  exit() {\n    this.abort();\n  }\n\n  abort() {\n    this.done = this.aborted = true;\n    this.error = false;\n    this.fire();\n    this.render();\n    this.out.write('\\n');\n    this.close();\n  }\n\n  async validate() {\n    let valid = await this.validator(this.value);\n    if (typeof valid === 'string') {\n      this.errorMsg = valid;\n      valid = false;\n    }\n    this.error = !valid;\n  }\n\n  async submit() {\n    await this.validate();\n    if (this.error) {\n      this.color = 'red';\n      this.fire();\n      this.render();\n      return;\n    }\n    this.done = true;\n    this.aborted = false;\n    this.fire();\n    this.render();\n    this.out.write('\\n');\n    this.close();\n  }\n\n  up() {\n    this.typed = '';\n    this.parts[this.cursor].up();\n    this.render();\n  }\n\n  down() {\n    this.typed = '';\n    this.parts[this.cursor].down();\n    this.render();\n  }\n\n  left() {\n    let prev = this.parts[this.cursor].prev();\n    if (prev == null) return this.bell();\n    this.moveCursor(this.parts.indexOf(prev));\n    this.render();\n  }\n\n  right() {\n    let next = this.parts[this.cursor].next();\n    if (next == null) return this.bell();\n    this.moveCursor(this.parts.indexOf(next));\n    this.render();\n  }\n\n  next() {\n    let next = this.parts[this.cursor].next();\n    this.moveCursor(next\n      ? this.parts.indexOf(next)\n      : this.parts.findIndex((part) => part instanceof DatePart));\n    this.render();\n  }\n\n  _(c) {\n    if (/\\d/.test(c)) {\n      this.typed += c;\n      this.parts[this.cursor].setTo(this.typed);\n      this.render();\n    }\n  }\n\n  render() {\n    if (this.closed) return;\n    if (this.firstRender) this.out.write(cursor.hide);\n    else this.out.write(clear(this.outputText, this.out.columns));\n    super.render();\n\n    // Print prompt\n    this.outputText = [\n      style.symbol(this.done, this.aborted),\n      color.bold(this.msg),\n      style.delimiter(false),\n      this.parts.reduce((arr, p, idx) => arr.concat(idx === this.cursor && !this.done ? color.cyan().underline(p.toString()) : p), [])\n          .join('')\n    ].join(' ');\n\n    // Print error\n    if (this.error) {\n      this.outputText += this.errorMsg.split('\\n').reduce(\n          (a, l, i) => a + `\\n${i ? ` ` : figures.pointerSmall} ${color.red().italic(l)}`, ``);\n    }\n\n    this.out.write(erase.line + cursor.to(0) + this.outputText);\n  }\n}\n\nmodule.exports = DatePrompt;\n"
  },
  {
    "path": "lib/elements/index.js",
    "content": "'use strict';\n\nmodule.exports = {\n  TextPrompt: require('./text'),\n  SelectPrompt: require('./select'),\n  TogglePrompt: require('./toggle'),\n  DatePrompt: require('./date'),\n  NumberPrompt: require('./number'),\n  MultiselectPrompt: require('./multiselect'),\n  AutocompletePrompt: require('./autocomplete'),\n  AutocompleteMultiselectPrompt: require('./autocompleteMultiselect'),\n  ConfirmPrompt: require('./confirm')\n};\n"
  },
  {
    "path": "lib/elements/multiselect.js",
    "content": "'use strict';\n\nconst color = require('kleur');\nconst { cursor } = require('sisteransi');\nconst Prompt = require('./prompt');\nconst { clear, figures, style, wrap, entriesToDisplay } = require('../util');\n\n/**\n * MultiselectPrompt Base Element\n * @param {Object} opts Options\n * @param {String} opts.message Message\n * @param {Array} opts.choices Array of choice objects\n * @param {String} [opts.hint] Hint to display\n * @param {String} [opts.warn] Hint shown for disabled choices\n * @param {Number} [opts.max] Max choices\n * @param {Number} [opts.cursor=0] Cursor start position\n * @param {Number} [opts.optionsPerPage=10] Max options to display at once\n * @param {Stream} [opts.stdin] The Readable stream to listen to\n * @param {Stream} [opts.stdout] The Writable stream to write readline data to\n */\nclass MultiselectPrompt extends Prompt {\n  constructor(opts={}) {\n    super(opts);\n    this.msg = opts.message;\n    this.cursor = opts.cursor || 0;\n    this.scrollIndex = opts.cursor || 0;\n    this.hint = opts.hint || '';\n    this.warn = opts.warn || '- This option is disabled -';\n    this.minSelected = opts.min;\n    this.showMinError = false;\n    this.maxChoices = opts.max;\n    this.instructions = opts.instructions;\n    this.optionsPerPage = opts.optionsPerPage || 10;\n    this.value = opts.choices.map((ch, idx) => {\n      if (typeof ch === 'string')\n        ch = {title: ch, value: idx};\n      return {\n        title: ch && (ch.title || ch.value || ch),\n        description: ch && ch.description,\n        value: ch && (ch.value === undefined ? idx : ch.value),\n        selected: ch && ch.selected,\n        disabled: ch && ch.disabled\n      };\n    });\n    this.clear = clear('', this.out.columns);\n    if (!opts.overrideRender) {\n      this.render();\n    }\n  }\n\n  reset() {\n    this.value.map(v => !v.selected);\n    this.cursor = 0;\n    this.fire();\n    this.render();\n  }\n\n  selected() {\n    return this.value.filter(v => v.selected);\n  }\n\n  exit() {\n    this.abort();\n  }\n\n  abort() {\n    this.done = this.aborted = true;\n    this.fire();\n    this.render();\n    this.out.write('\\n');\n    this.close();\n  }\n\n  submit() {\n    const selected = this.value\n      .filter(e => e.selected);\n    if (this.minSelected && selected.length < this.minSelected) {\n      this.showMinError = true;\n      this.render();\n    } else {\n      this.done = true;\n      this.aborted = false;\n      this.fire();\n      this.render();\n      this.out.write('\\n');\n      this.close();\n    }\n  }\n\n  first() {\n    this.cursor = 0;\n    this.render();\n  }\n\n  last() {\n    this.cursor = this.value.length - 1;\n    this.render();\n  }\n  next() {\n    this.cursor = (this.cursor + 1) % this.value.length;\n    this.render();\n  }\n\n  up() {\n    if (this.cursor === 0) {\n      this.cursor = this.value.length - 1;\n    } else {\n      this.cursor--;\n    }\n    this.render();\n  }\n\n  down() {\n    if (this.cursor === this.value.length - 1) {\n      this.cursor = 0;\n    } else {\n      this.cursor++;\n    }\n    this.render();\n  }\n\n  left() {\n    this.value[this.cursor].selected = false;\n    this.render();\n  }\n\n  right() {\n    if (this.value.filter(e => e.selected).length >= this.maxChoices) return this.bell();\n    this.value[this.cursor].selected = true;\n    this.render();\n  }\n\n  handleSpaceToggle() {\n    const v = this.value[this.cursor];\n\n    if (v.selected) {\n      v.selected = false;\n      this.render();\n    } else if (v.disabled || this.value.filter(e => e.selected).length >= this.maxChoices) {\n      return this.bell();\n    } else {\n      v.selected = true;\n      this.render();\n    }\n  }\n\n  toggleAll() {\n    if (this.maxChoices !== undefined || this.value[this.cursor].disabled) {\n      return this.bell();\n    }\n\n    const newSelected = !this.value[this.cursor].selected;\n    this.value.filter(v => !v.disabled).forEach(v => v.selected = newSelected);\n    this.render();\n  }\n\n  _(c, key) {\n    if (c === ' ') {\n      this.handleSpaceToggle();\n    } else if (c === 'a') {\n      this.toggleAll();\n    } else {\n      return this.bell();\n    }\n  }\n\n  renderInstructions() {\n    if (this.instructions === undefined || this.instructions) {\n      if (typeof this.instructions === 'string') {\n        return this.instructions;\n      }\n      return '\\nInstructions:\\n'\n        + `    ${figures.arrowUp}/${figures.arrowDown}: Highlight option\\n`\n        + `    ${figures.arrowLeft}/${figures.arrowRight}/[space]: Toggle selection\\n`\n        + (this.maxChoices === undefined ? `    a: Toggle all\\n` : '')\n        + `    enter/return: Complete answer`;\n    }\n    return '';\n  }\n\n  renderOption(cursor, v, i, arrowIndicator) {\n    const prefix = (v.selected ? color.green(figures.radioOn) : figures.radioOff) + ' ' + arrowIndicator + ' ';\n    let title, desc;\n\n    if (v.disabled) {\n      title = cursor === i ? color.gray().underline(v.title) : color.strikethrough().gray(v.title);\n    } else {\n      title = cursor === i ? color.cyan().underline(v.title) : v.title;\n      if (cursor === i && v.description) {\n        desc = ` - ${v.description}`;\n        if (prefix.length + title.length + desc.length >= this.out.columns\n          || v.description.split(/\\r?\\n/).length > 1) {\n          desc = '\\n' + wrap(v.description, { margin: prefix.length, width: this.out.columns });\n        }\n      }\n    }\n\n    return prefix + title + color.gray(desc || '');\n  }\n\n  // shared with autocompleteMultiselect\n  paginateOptions(options) {\n    if (options.length === 0) {\n      return color.red('No matches for this query.');\n    }\n\n    let { startIndex, endIndex } = entriesToDisplay(this.cursor, options.length, this.optionsPerPage);\n    let prefix, styledOptions = [];\n\n    for (let i = startIndex; i < endIndex; i++) {\n      if (i === startIndex && startIndex > 0) {\n        prefix = figures.arrowUp;\n      } else if (i === endIndex - 1 && endIndex < options.length) {\n        prefix = figures.arrowDown;\n      } else {\n        prefix = ' ';\n      }\n      styledOptions.push(this.renderOption(this.cursor, options[i], i, prefix));\n    }\n\n    return '\\n' + styledOptions.join('\\n');\n  }\n\n  // shared with autocomleteMultiselect\n  renderOptions(options) {\n    if (!this.done) {\n      return this.paginateOptions(options);\n    }\n    return '';\n  }\n\n  renderDoneOrInstructions() {\n    if (this.done) {\n      return this.value\n        .filter(e => e.selected)\n        .map(v => v.title)\n        .join(', ');\n    }\n\n    const output = [color.gray(this.hint), this.renderInstructions()];\n\n    if (this.value[this.cursor].disabled) {\n      output.push(color.yellow(this.warn));\n    }\n    return output.join(' ');\n  }\n\n  render() {\n    if (this.closed) return;\n    if (this.firstRender) this.out.write(cursor.hide);\n    super.render();\n\n    // print prompt\n    let prompt = [\n      style.symbol(this.done, this.aborted),\n      color.bold(this.msg),\n      style.delimiter(false),\n      this.renderDoneOrInstructions()\n    ].join(' ');\n    if (this.showMinError) {\n      prompt += color.red(`You must select a minimum of ${this.minSelected} choices.`);\n      this.showMinError = false;\n    }\n    prompt += this.renderOptions(this.value);\n\n    this.out.write(this.clear + prompt);\n    this.clear = clear(prompt, this.out.columns);\n  }\n}\n\nmodule.exports = MultiselectPrompt;\n"
  },
  {
    "path": "lib/elements/number.js",
    "content": "const color = require('kleur');\nconst Prompt = require('./prompt');\nconst { cursor, erase } = require('sisteransi');\nconst { style, figures, clear, lines } = require('../util');\n\nconst isNumber = /[0-9]/;\nconst isDef = any => any !== undefined;\nconst round = (number, precision) => {\n  let factor = Math.pow(10, precision);\n  return Math.round(number * factor) / factor;\n}\n\n/**\n * NumberPrompt Base Element\n * @param {Object} opts Options\n * @param {String} opts.message Message\n * @param {String} [opts.style='default'] Render style\n * @param {Number} [opts.initial] Default value\n * @param {Number} [opts.max=+Infinity] Max value\n * @param {Number} [opts.min=-Infinity] Min value\n * @param {Boolean} [opts.float=false] Parse input as floats\n * @param {Number} [opts.round=2] Round floats to x decimals\n * @param {Number} [opts.increment=1] Number to increment by when using arrow-keys\n * @param {Function} [opts.validate] Validate function\n * @param {Stream} [opts.stdin] The Readable stream to listen to\n * @param {Stream} [opts.stdout] The Writable stream to write readline data to\n * @param {String} [opts.error] The invalid error label\n */\nclass NumberPrompt extends Prompt {\n  constructor(opts={}) {\n    super(opts);\n    this.transform = style.render(opts.style);\n    this.msg = opts.message;\n    this.initial = isDef(opts.initial) ? opts.initial : '';\n    this.float = !!opts.float;\n    this.round = opts.round || 2;\n    this.inc = opts.increment || 1;\n    this.min = isDef(opts.min) ? opts.min : -Infinity;\n    this.max = isDef(opts.max) ? opts.max : Infinity;\n    this.errorMsg = opts.error || `Please Enter A Valid Value`;\n    this.validator = opts.validate || (() => true);\n    this.color = `cyan`;\n    this.value = ``;\n    this.typed = ``;\n    this.lastHit = 0;\n    this.render();\n  }\n\n  set value(v) {\n    if (!v && v !== 0) {\n      this.placeholder = true;\n      this.rendered = color.gray(this.transform.render(`${this.initial}`));\n      this._value = ``;\n    } else {\n      this.placeholder = false;\n      this.rendered = this.transform.render(`${round(v, this.round)}`);\n      this._value = round(v, this.round);\n    }\n    this.fire();\n  }\n\n  get value() {\n    return this._value;\n  }\n\n  parse(x) {\n    return this.float ? parseFloat(x) : parseInt(x);\n  }\n\n  valid(c) {\n    return c === `-` || c === `.` && this.float || isNumber.test(c)\n  }\n\n  reset() {\n    this.typed = ``;\n    this.value = ``;\n    this.fire();\n    this.render();\n  }\n\n  exit() {\n    this.abort();\n  }\n\n  abort() {\n    let x = this.value;\n    this.value = x !== `` ? x : this.initial;\n    this.done = this.aborted = true;\n    this.error = false;\n    this.fire();\n    this.render();\n    this.out.write(`\\n`);\n    this.close();\n  }\n\n  async validate() {\n    let valid = await this.validator(this.value);\n    if (typeof valid === `string`) {\n      this.errorMsg = valid;\n      valid = false;\n    }\n    this.error = !valid;\n  }\n\n  async submit() {\n    await this.validate();\n    if (this.error) {\n      this.color = `red`;\n      this.fire();\n      this.render();\n      return;\n    }\n    let x = this.value;\n    this.value = x !== `` ? x : this.initial;\n    this.done = true;\n    this.aborted = false;\n    this.error = false;\n    this.fire();\n    this.render();\n    this.out.write(`\\n`);\n    this.close();\n  }\n\n  up() {\n    this.typed = ``;\n    if(this.value === '') {\n      this.value = this.min === -Infinity ? 0 - this.inc : this.min - this.inc;\n    }\n    if (this.value >= this.max) return this.bell();\n    this.value += this.inc;\n    this.color = `cyan`;\n    this.fire();\n    this.render();\n  }\n\n  down() {\n    this.typed = ``;\n    if(this.value === '') {\n      this.value = this.min === -Infinity ? 0 + this.inc : this.min + this.inc;\n    }\n    if (this.value <= this.min) return this.bell();\n    this.value -= this.inc;\n    this.color = `cyan`;\n    this.fire();\n    this.render();\n  }\n\n  delete() {\n    let val = this.value.toString();\n    if (val.length === 0) return this.bell();\n    this.value = this.parse((val = val.slice(0, -1))) || ``;\n    if (this.value !== '' && this.value < this.min) {\n      this.value = this.min === -Infinity ? 0 : this.min;\n    }\n    this.color = `cyan`;\n    this.fire();\n    this.render();\n  }\n\n  next() {\n    this.value = this.initial;\n    this.fire();\n    this.render();\n  }\n\n  _(c, key) {\n    if (!this.valid(c)) return this.bell();\n\n    const now = Date.now();\n    if (now - this.lastHit > 1000) this.typed = ``; // 1s elapsed\n    this.typed += c;\n    this.lastHit = now;\n    this.color = `cyan`;\n\n    if (c === `.`) return this.fire();\n\n    this.value = Math.min(this.parse(this.typed), this.max);\n    if (this.value > this.max) this.value = this.max;\n    if (this.value < this.min) this.value = this.min;\n    this.fire();\n    this.render();\n  }\n\n  render() {\n    if (this.closed) return;\n    if (!this.firstRender) {\n      if (this.outputError)\n        this.out.write(cursor.down(lines(this.outputError, this.out.columns) - 1) + clear(this.outputError, this.out.columns));\n      this.out.write(clear(this.outputText, this.out.columns));\n    }\n    super.render();\n    this.outputError = '';\n\n    // Print prompt\n    this.outputText = [\n      style.symbol(this.done, this.aborted),\n      color.bold(this.msg),\n      style.delimiter(this.done),\n      !this.done || (!this.done && !this.placeholder)\n          ? color[this.color]().underline(this.rendered) : this.rendered\n    ].join(` `);\n\n    // Print error\n    if (this.error) {\n      this.outputError += this.errorMsg.split(`\\n`)\n          .reduce((a, l, i) => a + `\\n${i ? ` ` : figures.pointerSmall} ${color.red().italic(l)}`, ``);\n    }\n\n    this.out.write(erase.line + cursor.to(0) + this.outputText + cursor.save + this.outputError + cursor.restore);\n  }\n}\n\nmodule.exports = NumberPrompt;\n"
  },
  {
    "path": "lib/elements/prompt.js",
    "content": "'use strict';\n\nconst readline = require('readline');\nconst { action } = require('../util');\nconst EventEmitter = require('events');\nconst { beep, cursor } = require('sisteransi');\nconst color = require('kleur');\n\n/**\n * Base prompt skeleton\n * @param {Stream} [opts.stdin] The Readable stream to listen to\n * @param {Stream} [opts.stdout] The Writable stream to write readline data to\n */\nclass Prompt extends EventEmitter {\n  constructor(opts={}) {\n    super();\n\n    this.firstRender = true;\n    this.in = opts.stdin || process.stdin;\n    this.out = opts.stdout || process.stdout;\n    this.onRender = (opts.onRender || (() => void 0)).bind(this);\n    const rl = readline.createInterface({ input:this.in, escapeCodeTimeout:50 });\n    readline.emitKeypressEvents(this.in, rl);\n\n    if (this.in.isTTY) this.in.setRawMode(true);\n    const isSelect = [ 'SelectPrompt', 'MultiselectPrompt' ].indexOf(this.constructor.name) > -1;\n    const keypress = (str, key) => {\n      let a = action(key, isSelect);\n      if (a === false) {\n        this._ && this._(str, key);\n      } else if (typeof this[a] === 'function') {\n        this[a](key);\n      } else {\n        this.bell();\n      }\n    };\n\n    this.close = () => {\n      this.out.write(cursor.show);\n      this.in.removeListener('keypress', keypress);\n      if (this.in.isTTY) this.in.setRawMode(false);\n      rl.close();\n      this.emit(this.aborted ? 'abort' : this.exited ? 'exit' : 'submit', this.value);\n      this.closed = true;\n    };\n\n    this.in.on('keypress', keypress);\n  }\n\n  fire() {\n    this.emit('state', {\n      value: this.value,\n      aborted: !!this.aborted,\n      exited: !!this.exited\n    });\n  }\n\n  bell() {\n    this.out.write(beep);\n  }\n\n  render() {\n    this.onRender(color);\n    if (this.firstRender) this.firstRender = false;\n  }\n}\n\nmodule.exports = Prompt;\n"
  },
  {
    "path": "lib/elements/select.js",
    "content": "'use strict';\n\nconst color = require('kleur');\nconst Prompt = require('./prompt');\nconst { style, clear, figures, wrap, entriesToDisplay } = require('../util');\nconst { cursor } = require('sisteransi');\n\n/**\n * SelectPrompt Base Element\n * @param {Object} opts Options\n * @param {String} opts.message Message\n * @param {Array} opts.choices Array of choice objects\n * @param {String} [opts.hint] Hint to display\n * @param {Number} [opts.initial] Index of default value\n * @param {Stream} [opts.stdin] The Readable stream to listen to\n * @param {Stream} [opts.stdout] The Writable stream to write readline data to\n * @param {Number} [opts.optionsPerPage=10] Max options to display at once\n */\nclass SelectPrompt extends Prompt {\n  constructor(opts={}) {\n    super(opts);\n    this.msg = opts.message;\n    this.hint = opts.hint || '- Use arrow-keys. Return to submit.';\n    this.warn = opts.warn || '- This option is disabled';\n    this.cursor = opts.initial || 0;\n    this.choices = opts.choices.map((ch, idx) => {\n      if (typeof ch === 'string')\n        ch = {title: ch, value: idx};\n      return {\n        title: ch && (ch.title || ch.value || ch),\n        value: ch && (ch.value === undefined ? idx : ch.value),\n        description: ch && ch.description,\n        selected: ch && ch.selected,\n        disabled: ch && ch.disabled\n      };\n    });\n    this.optionsPerPage = opts.optionsPerPage || 10;\n    this.value = (this.choices[this.cursor] || {}).value;\n    this.clear = clear('', this.out.columns);\n    this.render();\n  }\n\n  moveCursor(n) {\n    this.cursor = n;\n    this.value = this.choices[n].value;\n    this.fire();\n  }\n\n  reset() {\n    this.moveCursor(0);\n    this.fire();\n    this.render();\n  }\n\n  exit() {\n    this.abort();\n  }\n\n  abort() {\n    this.done = this.aborted = true;\n    this.fire();\n    this.render();\n    this.out.write('\\n');\n    this.close();\n  }\n\n  submit() {\n    if (!this.selection.disabled) {\n      this.done = true;\n      this.aborted = false;\n      this.fire();\n      this.render();\n      this.out.write('\\n');\n      this.close();\n    } else\n      this.bell();\n  }\n\n  first() {\n    this.moveCursor(0);\n    this.render();\n  }\n\n  last() {\n    this.moveCursor(this.choices.length - 1);\n    this.render();\n  }\n\n  up() {\n    if (this.cursor === 0) {\n      this.moveCursor(this.choices.length - 1);\n    } else {\n      this.moveCursor(this.cursor - 1);\n    }\n    this.render();\n  }\n\n  down() {\n    if (this.cursor === this.choices.length - 1) {\n      this.moveCursor(0);\n    } else {\n      this.moveCursor(this.cursor + 1);\n    }\n    this.render();\n  }\n\n  next() {\n    this.moveCursor((this.cursor + 1) % this.choices.length);\n    this.render();\n  }\n\n  _(c, key) {\n    if (c === ' ') return this.submit();\n  }\n\n  get selection() {\n    return this.choices[this.cursor];\n  }\n\n  render() {\n    if (this.closed) return;\n    if (this.firstRender) this.out.write(cursor.hide);\n    else this.out.write(clear(this.outputText, this.out.columns));\n    super.render();\n\n    let { startIndex, endIndex } = entriesToDisplay(this.cursor, this.choices.length, this.optionsPerPage);\n\n    // Print prompt\n    this.outputText = [\n      style.symbol(this.done, this.aborted),\n      color.bold(this.msg),\n      style.delimiter(false),\n      this.done ? this.selection.title : this.selection.disabled\n          ? color.yellow(this.warn) : color.gray(this.hint)\n    ].join(' ');\n\n    // Print choices\n    if (!this.done) {\n      this.outputText += '\\n';\n      for (let i = startIndex; i < endIndex; i++) {\n        let title, prefix, desc = '', v = this.choices[i];\n\n        // Determine whether to display \"more choices\" indicators\n        if (i === startIndex && startIndex > 0) {\n          prefix = figures.arrowUp;\n        } else if (i === endIndex - 1 && endIndex < this.choices.length) {\n          prefix = figures.arrowDown;\n        } else {\n          prefix = ' ';\n        }\n\n        if (v.disabled) {\n          title = this.cursor === i ? color.gray().underline(v.title) : color.strikethrough().gray(v.title);\n          prefix = (this.cursor === i ? color.bold().gray(figures.pointer) + ' ' : '  ') + prefix;\n        } else {\n          title = this.cursor === i ? color.cyan().underline(v.title) : v.title;\n          prefix = (this.cursor === i ? color.cyan(figures.pointer) + ' ' : '  ') + prefix;\n          if (v.description && this.cursor === i) {\n            desc = ` - ${v.description}`;\n            if (prefix.length + title.length + desc.length >= this.out.columns\n                || v.description.split(/\\r?\\n/).length > 1) {\n              desc = '\\n' + wrap(v.description, { margin: 3, width: this.out.columns });\n            }\n          }\n        }\n\n        this.outputText += `${prefix} ${title}${color.gray(desc)}\\n`;\n      }\n    }\n\n    this.out.write(this.outputText);\n  }\n}\n\nmodule.exports = SelectPrompt;\n"
  },
  {
    "path": "lib/elements/text.js",
    "content": "const color = require('kleur');\nconst Prompt = require('./prompt');\nconst { erase, cursor } = require('sisteransi');\nconst { style, clear, lines, figures } = require('../util');\n\n/**\n * TextPrompt Base Element\n * @param {Object} opts Options\n * @param {String} opts.message Message\n * @param {String} [opts.style='default'] Render style\n * @param {String} [opts.initial] Default value\n * @param {Function} [opts.validate] Validate function\n * @param {Stream} [opts.stdin] The Readable stream to listen to\n * @param {Stream} [opts.stdout] The Writable stream to write readline data to\n * @param {String} [opts.error] The invalid error label\n */\nclass TextPrompt extends Prompt {\n  constructor(opts={}) {\n    super(opts);\n    this.transform = style.render(opts.style);\n    this.scale = this.transform.scale;\n    this.msg = opts.message;\n    this.initial = opts.initial || ``;\n    this.validator = opts.validate || (() => true);\n    this.value = ``;\n    this.errorMsg = opts.error || `Please Enter A Valid Value`;\n    this.cursor = Number(!!this.initial);\n    this.cursorOffset = 0;\n    this.clear = clear(``, this.out.columns);\n    this.render();\n  }\n\n  set value(v) {\n    if (!v && this.initial) {\n      this.placeholder = true;\n      this.rendered = color.gray(this.transform.render(this.initial));\n    } else {\n      this.placeholder = false;\n      this.rendered = this.transform.render(v);\n    }\n    this._value = v;\n    this.fire();\n  }\n\n  get value() {\n    return this._value;\n  }\n\n  reset() {\n    this.value = ``;\n    this.cursor = Number(!!this.initial);\n    this.cursorOffset = 0;\n    this.fire();\n    this.render();\n  }\n\n  exit() {\n    this.abort();\n  }\n\n  abort() {\n    this.value = this.value || this.initial;\n    this.done = this.aborted = true;\n    this.error = false;\n    this.red = false;\n    this.fire();\n    this.render();\n    this.out.write('\\n');\n    this.close();\n  }\n\n  async validate() {\n    let valid = await this.validator(this.value);\n    if (typeof valid === `string`) {\n      this.errorMsg = valid;\n      valid = false;\n    }\n    this.error = !valid;\n  }\n\n  async submit() {\n    this.value = this.value || this.initial;\n    this.cursorOffset = 0;\n    this.cursor = this.rendered.length;\n    await this.validate();\n    if (this.error) {\n      this.red = true;\n      this.fire();\n      this.render();\n      return;\n    }\n    this.done = true;\n    this.aborted = false;\n    this.fire();\n    this.render();\n    this.out.write('\\n');\n    this.close();\n  }\n\n  next() {\n    if (!this.placeholder) return this.bell();\n    this.value = this.initial;\n    this.cursor = this.rendered.length;\n    this.fire();\n    this.render();\n  }\n\n  moveCursor(n) {\n    if (this.placeholder) return;\n    this.cursor = this.cursor+n;\n    this.cursorOffset += n;\n  }\n\n  _(c, key) {\n    let s1 = this.value.slice(0, this.cursor);\n    let s2 = this.value.slice(this.cursor);\n    this.value = `${s1}${c}${s2}`;\n    this.red = false;\n    this.cursor = this.placeholder ? 0 : s1.length+1;\n    this.render();\n  }\n\n  delete() {\n    if (this.isCursorAtStart()) return this.bell();\n    let s1 = this.value.slice(0, this.cursor-1);\n    let s2 = this.value.slice(this.cursor);\n    this.value = `${s1}${s2}`;\n    this.red = false;\n    if (this.isCursorAtStart()) {\n      this.cursorOffset = 0\n    } else {\n      this.cursorOffset++;\n      this.moveCursor(-1);\n    }\n    this.render();\n  }\n\n  deleteForward() {\n    if(this.cursor*this.scale >= this.rendered.length || this.placeholder) return this.bell();\n    let s1 = this.value.slice(0, this.cursor);\n    let s2 = this.value.slice(this.cursor+1);\n    this.value = `${s1}${s2}`;\n    this.red = false;\n    if (this.isCursorAtEnd()) {\n      this.cursorOffset = 0;\n    } else {\n      this.cursorOffset++;\n    }\n    this.render();\n  }\n\n  first() {\n    this.cursor = 0;\n    this.render();\n  }\n\n  last() {\n    this.cursor = this.value.length;\n    this.render();\n  }\n\n  left() {\n    if (this.cursor <= 0 || this.placeholder) return this.bell();\n    this.moveCursor(-1);\n    this.render();\n  }\n\n  right() {\n    if (this.cursor*this.scale >= this.rendered.length || this.placeholder) return this.bell();\n    this.moveCursor(1);\n    this.render();\n  }\n\n  isCursorAtStart() {\n    return this.cursor === 0 || (this.placeholder && this.cursor === 1);\n  }\n\n  isCursorAtEnd() {\n    return this.cursor === this.rendered.length || (this.placeholder && this.cursor === this.rendered.length + 1)\n  }\n\n  render() {\n    if (this.closed) return;\n    if (!this.firstRender) {\n      if (this.outputError)\n        this.out.write(cursor.down(lines(this.outputError, this.out.columns) - 1) + clear(this.outputError, this.out.columns));\n      this.out.write(clear(this.outputText, this.out.columns));\n    }\n    super.render();\n    this.outputError = '';\n\n    this.outputText = [\n      style.symbol(this.done, this.aborted),\n      color.bold(this.msg),\n      style.delimiter(this.done),\n      this.red ? color.red(this.rendered) : this.rendered\n    ].join(` `);\n\n    if (this.error) {\n      this.outputError += this.errorMsg.split(`\\n`)\n          .reduce((a, l, i) => a + `\\n${i ? ' ' : figures.pointerSmall} ${color.red().italic(l)}`, ``);\n    }\n\n    this.out.write(erase.line + cursor.to(0) + this.outputText + cursor.save + this.outputError + cursor.restore + cursor.move(this.cursorOffset, 0));\n  }\n}\n\nmodule.exports = TextPrompt;"
  },
  {
    "path": "lib/elements/toggle.js",
    "content": "const color = require('kleur');\nconst Prompt = require('./prompt');\nconst { style, clear } = require('../util');\nconst { cursor, erase } = require('sisteransi');\n\n/**\n * TogglePrompt Base Element\n * @param {Object} opts Options\n * @param {String} opts.message Message\n * @param {Boolean} [opts.initial=false] Default value\n * @param {String} [opts.active='no'] Active label\n * @param {String} [opts.inactive='off'] Inactive label\n * @param {Stream} [opts.stdin] The Readable stream to listen to\n * @param {Stream} [opts.stdout] The Writable stream to write readline data to\n */\nclass TogglePrompt extends Prompt {\n  constructor(opts={}) {\n    super(opts);\n    this.msg = opts.message;\n    this.value = !!opts.initial;\n    this.active = opts.active || 'on';\n    this.inactive = opts.inactive || 'off';\n    this.initialValue = this.value;\n    this.render();\n  }\n\n  reset() {\n    this.value = this.initialValue;\n    this.fire();\n    this.render();\n  }\n\n  exit() {\n    this.abort();\n  }\n\n  abort() {\n    this.done = this.aborted = true;\n    this.fire();\n    this.render();\n    this.out.write('\\n');\n    this.close();\n  }\n\n  submit() {\n    this.done = true;\n    this.aborted = false;\n    this.fire();\n    this.render();\n    this.out.write('\\n');\n    this.close();\n  }\n\n  deactivate() {\n    if (this.value === false) return this.bell();\n    this.value = false;\n    this.render();\n  }\n\n  activate() {\n    if (this.value === true) return this.bell();\n    this.value = true;\n    this.render();\n  }\n\n  delete() {\n    this.deactivate();\n  }\n  left() {\n    this.deactivate();\n  }\n  right() {\n    this.activate();\n  }\n  down() {\n    this.deactivate();\n  }\n  up() {\n    this.activate();\n  }\n\n  next() {\n    this.value = !this.value;\n    this.fire();\n    this.render();\n  }\n\n  _(c, key) {\n    if (c === ' ') {\n      this.value = !this.value;\n    } else if (c === '1') {\n      this.value = true;\n    } else if (c === '0') {\n      this.value = false;\n    } else return this.bell();\n    this.render();\n  }\n\n  render() {\n    if (this.closed) return;\n    if (this.firstRender) this.out.write(cursor.hide);\n    else this.out.write(clear(this.outputText, this.out.columns));\n    super.render();\n\n    this.outputText = [\n      style.symbol(this.done, this.aborted),\n      color.bold(this.msg),\n      style.delimiter(this.done),\n      this.value ? this.inactive : color.cyan().underline(this.inactive),\n      color.gray('/'),\n      this.value ? color.cyan().underline(this.active) : this.active\n    ].join(' ');\n\n    this.out.write(erase.line + cursor.to(0) + this.outputText);\n  }\n}\n\nmodule.exports = TogglePrompt;\n"
  },
  {
    "path": "lib/index.js",
    "content": "'use strict';\n\nconst prompts = require('./prompts');\n\nconst passOn = ['suggest', 'format', 'onState', 'validate', 'onRender', 'type'];\nconst noop = () => {};\n\n/**\n * Prompt for a series of questions\n * @param {Array|Object} questions Single question object or Array of question objects\n * @param {Function} [onSubmit] Callback function called on prompt submit\n * @param {Function} [onCancel] Callback function called on cancel/abort\n * @returns {Object} Object with values from user input\n */\nasync function prompt(questions=[], { onSubmit=noop, onCancel=noop }={}) {\n  const answers = {};\n  const override = prompt._override || {};\n  questions = [].concat(questions);\n  let answer, question, quit, name, type, lastPrompt;\n\n  const getFormattedAnswer = async (question, answer, skipValidation = false) => {\n    if (!skipValidation && question.validate && question.validate(answer) !== true) {\n      return;\n    }\n    return question.format ? await question.format(answer, answers) : answer\n  };\n\n  for (question of questions) {\n    ({ name, type } = question);\n\n    // evaluate type first and skip if type is a falsy value\n    if (typeof type === 'function') {\n      type = await type(answer, { ...answers }, question)\n      question['type'] = type\n    }\n    if (!type) continue;\n\n    // if property is a function, invoke it unless it's a special function\n    for (let key in question) {\n      if (passOn.includes(key)) continue;\n      let value = question[key];\n      question[key] = typeof value === 'function' ? await value(answer, { ...answers }, lastPrompt) : value;\n    }\n\n    lastPrompt = question;\n\n    if (typeof question.message !== 'string') {\n      throw new Error('prompt message is required');\n    }\n\n    // update vars in case they changed\n    ({ name, type } = question);\n\n    if (prompts[type] === void 0) {\n      throw new Error(`prompt type (${type}) is not defined`);\n    }\n\n    if (override[question.name] !== undefined) {\n      answer = await getFormattedAnswer(question, override[question.name]);\n      if (answer !== undefined) {\n        answers[name] = answer;\n        continue;\n      }\n    }\n\n    try {\n      // Get the injected answer if there is one or prompt the user\n      answer = prompt._injected ? getInjectedAnswer(prompt._injected, question.initial) : await prompts[type](question);\n      answers[name] = answer = await getFormattedAnswer(question, answer, true);\n      quit = await onSubmit(question, answer, answers);\n    } catch (err) {\n      quit = !(await onCancel(question, answers));\n    }\n\n    if (quit) return answers;\n  }\n\n  return answers;\n}\n\nfunction getInjectedAnswer(injected, deafultValue) {\n  const answer = injected.shift();\n    if (answer instanceof Error) {\n      throw answer;\n    }\n\n    return (answer === undefined) ? deafultValue : answer;\n}\n\nfunction inject(answers) {\n  prompt._injected = (prompt._injected || []).concat(answers);\n}\n\nfunction override(answers) {\n  prompt._override = Object.assign({}, answers);\n}\n\nmodule.exports = Object.assign(prompt, { prompt, prompts, inject, override });\n"
  },
  {
    "path": "lib/prompts.js",
    "content": "'use strict';\nconst $ = exports;\nconst el = require('./elements');\nconst noop = v => v;\n\nfunction toPrompt(type, args, opts={}) {\n  return new Promise((res, rej) => {\n    const p = new el[type](args);\n    const onAbort = opts.onAbort || noop;\n    const onSubmit = opts.onSubmit || noop;\n    const onExit = opts.onExit || noop;\n    p.on('state', args.onState || noop);\n    p.on('submit', x => res(onSubmit(x)));\n    p.on('exit', x => res(onExit(x)));\n    p.on('abort', x => rej(onAbort(x)));\n  });\n}\n\n/**\n * Text prompt\n * @param {string} args.message Prompt message to display\n * @param {string} [args.initial] Default string value\n * @param {string} [args.style=\"default\"] Render style ('default', 'password', 'invisible')\n * @param {function} [args.onState] On state change callback\n * @param {function} [args.validate] Function to validate user input\n * @param {Stream} [args.stdin] The Readable stream to listen to\n * @param {Stream} [args.stdout] The Writable stream to write readline data to\n * @returns {Promise} Promise with user input\n */\n$.text = args => toPrompt('TextPrompt', args);\n\n/**\n * Password prompt with masked input\n * @param {string} args.message Prompt message to display\n * @param {string} [args.initial] Default string value\n * @param {function} [args.onState] On state change callback\n * @param {function} [args.validate] Function to validate user input\n * @param {Stream} [args.stdin] The Readable stream to listen to\n * @param {Stream} [args.stdout] The Writable stream to write readline data to\n * @returns {Promise} Promise with user input\n */\n$.password = args => {\n  args.style = 'password';\n  return $.text(args);\n};\n\n/**\n * Prompt where input is invisible, like sudo\n * @param {string} args.message Prompt message to display\n * @param {string} [args.initial] Default string value\n * @param {function} [args.onState] On state change callback\n * @param {function} [args.validate] Function to validate user input\n * @param {Stream} [args.stdin] The Readable stream to listen to\n * @param {Stream} [args.stdout] The Writable stream to write readline data to\n * @returns {Promise} Promise with user input\n */\n$.invisible = args => {\n  args.style = 'invisible';\n  return $.text(args);\n};\n\n/**\n * Number prompt\n * @param {string} args.message Prompt message to display\n * @param {number} args.initial Default number value\n * @param {function} [args.onState] On state change callback\n * @param {number} [args.max] Max value\n * @param {number} [args.min] Min value\n * @param {string} [args.style=\"default\"] Render style ('default', 'password', 'invisible')\n * @param {Boolean} [opts.float=false] Parse input as floats\n * @param {Number} [opts.round=2] Round floats to x decimals\n * @param {Number} [opts.increment=1] Number to increment by when using arrow-keys\n * @param {function} [args.validate] Function to validate user input\n * @param {Stream} [args.stdin] The Readable stream to listen to\n * @param {Stream} [args.stdout] The Writable stream to write readline data to\n * @returns {Promise} Promise with user input\n */\n$.number = args => toPrompt('NumberPrompt', args);\n\n/**\n * Date prompt\n * @param {string} args.message Prompt message to display\n * @param {number} args.initial Default number value\n * @param {function} [args.onState] On state change callback\n * @param {number} [args.max] Max value\n * @param {number} [args.min] Min value\n * @param {string} [args.style=\"default\"] Render style ('default', 'password', 'invisible')\n * @param {Boolean} [opts.float=false] Parse input as floats\n * @param {Number} [opts.round=2] Round floats to x decimals\n * @param {Number} [opts.increment=1] Number to increment by when using arrow-keys\n * @param {function} [args.validate] Function to validate user input\n * @param {Stream} [args.stdin] The Readable stream to listen to\n * @param {Stream} [args.stdout] The Writable stream to write readline data to\n * @returns {Promise} Promise with user input\n */\n$.date = args => toPrompt('DatePrompt', args);\n\n/**\n * Classic yes/no prompt\n * @param {string} args.message Prompt message to display\n * @param {boolean} [args.initial=false] Default value\n * @param {function} [args.onState] On state change callback\n * @param {Stream} [args.stdin] The Readable stream to listen to\n * @param {Stream} [args.stdout] The Writable stream to write readline data to\n * @returns {Promise} Promise with user input\n */\n$.confirm = args => toPrompt('ConfirmPrompt', args);\n\n/**\n * List prompt, split intput string by `seperator`\n * @param {string} args.message Prompt message to display\n * @param {string} [args.initial] Default string value\n * @param {string} [args.style=\"default\"] Render style ('default', 'password', 'invisible')\n * @param {string} [args.separator] String separator\n * @param {function} [args.onState] On state change callback\n * @param {Stream} [args.stdin] The Readable stream to listen to\n * @param {Stream} [args.stdout] The Writable stream to write readline data to\n * @returns {Promise} Promise with user input, in form of an `Array`\n */\n$.list = args => {\n  const sep = args.separator || ',';\n  return toPrompt('TextPrompt', args, {\n    onSubmit: str => str.split(sep).map(s => s.trim())\n  });\n};\n\n/**\n * Toggle/switch prompt\n * @param {string} args.message Prompt message to display\n * @param {boolean} [args.initial=false] Default value\n * @param {string} [args.active=\"on\"] Text for `active` state\n * @param {string} [args.inactive=\"off\"] Text for `inactive` state\n * @param {function} [args.onState] On state change callback\n * @param {Stream} [args.stdin] The Readable stream to listen to\n * @param {Stream} [args.stdout] The Writable stream to write readline data to\n * @returns {Promise} Promise with user input\n */\n$.toggle = args => toPrompt('TogglePrompt', args);\n\n/**\n * Interactive select prompt\n * @param {string} args.message Prompt message to display\n * @param {Array} args.choices Array of choices objects `[{ title, value }, ...]`\n * @param {number} [args.initial] Index of default value\n * @param {String} [args.hint] Hint to display\n * @param {function} [args.onState] On state change callback\n * @param {Stream} [args.stdin] The Readable stream to listen to\n * @param {Stream} [args.stdout] The Writable stream to write readline data to\n * @returns {Promise} Promise with user input\n */\n$.select = args => toPrompt('SelectPrompt', args);\n\n/**\n * Interactive multi-select / autocompleteMultiselect prompt\n * @param {string} args.message Prompt message to display\n * @param {Array} args.choices Array of choices objects `[{ title, value, [selected] }, ...]`\n * @param {number} [args.max] Max select\n * @param {string} [args.hint] Hint to display user\n * @param {Number} [args.cursor=0] Cursor start position\n * @param {function} [args.onState] On state change callback\n * @param {Stream} [args.stdin] The Readable stream to listen to\n * @param {Stream} [args.stdout] The Writable stream to write readline data to\n * @returns {Promise} Promise with user input\n */\n$.multiselect = args => {\n  args.choices = [].concat(args.choices || []);\n  const toSelected = items => items.filter(item => item.selected).map(item => item.value);\n  return toPrompt('MultiselectPrompt', args, {\n    onAbort: toSelected,\n    onSubmit: toSelected\n  });\n};\n\n$.autocompleteMultiselect = args => {\n  args.choices = [].concat(args.choices || []);\n  const toSelected = items => items.filter(item => item.selected).map(item => item.value);\n  return toPrompt('AutocompleteMultiselectPrompt', args, {\n    onAbort: toSelected,\n    onSubmit: toSelected\n  });\n};\n\nconst byTitle = (input, choices) => Promise.resolve(\n  choices.filter(item => item.title.slice(0, input.length).toLowerCase() === input.toLowerCase())\n);\n\n/**\n * Interactive auto-complete prompt\n * @param {string} args.message Prompt message to display\n * @param {Array} args.choices Array of auto-complete choices objects `[{ title, value }, ...]`\n * @param {Function} [args.suggest] Function to filter results based on user input. Defaults to sort by `title`\n * @param {number} [args.limit=10] Max number of results to show\n * @param {string} [args.style=\"default\"] Render style ('default', 'password', 'invisible')\n * @param {String} [args.initial] Index of the default value\n * @param {boolean} [opts.clearFirst] The first ESCAPE keypress will clear the input\n * @param {String} [args.fallback] Fallback message - defaults to initial value\n * @param {function} [args.onState] On state change callback\n * @param {Stream} [args.stdin] The Readable stream to listen to\n * @param {Stream} [args.stdout] The Writable stream to write readline data to\n * @returns {Promise} Promise with user input\n */\n$.autocomplete = args => {\n  args.suggest = args.suggest || byTitle;\n  args.choices = [].concat(args.choices || []);\n  return toPrompt('AutocompletePrompt', args);\n};\n"
  },
  {
    "path": "lib/util/action.js",
    "content": "'use strict';\n\nmodule.exports = (key, isSelect) => {\n  if (key.meta && key.name !== 'escape') return;\n  \n  if (key.ctrl) {\n    if (key.name === 'a') return 'first';\n    if (key.name === 'c') return 'abort';\n    if (key.name === 'd') return 'abort';\n    if (key.name === 'e') return 'last';\n    if (key.name === 'g') return 'reset';\n  }\n  \n  if (isSelect) {\n    if (key.name === 'j') return 'down';\n    if (key.name === 'k') return 'up';\n  }\n\n  if (key.name === 'return') return 'submit';\n  if (key.name === 'enter') return 'submit'; // ctrl + J\n  if (key.name === 'backspace') return 'delete';\n  if (key.name === 'delete') return 'deleteForward';\n  if (key.name === 'abort') return 'abort';\n  if (key.name === 'escape') return 'exit';\n  if (key.name === 'tab') return 'next';\n  if (key.name === 'pagedown') return 'nextPage';\n  if (key.name === 'pageup') return 'prevPage';\n  // TODO create home() in prompt types (e.g. TextPrompt)\n  if (key.name === 'home') return 'home';\n  // TODO create end() in prompt types (e.g. TextPrompt)\n  if (key.name === 'end') return 'end';\n\n  if (key.name === 'up') return 'up';\n  if (key.name === 'down') return 'down';\n  if (key.name === 'right') return 'right';\n  if (key.name === 'left') return 'left';\n\n  return false;\n};\n"
  },
  {
    "path": "lib/util/clear.js",
    "content": "'use strict';\n\nconst strip = require('./strip');\nconst { erase, cursor } = require('sisteransi');\n\nconst width = str => [...strip(str)].length;\n\n/**\n * @param {string} prompt\n * @param {number} perLine\n */\nmodule.exports = function(prompt, perLine) {\n  if (!perLine) return erase.line + cursor.to(0);\n\n  let rows = 0;\n  const lines = prompt.split(/\\r?\\n/);\n  for (let line of lines) {\n    rows += 1 + Math.floor(Math.max(width(line) - 1, 0) / perLine);\n  }\n\n  return erase.lines(rows);\n};\n"
  },
  {
    "path": "lib/util/entriesToDisplay.js",
    "content": "'use strict';\n\n/**\n * Determine what entries should be displayed on the screen, based on the\n * currently selected index and the maximum visible. Used in list-based\n * prompts like `select` and `multiselect`.\n *\n * @param {number} cursor the currently selected entry\n * @param {number} total the total entries available to display\n * @param {number} [maxVisible] the number of entries that can be displayed\n */\nmodule.exports = (cursor, total, maxVisible)  => {\n  maxVisible = maxVisible || total;\n\n  let startIndex = Math.min(total- maxVisible, cursor - Math.floor(maxVisible / 2));\n  if (startIndex < 0) startIndex = 0;\n\n  let endIndex = Math.min(startIndex + maxVisible, total);\n\n  return { startIndex, endIndex };\n};\n"
  },
  {
    "path": "lib/util/figures.js",
    "content": "'use strict';\t\n\n const main = {\n  arrowUp: '↑',\n  arrowDown: '↓',\n  arrowLeft: '←',\n  arrowRight: '→',\n  radioOn: '◉',\n  radioOff: '◯',\n  tick: '✔',\t\n  cross: '✖',\t\n  ellipsis: '…',\t\n  pointerSmall: '›',\t\n  line: '─',\t\n  pointer: '❯'\t\n};\t\nconst win = {\n  arrowUp: main.arrowUp,\n  arrowDown: main.arrowDown,\n  arrowLeft: main.arrowLeft,\n  arrowRight: main.arrowRight,\n  radioOn: '(*)',\n  radioOff: '( )',\t\n  tick: '√',\t\n  cross: '×',\t\n  ellipsis: '...',\t\n  pointerSmall: '»',\t\n  line: '─',\t\n  pointer: '>'\t\n};\t\nconst figures = process.platform === 'win32' ? win : main;\t\n\n module.exports = figures;\n"
  },
  {
    "path": "lib/util/index.js",
    "content": "'use strict';\n\nmodule.exports = {\n  action: require('./action'),\n  clear: require('./clear'),\n  style: require('./style'),\n  strip: require('./strip'),\n  figures: require('./figures'),\n  lines: require('./lines'),\n  wrap: require('./wrap'),\n  entriesToDisplay: require('./entriesToDisplay')\n};\n"
  },
  {
    "path": "lib/util/lines.js",
    "content": "'use strict';\n\nconst strip = require('./strip');\n\n/**\n * @param {string} msg\n * @param {number} perLine\n */\nmodule.exports = function (msg, perLine) {\n  let lines = String(strip(msg) || '').split(/\\r?\\n/);\n\n  if (!perLine) return lines.length;\n  return lines.map(l => Math.ceil(l.length / perLine))\n      .reduce((a, b) => a + b);\n};\n"
  },
  {
    "path": "lib/util/strip.js",
    "content": "'use strict';\n\nmodule.exports = str => {\n  const pattern = [\n    '[\\\\u001B\\\\u009B][[\\\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\\\d\\\\/#&.:=?%@~_]+)*|[a-zA-Z\\\\d]+(?:;[-a-zA-Z\\\\d\\\\/#&.:=?%@~_]*)*)?\\\\u0007)',\n    '(?:(?:\\\\d{1,4}(?:;\\\\d{0,4})*)?[\\\\dA-PRZcf-ntqry=><~]))'\n  ].join('|');\n\n  const RGX = new RegExp(pattern, 'g');\n  return typeof str === 'string' ? str.replace(RGX, '') : str;\n};\n"
  },
  {
    "path": "lib/util/style.js",
    "content": "'use strict';\n\nconst c = require('kleur');\nconst figures = require('./figures');\n\n// rendering user input.\nconst styles = Object.freeze({\n  password: { scale: 1, render: input => '*'.repeat(input.length) },\n  emoji: { scale: 2, render: input => '😃'.repeat(input.length) },\n  invisible: { scale: 0, render: input => '' },\n  default: { scale: 1, render: input => `${input}` }\n});\nconst render = type => styles[type] || styles.default;\n\n// icon to signalize a prompt.\nconst symbols = Object.freeze({\n  aborted: c.red(figures.cross),\n  done: c.green(figures.tick),\n  exited: c.yellow(figures.cross),\n  default: c.cyan('?')\n});\n\nconst symbol = (done, aborted, exited) =>\n  aborted ? symbols.aborted : exited ? symbols.exited : done ? symbols.done : symbols.default;\n\n// between the question and the user's input.\nconst delimiter = completing =>\n  c.gray(completing ? figures.ellipsis : figures.pointerSmall);\n\nconst item = (expandable, expanded) =>\n  c.gray(expandable ? (expanded ? figures.pointerSmall : '+') : figures.line);\n\nmodule.exports = {\n  styles,\n  render,\n  symbols,\n  symbol,\n  delimiter,\n  item\n};\n"
  },
  {
    "path": "lib/util/wrap.js",
    "content": "'use strict';\n\n/**\n * @param {string} msg The message to wrap\n * @param {object} opts\n * @param {number|string} [opts.margin] Left margin\n * @param {number} opts.width Maximum characters per line including the margin\n */\nmodule.exports = (msg, opts = {}) => {\n  const tab = Number.isSafeInteger(parseInt(opts.margin))\n    ? new Array(parseInt(opts.margin)).fill(' ').join('')\n    : (opts.margin || '');\n\n  const width = opts.width;\n\n  return (msg || '').split(/\\r?\\n/g)\n    .map(line => line\n      .split(/\\s+/g)\n      .reduce((arr, w) => {\n        if (w.length + tab.length >= width || arr[arr.length - 1].length + w.length + 1 < width)\n          arr[arr.length - 1] += ` ${w}`;\n        else arr.push(`${tab}${w}`);\n        return arr;\n      }, [ tab ])\n      .join('\\n'))\n    .join('\\n');\n};\n"
  },
  {
    "path": "license",
    "content": "MIT License\n\nCopyright (c) 2018 Terkel Gjervig Nielsen\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"prompts\",\n  \"version\": \"2.4.2\",\n  \"description\": \"Lightweight, beautiful and user-friendly prompts\",\n  \"license\": \"MIT\",\n  \"repository\": \"terkelg/prompts\",\n  \"main\": \"index.js\",\n  \"types\": \"index.d.ts\",\n  \"author\": {\n    \"name\": \"Terkel Gjervig\",\n    \"email\": \"terkel@terkel.com\",\n    \"url\": \"https://terkel.com\"\n  },\n  \"files\": [\n    \"lib\",\n    \"index.d.ts\",\n    \"index.js\"\n  ],\n  \"scripts\": {\n    \"start\": \"node lib/index.js\",\n    \"test\": \"tape test/*.js | tap-spec\",\n    \"test-types\": \"tsc --noEmit test/type-declarations.ts\"\n  },\n  \"keywords\": [\n    \"ui\",\n    \"prompts\",\n    \"cli\",\n    \"prompt\",\n    \"interface\",\n    \"command-line\",\n    \"input\",\n    \"command\",\n    \"stdin\",\n    \"menu\",\n    \"ask\",\n    \"interact\"\n  ],\n  \"dependencies\": {\n    \"kleur\": \"^4.0.1\",\n    \"sisteransi\": \"^1.0.5\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^18.11.17\",\n    \"tap-spec\": \"^5.0.0\",\n    \"tape\": \"^4.13.3\",\n    \"typescript\": \"^4.9.4\"\n  },\n  \"engines\": {\n    \"node\": \">= 14\"\n  }\n}\n"
  },
  {
    "path": "readme.md",
    "content": "<p align=\"center\">\n  <img src=\"https://github.com/terkelg/prompts/raw/master/prompts.png\" alt=\"Prompts\" width=\"500\" />\n</p>\n\n<h1 align=\"center\">❯ Prompts</h1>\n\n<p align=\"center\">\n  <a href=\"https://npmjs.org/package/prompts\">\n    <img src=\"https://img.shields.io/npm/v/prompts.svg\" alt=\"version\" />\n  </a>\n  <a href=\"https://github.com/terkelg/prompts/actions/workflows/test.yml\">\n    <img src=\"https://github.com/terkelg/prompts/actions/workflows/test.yml/badge.svg\" alt=\"test\" />\n  </a>\n  <a href=\"https://npmjs.org/package/prompts\">\n    <img src=\"https://img.shields.io/npm/dm/prompts.svg\" alt=\"downloads\" />\n  </a>\n  <a href=\"https://licenses.dev/npm/prompts\">\n    <img src=\"https://licenses.dev/b/npm/prompts\" alt=\"licenses\" />\n  </a>\n  <!---\n   <a href=\"https://packagephobia.now.sh/result?p=prompts\">\n    <img src=\"https://packagephobia.now.sh/badge?p=prompts\" alt=\"install size\" />\n  </a>\n  --->\n</p>\n\n<p align=\"center\">\n  <b>Lightweight, beautiful and user-friendly interactive prompts</b><br />\n  <sub>>_ Easy to use CLI prompts to enquire users for information▌</sub>\n</p>\n\n<br />\n\n* **Simple**: prompts has [no big dependencies](http://npm.anvaka.com/#/view/2d/prompts) nor is it broken into a [dozen](http://npm.anvaka.com/#/view/2d/inquirer) tiny modules that only work well together.\n* **User friendly**: prompt uses layout and colors to create beautiful cli interfaces.\n* **Promised**: uses promises and `async`/`await`. No callback hell.\n* **Flexible**: all prompts are independent and can be used on their own.\n* **Testable**: provides a way to submit answers programmatically.\n* **Unified**: consistent experience across all [prompts](#-types).\n\n\n![split](https://github.com/terkelg/prompts/raw/master/media/split.png)\n\n\n## ❯ Install\n\n```\n$ npm install --save prompts\n```\n\n> This package supports Node 14 and above\n\n![split](https://github.com/terkelg/prompts/raw/master/media/split.png)\n\n## ❯ Usage\n\n<img src=\"https://github.com/terkelg/prompts/raw/master/media/example.gif\" alt=\"example prompt\" width=\"499\" height=\"103\" />\n\n```js\nconst prompts = require('prompts');\n\n(async () => {\n  const response = await prompts({\n    type: 'number',\n    name: 'age',\n    message: 'How old are you?',\n    validate: value => value < 18 ? `Nightclub is 18+ only` : true\n  });\n\n  console.log(response); // => { age: 24 }\n})();\n```\n\n> See [`example.js`](https://github.com/terkelg/prompts/blob/master/example.js) for more options.\n\n\n![split](https://github.com/terkelg/prompts/raw/master/media/split.png)\n\n\n## ❯ Examples\n\n### Single Prompt\n\nPrompt with a single prompt object. Returns an object with the response.\n\n```js\nconst prompts = require('prompts');\n\n(async () => {\n  const response = await prompts({\n    type: 'text',\n    name: 'meaning',\n    message: 'What is the meaning of life?'\n  });\n\n  console.log(response.meaning);\n})();\n```\n\n### Prompt Chain\n\nPrompt with a list of prompt objects. Returns an object with the responses.\nMake sure to give each prompt a unique `name` property to prevent overwriting values.\n\n```js\nconst prompts = require('prompts');\n\nconst questions = [\n  {\n    type: 'text',\n    name: 'username',\n    message: 'What is your GitHub username?'\n  },\n  {\n    type: 'number',\n    name: 'age',\n    message: 'How old are you?'\n  },\n  {\n    type: 'text',\n    name: 'about',\n    message: 'Tell something about yourself',\n    initial: 'Why should I?'\n  }\n];\n\n(async () => {\n  const response = await prompts(questions);\n\n  // => response => { username, age, about }\n})();\n```\n\n### Dynamic Prompts\n\nPrompt properties can be functions too.\nPrompt Objects with `type` set to `falsy` values are skipped.\n\n```js\nconst prompts = require('prompts');\n\nconst questions = [\n  {\n    type: 'text',\n    name: 'dish',\n    message: 'Do you like pizza?'\n  },\n  {\n    type: prev => prev == 'pizza' ? 'text' : null,\n    name: 'topping',\n    message: 'Name a topping'\n  }\n];\n\n(async () => {\n  const response = await prompts(questions);\n})();\n```\n\n\n![split](https://github.com/terkelg/prompts/raw/master/media/split.png)\n\n\n## ❯ API\n\n### prompts(prompts, options)\n\nType: `Function`<br>\nReturns: `Object`\n\nPrompter function which takes your [prompt objects](#-prompt-objects) and returns an object with responses.\n\n\n#### prompts\n\nType: `Array|Object`<br>\n\nArray of [prompt objects](#-prompt-objects).\n These are the questions the user will be prompted. You can see the list of supported [prompt types here](#-types).\n\nPrompts can be submitted (<kbd>return</kbd>, <kbd>enter</kbd>) or canceled (<kbd>esc</kbd>, <kbd>abort</kbd>, <kbd>ctrl</kbd>+<kbd>c</kbd>, <kbd>ctrl</kbd>+<kbd>d</kbd>). No property is being defined on the returned response object when a prompt is canceled.\n\n#### options.onSubmit\n\nType: `Function`<br>\nDefault: `() => {}`\n\nCallback that's invoked after each prompt submission.\nIts signature is `(prompt, answer, answers)` where `prompt` is the current prompt object, `answer` the user answer to the current question and `answers` the user answers so far. Async functions are supported.\n\nReturn `true` to quit the prompt chain and return all collected responses so far, otherwise continue to iterate prompt objects.\n\n**Example:**\n```js\n(async () => {\n  const questions = [{ ... }];\n  const onSubmit = (prompt, answer) => console.log(`Thanks I got ${answer} from ${prompt.name}`);\n  const response = await prompts(questions, { onSubmit });\n})();\n```\n\n#### options.onCancel\n\nType: `Function`<br>\nDefault: `() => {}`\n\nCallback that's invoked when the user cancels/exits the prompt.\nIts signature is `(prompt, answers)` where `prompt` is the current prompt object and `answers` the user answers so far. Async functions are supported.\n\nReturn `true` to continue and prevent the prompt loop from aborting.\nOn cancel responses collected so far are returned.\n\n**Example:**\n```js\n(async () => {\n  const questions = [{ ... }];\n  const onCancel = prompt => {\n    console.log('Never stop prompting!');\n    return true;\n  }\n  const response = await prompts(questions, { onCancel });\n})();\n```\n\n### override\n\nType: `Function`\n\nPreanswer questions by passing an object with answers to `prompts.override`.\nPowerful when combined with arguments of process.\n\n**Example**\n```js\nconst prompts = require('prompts');\nprompts.override(require('yargs').argv);\n\n(async () => {\n  const response = await prompts([\n    {\n      type: 'text',\n      name: 'twitter',\n      message: `What's your twitter handle?`\n    },\n    {\n      type: 'multiselect',\n      name: 'color',\n      message: 'Pick colors',\n      choices: [\n        { title: 'Red', value: '#ff0000' },\n        { title: 'Green', value: '#00ff00' },\n        { title: 'Blue', value: '#0000ff' }\n      ],\n    }\n  ]);\n\n  console.log(response);\n})();\n```\n\n### inject(values)\n\nType: `Function`<br>\n\nProgrammatically inject responses. This enables you to prepare the responses ahead of time.\nIf any injected value is found the prompt is immediately resolved with the injected value.\nThis feature is intended for testing only.\n\n#### values\n\nType: `Array`\n\nArray with values to inject. Resolved values are removed from the internal inject array.\nEach value can be an array of values in order to provide answers for a question asked multiple times.\nIf a value is an instance of `Error` it will simulate the user cancelling/exiting the prompt.\n\n**Example:**\n```js\nconst prompts = require('prompts');\n\nprompts.inject([ '@terkelg', ['#ff0000', '#0000ff'] ]);\n\n(async () => {\n  const response = await prompts([\n    {\n      type: 'text',\n      name: 'twitter',\n      message: `What's your twitter handle?`\n    },\n    {\n      type: 'multiselect',\n      name: 'color',\n      message: 'Pick colors',\n      choices: [\n        { title: 'Red', value: '#ff0000' },\n        { title: 'Green', value: '#00ff00' },\n        { title: 'Blue', value: '#0000ff' }\n      ],\n    }\n  ]);\n\n  // => { twitter: 'terkelg', color: [ '#ff0000', '#0000ff' ] }\n})();\n```\n\n![split](https://github.com/terkelg/prompts/raw/master/media/split.png)\n\n\n## ❯ Prompt Objects\n\nPrompts Objects are JavaScript objects that define the \"questions\" and the [type of prompt](#-types).\nAlmost all prompt objects have the following properties:\n\n```js\n{\n  type: String | Function,\n  name: String | Function,\n  message: String | Function,\n  initial: String | Function | Async Function\n  format: Function | Async Function,\n  onRender: Function\n  onState: Function\n  stdin: Readable\n  stdout: Writeable\n}\n```\n\nEach property be of type `function` and will be invoked right before prompting the user.\n\nThe function signature is `(prev, values, prompt)`, where `prev` is the value from the previous prompt,\n`values` is the response object with all values collected so far and `prompt` is the previous prompt object.\n\n**Function example:**\n```js\n{\n  type: prev => prev > 3 ? 'confirm' : null,\n  name: 'confirm',\n  message: (prev, values) => `Please confirm that you eat ${values.dish} times ${prev} a day?`\n}\n```\n\nThe above prompt will be skipped if the value of the previous prompt is less than 3.\n\n### type\n\nType: `String|Function`\n\nDefines the type of prompt to display. See the list of [prompt types](#-types) for valid values.\n\nIf `type` is a falsy value the prompter will skip that question.\n```js\n{\n  type: null,\n  name: 'forgetme',\n  message: `I'll never be shown anyway`,\n}\n```\n\n### name\n\nType: `String|Function`\n\nThe response will be saved under this key/property in the returned response object.\nIn case you have multiple prompts with the same name only the latest response will be stored.\n\n> Make sure to give prompts unique names if you don't want to overwrite previous values.\n\n### message\n\nType: `String|Function`\n\nThe message to be displayed to the user.\n\n### initial\n\nType: `String|Function`\n\nOptional default prompt value. Async functions are supported too.\n\n### format\n\nType: `Function`\n\nReceive the user input and return the formatted value to be used inside the program.\nThe value returned will be added to the response object.\n\nThe function signature is `(val, values)`, where `val` is the value from the current prompt and\n`values` is the current response object in case you need to format based on previous responses.\n\n**Example:**\n```js\n{\n  type: 'number',\n  name: 'price',\n  message: 'Enter price',\n  format: val => Intl.NumberFormat(undefined, { style: 'currency', currency: 'USD' }).format(val);\n}\n```\n\n### onRender\n\nType: `Function`\n\nCallback for when the prompt is rendered.\nThe function receives [kleur](https://github.com/lukeed/kleur) as its first argument and `this` refers to the current prompt.\n\n**Example:**\n```js\n{\n  type: 'number',\n  message: 'This message will be overridden',\n  onRender(kleur) {\n    this.msg = kleur.cyan('Enter a number');\n  }\n}\n```\n\n### onState\n\nType: `Function`\n\nCallback for when the state of the current prompt changes.\nThe function signature is `(state)` where `state` is an object with a snapshot of the current state.\nThe state object has two properties `value` and `aborted`. E.g `{ value: 'This is ', aborted: false }`\n\n### stdin and stdout\n\nType: `Stream`\n\nBy default, prompts uses `process.stdin` for receiving input and `process.stdout` for writing output.\nIf you need to use different streams, for instance `process.stderr`, you can set these with the `stdin` and `stdout` properties.\n\n\n![split](https://github.com/terkelg/prompts/raw/master/media/split.png)\n\n\n## ❯ Types\n\n* [text](#textmessage-initial-style)\n* [password](#passwordmessage-initial)\n* [invisible](#invisiblemessage-initial)\n* [number](#numbermessage-initial-max-min-style)\n* [confirm](#confirmmessage-initial)\n* [list](#listmessage-initial)\n* [toggle](#togglemessage-initial-active-inactive)\n* [select](#selectmessage-choices-initial-hint-warn)\n* [multiselect](#multiselectmessage-choices-initial-max-hint-warn)\n* [autocompleteMultiselect](#multiselectmessage-choices-initial-max-hint-warn)\n* [autocomplete](#autocompletemessage-choices-initial-suggest-limit-style)\n* [date](#datemessage-initial-warn)\n\n***\n\n### text(message, [initial], [style])\n> Text prompt for free text input.\n\nHit <kbd>tab</kbd> to autocomplete to `initial` value when provided.\n\n#### Example\n<img src=\"https://github.com/terkelg/prompts/raw/master/media/text.gif\" alt=\"text prompt\" width=\"499\" height=\"103\" />\n\n```js\n{\n  type: 'text',\n  name: 'value',\n  message: `What's your twitter handle?`\n}\n```\n\n#### Options\n| Param | Type | Description |\n| ----- | :--: | ----------- |\n| message | `string` | Prompt message to display |\n| initial | `string` | Default string value |\n| style | `string` | Render style (`default`, `password`, `invisible`, `emoji`). Defaults to `default` |\n| format | `function` | Receive user input. The returned value will be added to the response object |\n| validate | `function` | Receive user input. Should return `true` if the value is valid, and an error message `String` otherwise. If `false` is returned, a default error message is shown |\n| onRender | `function` | On render callback. Keyword `this` refers to the current prompt |\n| onState | `function` | On state change callback. Function signature is an `object` with two properties: `value` and `aborted` |\n\n**↑ back to:** [Prompt types](#-types)\n\n***\n\n### password(message, [initial])\n> Password prompt with masked input.\n\nThis prompt is a similar to a prompt of type `'text'` with `style` set to `'password'`.\n\n#### Example\n<img src=\"https://github.com/terkelg/prompts/raw/master/media/password.gif\" alt=\"password prompt\" width=\"499\" height=\"103\" />\n\n```js\n{\n  type: 'password',\n  name: 'value',\n  message: 'Tell me a secret'\n}\n```\n\n#### Options\n| Param | Type | Description |\n| ----- | :--: | ----------- |\n| message | `string` | Prompt message to display |\n| initial | `string` | Default string value |\n| format | `function` | Receive user input. The returned value will be added to the response object |\n| validate | `function` | Receive user input. Should return `true` if the value is valid, and an error message `String` otherwise. If `false` is returned, a default error message is shown |\n| onRender | `function` | On render callback. Keyword `this` refers to the current prompt |\n| onState | `function` | On state change callback. Function signature is an `object` with two properties: `value` and `aborted` |\n\n**↑ back to:** [Prompt types](#-types)\n\n***\n\n### invisible(message, [initial])\n> Prompts user for invisible text input.\n\nThis prompt is working like `sudo` where the input is invisible.\nThis prompt is a similar to a prompt of type `'text'` with style set to `'invisible'`.\n\n#### Example\n<img src=\"https://github.com/terkelg/prompts/raw/master/media/invisible.gif\" alt=\"invisible prompt\" width=\"499\" height=\"103\" />\n\n```js\n{\n  type: 'invisible',\n  name: 'value',\n  message: 'Enter password'\n}\n```\n\n#### Options\n| Param | Type | Description |\n| ----- | :--: | ----------- |\n| message | `string` | Prompt message to display |\n| initial | `string` | Default string value |\n| format | `function` | Receive user input. The returned value will be added to the response object |\n| validate | `function` | Receive user input. Should return `true` if the value is valid, and an error message `String` otherwise. If `false` is returned, a default error message is shown |\n| onRender | `function` | On render callback. Keyword `this` refers to the current prompt |\n| onState | `function` | On state change callback. Function signature is an `object` with two properties: `value` and `aborted` |\n\n**↑ back to:** [Prompt types](#-types)\n\n***\n\n### number(message, initial, [max], [min], [style])\n> Prompts user for number input.\n\nYou can type in numbers and use <kbd>up</kbd>/<kbd>down</kbd> to increase/decrease the value. Only numbers are allowed as input. Hit <kbd>tab</kbd> to autocomplete to `initial` value when provided.\n\n#### Example\n<img src=\"https://github.com/terkelg/prompts/raw/master/media/number.gif\" alt=\"number prompt\" width=\"499\" height=\"103\" />\n\n```js\n{\n  type: 'number',\n  name: 'value',\n  message: 'How old are you?',\n  initial: 0,\n  style: 'default',\n  min: 2,\n  max: 10\n}\n```\n\n#### Options\n| Param | Type | Description |\n| ----- | :--: | ----------- |\n| message | `string` | Prompt message to display |\n| initial | `number` | Default number value |\n| format | `function` | Receive user input. The returned value will be added to the response object |\n| validate | `function` | Receive user input. Should return `true` if the value is valid, and an error message `String` otherwise. If `false` is returned, a default error message is shown |\n| max | `number` | Max value. Defaults to `Infinity` |\n| min | `number` | Min value. Defaults to `-infinity` |\n| float | `boolean` | Allow floating point inputs. Defaults to `false` |\n| round | `number` | Round `float` values to x decimals. Defaults to `2` |\n| increment | `number` | Increment step when using <kbd>arrow</kbd> keys. Defaults to `1` |\n| style | `string` | Render style (`default`, `password`, `invisible`, `emoji`). Defaults to `default` |\n| onRender | `function` | On render callback. Keyword `this` refers to the current prompt |\n| onState | `function` | On state change callback. Function signature is an `object` with two properties: `value` and `aborted` |\n\n**↑ back to:** [Prompt types](#-types)\n\n***\n\n### confirm(message, [initial])\n> Classic yes/no prompt.\n\nHit <kbd>y</kbd> or <kbd>n</kbd> to confirm/reject.\n\n#### Example\n<img src=\"https://github.com/terkelg/prompts/raw/master/media/confirm.gif\" alt=\"confirm prompt\" width=\"499\" height=\"103\" />\n\n```js\n{\n  type: 'confirm',\n  name: 'value',\n  message: 'Can you confirm?',\n  initial: true\n}\n```\n\n\n#### Options\n| Param | Type | Description |\n| ----- | :--: | ----------- |\n| message | `string` | Prompt message to display |\n| initial | `boolean` | Default value. Default is `false` |\n| format | `function` | Receive user input. The returned value will be added to the response object |\n| onRender | `function` | On render callback. Keyword `this` refers to the current prompt |\n| onState | `function` | On state change callback. Function signature is an `object` with two properties: `value` and `aborted` |\n\n**↑ back to:** [Prompt types](#-types)\n\n***\n\n### list(message, [initial])\n> List prompt that return an array.\n\nSimilar to the `text` prompt, but the output is an `Array` containing the\nstring separated by `separator`.\n\n```js\n{\n  type: 'list',\n  name: 'value',\n  message: 'Enter keywords',\n  initial: '',\n  separator: ','\n}\n```\n\n<img src=\"https://github.com/terkelg/prompts/raw/master/media/list.gif\" alt=\"list prompt\" width=\"499\" height=\"103\" />\n\n\n| Param | Type | Description |\n| ----- | :--: | ----------- |\n| message | `string` | Prompt message to display |\n| initial | `boolean` | Default value |\n| format | `function` | Receive user input. The returned value will be added to the response object |\n| separator | `string` | String separator. Will trim all white-spaces from start and end of string. Defaults to `','`  |\n| onRender | `function` | On render callback. Keyword `this` refers to the current prompt |\n| onState | `function` | On state change callback. Function signature is an `object` with two properties: `value` and `aborted` |\n\n**↑ back to:** [Prompt types](#-types)\n\n***\n\n### toggle(message, [initial], [active], [inactive])\n> Interactive toggle/switch prompt.\n\nUse tab or <kbd>arrow keys</kbd>/<kbd>tab</kbd>/<kbd>space</kbd> to switch between options.\n\n#### Example\n<img src=\"https://github.com/terkelg/prompts/raw/master/media/toggle.gif\" alt=\"toggle prompt\" width=\"499\" height=\"103\" />\n\n```js\n{\n  type: 'toggle',\n  name: 'value',\n  message: 'Can you confirm?',\n  initial: true,\n  active: 'yes',\n  inactive: 'no'\n}\n```\n\n#### Options\n| Param | Type | Description |\n| ----- | :--: | ----------- |\n| message | `string` | Prompt message to display |\n| initial | `boolean` | Default value. Defaults to `false` |\n| format | `function` | Receive user input. The returned value will be added to the response object |\n| active | `string` | Text for `active` state. Defaults to `'on'` |\n| inactive | `string` | Text for `inactive` state. Defaults to `'off'` |\n| onRender | `function` | On render callback. Keyword `this` refers to the current prompt |\n| onState | `function` | On state change callback. Function signature is an `object` with two properties: `value` and `aborted` |\n\n**↑ back to:** [Prompt types](#-types)\n\n***\n\n### select(message, choices, [initial], [hint], [warn])\n> Interactive select prompt.\n\nUse <kbd>up</kbd>/<kbd>down</kbd> to navigate. Use <kbd>tab</kbd> to cycle the list.\n\n#### Example\n<img src=\"https://github.com/terkelg/prompts/raw/master/media/select.gif\" alt=\"select prompt\" width=\"499\" height=\"130\" />\n\n```js\n{\n  type: 'select',\n  name: 'value',\n  message: 'Pick a color',\n  choices: [\n    { title: 'Red', description: 'This option has a description', value: '#ff0000' },\n    { title: 'Green', value: '#00ff00', disabled: true },\n    { title: 'Blue', value: '#0000ff' }\n  ],\n  initial: 1\n}\n```\n\n#### Options\n| Param | Type | Description |\n| ----- | :--: | ----------- |\n| message | `string` | Prompt message to display |\n| initial | `number` | Index of default value |\n| format | `function` | Receive user input. The returned value will be added to the response object |\n| hint | `string` | Hint to display to the user |\n| warn | `string` | Message to display when selecting a disabled option |\n| choices | `Array` | Array of strings or choices objects `[{ title, description, value, disabled }, ...]`. The choice's index in the array will be used as its value if it is not specified. |\n| onRender | `function` | On render callback. Keyword `this` refers to the current prompt |\n| onState | `function` | On state change callback. Function signature is an `object` with two properties: `value` and `aborted` |\n\n**↑ back to:** [Prompt types](#-types)\n\n***\n\n### multiselect(message, choices, [initial], [max], [hint], [warn])\n### autocompleteMultiselect(same)\n> Interactive multi-select prompt.\n> Autocomplete is a searchable multiselect prompt with the same options. Useful for long lists.\n\nUse <kbd>space</kbd> to toggle select/unselect and <kbd>up</kbd>/<kbd>down</kbd> to navigate. Use <kbd>tab</kbd> to cycle the list. You can also use <kbd>right</kbd> to select and <kbd>left</kbd> to deselect.\nBy default this prompt returns an `array` containing the **values** of the selected items - not their display title.\n\n#### Example\n<img src=\"https://github.com/terkelg/prompts/raw/master/media/multiselect.gif\" alt=\"multiselect prompt\" width=\"499\" height=\"130\" />\n\n```js\n{\n  type: 'multiselect',\n  name: 'value',\n  message: 'Pick colors',\n  choices: [\n    { title: 'Red', value: '#ff0000' },\n    { title: 'Green', value: '#00ff00', disabled: true },\n    { title: 'Blue', value: '#0000ff', selected: true }\n  ],\n  max: 2,\n  hint: '- Space to select. Return to submit'\n}\n```\n\n#### Options\n| Param | Type | Description |\n| ----- | :--: | ----------- |\n| message | `string` | Prompt message to display |\n| format | `function` | Receive user input. The returned value will be added to the response object |\n| instructions | `string` or `boolean` | Prompt instructions to display |\n| choices | `Array` | Array of strings or choices objects `[{ title, value, disabled }, ...]`. The choice's index in the array will be used as its value if it is not specified. |\n| optionsPerPage | `number` | Number of options displayed per page (default: 10) |\n| min | `number` | Min select - will display error |\n| max | `number` | Max select |\n| hint | `string` | Hint to display to the user |\n| warn | `string` | Message to display when selecting a disabled option |\n| onRender | `function` | On render callback. Keyword `this` refers to the current prompt |\n| onState | `function` | On state change callback. Function signature is an `object` with two properties: `value` and `aborted` |\n\nThis is one of the few prompts that don't take a initial value.\nIf you want to predefine selected values, give the choice object an `selected` property of `true`.\n\n**↑ back to:** [Prompt types](#-types)\n\n***\n\n### autocomplete(message, choices, [initial], [suggest], [limit], [style])\n> Interactive auto complete prompt.\n\nThe prompt will list options based on user input. Type to filter the list.\nUse <kbd>⇧</kbd>/<kbd>⇩</kbd> to navigate. Use <kbd>tab</kbd> to cycle the result. Use <kbd>Page Up</kbd>/<kbd>Page Down</kbd> (on Mac: <kbd>fn</kbd> + <kbd>⇧</kbd> / <kbd>⇩</kbd>) to change page. Hit <kbd>enter</kbd> to select the highlighted item below the prompt.\n\nThe default suggests function is sorting based on the `title` property of the choices.\nYou can overwrite how choices are being filtered by passing your own suggest function.\n\n#### Example\n<img src=\"https://github.com/terkelg/prompts/raw/master/media/autocomplete.gif\" alt=\"auto complete prompt\" width=\"499\" height=\"163\" />\n\n```js\n{\n  type: 'autocomplete',\n  name: 'value',\n  message: 'Pick your favorite actor',\n  choices: [\n    { title: 'Cage' },\n    { title: 'Clooney', value: 'silver-fox' },\n    { title: 'Gyllenhaal' },\n    { title: 'Gibson' },\n    { title: 'Grant' }\n  ]\n}\n```\n\n#### Options\n| Param | Type | Description |\n| ----- | :--: | ----------- |\n| message | `string` | Prompt message to display |\n| format | `function` | Receive user input. The returned value will be added to the response object |\n| choices | `Array` | Array of auto-complete choices objects `[{ title, value }, ...]` |\n| suggest | `function` | Filter function. Defaults to sort by `title` property. `suggest` should always return a promise. Filters using `title` by default  |\n| limit | `number` | Max number of results to show. Defaults to `10` |\n| style | `string` | Render style (`default`, `password`, `invisible`, `emoji`). Defaults to `'default'` |\n| initial | `string \\| number` | Default initial value |\n| clearFirst | `boolean` | The first ESCAPE keypress will clear the input |\n| fallback | `string` | Fallback message when no match is found. Defaults to `initial` value if provided |\n| onRender | `function` | On render callback. Keyword `this` refers to the current prompt |\n| onState | `function` | On state change callback. Function signature is an `object` with three properties: `value`, `aborted` and `exited` |\n\nExample on what a `suggest` function might look like:\n```js\nconst suggestByTitle = (input, choices) =>\n    Promise.resolve(choices.filter(i => i.title.slice(0, input.length) === input))\n```\n\n**↑ back to:** [Prompt types](#-types)\n\n***\n\n### date(message, [initial], [warn])\n> Interactive date prompt.\n\nUse <kbd>left</kbd>/<kbd>right</kbd>/<kbd>tab</kbd> to navigate. Use <kbd>up</kbd>/<kbd>down</kbd> to change date.\n\n#### Example\n<img src=\"https://github.com/terkelg/prompts/raw/master/media/date.gif\" alt=\"date prompt\" width=\"499\" height=\"103\" />\n\n```js\n{\n  type: 'date',\n  name: 'value',\n  message: 'Pick a date',\n  initial: new Date(1997, 09, 12),\n  validate: date => date > Date.now() ? 'Not in the future' : true\n}\n```\n\n#### Options\n| Param | Type | Description |\n| ----- | :--: | ----------- |\n| message | `string` | Prompt message to display |\n| initial | `date` | Default date |\n| locales | `object` | Use to define custom locales. See below for an example. |\n| mask | `string` | The format mask of the date. See below for more information.<br />Default: `YYYY-MM-DD HH:mm:ss` |\n| validate | `function` | Receive user input. Should return `true` if the value is valid, and an error message `String` otherwise. If `false` is returned, a default error message is shown |\n| onRender | `function` | On render callback. Keyword `this` refers to the current prompt |\n| onState | `function` | On state change callback. Function signature is an `object` with two properties: `value` and `aborted` |\n\nDefault locales:\n\n```javascript\n{\n  months: [\n    'January', 'February', 'March', 'April',\n    'May', 'June', 'July', 'August',\n    'September', 'October', 'November', 'December'\n  ],\n  monthsShort: [\n    'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n    'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'\n  ],\n  weekdays: [\n    'Sunday', 'Monday', 'Tuesday', 'Wednesday',\n    'Thursday', 'Friday', 'Saturday'\n  ],\n  weekdaysShort: [\n    'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'\n  ]\n}\n```\n>**Formatting**: See full list of formatting options in the [wiki](https://github.com/terkelg/prompts/wiki/Date-Time-Formatting)\n\n![split](https://github.com/terkelg/prompts/raw/master/media/split.png)\n\n**↑ back to:** [Prompt types](#-types)\n\n***\n\n## ❯ Credit\nMany of the prompts are based on the work of [derhuerst](https://github.com/derhuerst).\n\n\n## ❯ License\n\nMIT © [Terkel Gjervig](https://terkel.com)\n"
  },
  {
    "path": "test/prompts.js",
    "content": "'use strict';\n\nconst test = require('tape');\nconst prompt = require('../');\nconst { prompts } = prompt;\n\ntest('basics', t => {\n  t.plan(4);\n  t.equal(typeof prompts, 'object');\n  t.equal(typeof prompt, 'function');\n  t.equal(typeof prompt.prompt, 'function');\n  t.equal(typeof prompt.inject, 'function');\n});\n\ntest('prompts', t => {\n  t.plan(25);\n\n  const types = [\n    'text',\n    'password',\n    'invisible',\n    'number',\n    'confirm',\n    'list',\n    'toggle',\n    'select',\n    'multiselect',\n    'autocompleteMultiselect',\n    'autocomplete',\n    'date'\n  ];\n\n  types.forEach(p => {\n    t.true(p in prompts, `${prompts[p].name} exists`);\n    t.equal(typeof prompts[p], 'function', `${prompts[p].name} is typeof function`);\n  });\n\n  t.equal(Object.keys(prompts).length, types.length, 'all prompts are exported');\n});\n\ntest('injects', t => {\n  let injected = [ 1, 2, 3 ];\n  prompt.inject(injected);\n  t.same(prompt._injected, injected, 'injects array of answers');\n\n  prompt({ type: 'text', name:'a', message: 'a message' })\n    .then(foo => {\n      t.same(foo, { a:1 }, 'immediately returns object with injected answer');\n      t.same(prompt._injected, [ 2, 3 ], 'deletes the first answer from internal array');\n\n      prompt([{ type: 'text', name:'b', message: 'b message' }, { type: 'text', name:'c', message: 'c message' }])\n        .then(bar => {\n          t.same(bar, { b:2, c:3 }, 'immediately handles two prompts at once');\n          t.same(prompt._injected, [], 'leaves behind empty internal array when exhausted');\n          t.end();\n        });\n    });\n});\n"
  },
  {
    "path": "test/text.js",
    "content": "'use strict';\n\nconst test = require('tape');\nconst TextPrompt = require('../lib/elements/text');\n\ntest('move', (t) => {\n  t.plan(6);\n\n  const textPrompt = new TextPrompt();\n  textPrompt.value = 'Hello, world!';\n  textPrompt.last()\n  textPrompt.render()\n\n  t.same(textPrompt.cursorOffset, 0, 'cursorOffset is 0 at start');\n  t.same(textPrompt.cursor, textPrompt.rendered.length, 'cursor starts at 0')\n\n  textPrompt.right();\n  t.same(textPrompt.cursorOffset, 0, 'cursorOffset is unaffected when moved right from the end');\n  t.same(textPrompt.cursor, textPrompt.rendered.length, 'cursor is unaffected when moved right from the end')\n\n  textPrompt.left();\n  t.equal(textPrompt.cursorOffset, -1, 'cursorOffset is -1 when moved left');\n\n  textPrompt.right();\n  t.equal(textPrompt.cursorOffset, 0, 'cursorOffset is 0 when moved left');\n\n  t.end();\n});\n\ntest('delete', (t) => {\n  t.plan(4);\n\n  const textPrompt = new TextPrompt();\n  textPrompt.value = 'Hello, world!';\n  textPrompt.last();\n  textPrompt.render();\n\n  textPrompt.delete();\n  t.same(textPrompt.cursorOffset, 0, 'cursorOffset is 0 after delete');\n  t.same(textPrompt.cursor, textPrompt.rendered.length, 'cursor stays at end of line')\n\n  textPrompt.left();\n  textPrompt.deleteForward()\n  t.same(textPrompt.cursorOffset, 0, 'cursorOffset is 0 after deleteForward');\n  t.same(textPrompt.cursor, textPrompt.rendered.length, 'cursor stays at end of line')\n\n  textPrompt.submit();\n  t.end()\n});\n\ntest('submit', (t) => {\n  t.plan(2)\n  const textPrompt = new TextPrompt();\n  textPrompt.value = 'Hello, world!';\n  textPrompt.submit()\n\n  t.same(textPrompt.cursorOffset, 0, 'cursorOffset is reset on submit')\n  t.same(textPrompt.cursor, textPrompt.rendered.length, 'cursor is reset to end of line on submit')\n})\n"
  },
  {
    "path": "test/type-declarations.ts",
    "content": "import * as prompts from '../index';\n\ntype HasProperty<T, K> = K extends keyof T ? true : false;\n\n(async () => {\n\tconst response = await prompts({\n\t\ttype: 'number',\n\t\tname: 'value',\n\t\tmessage: 'Input value to double:',\n\t\tvalidate: (value: any) => (value < 0 ? `Cant be less than zero` : true),\n\t});\n\tconst HasPropValue: HasProperty<typeof response, 'value'> = true;\n\tconst DoesntHavePropAsdf: HasProperty<typeof response, 'asdf'> = false;\n})();\n\n(async () => {\n\tawait prompts([\n\t\t{\n\t\t\ttype: 'text',\n\t\t\tname: 'language',\n\t\t\tmessage: 'What langauge is the next greatest thing since sliced bread?',\n\t\t},\n\t\t{\n\t\t\ttype: (prev, values) => {\n\t\t\t\tconst HasPromptName: HasProperty<typeof values, 'language'> = true;\n\t\t\t\tconst DoesntHavePromptTypes: HasProperty<typeof values, 'text'> = false;\n\n\t\t\t\treturn prev === 'javascript' ? 'confirm' : null;\n\t\t\t},\n\t\t\tname: 'confirmation',\n\t\t\tmessage: 'Have you tried TypeScript?',\n\t\t},\n\t\t{\n\t\t\ttype: 'select',\n\t\t\tname: 'so-many-options',\n\t\t\tmessage: 'options, options!!',\n\t\t\tchoices: [\n\t\t\t\t{\n\t\t\t\t\ttitle: 'A',\n\t\t\t\t\tvalue: 'A',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttitle: 'B',\n\t\t\t\t\tvalue: { foo: 'bar' },\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttitle: 'C',\n\t\t\t\t\tvalue: 'C',\n\t\t\t\t\tdisabled: false,\n\t\t\t\t\tselected: false,\n\t\t\t\t\tdescription: 'a description',\n\t\t\t\t},\n\t\t\t],\n\t\t\twarn: 'Warning, option is disabled'\n\t\t},\n\t\t{\n\t\t\ttype: 'multiselect',\n\t\t\tname: 'choices',\n\t\t\tmessage: `why don't we have both?`,\n\t\t\tinstructions: false,\n\t\t\tchoices: [\n\t\t\t\t{\n\t\t\t\t\tvalue: 'A',\n\t\t\t\t\ttitle: 'A',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tvalue: 'B',\n\t\t\t\t\ttitle: 'B',\n\t\t\t\t},\n\t\t\t],\n\t\t\twarn: 'Warning, option is disabled'\n\t\t},\n\t]);\n})();\n\n(async () => {\n\tawait prompts([\n\t\t{\n\t\t\ttype: 'select',\n\t\t\tname: 'choices',\n\t\t\tinstructions: false,\n\t\t\tmessage: 'options, options!!',\n\t\t\tchoices: [\n\t\t\t\t{\n\t\t\t\t\tvalue: 'A',\n\t\t\t\t\ttitle: 'A',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttitle: 'B',\n\t\t\t\t},\n\t\t\t],\n\t\t\twarn: 'Warning, option is disabled'\n\t\t},\n\t\t{\n\t\t\ttype: 'select',\n\t\t\tname: 'subchoices',\n\t\t\tmessage: 'optionception!',\n\t\t\tchoices: (prev) => {\n\t\t\t\treturn [\n\t\t\t\t\t{\n\t\t\t\t\t\tvalue: prev + 'A',\n\t\t\t\t\t\ttitle: prev + 'A',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvalue: prev + 'B',\n\t\t\t\t\t\ttitle: prev + 'B',\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t},\n\t\t},\n\t]);\n})();\n\n// test for PromptObject.initial\n(async () => {\n\tawait prompts({\n\t\ttype: 'text',\n\t\tname: 'value',\n\t\tmessage: 'string',\n\t\tinitial: 'string'\n\t});\n\n\tawait prompts({\n\t\ttype: 'number',\n\t\tname: 'value',\n\t\tmessage: 'number',\n\t\tinitial: 0\n\t});\n\n\tawait prompts({\n\t\ttype: 'confirm',\n\t\tname: 'value',\n\t\tmessage: 'boolean',\n\t\tinitial: true\n\t});\n\n\tawait prompts({\n\t\ttype: 'date',\n\t\tname: 'value',\n\t\tmessage: 'date',\n\t\tinitial: new Date()\n\t});\n\n\tawait prompts({\n\t\ttype: 'text',\n\t\tname: 'value',\n\t\tmessage: 'function => string',\n\t\tinitial: () => 'initial value'\n\t});\n\n\tawait prompts({\n\t\ttype: 'number',\n\t\tname: 'value',\n\t\tmessage: 'function => number',\n\t\tinitial: () => 1\n\t});\n\n\tawait prompts({\n\t\ttype: 'confirm',\n\t\tname: 'value',\n\t\tmessage: 'function => boolean',\n\t\tinitial: () => true\n\t});\n\n\tawait prompts({\n\t\ttype: 'date',\n\t\tname: 'value',\n\t\tmessage: 'function => date',\n\t\tinitial: () => new Date()\n\t});\n\n\tawait prompts({\n\t\ttype: 'date',\n\t\tname: 'value',\n\t\tmessage: 'function => date',\n\t\tinitial: () => new Date()\n\t});\n\n\tawait prompts({\n\t\ttype: 'text',\n\t\tname: 'value',\n\t\tmessage: 'async function => string',\n\t\tinitial: async () => 'initial value'\n\t});\n\n\tawait prompts({\n\t\ttype: 'number',\n\t\tname: 'value',\n\t\tmessage: 'async function => number',\n\t\tinitial: async () => 1\n\t});\n\n\tawait prompts({\n\t\ttype: 'confirm',\n\t\tname: 'value',\n\t\tmessage: 'async function => boolean',\n\t\tinitial: async () => true\n\t});\n\n\tawait prompts({\n\t\ttype: 'date',\n\t\tname: 'value',\n\t\tmessage: 'async function => date',\n\t\tinitial: async () => new Date()\n\t});\n})();\n"
  },
  {
    "path": "test/util.js",
    "content": "'use strict';\n\nconst test = require('tape');\nconst { entriesToDisplay } = require('../lib/util');\n\ntest('entriesToDisplay', t => {\n  t.plan(11);\n  t.deepEqual(entriesToDisplay(0, 8, 5), { startIndex: 0, endIndex: 5 }, 'top of list');\n  t.deepEqual(entriesToDisplay(1, 8, 5), { startIndex: 0, endIndex: 5 }, '+1 from top');\n  t.deepEqual(entriesToDisplay(2, 8, 5), { startIndex: 0, endIndex: 5 }, '+2 from top');\n  t.deepEqual(entriesToDisplay(3, 8, 5), { startIndex: 1, endIndex: 6 }, '+3 from top');\n  t.deepEqual(entriesToDisplay(4, 8, 5), { startIndex: 2, endIndex: 7 }, '-3 from bottom');\n  t.deepEqual(entriesToDisplay(5, 8, 5), { startIndex: 3, endIndex: 8 }, '-2 from bottom');\n  t.deepEqual(entriesToDisplay(6, 8, 5), { startIndex: 3, endIndex: 8 }, '-1 from bottom');\n  t.deepEqual(entriesToDisplay(7, 8, 5), { startIndex: 3, endIndex: 8 }, 'bottom of list');\n\n  t.deepEqual(entriesToDisplay(0, 10, 11), { startIndex: 0, endIndex: 10 }, 'top of list when maxVisible greater than total');\n  t.deepEqual(entriesToDisplay(9, 10, 11), { startIndex: 0, endIndex: 10 }, 'bottom of list maxVisible greater than total');\n\n  t.deepEqual(entriesToDisplay(0, 10), { startIndex: 0, endIndex:10 }, 'maxVisible is optional');\n});\n"
  }
]