UNPKG

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