Spaces:
Runtime error
Runtime error
; | |
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; | |