UNPKG

10.2 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.CheckFailed = exports.run = void 0;
4const path = require("path");
5const commander = require("commander");
6// eslint-disable-next-line @typescript-eslint/no-var-requires
7const npmPackage = require(path.join(__dirname, '..', 'package.json'));
8const application_1 = require("./application");
9const App = require("./application");
10const chalk = require("chalk");
11// interface InitOptions extends Options {}
12const templateIssue = `${chalk.green('${uri}')}:${chalk.yellow('${row}:${col}')} - Unknown word (${chalk.red('${text}')})`;
13const templateIssueLegacy = `${chalk.green('${uri}')}[\${row}, \${col}]: Unknown word: ${chalk.red('${text}')}`;
14const templateIssueWordsOnly = '${text}';
15function genIssueEmitter(template) {
16 return function issueEmitter(issue) {
17 console.log(formatIssue(template, issue));
18 };
19}
20function errorEmitter(message, error) {
21 console.error(chalk.red(message), error.toString());
22}
23function infoEmitter(message, msgType) {
24 switch (msgType) {
25 case 'Debug':
26 console.info(chalk.cyan(message));
27 break;
28 case 'Info':
29 console.info(chalk.yellow(message));
30 break;
31 case 'Progress':
32 console.info(chalk.white(message));
33 break;
34 }
35}
36function debugEmitter(message) {
37 infoEmitter(message, App.MessageTypes.Debug);
38}
39function nullEmitter(_) {
40 /* empty */
41}
42async function asyncNullEmitter(_) {
43 /* empty */
44}
45function getEmitters(options) {
46 const issueTemplate = options.wordsOnly
47 ? templateIssueWordsOnly
48 : options.legacy
49 ? templateIssueLegacy
50 : templateIssue;
51 const { silent = false, issues } = options;
52 return {
53 issue: silent || !issues ? nullEmitter : genIssueEmitter(issueTemplate),
54 error: silent ? asyncNullEmitter : errorEmitter,
55 info: silent || !options.verbose ? nullEmitter : infoEmitter,
56 debug: options.debug ? debugEmitter : nullEmitter,
57 };
58}
59async function run(program, argv) {
60 const prog = program || commander;
61 const args = argv || process.argv;
62 prog.passCommandToAction(false);
63 return new Promise((resolve, rejects) => {
64 let showHelp = true;
65 prog.exitOverride();
66 prog.version(npmPackage.version)
67 .description('Spelling Checker for Code')
68 .option('-c, --config <cspell.json>', 'Configuration file to use. By default cspell looks for cspell.json in the current directory.')
69 .option('--no-color', 'Turn off color.')
70 .option('--color', 'Force color');
71 prog.option('-v, --verbose', 'display more information about the files being checked and the configuration')
72 .option('--local <local>', 'Set language locals. i.e. "en,fr" for English and French, or "en-GB" for British English.')
73 .option('--language-id <language>', 'Force programming language for unknown extensions. i.e. "php" or "scala"')
74 .option('--languageId <language>', 'Force programming language for unknown extensions. i.e. "php" or "scala"')
75 .option('--wordsOnly', 'Only output the words not found in the dictionaries.')
76 .option('-u, --unique', 'Only output the first instance of a word not found in the dictionaries.')
77 .option('--debug', 'Output information useful for debugging cspell.json files.')
78 .option('-e, --exclude <glob>', 'Exclude files matching the glob pattern')
79 .option('--no-issues', 'Do not show the spelling errors.')
80 .option('--no-summary', 'Turn off summary message in console')
81 .option('-s, --silent', 'Silent mode, suppress error messages')
82 .option('-r, --root <root folder>', 'Root directory, defaults to current directory.')
83 .option('--must-find-files', 'Error if no files are found', false)
84 .option('--no-must-find-files', 'Do not error is no files are found')
85 // The following options are planned features
86 // .option('-w, --watch', 'Watch for any changes to the matching files and report any errors')
87 // .option('--force', 'Force the exit value to always be 0')
88 .option('--legacy', 'Legacy output')
89 .arguments('<files...>')
90 .action((files, options) => {
91 const { mustFindFiles } = options;
92 const emitters = getEmitters(options);
93 if (!files || !files.length) {
94 return;
95 }
96 showHelp = false;
97 return App.lint(files, options, emitters).then((result) => {
98 if (options.summary && !options.silent) {
99 console.error('CSpell: Files checked: %d, Issues found: %d in %d files', result.files, result.issues, result.filesWithIssues.size);
100 }
101 if (result.issues || result.errors || (mustFindFiles && !result.files)) {
102 throw new CheckFailed('check failed', 1);
103 }
104 });
105 });
106 prog.command('trace')
107 .description('Trace words')
108 .option('-c, --config <cspell.json>', 'Configuration file to use. By default cspell looks for cspell.json in the current directory.')
109 .option('--local <local>', 'Set language locals. i.e. "en,fr" for English and French, or "en-GB" for British English.')
110 .option('--languageId <language>', 'Force programming language for unknown extensions. i.e. "php" or "scala"')
111 .option('--no-color', 'Turn off color.')
112 .option('--color', 'Force color')
113 .arguments('<words...>')
114 .action((words, options) => {
115 showHelp = false;
116 return App.trace(words, options).then((result) => {
117 result.forEach(emitTraceResult);
118 });
119 });
120 prog.command('check <files...>')
121 .description('Spell check file(s) and display the result. The full file is displayed in color.')
122 .option('-c, --config <cspell.json>', 'Configuration file to use. By default cspell looks for cspell.json in the current directory.')
123 .option('--no-color', 'Turn off color.')
124 .option('--color', 'Force color')
125 .action(async (files, options) => {
126 showHelp = false;
127 for (const filename of files) {
128 console.log(chalk.yellowBright(`Check file: ${filename}`));
129 console.log();
130 try {
131 const result = await application_1.checkText(filename, options);
132 for (const item of result.items) {
133 const fn = item.flagIE === App.IncludeExcludeFlag.EXCLUDE
134 ? chalk.gray
135 : item.isError
136 ? chalk.red
137 : chalk.whiteBright;
138 const t = fn(item.text);
139 process.stdout.write(t);
140 }
141 console.log();
142 }
143 catch (e) {
144 console.error(`Failed to read "${filename}"`);
145 }
146 console.log();
147 }
148 });
149 /*
150 program
151 .command('init')
152 .description('(Alpha) Initialize a cspell.json file.')
153 .option('-o, --output <cspell.json>', 'define where to write file.')
154 .option('--extends <cspell.json>', 'extend an existing cspell.json file.')
155 .action((options: InitOptions) => {
156 showHelp = false;
157 CSpellApplication.createInit(options).then(
158 () => process.exit(0),
159 () => process.exit(1)
160 );
161 console.log('Init');
162 });
163 */
164 const usage = `
165
166Examples:
167 cspell "*.js" Check all .js files in the current directory
168 cspell "**/*.js" Check all .js files from the current directory
169 cspell "src/**/*.js" Only check .js under src
170 cspell "**/*.txt" "**/*.js" Check both .js and .txt files.
171 cat LICENSE | cspell stdin Read from stdin the contents of LICENSE
172`;
173 prog.on('--help', function () {
174 console.log(usage);
175 showHelp = false;
176 });
177 function reject(e) {
178 if (showHelp) {
179 prog.help();
180 }
181 rejects(e);
182 }
183 try {
184 prog.parseAsync(args)
185 .then(() => {
186 if (showHelp) {
187 prog.help();
188 }
189 resolve();
190 })
191 .catch(reject);
192 }
193 catch (e) {
194 reject(e);
195 }
196 });
197}
198exports.run = run;
199function emitTraceResult(r) {
200 const terminalWidth = process.stdout.columns || 120;
201 const widthName = 20;
202 const w = chalk.green(r.word);
203 const f = r.found ? chalk.whiteBright('*') : chalk.dim('-');
204 const n = chalk.yellowBright(pad(r.dictName, widthName));
205 const used = [r.word.length, 1, widthName].reduce((a, b) => a + b, 3);
206 const widthSrc = terminalWidth - used;
207 const s = chalk.white(trimMid(r.dictSource, widthSrc));
208 const line = [w, f, n, s].join(' ');
209 console.log(line);
210}
211function pad(s, w) {
212 return (s + ' '.repeat(w)).substr(0, w);
213}
214function trimMid(s, w) {
215 if (s.length <= w) {
216 return s;
217 }
218 const l = Math.floor((w - 3) / 2);
219 const r = Math.ceil((w - 3) / 2);
220 return s.substr(0, l) + '...' + s.substr(-r);
221}
222function formatIssue(template, issue) {
223 const { uri = '', row, col, text } = issue;
224 return template
225 .replace(/\$\{uri\}/, uri)
226 .replace(/\$\{row\}/, row.toString())
227 .replace(/\$\{col\}/, col.toString())
228 .replace(/\$\{text\}/, text);
229}
230class CheckFailed extends Error {
231 constructor(message, errorCode) {
232 super(message);
233 this.errorCode = errorCode;
234 }
235}
236exports.CheckFailed = CheckFailed;
237//# sourceMappingURL=app.js.map
\No newline at end of file