'use strict';
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});
this.tracker = logger.tracker;
}
get _colorDiffAdded() {
return chalk.black.bgGreen;
}
get _colorDiffRemoved() {
return chalk.bgRed;
}
_colorLines(name, string) {
return string.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} [cb] Deprecated: callback for backward compatibility.
* @return {Object} promise answers
*/
prompt(questions, answers, cb) {
if (typeof answers === 'function') {
cb = answers;
answers = undefined;
}
const promise = this.promptModule(questions, answers);
if (typeof cb === 'function') {
promise.then(answers => cb(answers));
}
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 message = changes.map(string => {
if (string.added) {
return this._colorLines('Added', string.value);
}
if (string.removed) {
return this._colorLines('Removed', string.value);
}
return string.value;
}).join('');
// Legend
message = '\n' +
this._colorDiffRemoved('removed') +
' ' +
this._colorDiffAdded('added') +
'\n\n' +
message +
'\n';
this.console.log(message);
return message;
}
}
module.exports = TerminalAdapter;