grasp
Version:
JavaScript structural search, replace, and refactor
480 lines (479 loc) • 16 kB
JavaScript
// Generated by LiveScript 1.5.0
(function(){
var path, squery, equery, async, minimatch, flowParser, ref$, min, sortWith, lines, chars, split, join, map, Obj, format, formatResult, formatName, formatCount, replace, parseOptions, generateHelp, generateHelpForOption, help, _console, version, run, getQueryEngine, slice$ = [].slice, toString$ = {}.toString;
path = require('path');
squery = require('grasp-squery');
equery = require('grasp-equery');
async = require('async');
minimatch = require('minimatch');
flowParser = require('flow-parser');
ref$ = require('prelude-ls'), min = ref$.min, sortWith = ref$.sortWith, lines = ref$.lines, chars = ref$.chars, split = ref$.split, join = ref$.join, map = ref$.map, Obj = ref$.Obj;
format = require('./format'), formatResult = format.formatResult, formatName = format.formatName, formatCount = format.formatCount;
replace = require('./replace').replace;
ref$ = require('./options'), parseOptions = ref$.parse, generateHelp = ref$.generateHelp, generateHelpForOption = ref$.generateHelpForOption;
help = require('./help');
_console = console;
version = require('../package.json').version;
run = function(arg$){
var ref$, args, error, ref1$, callback, exit, data, stdin, fs, textFormat, input, console, options, positional, debug, e, versionString, getHelp, helpString, queryEngine, parser, parserOptions, that, selector, targets, targetsLen, replacement, isDir, color, bold, textFormatFuncs, resultsData, resultsFormat, callCallback, out, parsedSelector, resultsSortFunc, search, processResults, getToMap, end, exts, testExt, exclude, testExclude, targetPaths, searchTarget, cwd, this$ = this;
ref$ = arg$ != null
? arg$
: {}, args = ref$.args, error = (ref1$ = ref$.error) != null
? ref1$
: function(it){
throw new Error(it);
}, callback = (ref1$ = ref$.callback) != null
? ref1$
: function(){}, exit = (ref1$ = ref$.exit) != null
? ref1$
: function(){}, data = (ref1$ = ref$.data) != null ? ref1$ : false, stdin = ref$.stdin, fs = (ref1$ = ref$.fs) != null
? ref1$
: require('fs'), textFormat = (ref1$ = ref$.textFormat) != null
? ref1$
: require('cli-color'), input = ref$.input, console = (ref1$ = ref$.console) != null ? ref1$ : _console;
if (args == null) {
error('Error: Must specify arguments.');
exit(2);
return;
}
try {
options = parseOptions(args), positional = options._, debug = options.debug;
} catch (e$) {
e = e$;
error(e.message);
exit(2);
return;
}
if (debug) {
console.time('everything');
console.log('options:');
console.log(options);
}
if (options.version) {
versionString = "grasp v" + version;
callback(versionString);
exit(0, versionString);
return;
}
getHelp = function(positional){
positional == null && (positional = []);
return help(generateHelp, generateHelpForOption, positional, {
version: version
});
};
if (options.help) {
helpString = getHelp(positional);
callback(helpString);
exit(0, helpString);
return;
}
queryEngine = options.engine != null
? require(options.engine)
: options.squery
? squery
: options.equery ? equery : squery;
ref$ = (function(){
switch (options.parser[0]) {
case 'flow-parser':
return [flowParser, options.parser[1]];
default:
return [require(options.parser[0]), options.parser[1]];
}
}()), parser = ref$[0], parserOptions = ref$[1];
options.context == null && (options.context = (ref$ = options.NUM) != null ? ref$ : 0);
options.beforeContext == null && (options.beforeContext = options.context);
options.afterContext == null && (options.afterContext = options.context);
if ((that = options.file) != null) {
try {
selector = fs.readFileSync(that, 'utf8');
} catch (e$) {
e = e$;
error("Error: No such file '" + options.file + "'.");
exit(2);
return;
}
targets = positional;
} else {
selector = positional[0];
targets = slice$.call(positional, 1);
}
if (!targets.length) {
targets = options.recursive
? ['.']
: ['-'];
}
targetsLen = targets.length;
if ((that = options.replace) != null) {
replacement = that;
}
if (that = options.replaceFunc) {
replacement = that;
} else if (that = options.replaceFile) {
try {
replacement = fs.readFileSync(that, 'utf8').replace(/([\s\S]*)\n$/, '$1');
} catch (e$) {
e = e$;
error("Error: No such file '" + options.replaceFile + "'.");
exit(2);
return;
}
}
if (selector == null) {
error('Error: No selector specified.');
helpString = getHelp();
callback(helpString);
exit(2, helpString);
return;
}
if ((that = options.filename) != null) {
options.displayFilename = that;
} else if (targetsLen > 1) {
options.displayFilename = true;
} else {
try {
isDir = targets[0] === '-'
? false
: fs.lstatSync(targets[0]).isDirectory();
if (isDir && !options.recursive) {
console.warn("'" + targets[0] + "' is a directory. Use '-r, --recursive' to recursively search directories.");
}
options.displayFilename = isDir;
} catch (e$) {
e = e$;
error("Error: No such file or directory '" + targets[0] + "'.");
exit(2);
return;
}
}
color = Obj.map(function(it){
if (options.color) {
return it;
} else {
return function(it){
return it + "";
};
}
}, {
green: textFormat.green,
cyan: textFormat.cyan,
magenta: textFormat.magenta,
red: textFormat.red
});
bold = options.bold
? textFormat.bold
: function(it){
return it + "";
};
textFormatFuncs = {
color: color,
bold: bold
};
resultsData = [];
resultsFormat = 'default';
callCallback = !options.quiet && !options.json && !options.to && !options.inPlace;
out = function(it){
resultsData.push(it);
if (callCallback) {
callback(it);
}
};
if (debug) {
console.time('parse-selector');
}
parsedSelector = queryEngine.parse(selector);
if (debug) {
console.timeEnd('parse-selector');
console.log('parsed-selector:');
console.log(JSON.stringify(parsedSelector, null, 2));
}
resultsSortFunc = function(a, b){
var aStart, bStart, lineDiff;
aStart = a.loc.start;
bStart = b.loc.start;
lineDiff = aStart.line - bStart.line;
if (lineDiff === 0) {
return aStart.column - bStart.column;
} else {
return lineDiff;
}
};
search = function(name, input){
var cleanInput, parsedInput, e, results, resultsLen, count, that, sortedResults, slicedResults, replaced, inputLines, inputLinesLength, i$, len$, result;
if (debug) {
console.time("search-total:" + name);
}
cleanInput = input.replace(/^#!.*\n/, '');
try {
if (debug) {
console.time("parse-input:" + name);
}
parsedInput = parser.parse(cleanInput, parserOptions);
if (debug) {
console.timeEnd("parse-input:" + name);
}
if (options.printAst) {
console.log(JSON.stringify(parsedInput, null, 2));
}
} catch (e$) {
e = e$;
throw new Error("Error: Could not parse JavaScript from '" + name + "'. " + e.message);
}
if (debug) {
console.time("query:" + name);
}
results = queryEngine.queryParsed(parsedSelector, parsedInput);
if (debug) {
console.timeEnd("query:" + name);
}
resultsLen = results.length;
count = (that = options.maxCount) != null ? min(that, resultsLen) : resultsLen;
sortedResults = sortWith(resultsSortFunc, results);
slicedResults = slice$.call(sortedResults, 0, count);
if (replacement != null) {
try {
replaced = replace(replacement, cleanInput, slicedResults, queryEngine);
if (options.to || options.inPlace) {
resultsFormat = 'pairs';
out([name, replaced]);
} else {
out(replaced);
}
} catch (e$) {
e = e$;
console.error(name + ": Error during replacement. " + e.message + ".");
}
} else if (options.count) {
if (options.displayFilename) {
if (options.json || data) {
resultsFormat = 'pairs';
out([name, count]);
} else {
out(formatCount(color, count, name));
}
} else {
out(options.json || data
? count
: formatCount(color, count));
}
} else if (options.filesWithoutMatch || options.filesWithMatches) {
if (options.filesWithMatches && count || options.filesWithoutMatch && !count) {
out(options.json || data
? name
: formatName(color, name));
}
} else {
if (options.json || data) {
if (options.displayFilename) {
resultsFormat = 'pairs';
out([name, slicedResults]);
} else {
resultsFormat = 'lists';
out(slicedResults);
}
} else {
inputLines = lines(cleanInput);
inputLinesLength = cleanInput.length;
for (i$ = 0, len$ = slicedResults.length; i$ < len$; ++i$) {
result = slicedResults[i$];
out(formatResult(name, inputLines, inputLinesLength, textFormatFuncs, options, result));
}
}
}
if (debug) {
console.timeEnd("search-total:" + name);
}
};
processResults = function(){
if (resultsData.length) {
if (resultsFormat === 'pairs') {
return Obj.pairsToObj(resultsData);
} else if (resultsFormat === 'lists') {
if (targetsLen === 1) {
return resultsData[0];
} else {
return resultsData;
}
} else {
return resultsData;
}
} else {
return [];
}
};
getToMap = function(inputPaths){
var mapping, i$, len$, inputPath;
if (options.inPlace) {
return Obj.listsToObj(inputPaths, inputPaths);
} else if (toString$.call(options.to).slice(8, -1) === 'Object') {
return options.to;
} else {
mapping = {};
for (i$ = 0, len$ = inputPaths.length; i$ < len$; ++i$) {
inputPath = inputPaths[i$];
mapping[inputPath] = options.to.replace(/%/, path.basename(inputPath, path.extname(inputPath)));
}
return mapping;
}
};
end = function(inputPaths){
var exitCode, processedResults, toMap, inputPath, contents, targetPath, jsonString;
exitCode = resultsData.length ? 0 : 1;
processedResults = processResults();
if (replacement && options.to || options.inPlace) {
toMap = getToMap(inputPaths);
for (inputPath in processedResults) {
contents = processedResults[inputPath];
targetPath = toMap[inputPath];
if (targetPath === '-') {
callback(contents);
} else {
if (targetPath) {
fs.writeFileSync(targetPath, contents);
}
}
}
} else if (options.json) {
jsonString = JSON.stringify(processedResults);
callback(jsonString);
}
if (debug) {
console.timeEnd('everything');
}
return exit(exitCode, options.json ? jsonString : processedResults);
};
exts = options.extensions;
testExt = exts.length === 0 || exts.length === 1 && exts[0] === '.'
? function(){
return true;
}
: function(it){
return it.match(RegExp('\\.(?:' + exts.join('|') + ')$'));
};
exclude = options.exclude;
testExclude = !exclude || exclude.length === 0
? function(){
return true;
}
: function(file, basePath, upPath){
var filePath;
filePath = path.relative(basePath, path.join(upPath, file));
return exclude.every(function(excludePattern){
return !minimatch(filePath, excludePattern, options.minimatchOptions);
});
};
targetPaths = [];
searchTarget = function(basePath, upPath){
return function(target, done){
var output, targetPath, stat, fileContents, displayPath, e, this$ = this;
try {
if (target === '-') {
if (!stdin) {
throw new Error('Error: stdin not defined.');
}
targetPaths.push('-');
output = '';
stdin.setEncoding('utf-8');
stdin.on('data', (function(it){
return output += it;
}));
stdin.on('end', function(){
var e;
try {
search('(standard input)', output);
} catch (e$) {
e = e$;
console.error(e.message);
}
return done();
});
stdin.resume();
} else {
targetPath = path.resolve(upPath, target);
stat = fs.lstatSync(targetPath);
if (stat.isDirectory() && options.recursive) {
async.eachSeries(fs.readdirSync(targetPath), searchTarget(basePath, targetPath), function(){
return async.setImmediate(function(){
return done();
});
});
} else if (stat.isFile() && testExt(target) && testExclude(target, basePath, upPath)) {
fileContents = fs.readFileSync(targetPath, 'utf8');
displayPath = path.relative(basePath, targetPath);
targetPaths.push(displayPath);
search(displayPath, fileContents);
done();
} else {
done();
}
}
} catch (e$) {
e = e$;
console.error(e.message);
done();
}
};
};
if (input) {
search('(input)', input);
return end(['-']);
} else {
cwd = process.cwd();
async.eachSeries(targets, searchTarget(cwd, cwd), function(){
return end(targetPaths);
});
}
};
getQueryEngine = function(it){
return {
squery: 'grasp-squery',
equery: 'grasp-equery'
}[it] || it;
};
run.VERSION = version;
run.search = curry$(function(engine, selector, input){
return run({
args: {
_: [selector],
engine: getQueryEngine(engine)
},
input: input,
data: true,
exit: function(arg$, results){
return results;
}
});
});
run.replace = curry$(function(engine, selector, replacement, input){
var args;
args = {
_: [selector],
engine: getQueryEngine(engine)
};
if (toString$.call(replacement).slice(8, -1) === 'Function') {
args.replaceFunc = replacement;
} else {
args.replace = replacement;
}
return run({
args: args,
input: input,
exit: function(arg$, results){
return results[0];
}
});
});
module.exports = run;
function curry$(f, bound){
var context,
_curry = function(args) {
return f.length > 1 ? function(){
var params = args ? args.concat() : [];
context = bound ? context || this : this;
return params.push.apply(params, arguments) <
f.length && arguments.length ?
_curry.call(context, params) : f.apply(context, params);
} : f;
};
return _curry();
}
}).call(this);