better-peg-tracer
Version:
A better tracer for PEG.js
98 lines (79 loc) • 2.93 kB
JavaScript
;
var pad = require("pad");
var chalk = Object.assign(require("chalk"), { enabled: true });
var defaultValue = require("default-value");
module.exports = function createBetterPegTracer(parsedString) {
var currentLevel = 0;
var lastWasFail = false;
var parsedStringLines = parsedString.split("\n");
var lastSeenRule = [];
return {
trace: function trace(event) {
if (event.type === "rule.fail" || event.type === "rule.match") {
currentLevel -= 1;
}
var ruleIndent = pad("", currentLevel * 4);
var eventName = event.type.replace(/^rule\./, "");
var isMultiline = parsedStringLines.length > 1;
var startLine = event.location.start.line;
var endLine = event.location.end.line;
var startColumn = event.location.start.column;
var endColumn = event.location.end.column;
var firstLine = parsedStringLines[startLine - 1];
var lastLine = parsedStringLines[endLine - 1];
var affectedString = void 0,
color = void 0,
startPosition = void 0,
endPosition = void 0,
position = void 0;
if (isMultiline) {
startPosition = pad(4, startLine) + ":" + pad(2, startColumn);
if (startLine !== endLine || startColumn !== endColumn) {
endPosition = pad(4, endLine) + ":" + pad(2, endColumn);
}
} else {
startPosition = startColumn;
if (startColumn !== endColumn) {
endPosition = endColumn;
}
}
position = pad(8, startPosition) + " " + chalk.white("│") + " " + pad(8, defaultValue(endPosition, ""));
if (startLine === endLine) {
if (startColumn === endColumn) {
/* Not reading a range, but rather attempting to find a match from the current point. */
if (event.location.start.offset < parsedString.length) {
affectedString = chalk.gray(firstLine.slice(startColumn - 1) + " ...");
} else {
affectedString = "";
}
} else {
affectedString = firstLine.slice(startColumn - 1, endColumn - 1);
}
} else {
affectedString = firstLine.slice(startColumn - 1) + " ... " + lastLine.slice(0, endColumn - 1);
}
if (event.type === "rule.enter") {
lastSeenRule[currentLevel] = event.rule;
}
if (event.type === "rule.match") {
color = chalk.green;
} else if (event.type === "rule.fail") {
color = chalk.red;
} else {
color = chalk.white;
}
var crumbs = lastSeenRule.slice(0, currentLevel).concat([color(event.rule)]);
var limitedCrumbs = void 0;
if (crumbs.length > 6) {
limitedCrumbs = crumbs.slice(0, 2).concat(["... " + (crumbs.length - 5) + " hidden ..."]).concat(crumbs.slice(-3));
} else {
limitedCrumbs = crumbs;
}
var line = [position, pad(eventName, 5), chalk.gray(pad(limitedCrumbs.join(" -> "), "90")), affectedString].join(" " + chalk.white("│") + " ");
process.stdout.write(color(line + "\n"));
if (event.type === "rule.enter") {
currentLevel += 1;
}
}
};
};