Skip to content

Commit

Permalink
feat: show help for unrecognized commands (#308)
Browse files Browse the repository at this point in the history
  • Loading branch information
dephiros authored and tricoder42 committed Sep 6, 2018
1 parent 1832213 commit a7204d4
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"chalk": "^2.3.0",
"cli-table": "^0.3.1",
"commander": "^2.17.1",
"fuzzaldrin": "^2.1.0",
"date-fns": "^1.29.0",
"glob": "^7.1.2",
"inquirer": "^6.2.0",
Expand Down
11 changes: 11 additions & 0 deletions packages/cli/src/api/__snapshots__/utils.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`helpMisspelledCommand - show help for misspelled commands should return command is invalid if no commands are configured 1`] = `lingui: command compile is not a lingui command. See 'lingui --help' for the list of available commands.`;

exports[`helpMisspelledCommand - show help for misspelled commands should return suggestions for mispelled 1`] = `
lingui: command compilesss is not a lingui command. See 'lingui --help' for the list of available commands.
Did you mean: compile?
`;

exports[`helpMisspelledCommand - show help for misspelled commands shouldn't output anything if user passes no command 1`] = `undefined`;
38 changes: 38 additions & 0 deletions packages/cli/src/api/utils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fs from "fs"
import path from "path"
import chalk from "chalk"
import { score } from "fuzzaldrin"

export function removeDirectory(dir, keep = false) {
if (!fs.existsSync(dir)) return
Expand Down Expand Up @@ -33,6 +34,43 @@ export function prettyOrigin(origins) {
}
}

/**
* .. js:function:: helpMisspelledCommand(command [, availableCommands = []])
* :param: command - command passed to CLI
* :param: availableCommands - all commands defined in commander.js
*
* If unknown commands is passed to CLI, check it agains all available commands
* for possible misspelled letter. Output help with suggestions to console.
*/
export function helpMisspelledCommand(command, availableCommands = []) {
const commandNames = availableCommands.map(command => command.name())

// if no command is supplied, then commander.js shows help automatically
if (!command || commandNames.includes(command)) {
return
}

const suggestions = commandNames
.map(name => ({
name,
score: score(name, command.slice(0, name.length))
}))
.filter(nameScore => nameScore.score > 0)
.slice(0, 3)
.map(commandScore => chalk.inverse(commandScore.name))
.join(", ")

console.log(
`lingui: command ${command} is not a lingui command. ` +
`See 'lingui --help' for the list of available commands.`
)

if (suggestions) {
console.log()
console.log(`Did you mean: ${suggestions}?`)
}
}

export const splitOrigin = origin => origin.split(":")

export const joinOrigin = origin => origin.join(":")
44 changes: 44 additions & 0 deletions packages/cli/src/api/utils.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { helpMisspelledCommand } from "./utils"
import { mockConsole } from "../mocks"

function getConsoleMockCalls({ mock }) {
if (!mock.calls.length) return
return mock.calls.map(call => call[0]).join("\n")
}

describe("helpMisspelledCommand - show help for misspelled commands", function() {
function mockCommands(command, commandNames) {
return helpMisspelledCommand(
command,
commandNames.map(commandName => ({ name: () => commandName }))
)
}

it("shouldn't output anything if command is valid", function() {
mockConsole(console => {
mockCommands("compile", ["compile"])
expect(getConsoleMockCalls(console.log)).toBeUndefined()
})
})

it("shouldn't output anything if user passes no command", function() {
mockConsole(console => {
mockCommands("", ["compile"])
expect(getConsoleMockCalls(console.log)).toMatchSnapshot()
})
})

it("should return command is invalid if no commands are configured", function() {
mockConsole(console => {
mockCommands("compile", [])
expect(getConsoleMockCalls(console.log)).toMatchSnapshot()
})
})

it("should return suggestions for mispelled", function() {
mockConsole(console => {
mockCommands("compilesss", ["compile"])
expect(getConsoleMockCalls(console.log)).toMatchSnapshot()
})
})
})
4 changes: 4 additions & 0 deletions packages/cli/src/lingui.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/usr/bin/env node

import { helpMisspelledCommand } from "./api/utils"

const program = require("commander")

let version
Expand All @@ -19,3 +21,5 @@ program
.command("extract [files...]", "Extracts messages from source files")
.command("compile", "Compile message catalogs")
.parse(process.argv)

helpMisspelledCommand(process.argv[2], program.commands)
4 changes: 4 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2717,6 +2717,10 @@ functional-red-black-tree@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"

fuzzaldrin@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fuzzaldrin/-/fuzzaldrin-2.1.0.tgz#90204c3e2fdaa6941bb28d16645d418063a90e9b"

gauge@~2.7.3:
version "2.7.4"
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
Expand Down

0 comments on commit a7204d4

Please sign in to comment.