UNPKG

better-peg-tracer

Version:

A better tracer for PEG.js

98 lines (79 loc) 2.93 kB
'use strict'; 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; } } }; };