| library mustache.template_exception; |
| |
| import 'package:mustache/mustache.dart' as m; |
| |
| class TemplateException implements m.TemplateException { |
| |
| TemplateException(this.message, this.templateName, this.source, this.offset); |
| |
| final String message; |
| final String templateName; |
| final String source; |
| final int offset; |
| |
| bool _isUpdated = false; |
| int _line; |
| int _column; |
| String _context; |
| |
| int get line { |
| _update(); |
| return _line; |
| } |
| |
| int get column { |
| _update(); |
| return _column; |
| } |
| |
| String get context { |
| _update(); |
| return _context; |
| } |
| |
| String toString() { |
| var list = []; |
| if (templateName != null) list.add(templateName); |
| if (line != null) list.add(line); |
| if (column != null) list.add(column); |
| var location = list.isEmpty ? '' : ' (${list.join(':')})'; |
| return '$message$location\n$context'; |
| } |
| |
| // This source code is a modified version of FormatException.toString(). |
| void _update() { |
| if (_isUpdated) return; |
| _isUpdated = true; |
| |
| if (source == null |
| || offset == null |
| || (offset < 0 || offset > source.length)) |
| return; |
| |
| // Find line and character column. |
| int lineNum = 1; |
| int lineStart = 0; |
| bool lastWasCR; |
| for (int i = 0; i < offset; i++) { |
| int char = source.codeUnitAt(i); |
| if (char == 0x0a) { |
| if (lineStart != i || !lastWasCR) { |
| lineNum++; |
| } |
| lineStart = i + 1; |
| lastWasCR = false; |
| } else if (char == 0x0d) { |
| lineNum++; |
| lineStart = i + 1; |
| lastWasCR = true; |
| } |
| } |
| |
| _line = lineNum; |
| _column = offset - lineStart + 1; |
| |
| // Find context. |
| int lineEnd = source.length; |
| for (int i = offset; i < source.length; i++) { |
| int char = source.codeUnitAt(i); |
| if (char == 0x0a || char == 0x0d) { |
| lineEnd = i; |
| break; |
| } |
| } |
| int length = lineEnd - lineStart; |
| int start = lineStart; |
| int end = lineEnd; |
| String prefix = ""; |
| String postfix = ""; |
| if (length > 78) { |
| // Can't show entire line. Try to anchor at the nearest end, if |
| // one is within reach. |
| int index = offset - lineStart; |
| if (index < 75) { |
| end = start + 75; |
| postfix = "..."; |
| } else if (end - offset < 75) { |
| start = end - 75; |
| prefix = "..."; |
| } else { |
| // Neither end is near, just pick an area around the offset. |
| start = offset - 36; |
| end = offset + 36; |
| prefix = postfix = "..."; |
| } |
| } |
| String slice = source.substring(start, end); |
| int markOffset = offset - start + prefix.length; |
| |
| _context = "$prefix$slice$postfix\n${" " * markOffset}^\n"; |
| } |
| |
| } |
| |