UNPKG

pyr

Version:

A package for creating a script to store and run your most commonly used CLI commands

292 lines (263 loc) 8.41 kB
#!/usr/bin/env node const chalk = require('chalk'); const noop = require('lodash/noop'); const { ADD_COMMAND, Modification } = require('src/constants'); const { GlobalConfig } = require('src/config'); const { Script, Command, Directory } = require('src/config/script'); const { containsWhitespace, replaceWhitespace, isEmptyString, safeExit } = require('src/utility'); const { print, ERROR, MESSAGE } = require('src/messages'); const { prompts, inquirerPrompts } = require('src/shims/inquirer'); const CommandAdder = require('src/command-adder'); const Menu = require('src/menu'); const Operation = require('src/program/operations/operation'); const MAX_EXPECTED_ARGUMENTS_LENGTH = 1; const addCommandToOptionChoices = ({ script, optionKey, answers }) => { const option = script.getOption(optionKey); const choices = option.getChoices(); if (!choices.includes(answers.name)) { let index; if (choices.indexOf('back') > -1) { index = choices.indexOf('back'); } else { index = choices.indexOf('quit'); } choices.splice(index, 0, answers.name); } option.updateChoices(choices); } const addCommand = ({ script, optionKey, commandKey, command, answers }) => { script.addCommand({ commandKey: commandKey, command: command }); if (answers.path) { const directory = new Directory(answers.path); script.updateDirectory({ directoryKey: commandKey, directory: directory }); } addCommandToOptionChoices({ script: script, optionKey: optionKey, answers: answers }); GlobalConfig.save(); print(MESSAGE, 'savedNewCommand', answers.name, script.getName()); } const getUpdateCommandPrompt = (answers) => { let prompt = `Replace ${chalk.magenta.bold(answers.name)} with ${chalk.magenta.bold(answers.directive)} command`; if (!isEmptyString(answers.message) && isEmptyString(answers.path)) { prompt += ` and ${chalk.magenta.bold(answers.message)} message?`; } else if (isEmptyString(answers.message) && !isEmptyString(answers.path)) { prompt += ` and ${chalk.magenta.bold(answers.path)} directory?`; } else if (!isEmptyString(answers.message) && !isEmptyString(answers.path)) { prompt += `, ${chalk.magenta.bold(answers.message)} message and ${chalk.magenta.bold(answers.path)} directory?`; } return prompt; } const updateCommand = ({ prompts, script, optionKey, commandKey, command, answers }) => { const promptsSubscription = prompts.subscribe(({ answer }) => { if (answer) { script.updateCommand({ commandKey: commandKey, command: command }); if (answers.path) { const directory = new Directory(answers.path); script.updateDirectory({ directoryKey: commandKey, directory: directory }); } addCommandToOptionChoices({ script: script, optionKey: optionKey, answers: answers }); GlobalConfig.save(); print(MESSAGE, 'replacedCommand', answers.name, answers.directive); } else { print(MESSAGE, 'didNotReplaceCommand', answers.name, answers.directive); } promptsSubscription.unsubscribe(); prompts.complete(); }, noop, noop); // add's a new line before the question asking user if they want to update command is printed console.log(''); prompts.next({ type: 'confirm', name: 'confirm-replace-command', message: getUpdateCommandPrompt(answers) }); } const addNewCommand = ({ script, optionKey }) => { const commandAdder = new CommandAdder(); // add's a new line before the questions asking user to describe new command print(MESSAGE, 'addingCommandTitle'); const promptsSubscription = inquirerPrompts.subscribe(({ answer }) => { commandAdder.nextAnswer(answer); const question = commandAdder.nextQuestion(); if (question) { inquirerPrompts.next(question); } else { promptsSubscription.unsubscribe(); const key = commandAdder.answers.name; if (containsWhitespace(key)) { key = replaceWhitespace(key, '.'); } const commandKey = `${optionKey}.${key}`; const command = new Command({ directive: commandAdder.answers.directive, message: commandAdder.answers.message, }); if (script.getCommand(commandKey)) { updateCommand({ prompts: prompts, script: script, optionKey: optionKey, commandKey: commandKey, command: command, answers: commandAdder.answers }); } else { addCommand({ script: script, optionKey: optionKey, commandKey: commandKey, command: command, answers: commandAdder.answers }); } inquirerPrompts.complete(); } }, (err) => { console.warn(err); }, () => {}); inquirerPrompts.next(commandAdder.nextQuestion()); } const getOptionChoicesWithAddingChoices = (script, optionKey) => { const choices = script.getOption(optionKey).getChoices(); let index; if (choices.indexOf('back') > -1) { index = choices.indexOf('back'); } else { index = choices.indexOf('quit'); } // Append adding commands just before `back` and `quit` choices.splice(index, 0, ADD_COMMAND); return choices; } const getOptionChoicesWithoutCommands = (script, optionKey) => { const choices = script.getOption(optionKey).getChoices(); return choices.filter(choice => { const key = choice; if (containsWhitespace(key)) { key = replaceWhitespace(key); } return !script.getCommand(`${optionKey}.${key}`); }); } const getScriptModifiedForAdding = script => { const copiedScript = Script.copy(script); for (optionKey in copiedScript.getOptions()) { const option = copiedScript.getOption(optionKey); const modifiedMessage = `Add a ${chalk.magenta.bold('command')} to ${chalk.cyan.bold(option.getMessage())}`; option.updateMessage(modifiedMessage); option.updateChoices(getOptionChoicesWithoutCommands(copiedScript, optionKey)); option.updateChoices(getOptionChoicesWithAddingChoices(copiedScript, optionKey)) } return copiedScript; } const handler = args => { GlobalConfig.load(); if (Object.keys(GlobalConfig.getScripts()).length === 0) { print(ERROR, 'noSavedScripts'); safeExit(); } else if (args.length === 0) { const menu = new Menu({ operationName: operation.name, operationRun: operation.run }); menu.run(); } else { const scriptName = args[0]; GlobalConfig.load(); const script = GlobalConfig.getScript(scriptName); if (script) { const scriptModifiedForAdding = getScriptModifiedForAdding(script); print(MESSAGE, 'runningScriptInModifyMode', scriptName); const promise = scriptModifiedForAdding.run(); promise.then(({ modification, optionKey }) => { if (modification === Modification.ADD_COMMAND) { addNewCommand({ script: script, optionKey: optionKey }); } }); } else { print(ERROR, 'scriptDoesNotExist', scriptName); } } }; const operation = { name: 'modify', flag: 'm', description: 'modify a previously saved script', args: [{ name: 'script name', required: false }], whitelist: [], run: handler }; module.exports = new Operation(operation);