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.
		
		
		
		
		
			
		
			
				
					102 lines
				
				3.0 KiB
			
		
		
			
		
	
	
					102 lines
				
				3.0 KiB
			| 
											3 years ago
										 | '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; |