You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
101 lines
3.0 KiB
101 lines
3.0 KiB
'use strict'; |
|
|
|
|
|
var common = require('./common'); |
|
|
|
|
|
// get snippet for a single line, respecting maxLength |
|
function getLine(buffer, lineStart, lineEnd, position, maxLineLength) { |
|
var head = ''; |
|
var tail = ''; |
|
var maxHalfLength = Math.floor(maxLineLength / 2) - 1; |
|
|
|
if (position - lineStart > maxHalfLength) { |
|
head = ' ... '; |
|
lineStart = position - maxHalfLength + head.length; |
|
} |
|
|
|
if (lineEnd - position > maxHalfLength) { |
|
tail = ' ...'; |
|
lineEnd = position + maxHalfLength - tail.length; |
|
} |
|
|
|
return { |
|
str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, '→') + tail, |
|
pos: position - lineStart + head.length // relative position |
|
}; |
|
} |
|
|
|
|
|
function padStart(string, max) { |
|
return common.repeat(' ', max - string.length) + string; |
|
} |
|
|
|
|
|
function makeSnippet(mark, options) { |
|
options = Object.create(options || null); |
|
|
|
if (!mark.buffer) return null; |
|
|
|
if (!options.maxLength) options.maxLength = 79; |
|
if (typeof options.indent !== 'number') options.indent = 1; |
|
if (typeof options.linesBefore !== 'number') options.linesBefore = 3; |
|
if (typeof options.linesAfter !== 'number') options.linesAfter = 2; |
|
|
|
var re = /\r?\n|\r|\0/g; |
|
var lineStarts = [ 0 ]; |
|
var lineEnds = []; |
|
var match; |
|
var foundLineNo = -1; |
|
|
|
while ((match = re.exec(mark.buffer))) { |
|
lineEnds.push(match.index); |
|
lineStarts.push(match.index + match[0].length); |
|
|
|
if (mark.position <= match.index && foundLineNo < 0) { |
|
foundLineNo = lineStarts.length - 2; |
|
} |
|
} |
|
|
|
if (foundLineNo < 0) foundLineNo = lineStarts.length - 1; |
|
|
|
var result = '', i, line; |
|
var lineNoLength = Math.min(mark.line + options.linesAfter, lineEnds.length).toString().length; |
|
var maxLineLength = options.maxLength - (options.indent + lineNoLength + 3); |
|
|
|
for (i = 1; i <= options.linesBefore; i++) { |
|
if (foundLineNo - i < 0) break; |
|
line = getLine( |
|
mark.buffer, |
|
lineStarts[foundLineNo - i], |
|
lineEnds[foundLineNo - i], |
|
mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]), |
|
maxLineLength |
|
); |
|
result = common.repeat(' ', options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) + |
|
' | ' + line.str + '\n' + result; |
|
} |
|
|
|
line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength); |
|
result += common.repeat(' ', options.indent) + padStart((mark.line + 1).toString(), lineNoLength) + |
|
' | ' + line.str + '\n'; |
|
result += common.repeat('-', options.indent + lineNoLength + 3 + line.pos) + '^' + '\n'; |
|
|
|
for (i = 1; i <= options.linesAfter; i++) { |
|
if (foundLineNo + i >= lineEnds.length) break; |
|
line = getLine( |
|
mark.buffer, |
|
lineStarts[foundLineNo + i], |
|
lineEnds[foundLineNo + i], |
|
mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]), |
|
maxLineLength |
|
); |
|
result += common.repeat(' ', options.indent) + padStart((mark.line + i + 1).toString(), lineNoLength) + |
|
' | ' + line.str + '\n'; |
|
} |
|
|
|
return result.replace(/\n$/, ''); |
|
} |
|
|
|
|
|
module.exports = makeSnippet;
|
|
|