UNPKG

3.09 kBJavaScriptView Raw
1'use strict';
2
3
4var common = require('./common');
5
6
7// get snippet for a single line, respecting maxLength
8function 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
30function padStart(string, max) {
31 return common.repeat(' ', max - string.length) + string;
32}
33
34
35function 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
101module.exports = makeSnippet;