1 | var ansi = require('ansi-escape-sequences')
|
2 | var strip = require('strip-ansi')
|
3 | var path = require('path')
|
4 | var fs = require('fs')
|
5 |
|
6 | var cwd = process.cwd()
|
7 |
|
8 | module.exports = ttyError
|
9 |
|
10 | function ttyError (src, sub, err) {
|
11 | var longFilename = err.filename || err.fileName
|
12 | if (!longFilename || !getErrorLocation(err)) return err
|
13 |
|
14 | var filename = path.relative(cwd, longFilename)
|
15 | var loc = getErrorLocation(err)
|
16 | var line = loc.line
|
17 | var col = loc.column + 1
|
18 |
|
19 | var lineNum = String(line) + ' '
|
20 | var padLen = lineNum.length
|
21 | var empty = padLeft('|', padLen + 1)
|
22 | var arrow = padLeft('--> ', padLen + 4 - 1)
|
23 | var syntaxError = padLeft('', col) + '^ ' + getErrorMessage(err)
|
24 |
|
25 | try {
|
26 | var file = fs.readFileSync(longFilename, 'utf8')
|
27 | } catch (e) {
|
28 | return err
|
29 | }
|
30 |
|
31 | var arr = file.split('\n')
|
32 | var code = arr[line - 1] || '<code>'
|
33 |
|
34 | var str = ''
|
35 | str += `${clr(`Failed while processing '${src}'.`, 'red')}\n\n`
|
36 | str += clr(arrow, 'blue') + clr(filename + `:${line}:${col}`, 'white') + '\n'
|
37 | str += clr(empty, 'blue') + '\n'
|
38 | str += clr(lineNum + '|', 'blue') + ` ${clr(code, 'white')}\n`
|
39 | str += clr(empty, 'blue') + clr(syntaxError, 'red') + '\n\n'
|
40 | str += clr(`Hmmm. We're having trouble parsing a file.`, 'white')
|
41 |
|
42 | err.pretty = str
|
43 | return err
|
44 | }
|
45 |
|
46 | function clr (text, color, style) {
|
47 | return process.stdout.isTTY ? ansi.format(text, color, style) : text
|
48 | }
|
49 |
|
50 | function padLeft (str, num, char) {
|
51 | str = String(str)
|
52 | var len = strip(str).length
|
53 | return pad(num - len, char) + str
|
54 | }
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 | function pad (len, char) {
|
63 | char = String(char === undefined ? ' ' : char)
|
64 | var res = ''
|
65 | while (res.length < len) res += char
|
66 | return res
|
67 | }
|
68 |
|
69 | function getErrorLocation (err) {
|
70 | if (err.loc) return err.loc
|
71 | if (typeof err.line === 'number' && typeof err.column === 'number') {
|
72 | return {
|
73 | line: err.line,
|
74 | column: err.column
|
75 | }
|
76 | }
|
77 | return null
|
78 | }
|
79 |
|
80 | function getErrorMessage (err) {
|
81 | var loc = getErrorLocation(err)
|
82 | var message = err.message
|
83 |
|
84 | .replace(/^.*?:|while parsing file:.*?$/g, '')
|
85 |
|
86 | .replace('(' + loc.line + ':' + loc.column + ')', '')
|
87 |
|
88 | .replace('(' + loc.line + ',' + loc.column + ')', '')
|
89 |
|
90 | return message || 'Syntax Error'
|
91 | }
|