'use strict'; const _ = require('lodash'); const inquirer = require('inquirer'); const diff = require('diff'); const chalk = require('chalk'); const logger = require('./util/log'); class TerminalAdapter { /** * `TerminalAdapter` is the default implementation of `Adapter`, an abstraction * layer that defines the I/O interactions. * * It provides a CLI interaction * * @constructor * @param {Object} [options] * @param {Console} [options.console] */ constructor(options = {}) { const stdout = options.stdout || process.stdout; const stderr = options.stderr || options.stdout || process.stderr; this.promptModule = inquirer.createPromptModule({skipTTYChecks: true, input: options.stdin, output: stdout}); this.console = options.console || new console.Console(stdout, stderr); this.log = logger({console: this.console, stdout: options.stdout}); } get _colorDiffAdded() { return chalk.black.bgGreen; } get _colorDiffRemoved() { return chalk.bgRed; } _colorLines(name, str) { return str.split('\n').map(line => this[`_colorDiff${name}`](line)).join('\n'); } /** * Prompt a user for one or more questions and pass * the answer(s) to the provided callback. * * It shares its interface with `Base.prompt` * * (Defined inside the constructor to keep interfaces separated between * instances) * * @param {Object|Object[]} questions * @param {Object} [answers] Answers to be passed to inquirer * @param {Function} [callback] callback */ prompt(questions, answers, cb) { if (typeof answers === 'function') { cb = answers; answers = undefined; } const promise = this.promptModule(questions, answers); promise.then(cb || _.noop); return promise; } /** * Shows a color-based diff of two strings * * @param {string} actual * @param {string} expected * @param {Array} changes returned by diff. */ diff(actual, expected, changes) { if (Array.isArray(actual)) { changes = actual; } changes = changes || diff.diffLines(actual, expected); let msg = changes.map(str => { if (str.added) { return this._colorLines('Added', str.value); } if (str.removed) { return this._colorLines('Removed', str.value); } return str.value; }).join(''); // Legend msg = '\n' + this._colorDiffRemoved('removed') + ' ' + this._colorDiffAdded('added') + '\n\n' + msg + '\n'; this.console.log(msg); return msg; } } module.exports = TerminalAdapter;