| 'use strict'; | 
|   | 
| const colors = require('ansi-colors'); | 
| const interpolate = require('../interpolate'); | 
| const Prompt = require('../prompt'); | 
|   | 
| class SnippetPrompt extends Prompt { | 
|   constructor(options) { | 
|     super(options); | 
|     this.cursorHide(); | 
|     this.reset(true); | 
|   } | 
|   | 
|   async initialize() { | 
|     this.interpolate = await interpolate(this); | 
|     await super.initialize(); | 
|   } | 
|   | 
|   async reset(first) { | 
|     this.state.keys = []; | 
|     this.state.invalid = new Map(); | 
|     this.state.missing = new Set(); | 
|     this.state.completed = 0; | 
|     this.state.values = {}; | 
|   | 
|     if (first !== true) { | 
|       await this.initialize(); | 
|       await this.render(); | 
|     } | 
|   } | 
|   | 
|   moveCursor(n) { | 
|     let item = this.getItem(); | 
|     this.cursor += n; | 
|     item.cursor += n; | 
|   } | 
|   | 
|   dispatch(ch, key) { | 
|     if (!key.code && !key.ctrl && ch != null && this.getItem()) { | 
|       this.append(ch, key); | 
|       return; | 
|     } | 
|     this.alert(); | 
|   } | 
|   | 
|   append(ch, key) { | 
|     let item = this.getItem(); | 
|     let prefix = item.input.slice(0, this.cursor); | 
|     let suffix = item.input.slice(this.cursor); | 
|     this.input = item.input = `${prefix}${ch}${suffix}`; | 
|     this.moveCursor(1); | 
|     this.render(); | 
|   } | 
|   | 
|   delete() { | 
|     let item = this.getItem(); | 
|     if (this.cursor <= 0 || !item.input) return this.alert(); | 
|     let suffix = item.input.slice(this.cursor); | 
|     let prefix = item.input.slice(0, this.cursor - 1); | 
|     this.input = item.input = `${prefix}${suffix}`; | 
|     this.moveCursor(-1); | 
|     this.render(); | 
|   } | 
|   | 
|   increment(i) { | 
|     return i >= this.state.keys.length - 1 ? 0 : i + 1; | 
|   } | 
|   | 
|   decrement(i) { | 
|     return i <= 0 ? this.state.keys.length - 1 : i - 1; | 
|   } | 
|   | 
|   first() { | 
|     this.state.index = 0; | 
|     this.render(); | 
|   } | 
|   | 
|   last() { | 
|     this.state.index = this.state.keys.length - 1; | 
|     this.render(); | 
|   } | 
|   | 
|   right() { | 
|     if (this.cursor >= this.input.length) return this.alert(); | 
|     this.moveCursor(1); | 
|     this.render(); | 
|   } | 
|   | 
|   left() { | 
|     if (this.cursor <= 0) return this.alert(); | 
|     this.moveCursor(-1); | 
|     this.render(); | 
|   } | 
|   | 
|   prev() { | 
|     this.state.index = this.decrement(this.state.index); | 
|     this.getItem(); | 
|     this.render(); | 
|   } | 
|   | 
|   next() { | 
|     this.state.index = this.increment(this.state.index); | 
|     this.getItem(); | 
|     this.render(); | 
|   } | 
|   | 
|   up() { | 
|     this.prev(); | 
|   } | 
|   | 
|   down() { | 
|     this.next(); | 
|   } | 
|   | 
|   format(value) { | 
|     let color = this.state.completed < 100 ? this.styles.warning : this.styles.success; | 
|     if (this.state.submitted === true && this.state.completed !== 100) { | 
|       color = this.styles.danger; | 
|     } | 
|     return color(`${this.state.completed}% completed`); | 
|   } | 
|   | 
|   async render() { | 
|     let { index, keys = [], submitted, size } = this.state; | 
|   | 
|     let newline = [this.options.newline, '\n'].find(v => v != null); | 
|     let prefix = await this.prefix(); | 
|     let separator = await this.separator(); | 
|     let message = await this.message(); | 
|   | 
|     let prompt = [prefix, message, separator].filter(Boolean).join(' '); | 
|     this.state.prompt = prompt; | 
|   | 
|     let header = await this.header(); | 
|     let error = (await this.error()) || ''; | 
|     let hint = (await this.hint()) || ''; | 
|     let body = submitted ? '' : await this.interpolate(this.state); | 
|   | 
|     let key = this.state.key = keys[index] || ''; | 
|     let input = await this.format(key); | 
|     let footer = await this.footer(); | 
|     if (input) prompt += ' ' + input; | 
|     if (hint && !input && this.state.completed === 0) prompt += ' ' + hint; | 
|   | 
|     this.clear(size); | 
|     let lines = [header, prompt, body, footer, error.trim()]; | 
|     this.write(lines.filter(Boolean).join(newline)); | 
|     this.restore(); | 
|   } | 
|   | 
|   getItem(name) { | 
|     let { items, keys, index } = this.state; | 
|     let item = items.find(ch => ch.name === keys[index]); | 
|     if (item && item.input != null) { | 
|       this.input = item.input; | 
|       this.cursor = item.cursor; | 
|     } | 
|     return item; | 
|   } | 
|   | 
|   async submit() { | 
|     if (typeof this.interpolate !== 'function') await this.initialize(); | 
|     await this.interpolate(this.state, true); | 
|   | 
|     let { invalid, missing, output, values } = this.state; | 
|     if (invalid.size) { | 
|       let err = ''; | 
|       for (let [key, value] of invalid) err += `Invalid ${key}: ${value}\n`; | 
|       this.state.error = err; | 
|       return super.submit(); | 
|     } | 
|   | 
|     if (missing.size) { | 
|       this.state.error = 'Required: ' + [...missing.keys()].join(', '); | 
|       return super.submit(); | 
|     } | 
|   | 
|     let lines = colors.unstyle(output).split('\n'); | 
|     let result = lines.map(v => v.slice(1)).join('\n'); | 
|     this.value = { values, result }; | 
|     return super.submit(); | 
|   } | 
| } | 
|   | 
| module.exports = SnippetPrompt; |