From 491a582620b64ed4acbccd04f687adc28a5e4cff Mon Sep 17 00:00:00 2001 From: James George Date: Mon, 2 Nov 2020 18:41:01 +0530 Subject: [PATCH] feat: suggest the closest match based on the Levenshtein distance algorithm (#2010) * feat: suggest the closest match for an unknown flag * tests: add test case for flag suggestion * tests: assert for exit code --- packages/webpack-cli/lib/bootstrap.js | 6 ++++++ packages/webpack-cli/package.json | 1 + test/unknown/unknown.test.js | 9 ++++++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/webpack-cli/lib/bootstrap.js b/packages/webpack-cli/lib/bootstrap.js index 56996ec64c7..b6fc82879c6 100644 --- a/packages/webpack-cli/lib/bootstrap.js +++ b/packages/webpack-cli/lib/bootstrap.js @@ -3,6 +3,7 @@ const { core } = require('./utils/cli-flags'); const logger = require('./utils/logger'); const { isCommandUsed } = require('./utils/arg-utils'); const argParser = require('./utils/arg-parser'); +const leven = require('leven'); process.title = 'webpack-cli'; @@ -39,6 +40,11 @@ const runCLI = async (cliArgs) => { if (parsedArgs.unknownArgs.length > 0) { parsedArgs.unknownArgs.forEach(async (unknown) => { logger.error(`Unknown argument: ${unknown}`); + const strippedFlag = unknown.substr(2); + const { name: suggestion } = core.find((flag) => leven(strippedFlag, flag.name) < 3); + if (suggestion) { + logger.raw(`Did you mean --${suggestion}?`); + } }); process.exit(2); diff --git a/packages/webpack-cli/package.json b/packages/webpack-cli/package.json index c6e0534cd41..67855ac6601 100644 --- a/packages/webpack-cli/package.json +++ b/packages/webpack-cli/package.json @@ -37,6 +37,7 @@ "execa": "^4.1.0", "import-local": "^3.0.2", "interpret": "^2.2.0", + "leven": "^3.1.0", "rechoir": "^0.7.0", "v8-compile-cache": "^2.2.0", "webpack-merge": "^4.2.2" diff --git a/test/unknown/unknown.test.js b/test/unknown/unknown.test.js index 8352b345d6f..903122b2495 100644 --- a/test/unknown/unknown.test.js +++ b/test/unknown/unknown.test.js @@ -2,8 +2,15 @@ const { run } = require('../utils/test-utils'); describe('unknown behaviour', () => { it('warns the user if an unknown flag is passed in', () => { - const { stderr } = run(__dirname, ['--unknown']); + const { stderr, exitCode } = run(__dirname, ['--unknown']); expect(stderr).toBeTruthy(); expect(stderr).toContain('Unknown argument: --unknown'); + expect(exitCode).toBe(2); + }); + it('suggests the closest match to an unknown flag', () => { + const { stderr, stdout, exitCode } = run(__dirname, ['--entyr', './a.js']); + expect(stderr).toContain('Unknown argument: --entyr'); + expect(stdout).toContain('Did you mean --entry?'); + expect(exitCode).toBe(2); }); });