feat: support detailed `--help` (#2847)

* feat: support detailed --help

* refactor: put alias first, separate with comma

* feat: support detailed --help for --no-option

* docs: add missing type

* docs: remove `This requires node 8 or a transform`

* docs: remove config-precedence's choice descriptions in option.description

* docs: replace `option-name` with `flag`

* docs: update docs for `choices`

* docs: update `help` description

* docs: update error message

* docs: replace `undocumented` with empty string

* refactor: extract `getOptionDefaultValue`

* refactor: dynamically generate `defaults to ...`

* refactor: extract `getOptionWithLevenSuggestion`

* refactor: extract `createChoiceUsages`

* refactor: remove `optionTitleName`

* test: add `--help` tests for all options

* fix: handle `--help --help`

* feat: support `--help <alias>`

* refactor: use `flattenArray`

* feat: handle `--help <unknown>`

* docs: add description for `semi`, `color` and `bracket-spacing`

* fix: remove unnecessary option in `--help`
master
Ika 2017-09-21 13:54:13 +08:00 committed by Simon Lydell
parent 9b0d6b8de0
commit 184e368a9a
7 changed files with 588 additions and 72 deletions

View File

@ -28,6 +28,7 @@
"ignore": "^3.3.3", "ignore": "^3.3.3",
"jest-docblock": "21.1.0", "jest-docblock": "21.1.0",
"jest-validate": "21.1.0", "jest-validate": "21.1.0",
"leven": "2.1.0",
"mem": "1.1.0", "mem": "1.1.0",
"minimatch": "3.0.4", "minimatch": "3.0.4",
"minimist": "1.2.0", "minimist": "1.2.0",

View File

@ -48,8 +48,12 @@ const categoryOrder = [
* // Specify available choices for validation. They will also be displayed * // Specify available choices for validation. They will also be displayed
* // in --help as <a|b|c>. * // in --help as <a|b|c>.
* // Use an object instead of a string if a choice is deprecated and should * // Use an object instead of a string if a choice is deprecated and should
* // be treated as `redirect` instead. * // be treated as `redirect` instead, or if you'd like to add description for
* choices?: Array<string | { value: string, deprecated: boolean, redirect: string }>; * // the choice.
* choices?: Array<
* | string
* | { value: string, description?: string, deprecated?: boolean, redirect?: string }
* >;
* *
* // If the option has a value that is an exception to the regular value * // If the option has a value that is an exception to the regular value
* // constraints, indicate that value here (or use a function for more * // constraints, indicate that value here (or use a function for more
@ -75,6 +79,7 @@ const detailedOptions = normalizeDetailedOptions({
type: "boolean", type: "boolean",
category: CATEGORY_FORMAT, category: CATEGORY_FORMAT,
forwardToApi: true, forwardToApi: true,
description: "Print spaces between brackets.",
oppositeDescription: "Do not print spaces between brackets." oppositeDescription: "Do not print spaces between brackets."
}, },
color: { color: {
@ -84,6 +89,7 @@ const detailedOptions = normalizeDetailedOptions({
// See https://github.com/chalk/supports-color/#info for more information. // See https://github.com/chalk/supports-color/#info for more information.
type: "boolean", type: "boolean",
default: true, default: true,
description: "Colorize error messages.",
oppositeDescription: "Do not colorize error messages." oppositeDescription: "Do not colorize error messages."
}, },
config: { config: {
@ -97,15 +103,25 @@ const detailedOptions = normalizeDetailedOptions({
type: "choice", type: "choice",
category: CATEGORY_CONFIG, category: CATEGORY_CONFIG,
default: "cli-override", default: "cli-override",
choices: ["cli-override", "file-override", "prefer-file"], choices: [
{
value: "cli-override",
description: "CLI options take precedence over config file"
},
{
value: "file-override",
description: "Config file take precedence over CLI options"
},
{
value: "prefer-file",
description: dedent(` description: dedent(`
Define in which order config files and CLI options should be evaluated If a config file is found will evaluate it and ignore other CLI options.
cli-override | default config => config file => CLI options If no config file is found CLI options will evaluate as normal.
file-override | default config => CLI options => config file
prefer-file | default config => config file (if config file is found) or
default config => CLI options (if no config file is found)
Defaults to cli-override.
`) `)
}
],
description:
"Define in which order config files and CLI options should be evaluated."
}, },
"cursor-offset": { "cursor-offset": {
type: "int", type: "int",
@ -136,18 +152,18 @@ const detailedOptions = normalizeDetailedOptions({
deprecated: "Use `--parser flow` instead." deprecated: "Use `--parser flow` instead."
}, },
help: { help: {
type: "boolean", type: "flag",
alias: "h", alias: "h",
description: "Show help." description: dedent(`
Show CLI usage, or details about the given flag.
Example: --help write
`)
}, },
"ignore-path": { "ignore-path": {
type: "path", type: "path",
category: CATEGORY_CONFIG, category: CATEGORY_CONFIG,
default: ".prettierignore", default: ".prettierignore",
description: dedent(` description: "Path to a file with patterns describing files to ignore."
Path to a file with patterns describing files to ignore.
Defaults to ./.prettierignore.
`)
}, },
"jsx-bracket-same-line": { "jsx-bracket-same-line": {
type: "boolean", type: "boolean",
@ -168,14 +184,14 @@ const detailedOptions = normalizeDetailedOptions({
forwardToApi: true, forwardToApi: true,
exception: value => typeof value === "string", // Allow path to a parser module. exception: value => typeof value === "string", // Allow path to a parser module.
choices: ["flow", "babylon", "typescript", "postcss", "json", "graphql"], choices: ["flow", "babylon", "typescript", "postcss", "json", "graphql"],
description: "Which parser to use. Defaults to babylon.", description: "Which parser to use.",
getter: (value, argv) => (argv["flow-parser"] ? "flow" : value) getter: (value, argv) => (argv["flow-parser"] ? "flow" : value)
}, },
"print-width": { "print-width": {
type: "int", type: "int",
category: CATEGORY_FORMAT, category: CATEGORY_FORMAT,
forwardToApi: true, forwardToApi: true,
description: "The line length where Prettier will try wrap. Defaults to 80." description: "The line length where Prettier will try wrap."
}, },
"range-end": { "range-end": {
type: "int", type: "int",
@ -186,7 +202,6 @@ const detailedOptions = normalizeDetailedOptions({
Format code ending at a given character offset (exclusive). Format code ending at a given character offset (exclusive).
The range will extend forwards to the end of the selected statement. The range will extend forwards to the end of the selected statement.
This option cannot be used with --cursor-offset. This option cannot be used with --cursor-offset.
Defaults to Infinity.
`) `)
}, },
"range-start": { "range-start": {
@ -197,7 +212,6 @@ const detailedOptions = normalizeDetailedOptions({
Format code starting at a given character offset. Format code starting at a given character offset.
The range will extend backwards to the start of the first line containing the selected statement. The range will extend backwards to the start of the first line containing the selected statement.
This option cannot be used with --cursor-offset. This option cannot be used with --cursor-offset.
Defaults to 0.
`) `)
}, },
"require-pragma": { "require-pragma": {
@ -212,6 +226,7 @@ const detailedOptions = normalizeDetailedOptions({
type: "boolean", type: "boolean",
category: CATEGORY_FORMAT, category: CATEGORY_FORMAT,
forwardToApi: true, forwardToApi: true,
description: "Print semicolons.",
oppositeDescription: oppositeDescription:
"Do not print semicolons, except at the beginning of lines which may need them." "Do not print semicolons, except at the beginning of lines which may need them."
}, },
@ -234,20 +249,27 @@ const detailedOptions = normalizeDetailedOptions({
type: "int", type: "int",
category: CATEGORY_FORMAT, category: CATEGORY_FORMAT,
forwardToApi: true, forwardToApi: true,
description: "Number of spaces per indentation level. Defaults to 2." description: "Number of spaces per indentation level."
}, },
"trailing-comma": { "trailing-comma": {
type: "choice", type: "choice",
category: CATEGORY_FORMAT, category: CATEGORY_FORMAT,
forwardToApi: true, forwardToApi: true,
choices: [ choices: [
"none", { value: "none", description: "No trailing commas." },
"es5", {
"all", value: "es5",
description:
"Trailing commas where valid in ES5 (objects, arrays, etc.)"
},
{
value: "all",
description:
"Trailing commas wherever possible (including function arguments)."
},
{ value: "", deprecated: true, redirect: "es5" } { value: "", deprecated: true, redirect: "es5" }
], ],
description: description: "Print trailing commas wherever possible when multi-line."
"Print trailing commas wherever possible when multi-line. Defaults to none."
}, },
"use-tabs": { "use-tabs": {
type: "boolean", type: "boolean",
@ -332,8 +354,11 @@ function normalizeDetailedOptions(rawDetailedOptions) {
: kebabToCamel(name)), : kebabToCamel(name)),
choices: choices:
option.choices && option.choices &&
option.choices.map( option.choices.map(choice =>
choice => (typeof choice === "object" ? choice : { value: choice }) Object.assign(
{ description: "", deprecated: false },
typeof choice === "object" ? choice : { value: choice }
)
), ),
getter: option.getter || (value => value) getter: option.getter || (value => value)
}); });

View File

@ -9,6 +9,7 @@ const globby = require("globby");
const ignore = require("ignore"); const ignore = require("ignore");
const chalk = require("chalk"); const chalk = require("chalk");
const readline = require("readline"); const readline = require("readline");
const leven = require("leven");
const prettier = eval("require")("../index"); const prettier = eval("require")("../index");
const cleanAST = require("./clean-ast").cleanAST; const cleanAST = require("./clean-ast").cleanAST;
@ -18,6 +19,8 @@ const validator = require("./cli-validator");
const apiDefaultOptions = require("./options").defaults; const apiDefaultOptions = require("./options").defaults;
const OPTION_USAGE_THRESHOLD = 25; const OPTION_USAGE_THRESHOLD = 25;
const CHOICE_USAGE_MARGIN = 3;
const CHOICE_USAGE_INDENTATION = 2;
function getOptions(argv) { function getOptions(argv) {
return constant.detailedOptions return constant.detailedOptions
@ -333,8 +336,7 @@ function formatFiles(argv) {
}); });
} }
function createUsage() { function getOptionsWithOpposites(options) {
const options = constant.detailedOptions;
// Add --no-foo after --foo. // Add --no-foo after --foo.
const optionsWithOpposites = options.map(option => [ const optionsWithOpposites = options.map(option => [
option.description ? option : null, option.description ? option : null,
@ -346,11 +348,21 @@ function createUsage() {
}) })
: null : null
]); ]);
const flattenedOptions = [].concat return flattenArray(optionsWithOpposites).filter(Boolean);
.apply([], optionsWithOpposites) }
.filter(Boolean);
const groupedOptions = groupBy(flattenedOptions, option => option.category); function createUsage() {
const options = getOptionsWithOpposites(constant.detailedOptions).filter(
// remove unnecessary option (e.g. `semi`, `color`, etc.), which is only used for --help <flag>
option =>
!(
option.type === "boolean" &&
option.oppositeDescription &&
!option.name.startsWith("no-")
)
);
const groupedOptions = groupBy(options, option => option.category);
const firstCategories = constant.categoryOrder.slice(0, -1); const firstCategories = constant.categoryOrder.slice(0, -1);
const lastCategories = constant.categoryOrder.slice(-1); const lastCategories = constant.categoryOrder.slice(-1);
@ -372,20 +384,31 @@ function createUsage() {
} }
function createOptionUsage(option, threshold) { function createOptionUsage(option, threshold) {
const name = `--${option.name}`; const header = createOptionUsageHeader(option);
const alias = option.alias ? `or -${option.alias}` : null; const optionDefaultValue = getOptionDefaultValue(option.name);
const type = createOptionUsageType(option); return createOptionUsageRow(
const header = [name, alias, type].filter(Boolean).join(" "); header,
`${option.description}${optionDefaultValue === undefined
? ""
: `\nDefaults to ${optionDefaultValue}.`}`,
threshold
);
}
function createOptionUsageHeader(option) {
const name = `--${option.name}`;
const alias = option.alias ? `-${option.alias},` : null;
const type = createOptionUsageType(option);
return [alias, name, type].filter(Boolean).join(" ");
}
function createOptionUsageRow(header, content, threshold) {
const separator = const separator =
header.length >= threshold header.length >= threshold
? `\n${" ".repeat(threshold)}` ? `\n${" ".repeat(threshold)}`
: " ".repeat(threshold - header.length); : " ".repeat(threshold - header.length);
const description = option.description.replace( const description = content.replace(/\n/g, `\n${" ".repeat(threshold)}`);
/\n/g,
`\n${" ".repeat(threshold)}`
);
return `${header}${separator}${description}`; return `${header}${separator}${description}`;
} }
@ -404,6 +427,109 @@ function createOptionUsageType(option) {
} }
} }
function flattenArray(array) {
return [].concat.apply([], array);
}
function getOptionWithLevenSuggestion(options, optionName) {
// support aliases
const optionNameContainers = flattenArray(
options.map((option, index) => [
{ value: option.name, index },
option.alias ? { value: option.alias, index } : null
])
).filter(Boolean);
const optionNameContainer = optionNameContainers.find(
optionNameContainer => optionNameContainer.value === optionName
);
if (optionNameContainer !== undefined) {
return options[optionNameContainer.index];
}
const suggestedOptionNameContainer = optionNameContainers.find(
optionNameContainer => leven(optionNameContainer.value, optionName) < 3
);
if (suggestedOptionNameContainer !== undefined) {
const suggestedOptionName = suggestedOptionNameContainer.value;
console.warn(
`Unknown option name "${optionName}", did you mean "${suggestedOptionName}"?\n`
);
return options[suggestedOptionNameContainer.index];
}
console.warn(`Unknown option name "${optionName}"\n`);
return options.find(option => option.name === "help");
}
function createChoiceUsages(choices, margin, indentation) {
const activeChoices = choices.filter(choice => !choice.deprecated);
const threshold =
activeChoices
.map(choice => choice.value.length)
.reduce((current, length) => Math.max(current, length), 0) + margin;
return activeChoices.map(choice =>
indent(
createOptionUsageRow(choice.value, choice.description, threshold),
indentation
)
);
}
function createDetailedUsage(optionName) {
const option = getOptionWithLevenSuggestion(
getOptionsWithOpposites(constant.detailedOptions),
optionName
);
const header = createOptionUsageHeader(option);
const description = `\n\n${indent(option.description, 2)}`;
const choices =
option.type !== "choice"
? ""
: `\n\nValid options:\n\n${createChoiceUsages(
option.choices,
CHOICE_USAGE_MARGIN,
CHOICE_USAGE_INDENTATION
).join("\n")}`;
const optionDefaultValue = getOptionDefaultValue(option.name);
const defaults =
optionDefaultValue !== undefined
? `\n\nDefault: ${optionDefaultValue}`
: "";
return `${header}${description}${choices}${defaults}`;
}
function getOptionDefaultValue(optionName) {
// --no-option
if (!(optionName in constant.detailedOptionMap)) {
return undefined;
}
const option = constant.detailedOptionMap[optionName];
if (option.default !== undefined) {
return option.default;
}
const optionCamelName = kebabToCamel(optionName);
if (optionCamelName in apiDefaultOptions) {
return apiDefaultOptions[optionCamelName];
}
return undefined;
}
function kebabToCamel(str) {
return str.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
}
function indent(str, spaces) { function indent(str, spaces) {
return str.replace(/^/gm, " ".repeat(spaces)); return str.replace(/^/gm, " ".repeat(spaces));
} }
@ -511,5 +637,6 @@ module.exports = {
formatStdin, formatStdin,
formatFiles, formatFiles,
createUsage, createUsage,
createDetailedUsage,
normalizeArgv normalizeArgv
}; };

View File

@ -20,8 +20,12 @@ function run(args) {
process.exit(0); process.exit(0);
} }
if (argv["help"]) { if (argv["help"] !== undefined) {
console.log(util.createUsage()); console.log(
typeof argv["help"] === "string" && argv["help"] !== ""
? util.createDetailedUsage(argv["help"])
: util.createUsage()
);
process.exit(0); process.exit(0);
} }

View File

@ -1,5 +1,276 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`show detailed usage with --help bracket-spacing 1`] = `
"--bracket-spacing
Print spaces between brackets.
Default: true
"
`;
exports[`show detailed usage with --help color 1`] = `
"--color
Colorize error messages.
Default: true
"
`;
exports[`show detailed usage with --help config 1`] = `
"--config <path>
Path to a Prettier configuration file (.prettierrc, package.json, prettier.config.js).
"
`;
exports[`show detailed usage with --help config-precedence 1`] = `
"--config-precedence <cli-override|file-override|prefer-file>
Define in which order config files and CLI options should be evaluated.
Valid options:
cli-override CLI options take precedence over config file
file-override Config file take precedence over CLI options
prefer-file If a config file is found will evaluate it and ignore other CLI options.
If no config file is found CLI options will evaluate as normal.
Default: cli-override
"
`;
exports[`show detailed usage with --help cursor-offset 1`] = `
"--cursor-offset <int>
Print (to stderr) where a cursor at the given position would move to after formatting.
This option cannot be used with --range-start and --range-end.
Default: -1
"
`;
exports[`show detailed usage with --help find-config-path 1`] = `
"--find-config-path <path>
Find and print the path to a configuration file for the given input file.
"
`;
exports[`show detailed usage with --help help 1`] = `
"-h, --help <flag>
Show CLI usage, or details about the given flag.
Example: --help write
"
`;
exports[`show detailed usage with --help ignore-path 1`] = `
"--ignore-path <path>
Path to a file with patterns describing files to ignore.
Default: .prettierignore
"
`;
exports[`show detailed usage with --help jsx-bracket-same-line 1`] = `
"--jsx-bracket-same-line
Put > on the last line instead of at a new line.
Default: false
"
`;
exports[`show detailed usage with --help l (alias) 1`] = `
"-l, --list-different
Print the names of files that are different from Prettier's formatting.
"
`;
exports[`show detailed usage with --help list-different 1`] = `
"-l, --list-different
Print the names of files that are different from Prettier's formatting.
"
`;
exports[`show detailed usage with --help no-bracket-spacing 1`] = `
"--no-bracket-spacing
Do not print spaces between brackets.
"
`;
exports[`show detailed usage with --help no-color 1`] = `
"--no-color
Do not colorize error messages.
"
`;
exports[`show detailed usage with --help no-config 1`] = `
"--no-config
Do not look for a configuration file.
"
`;
exports[`show detailed usage with --help no-semi 1`] = `
"--no-semi
Do not print semicolons, except at the beginning of lines which may need them.
"
`;
exports[`show detailed usage with --help parser 1`] = `
"--parser <flow|babylon|typescript|postcss|json|graphql>
Which parser to use.
Valid options:
flow
babylon
typescript
postcss
json
graphql
Default: babylon
"
`;
exports[`show detailed usage with --help print-width 1`] = `
"--print-width <int>
The line length where Prettier will try wrap.
Default: 80
"
`;
exports[`show detailed usage with --help range-end 1`] = `
"--range-end <int>
Format code ending at a given character offset (exclusive).
The range will extend forwards to the end of the selected statement.
This option cannot be used with --cursor-offset.
Default: Infinity
"
`;
exports[`show detailed usage with --help range-start 1`] = `
"--range-start <int>
Format code starting at a given character offset.
The range will extend backwards to the start of the first line containing the selected statement.
This option cannot be used with --cursor-offset.
Default: 0
"
`;
exports[`show detailed usage with --help require-pragma 1`] = `
"--require-pragma
Require either '@prettier' or '@format' to be present in the file's first docblock comment
in order for it to be formatted.
Default: false
"
`;
exports[`show detailed usage with --help semi 1`] = `
"--semi
Print semicolons.
Default: true
"
`;
exports[`show detailed usage with --help single-quote 1`] = `
"--single-quote
Use single quotes instead of double quotes.
Default: false
"
`;
exports[`show detailed usage with --help stdin 1`] = `
"--stdin
Force reading input from stdin.
"
`;
exports[`show detailed usage with --help stdin-filepath 1`] = `
"--stdin-filepath <path>
Path to the file to pretend that stdin comes from.
"
`;
exports[`show detailed usage with --help tab-width 1`] = `
"--tab-width <int>
Number of spaces per indentation level.
Default: 2
"
`;
exports[`show detailed usage with --help trailing-comma 1`] = `
"--trailing-comma <none|es5|all>
Print trailing commas wherever possible when multi-line.
Valid options:
none No trailing commas.
es5 Trailing commas where valid in ES5 (objects, arrays, etc.)
all Trailing commas wherever possible (including function arguments).
Default: none
"
`;
exports[`show detailed usage with --help use-tabs 1`] = `
"--use-tabs
Indent with tabs instead of spaces.
Default: false
"
`;
exports[`show detailed usage with --help version 1`] = `
"-v, --version
Print Prettier version.
"
`;
exports[`show detailed usage with --help with-node-modules 1`] = `
"--with-node-modules
Process files inside 'node_modules' directory.
"
`;
exports[`show detailed usage with --help write 1`] = `
"--write
Edit files in-place. (Beware!)
"
`;
exports[`show usage with --help 1`] = ` exports[`show usage with --help 1`] = `
"Usage: prettier [options] [file/glob ...] "Usage: prettier [options] [file/glob ...]
@ -8,44 +279,48 @@ Stdin is read if it is piped to Prettier and no files are given.
Output options: Output options:
--list-different or -l Print the names of files that are different from Prettier's formatting. -l, --list-different Print the names of files that are different from Prettier's formatting.
--write Edit files in-place. (Beware!) --write Edit files in-place. (Beware!)
Format options: Format options:
--no-bracket-spacing Do not print spaces between brackets. --no-bracket-spacing Do not print spaces between brackets.
--jsx-bracket-same-line Put > on the last line instead of at a new line. --jsx-bracket-same-line Put > on the last line instead of at a new line.
Defaults to false.
--parser <flow|babylon|typescript|postcss|json|graphql> --parser <flow|babylon|typescript|postcss|json|graphql>
Which parser to use. Defaults to babylon. Which parser to use.
--print-width <int> The line length where Prettier will try wrap. Defaults to 80. Defaults to babylon.
--print-width <int> The line length where Prettier will try wrap.
Defaults to 80.
--no-semi Do not print semicolons, except at the beginning of lines which may need them. --no-semi Do not print semicolons, except at the beginning of lines which may need them.
--single-quote Use single quotes instead of double quotes. --single-quote Use single quotes instead of double quotes.
--tab-width <int> Number of spaces per indentation level. Defaults to 2. Defaults to false.
--tab-width <int> Number of spaces per indentation level.
Defaults to 2.
--trailing-comma <none|es5|all> --trailing-comma <none|es5|all>
Print trailing commas wherever possible when multi-line. Defaults to none. Print trailing commas wherever possible when multi-line.
Defaults to none.
--use-tabs Indent with tabs instead of spaces. --use-tabs Indent with tabs instead of spaces.
Defaults to false.
Config options: Config options:
--config <path> Path to a Prettier configuration file (.prettierrc, package.json, prettier.config.js). --config <path> Path to a Prettier configuration file (.prettierrc, package.json, prettier.config.js).
--no-config Do not look for a configuration file. --no-config Do not look for a configuration file.
--config-precedence <cli-override|file-override|prefer-file> --config-precedence <cli-override|file-override|prefer-file>
Define in which order config files and CLI options should be evaluated Define in which order config files and CLI options should be evaluated.
cli-override | default config => config file => CLI options
file-override | default config => CLI options => config file
prefer-file | default config => config file (if config file is found) or
default config => CLI options (if no config file is found)
Defaults to cli-override. Defaults to cli-override.
--find-config-path <path> --find-config-path <path>
Find and print the path to a configuration file for the given input file. Find and print the path to a configuration file for the given input file.
--ignore-path <path> Path to a file with patterns describing files to ignore. --ignore-path <path> Path to a file with patterns describing files to ignore.
Defaults to ./.prettierignore. Defaults to .prettierignore.
--with-node-modules Process files inside 'node_modules' directory. --with-node-modules Process files inside 'node_modules' directory.
Editor options: Editor options:
--cursor-offset <int> Print (to stderr) where a cursor at the given position would move to after formatting. --cursor-offset <int> Print (to stderr) where a cursor at the given position would move to after formatting.
This option cannot be used with --range-start and --range-end. This option cannot be used with --range-start and --range-end.
Defaults to -1.
--range-end <int> Format code ending at a given character offset (exclusive). --range-end <int> Format code ending at a given character offset (exclusive).
The range will extend forwards to the end of the selected statement. The range will extend forwards to the end of the selected statement.
This option cannot be used with --cursor-offset. This option cannot be used with --cursor-offset.
@ -58,14 +333,54 @@ Editor options:
Other options: Other options:
--no-color Do not colorize error messages. --no-color Do not colorize error messages.
--help or -h Show help. -h, --help <flag> Show CLI usage, or details about the given flag.
Example: --help write
--require-pragma Require either '@prettier' or '@format' to be present in the file's first docblock comment --require-pragma Require either '@prettier' or '@format' to be present in the file's first docblock comment
in order for it to be formatted. in order for it to be formatted.
Defaults to false.
--stdin Force reading input from stdin. --stdin Force reading input from stdin.
--stdin-filepath <path> Path to the file to pretend that stdin comes from. --stdin-filepath <path> Path to the file to pretend that stdin comes from.
--version or -v Print Prettier version. -v, --version Print Prettier version.
"
`;
exports[`show warning with --help not-found (typo) 1`] = `
"--parser <flow|babylon|typescript|postcss|json|graphql>
Which parser to use.
Valid options:
flow
babylon
typescript
postcss
json
graphql
Default: babylon
"
`;
exports[`show warning with --help not-found (typo) 2`] = `
"Unknown option name \\"parserr\\", did you mean \\"parser\\"?
"
`;
exports[`show warning with --help not-found 1`] = `
"-h, --help <flag>
Show CLI usage, or details about the given flag.
Example: --help write
"
`;
exports[`show warning with --help not-found 2`] = `
"Unknown option name \\"not-found\\"
" "
`; `;
@ -77,44 +392,48 @@ Stdin is read if it is piped to Prettier and no files are given.
Output options: Output options:
--list-different or -l Print the names of files that are different from Prettier's formatting. -l, --list-different Print the names of files that are different from Prettier's formatting.
--write Edit files in-place. (Beware!) --write Edit files in-place. (Beware!)
Format options: Format options:
--no-bracket-spacing Do not print spaces between brackets. --no-bracket-spacing Do not print spaces between brackets.
--jsx-bracket-same-line Put > on the last line instead of at a new line. --jsx-bracket-same-line Put > on the last line instead of at a new line.
Defaults to false.
--parser <flow|babylon|typescript|postcss|json|graphql> --parser <flow|babylon|typescript|postcss|json|graphql>
Which parser to use. Defaults to babylon. Which parser to use.
--print-width <int> The line length where Prettier will try wrap. Defaults to 80. Defaults to babylon.
--print-width <int> The line length where Prettier will try wrap.
Defaults to 80.
--no-semi Do not print semicolons, except at the beginning of lines which may need them. --no-semi Do not print semicolons, except at the beginning of lines which may need them.
--single-quote Use single quotes instead of double quotes. --single-quote Use single quotes instead of double quotes.
--tab-width <int> Number of spaces per indentation level. Defaults to 2. Defaults to false.
--tab-width <int> Number of spaces per indentation level.
Defaults to 2.
--trailing-comma <none|es5|all> --trailing-comma <none|es5|all>
Print trailing commas wherever possible when multi-line. Defaults to none. Print trailing commas wherever possible when multi-line.
Defaults to none.
--use-tabs Indent with tabs instead of spaces. --use-tabs Indent with tabs instead of spaces.
Defaults to false.
Config options: Config options:
--config <path> Path to a Prettier configuration file (.prettierrc, package.json, prettier.config.js). --config <path> Path to a Prettier configuration file (.prettierrc, package.json, prettier.config.js).
--no-config Do not look for a configuration file. --no-config Do not look for a configuration file.
--config-precedence <cli-override|file-override|prefer-file> --config-precedence <cli-override|file-override|prefer-file>
Define in which order config files and CLI options should be evaluated Define in which order config files and CLI options should be evaluated.
cli-override | default config => config file => CLI options
file-override | default config => CLI options => config file
prefer-file | default config => config file (if config file is found) or
default config => CLI options (if no config file is found)
Defaults to cli-override. Defaults to cli-override.
--find-config-path <path> --find-config-path <path>
Find and print the path to a configuration file for the given input file. Find and print the path to a configuration file for the given input file.
--ignore-path <path> Path to a file with patterns describing files to ignore. --ignore-path <path> Path to a file with patterns describing files to ignore.
Defaults to ./.prettierignore. Defaults to .prettierignore.
--with-node-modules Process files inside 'node_modules' directory. --with-node-modules Process files inside 'node_modules' directory.
Editor options: Editor options:
--cursor-offset <int> Print (to stderr) where a cursor at the given position would move to after formatting. --cursor-offset <int> Print (to stderr) where a cursor at the given position would move to after formatting.
This option cannot be used with --range-start and --range-end. This option cannot be used with --range-start and --range-end.
Defaults to -1.
--range-end <int> Format code ending at a given character offset (exclusive). --range-end <int> Format code ending at a given character offset (exclusive).
The range will extend forwards to the end of the selected statement. The range will extend forwards to the end of the selected statement.
This option cannot be used with --cursor-offset. This option cannot be used with --cursor-offset.
@ -127,12 +446,14 @@ Editor options:
Other options: Other options:
--no-color Do not colorize error messages. --no-color Do not colorize error messages.
--help or -h Show help. -h, --help <flag> Show CLI usage, or details about the given flag.
Example: --help write
--require-pragma Require either '@prettier' or '@format' to be present in the file's first docblock comment --require-pragma Require either '@prettier' or '@format' to be present in the file's first docblock comment
in order for it to be formatted. in order for it to be formatted.
Defaults to false.
--stdin Force reading input from stdin. --stdin Force reading input from stdin.
--stdin-filepath <path> Path to the file to pretend that stdin comes from. --stdin-filepath <path> Path to the file to pretend that stdin comes from.
--version or -v Print Prettier version. -v, --version Print Prettier version.
" "

View File

@ -2,6 +2,7 @@
const prettier = require("../.."); const prettier = require("../..");
const runPrettier = require("../runPrettier"); const runPrettier = require("../runPrettier");
const constant = require("../../src/cli-constant");
test("show version with --version", () => { test("show version with --version", () => {
const result = runPrettier("cli/with-shebang", ["--version"]); const result = runPrettier("cli/with-shebang", ["--version"]);
@ -17,6 +18,43 @@ test("show usage with --help", () => {
expect(result.status).toEqual(0); expect(result.status).toEqual(0);
}); });
test(`show detailed usage with --help l (alias)`, () => {
const result = runPrettier("cli", ["--help", "l"]);
expect(result.stdout).toMatchSnapshot();
expect(result.status).toEqual(0);
});
constant.detailedOptions.forEach(option => {
const optionNames = [
option.description ? option.name : null,
option.oppositeDescription ? `no-${option.name}` : null
].filter(Boolean);
optionNames.forEach(optionName => {
test(`show detailed usage with --help ${optionName}`, () => {
const result = runPrettier("cli", ["--help", optionName]);
expect(result.stdout).toMatchSnapshot();
expect(result.status).toEqual(0);
});
});
});
test("show warning with --help not-found", () => {
const result = runPrettier("cli", ["--help", "not-found"]);
expect(result.stdout).toMatchSnapshot();
expect(result.stderr).toMatchSnapshot();
expect(result.status).toEqual(0);
});
test("show warning with --help not-found (typo)", () => {
const result = runPrettier("cli", ["--help", "parserr"]);
expect(result.stdout).toMatchSnapshot();
expect(result.stderr).toMatchSnapshot();
expect(result.status).toEqual(0);
});
test("throw error with --write + --debug-check", () => { test("throw error with --write + --debug-check", () => {
const result = runPrettier("cli", ["--write", "--debug-check"]); const result = runPrettier("cli", ["--write", "--debug-check"]);

View File

@ -2581,7 +2581,7 @@ lcid@^1.0.0:
dependencies: dependencies:
invert-kv "^1.0.0" invert-kv "^1.0.0"
leven@^2.1.0: leven@2.1.0, leven@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"