-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
124 lines (108 loc) · 3.13 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
const { clearScreenDown, cursorTo, moveCursor } = require('readline')
const { inspect } = require('util')
const truncate = require('cli-truncate')
/**
* Default error handler `onerror(err)` when one is not
* given to the `preview()` function.
* @private
*/
function defaultErrorHandler(err) {
throw err
}
/**
* Default pretty handler `pretty(result)` when one is not given
* to the `preview()` function.
* @private
*/
function defaultPrettyHandler(result, opts) {
return inspect(result, {
getters: true,
colors: true,
sorted: true,
depth: 3,
...opts
})
}
/**
* Renders a preview of a mixed result value with the output truncated
* to fit the viewport of the terminal.
* @public
* @param {REPLServer} server
* @param {?Mixed} result
* @param {Object} opts
*/
function preview(server, result, opts) {
opts = { ...opts }
const { onerror = defaultErrorHandler } = opts
const { pretty = defaultPrettyHandler } = opts
return process.nextTick(tick)
function tick() {
try {
render()
} catch (err) {
onerror(err)
}
}
function render() {
const { cursorPosition, displayPosition } = getCursorPreviewPosition(server)
const cols = displayPosition.cols - cursorPosition.cols
const rows = displayPosition.rows - cursorPosition.rows
let output = ''
moveCursor(server.output, cols, rows)
clearScreenDown(server.output)
if (result) {
output = pretty(result)
if (output) {
output = output
// split the output because we'll only show a few lines
.split('\n')
// select as lines as there are rows available to use
.slice(0, server.output.rows - rows - 1)
if (false !== opts.truncate) {
// truncate output with a little padding
output = output.map((o) => truncate(o, server.output.columns - 8))
}
const lines = output.length
output = output.join('\n')
server.output.write(`\n${output}`)
cursorTo(server.output, cursorPosition.cols)
moveCursor(server.output, cols, -rows - lines)
}
} else {
moveCursor(server.output, cols, rows)
clearScreenDown(server.output)
}
}
}
// borrowed from: https://github.com/nodejs/node/blob/master/lib/internal/repl/utils.js
function getCursorPreviewPosition(server) {
const displayPosition = server._getDisplayPos(`${server._prompt}${server.line}`)
const cursorPosition = server.line.length !== server.cursor
? server.getCursorPos()
: displayPosition
return { displayPosition, cursorPosition }
}
/**
* A module that provides a function for drawing previewed result output
* in a REPL context.
* @public
* @module repl-preview
* @example
* const { preview } = require('repl-preview')
* const keypress = require('repl-preview')
* const repl = require('repl')
* const vm = require('vm')
*
* const server = repl.start()
* keypress(server.input, (line, key) => {
* try {
* const result = vm.runInContext(vm.createContent({ ...server.context }), line)
* preview(server, result)
* } catch (err) {
* // handle possible error
* }
* })
*/
module.exports = {
preview
}