[d565449] | 1 | 'use strict';
|
---|
| 2 |
|
---|
| 3 |
|
---|
| 4 | var common = require('./common');
|
---|
| 5 |
|
---|
| 6 |
|
---|
| 7 | // get snippet for a single line, respecting maxLength
|
---|
| 8 | function getLine(buffer, lineStart, lineEnd, position, maxLineLength) {
|
---|
| 9 | var head = '';
|
---|
| 10 | var tail = '';
|
---|
| 11 | var maxHalfLength = Math.floor(maxLineLength / 2) - 1;
|
---|
| 12 |
|
---|
| 13 | if (position - lineStart > maxHalfLength) {
|
---|
| 14 | head = ' ... ';
|
---|
| 15 | lineStart = position - maxHalfLength + head.length;
|
---|
| 16 | }
|
---|
| 17 |
|
---|
| 18 | if (lineEnd - position > maxHalfLength) {
|
---|
| 19 | tail = ' ...';
|
---|
| 20 | lineEnd = position + maxHalfLength - tail.length;
|
---|
| 21 | }
|
---|
| 22 |
|
---|
| 23 | return {
|
---|
| 24 | str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, '→') + tail,
|
---|
| 25 | pos: position - lineStart + head.length // relative position
|
---|
| 26 | };
|
---|
| 27 | }
|
---|
| 28 |
|
---|
| 29 |
|
---|
| 30 | function padStart(string, max) {
|
---|
| 31 | return common.repeat(' ', max - string.length) + string;
|
---|
| 32 | }
|
---|
| 33 |
|
---|
| 34 |
|
---|
| 35 | function makeSnippet(mark, options) {
|
---|
| 36 | options = Object.create(options || null);
|
---|
| 37 |
|
---|
| 38 | if (!mark.buffer) return null;
|
---|
| 39 |
|
---|
| 40 | if (!options.maxLength) options.maxLength = 79;
|
---|
| 41 | if (typeof options.indent !== 'number') options.indent = 1;
|
---|
| 42 | if (typeof options.linesBefore !== 'number') options.linesBefore = 3;
|
---|
| 43 | if (typeof options.linesAfter !== 'number') options.linesAfter = 2;
|
---|
| 44 |
|
---|
| 45 | var re = /\r?\n|\r|\0/g;
|
---|
| 46 | var lineStarts = [ 0 ];
|
---|
| 47 | var lineEnds = [];
|
---|
| 48 | var match;
|
---|
| 49 | var foundLineNo = -1;
|
---|
| 50 |
|
---|
| 51 | while ((match = re.exec(mark.buffer))) {
|
---|
| 52 | lineEnds.push(match.index);
|
---|
| 53 | lineStarts.push(match.index + match[0].length);
|
---|
| 54 |
|
---|
| 55 | if (mark.position <= match.index && foundLineNo < 0) {
|
---|
| 56 | foundLineNo = lineStarts.length - 2;
|
---|
| 57 | }
|
---|
| 58 | }
|
---|
| 59 |
|
---|
| 60 | if (foundLineNo < 0) foundLineNo = lineStarts.length - 1;
|
---|
| 61 |
|
---|
| 62 | var result = '', i, line;
|
---|
| 63 | var lineNoLength = Math.min(mark.line + options.linesAfter, lineEnds.length).toString().length;
|
---|
| 64 | var maxLineLength = options.maxLength - (options.indent + lineNoLength + 3);
|
---|
| 65 |
|
---|
| 66 | for (i = 1; i <= options.linesBefore; i++) {
|
---|
| 67 | if (foundLineNo - i < 0) break;
|
---|
| 68 | line = getLine(
|
---|
| 69 | mark.buffer,
|
---|
| 70 | lineStarts[foundLineNo - i],
|
---|
| 71 | lineEnds[foundLineNo - i],
|
---|
| 72 | mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]),
|
---|
| 73 | maxLineLength
|
---|
| 74 | );
|
---|
| 75 | result = common.repeat(' ', options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) +
|
---|
| 76 | ' | ' + line.str + '\n' + result;
|
---|
| 77 | }
|
---|
| 78 |
|
---|
| 79 | line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength);
|
---|
| 80 | result += common.repeat(' ', options.indent) + padStart((mark.line + 1).toString(), lineNoLength) +
|
---|
| 81 | ' | ' + line.str + '\n';
|
---|
| 82 | result += common.repeat('-', options.indent + lineNoLength + 3 + line.pos) + '^' + '\n';
|
---|
| 83 |
|
---|
| 84 | for (i = 1; i <= options.linesAfter; i++) {
|
---|
| 85 | if (foundLineNo + i >= lineEnds.length) break;
|
---|
| 86 | line = getLine(
|
---|
| 87 | mark.buffer,
|
---|
| 88 | lineStarts[foundLineNo + i],
|
---|
| 89 | lineEnds[foundLineNo + i],
|
---|
| 90 | mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]),
|
---|
| 91 | maxLineLength
|
---|
| 92 | );
|
---|
| 93 | result += common.repeat(' ', options.indent) + padStart((mark.line + i + 1).toString(), lineNoLength) +
|
---|
| 94 | ' | ' + line.str + '\n';
|
---|
| 95 | }
|
---|
| 96 |
|
---|
| 97 | return result.replace(/\n$/, '');
|
---|
| 98 | }
|
---|
| 99 |
|
---|
| 100 |
|
---|
| 101 | module.exports = makeSnippet;
|
---|