| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env node | |
| 2 'use strict'; | |
| 3 | |
| 4 var fs = require('fs'); | |
| 5 var os = require('os'); | |
| 6 var path = require('path'); | |
| 7 var spawn = require('child_process').spawn; | |
| 8 var globby = require('globby'); | |
| 9 var async = require('async'); | |
| 10 | |
| 11 var VERSION = '1.0.45'; | |
| 12 var LOCATION = __filename; | |
| 13 var CLANG_FORMAT_NODE_MODULES_PATH = path.resolve(__dirname, '..', '..', 'node_m
odules', 'clang-format'); | |
| 14 | |
| 15 /** | |
| 16 * Start a child process running the native clang-format binary. | |
| 17 * @param file a Vinyl virtual file reference | |
| 18 * @param enc the encoding to use for reading stdout | |
| 19 * @param style valid argument to clang-format's '-style' flag | |
| 20 * @param done callback invoked when the child process terminates | |
| 21 * @returns {Stream} the formatted code | |
| 22 */ | |
| 23 function clangFormat(file, enc, style, done) { | |
| 24 var args = ['-style=' + style, file.path]; | |
| 25 return spawnClangFormat(args, done, ['ignore', 'pipe', process.stderr]).stdout
; | |
| 26 } | |
| 27 | |
| 28 /** | |
| 29 * Spawn the clang-format binary with given arguments. | |
| 30 */ | |
| 31 function spawnClangFormat(args, done, stdio) { | |
| 32 // WARNING: This function's interface should stay stable across versions for t
he cross-version | |
| 33 // loading below to work. | |
| 34 if (args.indexOf('-version') !== -1 || args.indexOf('--version') !== -1) { | |
| 35 // Print our version. | |
| 36 // This makes it impossible to format files called '-version' or '--version'
. That's a feature. | |
| 37 // minimist & Co don't support single dash args, which we need to match bina
ry clang-format. | |
| 38 console.log('clang-format NPM version', VERSION, 'at', LOCATION); | |
| 39 process.exit(0); | |
| 40 } | |
| 41 var nativeBinary; | |
| 42 if (os.platform() === 'win32') | |
| 43 nativeBinary = CLANG_FORMAT_NODE_MODULES_PATH + '/bin/win32/clang-format.exe
'; | |
| 44 else | |
| 45 nativeBinary = CLANG_FORMAT_NODE_MODULES_PATH + '/bin/' + os.platform() + '_
' + os.arch() + '/clang-format'; | |
| 46 | |
| 47 if (!fs.existsSync(nativeBinary)) { | |
| 48 message = 'FATAL: This module doesn\'t bundle the clang-format executable fo
r your platform. ' + | |
| 49 '(' + os.platform() + '_' + os.arch() + ')\n' + | |
| 50 'Consider installing it with your native package manager instead.\n'; | |
| 51 throw new Error(message); | |
| 52 } | |
| 53 | |
| 54 // extract glob, if present | |
| 55 var globString = args.filter(function(arg) { | |
| 56 return arg.indexOf('--glob=') === 0; | |
| 57 }) | |
| 58 .map(function(arg) { | |
| 59 return arg.replace('--glob=', ''); | |
| 60 }) | |
| 61 .shift(); | |
| 62 | |
| 63 // extract ignore, if present | |
| 64 var ignore = args.filter(function(arg) { | |
| 65 return arg.indexOf('--ignore=') === 0; | |
| 66 }) | |
| 67 .map(function(arg) { | |
| 68 return arg.replace('--ignore=', ''); | |
| 69 }) | |
| 70 .shift(); | |
| 71 | |
| 72 if (globString) { | |
| 73 var globs = globString.split(','); | |
| 74 // remove glob and ignore from arg list | |
| 75 args = args.filter(function(arg) { | |
| 76 return arg.indexOf('--glob=') === -1; | |
| 77 }) | |
| 78 .filter(function(arg) { | |
| 79 return arg.indexOf('--ignore=') === -1; | |
| 80 }); | |
| 81 | |
| 82 var options = {}; | |
| 83 if (ignore) | |
| 84 options.ignore = ignore.split(','); | |
| 85 | |
| 86 | |
| 87 return globby(globs, options).then(function(files) { | |
| 88 // split file array into chunks of 30 | |
| 89 var i, j, chunks = [], chunkSize = 30; | |
| 90 for (i = 0, j = files.length; i < j; i += chunkSize) | |
| 91 chunks.push(files.slice(i, i + chunkSize)); | |
| 92 | |
| 93 | |
| 94 // launch a new process for each chunk | |
| 95 async.series( | |
| 96 chunks.map(function(chunk) { | |
| 97 return function(callback) { | |
| 98 var clangFormatProcess = spawn(nativeBinary, args.concat(chunk), {
stdio: stdio}); | |
| 99 clangFormatProcess.on('close', function(exit) { | |
| 100 if (exit !== 0) | |
| 101 callback(exit); | |
| 102 else | |
| 103 callback(null, exit); | |
| 104 }); | |
| 105 }; | |
| 106 }), | |
| 107 function(err, results) { | |
| 108 if (err) | |
| 109 done(err); | |
| 110 console.log('\n'); | |
| 111 console.log('ran clang-format on', files.length, files.length === 1
? 'file' : 'files'); | |
| 112 done(results.shift() || 0); | |
| 113 }); | |
| 114 }); | |
| 115 } else { | |
| 116 var clangFormatProcess = spawn(nativeBinary, args, {stdio: stdio}); | |
| 117 clangFormatProcess.on('close', function(exit) { | |
| 118 if (exit) | |
| 119 done(exit); | |
| 120 }); | |
| 121 return clangFormatProcess; | |
| 122 } | |
| 123 } | |
| 124 | |
| 125 function main() { | |
| 126 try { | |
| 127 // Pass all arguments to clang-format, including e.g. -version etc. | |
| 128 spawnClangFormat(process.argv.slice(2), process.exit, 'inherit'); | |
| 129 } catch (e) { | |
| 130 process.stdout.write(e.message); | |
| 131 process.exit(1); | |
| 132 } | |
| 133 } | |
| 134 | |
| 135 module.exports = clangFormat; | |
| 136 module.exports.version = VERSION; | |
| 137 module.exports.location = LOCATION; | |
| 138 module.exports.spawnClangFormat = spawnClangFormat; | |
| 139 | |
| 140 if (require.main === module) | |
| 141 main(); | |
| OLD | NEW |