grasp
Version:
JavaScript structural search, replace, and refactor
324 lines (323 loc) • 12.3 kB
JavaScript
// Generated by LiveScript 1.5.0
(function(){
var ref$, lines, unlines, filter, fold, capitalize, camelize, dasherize, levn, getRaw, filterRegex, replacer, getReplacementFunc, replace, slice$ = [].slice, toString$ = {}.toString;
ref$ = require('prelude-ls'), lines = ref$.lines, unlines = ref$.unlines, filter = ref$.filter, fold = ref$.fold, capitalize = ref$.capitalize, camelize = ref$.camelize, dasherize = ref$.dasherize;
levn = require('levn');
getRaw = function(input, node){
var raw, that, start, end;
raw = (that = node.raw)
? that
: node.range != null
? (start = node.range[0], end = node.range[1], input.slice(start, end))
: node.key != null && node.value != null ? input.slice(node.key.start, node.value.end) : '';
node.raw = raw;
return (node.rawPrepend || '') + "" + raw + (node.rawAppend || '');
};
filterRegex = /\s+\|\s+([-a-zA-Z]+)((?:\s+(?:'(?:\\'|[^'])*'|"(?:\\"|[^"])*"|[^\|\s]+))*)/;
replacer = function(input, node, queryEngine){
return function(arg$, replacementArg){
var noFilters, origResults, ref$, filters, selector, that, e, results, rawPrepend, rawAppend, join, textOperations, filterName, argsStr, args, ref1$, pre, post, i$, len$, arg, result, n, len, rawResults, res$, outputString, this$ = this;
noFilters = false;
if (/^\s*\|\s+/.test(replacementArg)) {
origResults = [node];
ref$ = (" " + replacementArg.trim()).split(filterRegex), filters = slice$.call(ref$, 1);
} else {
ref$ = replacementArg.trim().split(filterRegex), selector = ref$[0], filters = slice$.call(ref$, 1);
if (that = (ref$ = node._named) != null ? ref$[selector] : void 8) {
origResults = [].concat(that);
} else {
try {
origResults = queryEngine.query(selector, node);
} catch (e$) {
e = e$;
noFilters = true;
}
}
}
if (noFilters || !origResults.length) {
origResults = queryEngine.query(replacementArg, node);
filters = [];
}
if (origResults.length) {
results = origResults;
rawPrepend = '';
rawAppend = '';
join = null;
textOperations = [];
while (filters.length) {
filterName = filters.shift();
argsStr = filters.shift().trim();
argsStr += filters.shift();
args = levn.parse('Array', argsStr);
if (!args.length && (filterName === 'prepend' || filterName === 'before' || filterName === 'after' || filterName === 'prepend' || filterName === 'append' || filterName === 'wrap' || filterName === 'nth' || filterName === 'nth-last' || filterName === 'slice' || filterName === 'each' || filterName === 'replace' || filterName === 'substring' || filterName === 'substr' || filterName === 'str-slice')) {
throw new Error("No arguments supplied for '" + filterName + "' filter");
} else if (in$(filterName, ['replace']) && args.length < 2) {
throw new Error("Must supply at least two arguments for '" + filterName + "' filter");
}
switch (filterName) {
case 'join':
join = args.length ? args[0] + "" : '';
break;
case 'before':
rawPrepend = args[0] + "" + rawPrepend;
break;
case 'after':
rawAppend += args[0] + "";
break;
case 'wrap':
ref1$ = args.length === 1 ? [args[0], args[0]] : args, pre = ref1$[0], post = ref1$[1];
rawPrepend = pre + "" + rawPrepend;
rawAppend += post + "";
break;
case 'prepend':
for (i$ = 0, len$ = args.length; i$ < len$; ++i$) {
arg = args[i$];
results.unshift({
type: 'Raw',
raw: arg + ""
});
}
break;
case 'append':
for (i$ = 0, len$ = args.length; i$ < len$; ++i$) {
arg = args[i$];
results.push({
type: 'Raw',
raw: arg + ""
});
}
break;
case 'each':
if (args.length < 2) {
throw new Error("No arguments supplied for 'each " + args[0] + "'");
}
switch (args[0]) {
case 'before':
for (i$ = 0, len$ = results.length; i$ < len$; ++i$) {
result = results[i$];
result.rawPrepend = args[1] + "" + ((ref1$ = result.rawPrepend) != null ? ref1$ : '');
}
break;
case 'after':
for (i$ = 0, len$ = results.length; i$ < len$; ++i$) {
result = results[i$];
result.rawAppend = ((ref1$ = result.rawAppend) != null ? ref1$ : '') + "" + args[1];
}
break;
case 'wrap':
ref1$ = args.length === 2
? [args[1], args[1]]
: [args[1], args[2]], pre = ref1$[0], post = ref1$[1];
for (i$ = 0, len$ = results.length; i$ < len$; ++i$) {
result = results[i$];
result.rawPrepend = pre + "" + ((ref1$ = result.rawPrepend) != null ? ref1$ : '');
result.rawAppend = ((ref1$ = result.rawAppend) != null ? ref1$ : '') + "" + post;
}
break;
default:
throw new Error("'" + args[0] + "' is not supported by 'each'");
}
break;
case 'nth':
n = +args[0];
results = results.slice(n, n + 1);
break;
case 'nth-last':
n = results.length - +args[0] - 1;
results = results.slice(n, n + 1);
break;
case 'first':
case 'head':
results = results.slice(0, 1);
break;
case 'tail':
results = results.slice(1);
break;
case 'last':
len = results.length;
results = results.slice(len - 1, len);
break;
case 'initial':
results = results.slice(0, results.length - 1);
break;
case 'slice':
results = [].slice.apply(results, args);
break;
case 'reverse':
results.reverse();
break;
case 'replace':
(fn$.call(this, args));
break;
case 'lowercase':
textOperations.push(fn1$);
break;
case 'uppercase':
textOperations.push(fn2$);
break;
case 'capitalize':
textOperations.push(capitalize);
break;
case 'uncapitalize':
textOperations.push(fn3$);
break;
case 'camelize':
textOperations.push(camelize);
break;
case 'dasherize':
textOperations.push(dasherize);
break;
case 'trim':
textOperations.push(fn4$);
break;
case 'substring':
(fn5$.call(this, args));
break;
case 'substr':
(fn6$.call(this, args));
break;
case 'str-slice':
(fn7$.call(this, args));
break;
default:
throw new Error("Invalid filter: " + filterName + (argsStr ? " " + argsStr : ''));
}
}
res$ = [];
for (i$ = 0, len$ = results.length; i$ < len$; ++i$) {
result = results[i$];
res$.push(getRaw(input, result));
}
rawResults = res$;
outputString = rawPrepend + "" + (join != null
? rawResults.join(join)
: rawResults[0]) + rawAppend;
if (textOperations.length) {
return fold(curry$(function(x$, y$){
return y$(x$);
}), outputString, textOperations);
} else {
return outputString;
}
} else {
return '';
}
function fn$(args){
var this$ = this;
textOperations.push(function(it){
return it.replace(args[0], args[1]);
});
}
function fn1$(it){
return it.toLowerCase();
}
function fn2$(it){
return it.toUpperCase();
}
function fn3$(it){
return it.charAt(0).toLowerCase() + it.slice(1);
}
function fn4$(it){
return it.trim();
}
function fn5$(args){
var this$ = this;
textOperations.push(function(it){
return it.substring(args[0], args[1]);
});
}
function fn6$(args){
var this$ = this;
textOperations.push(function(it){
return it.substr(args[0], args[1]);
});
}
function fn7$(args){
var this$ = this;
textOperations.push(function(it){
return it.slice(args[0], args[1]);
});
}
};
};
getReplacementFunc = function(replacement, input, queryEngine){
var replacementPrime;
if (toString$.call(replacement).slice(8, -1) === 'Function') {
return function(node){
return replacement(function(it){
return getRaw(input, it);
}, node, function(it){
return queryEngine.query(it, node);
}, node._named);
};
} else {
replacementPrime = replacement.replace(/\\n/g, '\n');
return function(node){
return replacementPrime.replace(/{{}}/g, function(){
return getRaw(input, node);
}).replace(/{{((?:[^}]|}[^}])+)}}/g, replacer(input, node, queryEngine));
};
}
};
replace = function(replacement, input, nodes, queryEngine){
var inputLines, colOffset, lineOffset, lastLine, prevNode, replaceNode, i$, len$, node, ref$, ref1$, ref2$, start, end, startLineNum, endLineNum, numberOfLines, startCol, endCol, replaceLines, startLine, endLine, startContext, endContext, replaceLast, endLen;
inputLines = lines(input);
colOffset = 0;
lineOffset = 0;
lastLine = null;
prevNode = {
range: [0, 0]
};
replaceNode = getReplacementFunc(replacement, input, queryEngine);
for (i$ = 0, len$ = nodes.length; i$ < len$; ++i$) {
node = nodes[i$];
if (((ref$ = node.range) != null ? ref$[0] : void 8) < ((ref1$ = prevNode.range) != null ? ref1$[1] : void 8)) {
continue;
}
ref2$ = node.loc, start = ref2$.start, end = ref2$.end;
startLineNum = start.line - 1 + lineOffset;
endLineNum = end.line - 1 + lineOffset;
numberOfLines = endLineNum - startLineNum + 1;
colOffset = lastLine === startLineNum ? colOffset : 0;
startCol = start.column + colOffset;
endCol = end.column + (startLineNum === endLineNum ? colOffset : 0);
replaceLines = lines(replaceNode(node));
startLine = inputLines[startLineNum];
endLine = inputLines[endLineNum];
startContext = startLine.slice(0, startCol);
endContext = endLine.slice(endCol);
replaceLines[0] = startContext + "" + ((ref2$ = replaceLines[0]) != null ? ref2$ : '');
replaceLast = replaceLines[replaceLines.length - 1];
endLen = replaceLast.length;
replaceLines[replaceLines.length - 1] = replaceLast + "" + endContext;
inputLines.splice(startLineNum, numberOfLines);
inputLines = inputLines.slice(0, startLineNum).concat(replaceLines).concat(inputLines.slice(startLineNum));
lineOffset += replaceLines.length - numberOfLines;
colOffset += endLen - endCol;
lastLine = endLineNum + lineOffset;
prevNode = node;
}
return unlines(inputLines);
};
module.exports = {
replace: replace
};
function in$(x, xs){
var i = -1, l = xs.length >>> 0;
while (++i < l) if (x === xs[i]) return true;
return false;
}
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);