CLI improvements (#478)
* Add `--help` CLI flag * Don't pick up unknown CLI options This prevents people from adding new CLI options in the future, but forgetting to add it explicitly to minimist, resulting in a false "Ignored unknown option" warning. * Add `-h` and `-v` option aliases It always bugs me when those don't do `--help` and `--version` for no reason in CLIs. * Allow `echo 'test' | prettier` without the `--stdin` flag * Improve CLI error handling and validation - Handle errors the same way both when using stdin and when using files. - Print validation errors nicely. - Validate int options, instead of silently ignoring bad input. - Warn about unknown parsers, falling back to babylon. If a new parser is added in the future, this allows graceful degradation for tools running an older version of prettier. (Just like how unknown options are warnings instead of errors.) - Add comments. * Run prettier on bin/prettier.jsmaster
parent
03b4ed2fcf
commit
239521e97d
|
@ -19,16 +19,19 @@ const argv = minimist(process.argv.slice(2), {
|
|||
// listed here is to avoid "Ignored unknown option: --no-color" warnings.
|
||||
// See https://github.com/chalk/supports-color/#info for more information.
|
||||
"color",
|
||||
"help",
|
||||
"version",
|
||||
"debug-print-doc",
|
||||
// Deprecated in 0.0.10
|
||||
"flow-parser"
|
||||
],
|
||||
string: [ "print-width", "tab-width", "parser" ],
|
||||
string: ["print-width", "tab-width", "parser"],
|
||||
default: { color: true, "bracket-spacing": true, parser: "babylon" },
|
||||
alias: { help: "h", version: "v" },
|
||||
unknown: param => {
|
||||
if (param.startsWith("-")) {
|
||||
console.warn("Ignored unknown option: " + param + "\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -40,9 +43,9 @@ if (argv["version"]) {
|
|||
|
||||
const filepatterns = argv["_"];
|
||||
const write = argv["write"];
|
||||
const stdin = argv["stdin"];
|
||||
const stdin = argv["stdin"] || !filepatterns.length && !process.stdin.isTTY;
|
||||
|
||||
if (!filepatterns.length && !stdin) {
|
||||
if (argv["help"] || !filepatterns.length && !stdin) {
|
||||
console.log(
|
||||
"Usage: prettier [opts] [filename ...]\n\n" +
|
||||
"Available options:\n" +
|
||||
|
@ -61,28 +64,63 @@ if (!filepatterns.length && !stdin) {
|
|||
" --no-bracket-spacing\n" +
|
||||
" --bracket-spacing=false"
|
||||
);
|
||||
process.exit(1);
|
||||
process.exit(argv["help"] ? 0 : 1);
|
||||
}
|
||||
|
||||
function getParser() {
|
||||
function getParserOption() {
|
||||
const optionName = "parser";
|
||||
const value = argv[optionName];
|
||||
|
||||
if (value === undefined) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// For backward compatibility. Deprecated in 0.0.10
|
||||
if (argv["flow-parser"]) {
|
||||
console.warn("`--flow-parser` is deprecated. Use `--parser flow` instead.");
|
||||
return "flow";
|
||||
}
|
||||
|
||||
if (argv["parser"] === "flow") {
|
||||
return "flow";
|
||||
if (value === "flow" || value === "babylon") {
|
||||
return value;
|
||||
}
|
||||
|
||||
console.warn(
|
||||
"Ignoring unknown --" +
|
||||
optionName +
|
||||
' value, falling back to "babylon":\n' +
|
||||
' Expected "flow" or "babylon", but received: ' +
|
||||
JSON.stringify(value)
|
||||
);
|
||||
|
||||
return "babylon";
|
||||
}
|
||||
|
||||
function getIntOption(optionName) {
|
||||
const value = argv[optionName];
|
||||
|
||||
if (value === undefined) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (/^\d+$/.test(value)) {
|
||||
return Number(value);
|
||||
}
|
||||
|
||||
console.error(
|
||||
"Invalid --" +
|
||||
optionName +
|
||||
" value. Expected an integer, but received: " +
|
||||
JSON.stringify(value)
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const options = {
|
||||
printWidth: argv["print-width"] && parseInt(argv["print-width"]),
|
||||
tabWidth: argv["tab-width"] && parseInt(argv["tab-width"]),
|
||||
printWidth: getIntOption("print-width"),
|
||||
tabWidth: getIntOption("tab-width"),
|
||||
bracketSpacing: argv["bracket-spacing"],
|
||||
parser: getParser(),
|
||||
parser: getParserOption(),
|
||||
singleQuote: argv["single-quote"],
|
||||
trailingComma: argv["trailing-comma"]
|
||||
};
|
||||
|
@ -95,14 +133,37 @@ function format(input) {
|
|||
return prettier.format(input, options);
|
||||
}
|
||||
|
||||
function handleError(filename, e) {
|
||||
const isParseError = Boolean(e && e.loc);
|
||||
const isValidationError = /Validation Error/.test(e && e.message);
|
||||
|
||||
// For parse errors and validation errors, we only want to show the error
|
||||
// message formatted in a nice way. `String(e)` takes care of that. Other
|
||||
// (unexpected) errors are passed as-is as a separate argument to
|
||||
// `console.error`. That includes the stack trace (if any), and shows a nice
|
||||
// `util.inspect` of throws things that aren't `Error` objects. (The Flow
|
||||
// parser has mistakenly thrown arrays sometimes.)
|
||||
if (isParseError) {
|
||||
console.error(filename + ": " + String(e));
|
||||
} else if (isValidationError) {
|
||||
console.error(String(e));
|
||||
// If validation fails for one file, it will fail for all of them.
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.error(filename + ":", e);
|
||||
}
|
||||
|
||||
// Don't exit the process if one file failed
|
||||
process.exitCode = 2;
|
||||
}
|
||||
|
||||
if (stdin) {
|
||||
getStdin().then(input => {
|
||||
try {
|
||||
// Don't use `console.log` here since it adds an extra newline at the end.
|
||||
process.stdout.write(format(input));
|
||||
} catch (e) {
|
||||
process.exitCode = 2;
|
||||
console.error("stdin: " + e);
|
||||
handleError("stdin", e);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
@ -124,13 +185,7 @@ if (stdin) {
|
|||
try {
|
||||
output = format(input);
|
||||
} catch (e) {
|
||||
process.exitCode = 2;
|
||||
if(e.loc) {
|
||||
console.error(filename + ": " + e);
|
||||
}
|
||||
else {
|
||||
console.error(filename + ":", e);
|
||||
}
|
||||
handleError(filename, e);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue