UNPKG

4.88 kBPlain TextView Raw
1#!/usr/bin/env node
2var fs = require('fs');
3var util = require('util');
4var path = require('path');
5var child_process = require('child_process');
6
7var esformatter = require('esformatter');
8var escodegen = require('escodegen');
9var _ = require('underscore');
10
11var jsfmt = require('../index.js');
12
13var tmp = require('tmp');
14tmp.setGracefulCleanup();
15
16var argv = require('minimist')(process.argv.slice(2), {
17 'string': ['rewrite', 'search'],
18 'boolean': ['comments', 'diff', 'format', 'list', 'write'],
19 'default': {
20 comments: true,
21 diff: false,
22 format: false,
23 list: false,
24 write: false
25 },
26 'alias': {
27 comments: 'c',
28 diff: 'd',
29 format: 'f',
30 list: 'l',
31 rewrite: 'r',
32 search: 's',
33 write: 'w'
34 }
35});
36
37if (argv.help || (!argv.format && !argv.search && !argv.rewrite)) {
38 console.log('jsfmt [flags] [path ...]');
39 console.log('\tAction:');
40 console.log('\t--format=false, -f=false: format the input javascript');
41 console.log('\t--search="", -s="": search rule (e.g., \'a.slice\')');
42 console.log('\t--rewrite="", -r="": rewrite rule (e.g., \'a.slice(b, len(a) -> a.slice(b)\')');
43 console.log('');
44 console.log('\tOutput (default is stdout):');
45 console.log("\t--list=false, -l=false: list files whose formatting differs from jsfmt's");
46 console.log('\t--diff=false, -d=false: display diffs instead of rewriting files');
47 console.log('\t--write=false, -w=false: write result to (source) file instead of stdout');
48 console.log('');
49 console.log('\tConfig:');
50 console.log('\t--comments=true, -c=true: include comments in result');
51 return;
52}
53
54function diff(pathA, pathB, callback) {
55 child_process.exec([
56 'git', 'diff', '--ignore-space-at-eol', '-b', '--no-index', '--', pathA, pathB
57 ].join(' '), callback);
58}
59
60function handleDiff(fullPath, originalJavascript, formattedJavascript) {
61 if (fullPath == 'stdin') {
62 tmp.file(function(err, pathA, fdA) {
63 if (err) throw err;
64 fs.writeSync(fdA, originalJavascript);
65
66 tmp.file(function(err, pathB, fdB) {
67 if (err) throw err;
68 fs.writeSync(fdB, formattedJavascript);
69
70 diff(pathA, pathB, function(err, stdout, stderr) {
71 if (stdout) console.log(stdout);
72 if (stderr) console.log(stderr);
73 });
74 });
75 });
76 } else {
77 tmp.file(function(err, pathA, fdA) {
78 if (err) throw err;
79 fs.writeSync(fdA, formattedJavascript);
80
81 diff(fullPath, pathA, function(err, stdout, stderr) {
82 if (stdout) console.log(stdout);
83 if (stderr) console.log(stderr);
84 });
85 });
86 }
87}
88
89function handleJavascript(fullPath, original) {
90 var formattingOptions = {
91 preset: 'default',
92 indent: {
93 value: ' '
94 }
95 };
96
97 var js = original;
98
99 if (argv.search) {
100 var cwd = process.cwd();
101 var relativePath = path.relative(cwd, fullPath);
102 jsfmt.search(js, argv.search).forEach(function(match) {
103 var node = match.node;
104 var loc = node.loc;
105 var startLine = loc.start.line;
106 var endLine = loc.end.line;
107 console.log([relativePath, _.uniq([startLine, endLine]).join(':')].join(':'));
108
109 var partialJavascript = js.split('\n').slice(startLine - 1, endLine).join('\n');
110 console.log(partialJavascript, '\n');
111 });
112 return;
113 }
114
115 if (argv.rewrite) {
116 js = jsfmt.rewrite(js, argv.rewrite).toString();
117 }
118
119 if (argv.format) {
120 js = esformatter.format(js, formattingOptions);
121 }
122
123 if (argv.diff) {
124 handleDiff(fullPath, original, js)
125 } else if (argv.list && original != js) {
126 // Print filenames who differ
127 console.log(fullPath);
128 } else if (argv.write) {
129 // Overwrite original file
130 fs.writeFileSync(fullPath, js);
131 } else {
132 // Print to stdout
133 console.log(js);
134 }
135}
136
137function handleDirectory(currentPath, callback) {
138 child_process.execFile('find', [currentPath, '-name', '*.js'], function(err, stdout, stderr) {
139 var paths = _.filter(stdout.split('\n').slice(0, -1), function(currentPath) {
140 return path.basename(currentPath).indexOf('.') != 0; // Remove hidden files
141 });
142 callback(paths);
143 });
144}
145
146var paths = argv._;
147
148if (paths.length > 0) {
149 paths.forEach(function(currentPath) {
150 var fullPath = path.join(process.cwd(), currentPath);
151 if (fs.statSync(fullPath).isDirectory()) {
152 handleDirectory(fullPath, function(paths) {
153 _.each(paths, function(fullPath) {
154 handleJavascript(path.normalize(fullPath), fs.readFileSync(fullPath, 'utf-8'));
155 });
156 });
157 } else {
158 handleJavascript(fullPath, fs.readFileSync(fullPath, 'utf-8'));
159 }
160 });
161} else {
162 var js = '';
163 process.stdin.setEncoding('utf8');
164 process.stdin.on('readable', function(chunk) {
165 var chunk = process.stdin.read();
166 if (chunk != null) {
167 js += chunk;
168 }
169 });
170 process.stdin.on('end', function() {
171 handleJavascript('stdin', js);
172 });
173}