diff --git a/lib/LimitWarningInputPrompt.js b/lib/LimitWarningInputPrompt.js new file mode 100644 index 00000000..38ded29c --- /dev/null +++ b/lib/LimitWarningInputPrompt.js @@ -0,0 +1,18 @@ +const LimitedInputPrompt = require('./LimitedInputPrompt'); + +class LimitWarningInputPrompt extends LimitedInputPrompt { + // eslint-disable-next-line class-methods-use-this + generateSpacer () { + return 'No limit mode'; + } + + onKeypress () { + this.render(); + } + + getCharsLeftPlainText () { + return `${this.leadingLength + this.rl.line.length}/${this.opt.maxLength}`; + } +} + +module.exports = LimitWarningInputPrompt; diff --git a/lib/LimitedInputPrompt.js b/lib/LimitedInputPrompt.js index 97d63aad..1cc571c8 100644 --- a/lib/LimitedInputPrompt.js +++ b/lib/LimitedInputPrompt.js @@ -9,7 +9,7 @@ class LimitedInputPrompt extends InputPrompt { this.throwParamError('maxLength'); } this.originalMessage = this.opt.message; - this.spacer = new Array(this.opt.maxLength).fill('-').join(''); + this.spacer = this.generateSpacer(); if (this.opt.leadingLabel) { if (typeof this.opt.leadingLabel === 'function') { @@ -24,6 +24,10 @@ class LimitedInputPrompt extends InputPrompt { this.leadingLength = this.leadingLabel.length; } + generateSpacer () { + return new Array(this.opt.maxLength).fill('-').join(''); + } + remainingChar () { return this.opt.maxLength - this.leadingLength - this.rl.line.length; } @@ -39,16 +43,22 @@ class LimitedInputPrompt extends InputPrompt { getCharsLeftText () { const chars = this.remainingChar(); + const text = this.getCharsLeftPlainText(chars); if (chars > 15) { - return chalk.green(`${chars} chars left`); + return chalk.green(text); } else if (chars > 5) { - return chalk.yellow(`${chars} chars left`); + return chalk.yellow(text); } else { - return chalk.red(`${chars} chars left`); + return chalk.red(text); } } + // eslint-disable-next-line class-methods-use-this + getCharsLeftPlainText (chars) { + return `${chars} chars left`; + } + render (error) { let bottomContent = ''; let message = this.getQuestion(); diff --git a/lib/cli.js b/lib/cli.js index c3d7b5d6..80aa9876 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -9,6 +9,7 @@ const runInteractiveQuestions = require('./runInteractiveQuestions'); const runNonInteractiveMode = require('./runNonInteractiveMode'); const formatCommitMessage = require('./formatCommitMessage'); const getGitDir = require('./util/getGitDir'); +const ObjectBuilder = require('./util/ObjectBuilder'); // eslint-disable-next-line no-process-env const executeCommand = (command, env = process.env) => { @@ -31,11 +32,12 @@ const main = async () => { let state = null; - if (cliOptions.disableEmoji) { - state = createState({disableEmoji: cliOptions.disableEmoji}); - } else { - state = createState(); - } + const configFromFlags = new ObjectBuilder() + .if(cliOptions.disableEmoji).add({disableEmoji: true}) + .if(cliOptions.nonLimit).add({withoutLimit: true}) + .build(); + + state = createState(configFromFlags); if (cliOptions.dryRun) { // eslint-disable-next-line no-console diff --git a/lib/parseArgs.js b/lib/parseArgs.js index 503171c1..92cc5880 100644 --- a/lib/parseArgs.js +++ b/lib/parseArgs.js @@ -15,6 +15,7 @@ const helpScreen = ` --disable-emoji don't add emoji to commit title --format custom formatting options for subject --non-interactive run git-cz in non-interactive mode + --non-limit allow the subject to have any length non-interactive mode options: --type type of the commit, defaults to "chore" @@ -39,6 +40,7 @@ const parseArgs = () => { breaking, issues, lerna, + 'non-limit': nonLimit, scope, subject, type, @@ -58,7 +60,8 @@ const parseArgs = () => { 'disable-emoji', 'non-interactive', 'hook', - 'dry-run' + 'dry-run', + 'non-limit' ], string: [ 'format', @@ -89,6 +92,7 @@ const parseArgs = () => { help, hook, nonInteractive, + nonLimit, version }; diff --git a/lib/questions/subject.js b/lib/questions/subject.js index 26de39b4..567df04b 100644 --- a/lib/questions/subject.js +++ b/lib/questions/subject.js @@ -26,7 +26,7 @@ exports.createQuestion = (state) => { maxLength: config.maxMessageLength - 3, message: 'Write a short, imperative mood description of the change:', name: 'subject', - type: 'limitedInput', + type: config.withoutLimit ? 'limitWarningInput' : 'limitedInput', validate: (input) => input.length >= config.minMessageLength || minTitleLengthErrorMessage }; diff --git a/lib/runInteractiveQuestions.js b/lib/runInteractiveQuestions.js index c3d4075d..9021830c 100644 --- a/lib/runInteractiveQuestions.js +++ b/lib/runInteractiveQuestions.js @@ -1,9 +1,11 @@ const inquirer = require('inquirer'); const AutocompletePrompt = require('inquirer-list-search-prompt'); const LimitedInputPrompt = require('./LimitedInputPrompt'); +const LimitWarningInputPrompt = require('./LimitWarningInputPrompt'); const createQuestions = require('./createQuestions'); inquirer.registerPrompt('limitedInput', LimitedInputPrompt); +inquirer.registerPrompt('limitWarningInput', LimitWarningInputPrompt); inquirer.registerPrompt('autocomplete', AutocompletePrompt); // if (IS_LERNA_PROJECT) { diff --git a/lib/util/ObjectBuilder.js b/lib/util/ObjectBuilder.js new file mode 100644 index 00000000..244525ca --- /dev/null +++ b/lib/util/ObjectBuilder.js @@ -0,0 +1,40 @@ +class ObjectBuilder { + constructor (initial) { + this.currentObject = initial || {}; + } + + /** + * @param {boolean} condition + * @returns {{ add: ConditionalObjectBuilder["add"] }} + */ + if (condition) { + return { + add: (mappedValues) => { + if (condition) { + return this.add(mappedValues); + } + + return this; + } + }; + } + + /** + * @param {{ [key: string]: value }} mappedValues + * @returns {ConditionalObjectBuilder} + */ + add (mappedValues) { + Object.keys(mappedValues) + .forEach((key) => { + this.currentObject[key] = mappedValues[key]; + }); + + return this; + } + + build () { + return this.currentObject; + } +} + +module.exports = ObjectBuilder;