123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- '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;
|