-
-
Notifications
You must be signed in to change notification settings - Fork 219
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Export getLineAndColumnMessage via ohm.util.
- Loading branch information
Showing
13 changed files
with
476 additions
and
362 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
'use strict'; | ||
|
||
// -------------------------------------------------------------------- | ||
// Imports | ||
// -------------------------------------------------------------------- | ||
|
||
var common = require('./common'); | ||
|
||
// -------------------------------------------------------------------- | ||
// Private stuff | ||
// -------------------------------------------------------------------- | ||
|
||
// Given an array of numbers `arr`, return an array of the numbers as strings, | ||
// right-justified and padded to the same length. | ||
function padNumbersToEqualLength(arr) { | ||
var maxLen = 0; | ||
var strings = arr.map(function(n) { | ||
var str = n.toString(); | ||
maxLen = Math.max(maxLen, str.length); | ||
return str; | ||
}); | ||
return strings.map(function(s) { return common.padLeft(s, maxLen); }); | ||
} | ||
|
||
// -------------------------------------------------------------------- | ||
// Exports | ||
// -------------------------------------------------------------------- | ||
|
||
// Return an object with the line and column information for the given | ||
// offset in `str`. | ||
exports.getLineAndColumn = function(str, offset) { | ||
var lineNum = 1; | ||
var colNum = 1; | ||
|
||
var currOffset = 0; | ||
var lineStartOffset = 0; | ||
|
||
var nextLine = null; | ||
var prevLine = null; | ||
var prevLineStartOffset = -1; | ||
|
||
while (currOffset < offset) { | ||
var c = str.charAt(currOffset++); | ||
if (c === '\n') { | ||
lineNum++; | ||
colNum = 1; | ||
prevLineStartOffset = lineStartOffset; | ||
lineStartOffset = currOffset; | ||
} else if (c !== '\r') { | ||
colNum++; | ||
} | ||
} | ||
|
||
// Find the end of the target line. | ||
var lineEndOffset = str.indexOf('\n', lineStartOffset); | ||
if (lineEndOffset === -1) { | ||
lineEndOffset = str.length; | ||
} else { | ||
// Get the next line. | ||
var nextLineEndOffset = str.indexOf('\n', lineEndOffset + 1); | ||
nextLine = nextLineEndOffset === -1 ? str.slice(lineEndOffset) | ||
: str.slice(lineEndOffset, nextLineEndOffset); | ||
// Strip leading and trailing EOL char(s). | ||
nextLine = nextLine.replace(/^\r?\n/, '').replace(/\r$/, ''); | ||
} | ||
|
||
// Get the previous line. | ||
if (prevLineStartOffset >= 0) { | ||
prevLine = str.slice(prevLineStartOffset, lineStartOffset) | ||
.replace(/\r?\n$/, ''); // Strip trailing EOL char(s). | ||
} | ||
|
||
// Get the target line, stripping a trailing carriage return if necessary. | ||
var line = str.slice(lineStartOffset, lineEndOffset).replace(/\r$/, ''); | ||
|
||
return { | ||
lineNum: lineNum, | ||
colNum: colNum, | ||
line: line, | ||
prevLine: prevLine, | ||
nextLine: nextLine | ||
}; | ||
}; | ||
|
||
// Return a nicely-formatted string describing the line and column for the | ||
// given offset in `str`. | ||
exports.getLineAndColumnMessage = function(str, offset) { | ||
var lineAndCol = exports.getLineAndColumn(str, offset); | ||
var sb = new common.StringBuffer(); | ||
sb.append('Line ' + lineAndCol.lineNum + ', col ' + lineAndCol.colNum + ':\n'); | ||
|
||
// An array of the previous, current, and next line numbers as strings of equal length. | ||
var lineNumbers = padNumbersToEqualLength([ | ||
lineAndCol.prevLine == null ? 0 : lineAndCol.lineNum - 1, | ||
lineAndCol.lineNum, | ||
lineAndCol.nextLine == null ? 0 : lineAndCol.lineNum + 1 | ||
]); | ||
|
||
// Helper for appending formatting input lines to the buffer. | ||
function appendLine(num, content, prefix) { | ||
sb.append(prefix + lineNumbers[num] + ' | ' + content + '\n'); | ||
} | ||
|
||
// Include the previous line for context if possible. | ||
if (lineAndCol.prevLine != null) { | ||
appendLine(0, lineAndCol.prevLine, ' '); | ||
} | ||
// Line that the error occurred on. | ||
appendLine(1, lineAndCol.line, '> '); | ||
|
||
// Line indicating the column on which the error occurred. | ||
var gutterWidth = 2 + lineNumbers[1].length + 3; | ||
sb.append(common.padLeft('^', gutterWidth + lineAndCol.colNum) + '\n'); | ||
|
||
// Include the next line for context if possible. | ||
if (lineAndCol.nextLine != null) { | ||
appendLine(2, lineAndCol.nextLine, ' '); | ||
} | ||
return sb.contents(); | ||
}; |
Oops, something went wrong.