UNPKG

12.8 kBJavaScriptView Raw
1import { Option as CommanderOption } from 'commander';
2import * as App from './application.mjs';
3import { DEFAULT_CACHE_LOCATION } from './util/cache/index.js';
4import { CheckFailed } from './util/errors.js';
5import { unindent } from './util/unindent.js';
6// interface InitOptions extends Options {}
7const usage = `\
8[options] [globs...] [file://<path> ...] [stdin[://<path>]]
9
10Patterns:
11 - [globs...] Glob Patterns
12 - [stdin] Read from "stdin" assume text file.
13 - [stdin://<path>] Read from "stdin", use <path> for file type and config.
14 - [file://<path>] Check the file at <path>
15
16Examples:
17 cspell . Recursively check all files.
18 cspell lint . The same as "cspell ."
19 cspell "*.js" Check all .js files in the current directory
20 cspell "**/*.js" Check all .js files recursively
21 cspell "src/**/*.js" Only check .js under src
22 cspell "**/*.txt" "**/*.js" Check both .js and .txt files.
23 cspell "**/*.{txt,js,md}" Check .txt, .js, and .md files.
24 cat LICENSE | cspell stdin Check stdin
25 cspell stdin://docs/doc.md Check stdin as if it was "./docs/doc.md"\
26`;
27const advanced = `
28More Examples:
29
30 cspell "**/*.js" --reporter @cspell/cspell-json-reporter
31 This will spell check all ".js" files recursively and use
32 "@cspell/cspell-json-reporter".
33
34 cspell . --reporter default
35 This will force the default reporter to be used overriding
36 any reporters defined in the configuration.
37
38 cspell . --reporter ./<path>/reporter.cjs
39 Use a custom reporter. See API for details.
40
41 cspell "*.md" --exclude CHANGELOG.md --files README.md CHANGELOG.md
42 Spell check only check "README.md" but NOT "CHANGELOG.md".
43
44 cspell "/*.md" --no-must-find-files --files $FILES
45 Only spell check the "/*.md" files in $FILES,
46 where $FILES is a shell variable that contains the list of files.
47
48References:
49 https://cspell.org
50 https://github.com/streetsidesoftware/cspell
51`;
52function collect(value, previous) {
53 const values = Array.isArray(value) ? value : [value];
54 return previous ? [...previous, ...values] : values;
55}
56export function commandLint(prog) {
57 const spellCheckCommand = prog.command('lint', { isDefault: true });
58 spellCheckCommand
59 .description('Check spelling')
60 .option('-c, --config <cspell.json>', 'Configuration file to use. By default cspell looks for cspell.json in the current directory.')
61 .option('-v, --verbose', 'Display more information about the files being checked and the configuration.')
62 .option('--locale <locale>', 'Set language locales. i.e. "en,fr" for English and French, or "en-GB" for British English.')
63 .option('--language-id <file-type>', 'Force programming language for unknown extensions. i.e. "php" or "scala"')
64 .addOption(crOpt('--languageId <file-type>', 'Alias of "--language-id". Force programming language for unknown extensions. i.e. "php" or "scala"').hideHelp())
65 .option('--words-only', 'Only output the words not found in the dictionaries.')
66 .addOption(crOpt('--wordsOnly', 'Only output the words not found in the dictionaries.').hideHelp())
67 .option('-u, --unique', 'Only output the first instance of a word not found in the dictionaries.')
68 .option('-e, --exclude <glob>', 'Exclude files matching the glob pattern. This option can be used multiple times to add multiple globs. ', collect)
69 // .option('--include <glob>', 'Include files matching the glob pattern. This option can be used multiple times.', collect)
70 .option('--file-list <path or stdin>', 'Specify a list of files to be spell checked.' +
71 ' The list is filtered against the glob file patterns.' +
72 ' Note: the format is 1 file path per line.', collect)
73 .option('--file [file...]', 'Specify files to spell check. They are filtered by the [globs...].', collect)
74 .addOption(crOpt('--files [file...]', 'Alias of "--file". Files to spell check.', collect).hideHelp())
75 .option('--no-issues', 'Do not show the spelling errors.')
76 .option('--no-progress', 'Turn off progress messages')
77 .option('--no-summary', 'Turn off summary message in console.')
78 .option('-s, --silent', 'Silent mode, suppress error messages.')
79 .option('--no-exit-code', 'Do not return an exit code if issues are found.')
80 .addOption(crOpt('--quiet', 'Only show spelling issues or errors.').implies({
81 summary: false,
82 progress: false,
83 }))
84 .option('--fail-fast', 'Exit after first file with an issue or error.')
85 .addOption(crOpt('--no-fail-fast', 'Process all files even if there is an error.').hideHelp())
86 .option('-r, --root <root folder>', 'Root directory, defaults to current directory.')
87 .addOption(crOpt('--relative', 'Issues are displayed relative to the root.').default(true).hideHelp())
88 .option('--no-relative', 'Issues are displayed with absolute path instead of relative to the root.')
89 .option('--show-context', 'Show the surrounding text around an issue.')
90 .option('--show-suggestions', 'Show spelling suggestions.')
91 .addOption(crOpt('--no-show-suggestions', 'Do not show spelling suggestions or fixes.').default(undefined))
92 .addOption(crOpt('--must-find-files', 'Error if no files are found.').default(true).hideHelp())
93 .option('--no-must-find-files', 'Do not error if no files are found.')
94 // The --filter-files option is still under design review.
95 // .option('--filter-files', 'Use the `files` configuration to filter files found.')
96 // .option(
97 // '--no-filter-files',
98 // 'Do NOT use the `files` configuration to filter files (Only applies to --files options).',
99 // )
100 // The following options are planned features
101 // .option('-w, --watch', 'Watch for any changes to the matching files and report any errors')
102 // .option('--force', 'Force the exit value to always be 0')
103 .addOption(crOpt('--legacy', 'Legacy output').hideHelp())
104 .addOption(crOpt('--local <local>', 'Deprecated -- Use: --locale').hideHelp())
105 .option('--cache', 'Use cache to only check changed files.')
106 .option('--no-cache', 'Do not use cache.')
107 .option('--cache-reset', 'Reset the cache file.')
108 .addOption(crOpt('--cache-strategy <strategy>', 'Strategy to use for detecting changed files.').choices([
109 'metadata',
110 'content',
111 ]))
112 .option('--cache-location <path>', `Path to the cache file or directory. (default: "${DEFAULT_CACHE_LOCATION}")`)
113 .option('--dot', 'Include files and directories starting with `.` (period) when matching globs.')
114 .option('--gitignore', 'Ignore files matching glob patterns found in .gitignore files.')
115 .option('--no-gitignore', 'Do NOT use .gitignore files.')
116 .option('--gitignore-root <path>', 'Prevent searching for .gitignore files past root.', collect)
117 .option('--validate-directives', 'Validate in-document CSpell directives.')
118 .addOption(crOpt('--no-validate-directives', 'Do not validate in-document CSpell directives.').hideHelp())
119 .option('--no-color', 'Turn off color.')
120 .option('--color', 'Force color.')
121 .addOption(crOpt('--default-configuration', 'Load the default configuration and dictionaries.').hideHelp())
122 .addOption(crOpt('--no-default-configuration', 'Do not load the default configuration and dictionaries.'))
123 .option('--debug', 'Output information useful for debugging cspell.json files.')
124 .option('--reporter <module|path>', 'Specify one or more reporters to use.', collect)
125 .addOption(crOpt('--skip-validation', 'Collect and process documents, but do not spell check.')
126 .implies({ cache: false })
127 .hideHelp())
128 .addOption(crOpt('--issues-summary-report', 'Output a summary of issues found.').hideHelp())
129 .addOption(crOpt('--show-perf-summary', 'Output a performance summary report.').hideHelp())
130 .option('--issue-template [template]', 'Use a custom issue template. See --help --issue-template for details.')
131 // Planned options
132 // .option('--dictionary <dictionary name>', 'Enable a dictionary by name.', collect)
133 // .option('--no-dictionary <dictionary name>', 'Disable a dictionary by name.', collect)
134 // .option('--import', 'Import a configuration file.', collect)
135 .usage(usage)
136 .addHelpText('after', augmentCommandHelp)
137 .arguments('[globs...]')
138 .action(async (fileGlobs, options) => {
139 // console.error('lint: %o', { fileGlobs, options });
140 const useExitCode = options.exitCode ?? true;
141 if (options.skipValidation) {
142 options.cache = false;
143 }
144 App.parseApplicationFeatureFlags(options.flag);
145 const { mustFindFiles, fileList, files, file } = options;
146 const result = await App.lint(fileGlobs, options);
147 if (!fileGlobs.length && !result.files && !result.errors && !fileList && !files?.length && !file?.length) {
148 spellCheckCommand.outputHelp();
149 throw new CheckFailed('outputHelp', 1);
150 }
151 if (result.errors || (mustFindFiles && !result.files)) {
152 throw new CheckFailed('check failed', 1);
153 }
154 if (result.issues) {
155 const exitCode = useExitCode ? 1 : 0;
156 throw new CheckFailed('check failed', exitCode);
157 }
158 return;
159 });
160 return spellCheckCommand;
161}
162function helpIssueTemplate(opts) {
163 if (!('issueTemplate' in opts))
164 return '';
165 return unindent `
166 Issue Template:
167 Use "--issue-template" to set the template to use when reporting issues.
168
169 The template is a string that can contain the following placeholders:
170 - $filename - the file name
171 - $col - the column number
172 - $row - the row number
173 - $text - the word that is misspelled
174 - $message - the issues message: "unknown word", "word is misspelled", etc.
175 - $messageColored - the issues message with color based upon the message type.
176 - $uri - the URI of the file
177 - $suggestions - suggestions for the misspelled word (if requested)
178 - $quickFix - possible quick fixes for the misspelled word.
179 - $contextFull - the full context of the misspelled word.
180 - $contextLeft - the context to the left of the misspelled word.
181 - $contextRight - the context to the right of the misspelled word.
182
183 Color is supported using the following template pattern:
184 - \`{<style[.style]> <text>}\` - where \`<style>\` is a style name and \`<text>\` is the text to style.
185
186 Styles
187 - \`bold\`, \`italic\`, \`underline\`, \`strikethrough\`, \`dim\`, \`inverse\`
188 - \`black\`, \`red\`, \`green\`, \`yellow\`, \`blue\`, \`magenta\`, \`cyan\`, \`white\`
189
190 Example:
191 --issue-template '{green $filename}:{yellow $row}:{yellow $col} $message {red $text} $quickFix {dim $suggestions}'
192 `;
193}
194/**
195 * Add additional help text to the command.
196 * When the verbose flag is set, show the hidden options.
197 * @param context
198 * @returns
199 */
200function augmentCommandHelp(context) {
201 const output = [];
202 const command = context.command;
203 const opts = command.opts();
204 const showHidden = !!opts.verbose;
205 const hiddenHelp = [];
206 const help = command.createHelp();
207 const hiddenOptions = command.options.filter((opt) => opt.hidden && showHidden);
208 const flagColWidth = Math.max(...command.options.map((opt) => opt.flags.length), 0);
209 const indent = flagColWidth + 4;
210 for (const options of hiddenOptions) {
211 if (!hiddenHelp.length) {
212 hiddenHelp.push('\nHidden Options:');
213 }
214 hiddenHelp.push(help.wrap(` ${options.flags.padEnd(flagColWidth)} ${options.description}`, process.stdout.columns || 80, indent));
215 }
216 output.push(...hiddenHelp, advanced);
217 return helpIssueTemplate(opts) + output.join('\n');
218}
219/**
220 * Create Option - a helper function to create a commander option.
221 * @param name - the name of the option
222 * @param description - the description of the option
223 * @param parseArg - optional function to parse the argument
224 * @param defaultValue - optional default value
225 * @returns CommanderOption
226 */
227function crOpt(name, description, parseArg, defaultValue) {
228 const option = new CommanderOption(name, description);
229 if (parseArg) {
230 option.argParser(parseArg);
231 }
232 if (defaultValue !== undefined) {
233 option.default(defaultValue);
234 }
235 return option;
236}
237//# sourceMappingURL=commandLint.js.map
\No newline at end of file