Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chore: Replace the inquirer dependency with enquirer #13254

Merged
merged 9 commits into from Jun 9, 2020
137 changes: 74 additions & 63 deletions lib/init/config-initializer.js
Expand Up @@ -12,7 +12,7 @@

const util = require("util"),
path = require("path"),
inquirer = require("inquirer"),
enquirer = require("enquirer"),
ProgressBar = require("progress"),
semver = require("semver"),
espree = require("espree"),
Expand Down Expand Up @@ -146,7 +146,7 @@ function getModulesList(config, installESLint) {
*
* Note: This clones the config object and returns a new config to avoid mutating
* the original config parameter.
* @param {Object} answers answers received from inquirer
* @param {Object} answers answers received from enquirer
* @param {Object} config config object
* @returns {Object} config object with configured rules
*/
Expand Down Expand Up @@ -253,7 +253,7 @@ function configureRules(answers, config) {

/**
* process user's answers and create config object
* @param {Object} answers answers received from inquirer
* @param {Object} answers answers received from enquirer
* @returns {Object} config object
*/
function processAnswers(answers) {
Expand Down Expand Up @@ -412,7 +412,7 @@ function installModules(modules) {
npmUtils.installSyncSaveDev(modules);
}

/* istanbul ignore next: no need to test inquirer */
/* istanbul ignore next: no need to test enquirer */
/**
* Ask user to install modules.
* @param {string[]} modules Array of modules to be installed.
Expand All @@ -428,14 +428,17 @@ function askInstallModules(modules, packageJsonExists) {

log.info("The config that you've selected requires the following dependencies:\n");
log.info(modules.join(" "));
return inquirer.prompt([
return enquirer.prompt([
{
type: "confirm",
name: "executeInstallation",
message: "Would you like to install them now with npm?",
default: true,
when() {
return modules.length && packageJsonExists;
initial: () => true,
skip() {
return !(modules.length && packageJsonExists);
},
result(input) {
return this.skip ? null : input;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This result method is needed since enquirer will even return the initial value when the question is skipped, unlike inquirer.

}
}
]).then(({ executeInstallation }) => {
Expand All @@ -445,110 +448,115 @@ function askInstallModules(modules, packageJsonExists) {
});
}

/* istanbul ignore next: no need to test inquirer */
/* istanbul ignore next: no need to test enquirer */
/**
* Ask use a few questions on command prompt
* @returns {Promise} The promise with the result of the prompt
*/
function promptUser() {

return inquirer.prompt([
return enquirer.prompt([
{
type: "list",
type: "select",
name: "purpose",
message: "How would you like to use ESLint?",
default: "problems",
initial: 1,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The returned number matches the name value of nth in the choices array.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add that as a comment?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Siilwyn can you add this as a comment in the file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes 👍
(Didn't get a notification for your first comment.)

choices: [
{ name: "To check syntax only", value: "syntax" },
{ name: "To check syntax and find problems", value: "problems" },
{ name: "To check syntax, find problems, and enforce code style", value: "style" }
{ message: "To check syntax only", name: "syntax" },
{ message: "To check syntax and find problems", name: "problems" },
{ message: "To check syntax, find problems, and enforce code style", name: "style" }
]
},
{
type: "list",
type: "select",
name: "moduleType",
message: "What type of modules does your project use?",
default: "esm",
initial: 0,
choices: [
{ name: "JavaScript modules (import/export)", value: "esm" },
{ name: "CommonJS (require/exports)", value: "commonjs" },
{ name: "None of these", value: "none" }
{ message: "JavaScript modules (import/export)", name: "esm" },
{ message: "CommonJS (require/exports)", name: "commonjs" },
{ message: "None of these", name: "none" }
]
},
{
type: "list",
type: "select",
name: "framework",
message: "Which framework does your project use?",
default: "react",
initial: 0,
choices: [
{ name: "React", value: "react" },
{ name: "Vue.js", value: "vue" },
{ name: "None of these", value: "none" }
{ message: "React", name: "react" },
{ message: "Vue.js", name: "vue" },
{ message: "None of these", name: "none" }
]
},
{
type: "confirm",
name: "typescript",
message: "Does your project use TypeScript?",
default: false
initial: () => false
},
{
type: "checkbox",
type: "multiselect",
nzakas marked this conversation as resolved.
Show resolved Hide resolved
name: "env",
message: "Where does your code run?",
default: ["browser"],
initial: 0,
choices: [
{ name: "Browser", value: "browser" },
{ name: "Node", value: "node" }
{ message: "Browser", name: "browser" },
{ message: "Node", name: "node" }
]
},
{
type: "list",
type: "select",
name: "source",
message: "How would you like to define a style for your project?",
default: "guide",
choices: [
{ name: "Use a popular style guide", value: "guide" },
{ name: "Answer questions about your style", value: "prompt" },
{ name: "Inspect your JavaScript file(s)", value: "auto" }
{ message: "Use a popular style guide", name: "guide" },
{ message: "Answer questions about your style", name: "prompt" },
{ message: "Inspect your JavaScript file(s)", name: "auto" }
],
when(answers) {
return answers.purpose === "style";
skip() {
return this.state.answers.purpose !== "style";
},
Comment on lines +521 to +523
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The skip method is the reverse of when so the conditional statement is reversed.

result(input) {
return this.skip ? null : input;
Copy link
Member

@yeonjuan yeonjuan May 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Siilwyn
It seems not working as we expected.
When I answered with the "guide," in this step. but the selecting styleguide step was skipped.

✔ How would you like to use ESLint? · style
✔ What type of modules does your project use? · none
✔ Which framework does your project use? · none
✔ Does your project use TypeScript? · No / Yes
✔ Where does your code run? · browser
✔ How would you like to define a style for your project? · guide
✔ What format do you want your config file to be in? · JavaScript
✔ What style of indentation do you use? · tab
✔ What quotes do you use for strings? · double
✔ What line endings do you use? · unix
✔ Do you require semicolons? · No / Yes
Successfully created .eslintrc.js file in

It seems the this.skip is a function (truthy value), so the result always be a null
Maybe we should change all the logic which uses this.skip

스크린샷 2020-05-05 오후 10 19 31

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! That was a typo sorry about that. I was testing it on one question with skipped got it working but then messed up the copy paste on all somehow.

}
},
{
type: "list",
type: "select",
name: "styleguide",
message: "Which style guide do you want to follow?",
choices: [
{ name: "Airbnb: https://github.com/airbnb/javascript", value: "airbnb" },
{ name: "Standard: https://github.com/standard/standard", value: "standard" },
{ name: "Google: https://github.com/google/eslint-config-google", value: "google" }
{ message: "Airbnb: https://github.com/airbnb/javascript", name: "airbnb" },
{ message: "Standard: https://github.com/standard/standard", name: "standard" },
{ message: "Google: https://github.com/google/eslint-config-google", name: "google" }
],
when(answers) {
answers.packageJsonExists = npmUtils.checkPackageJson();
return answers.source === "guide" && answers.packageJsonExists;
skip() {
this.state.answers.packageJsonExists = npmUtils.checkPackageJson();
return !(this.state.answers.source === "guide" && this.state.answers.packageJsonExists);
},
result(input) {
return this.skip ? null : input;
}
},
{
type: "input",
name: "patterns",
message: "Which file(s), path(s), or glob(s) should be examined?",
when(answers) {
return (answers.source === "auto");
skip() {
return this.state.answers.source !== "auto";
},
validate(input) {
if (input.trim().length === 0 && input.trim() !== ",") {
if (!this.skip && input.trim().length === 0 && input.trim() !== ",") {
return "You must tell us what code to examine. Try again.";
}
return true;
}
},
{
type: "list",
type: "select",
name: "format",
message: "What format do you want your config file to be in?",
default: "JavaScript",
initial: 0,
choices: ["JavaScript", "YAML", "JSON"]
},
{
Expand All @@ -561,9 +569,12 @@ function promptUser() {

return `The style guide "${answers.styleguide}" requires eslint@${answers.requiredESLintVersionRange}. You are currently using eslint@${answers.localESLintVersion}.\n Do you want to ${verb}?`;
},
default: true,
when(answers) {
return answers.source === "guide" && answers.packageJsonExists && hasESLintVersionConflict(answers);
initial: () => true,
skip() {
return !(this.state.answers.source === "guide" && this.state.answers.packageJsonExists && hasESLintVersionConflict(this.state.answers));
},
result(input) {
return this.skip ? null : input;
}
}
]).then(earlyAnswers => {
Expand Down Expand Up @@ -616,33 +627,33 @@ function promptUser() {
}

// continue with the style questions otherwise...
return inquirer.prompt([
return enquirer.prompt([
{
type: "list",
type: "select",
name: "indent",
message: "What style of indentation do you use?",
default: "tab",
choices: [{ name: "Tabs", value: "tab" }, { name: "Spaces", value: 4 }]
initial: 0,
choices: [{ message: "Tabs", name: "tab" }, { message: "Spaces", name: 4 }]
},
{
type: "list",
type: "select",
name: "quotes",
message: "What quotes do you use for strings?",
default: "double",
choices: [{ name: "Double", value: "double" }, { name: "Single", value: "single" }]
initial: 0,
choices: [{ message: "Double", name: "double" }, { message: "Single", name: "single" }]
},
{
type: "list",
type: "select",
name: "linebreak",
message: "What line endings do you use?",
default: "unix",
choices: [{ name: "Unix", value: "unix" }, { name: "Windows", value: "windows" }]
initial: 0,
choices: [{ message: "Unix", name: "unix" }, { message: "Windows", name: "windows" }]
},
{
type: "confirm",
name: "semi",
message: "Do you require semicolons?",
default: true
initial: () => true
}
]).then(answers => {
const totalAnswers = Object.assign({}, earlyAnswers, answers);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -52,6 +52,7 @@
"cross-spawn": "^7.0.2",
"debug": "^4.0.1",
"doctrine": "^3.0.0",
"enquirer": "^2.3.5",
"eslint-scope": "^5.0.0",
"eslint-utils": "^2.0.0",
"eslint-visitor-keys": "^1.1.0",
Expand All @@ -65,7 +66,6 @@
"ignore": "^4.0.6",
"import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4",
"inquirer": "^7.0.0",
"is-glob": "^4.0.0",
"js-yaml": "^3.13.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
Expand Down