UNPKG

3.35 kBJavaScriptView Raw
1const _readline = require('readline');
2
3// low-level terminal interactions
4class Terminal{
5
6 constructor(outputStream){
7 this.stream = outputStream;
8
9 // default: line wrapping enabled
10 this.linewrap = true;
11
12 // current, relative y position
13 this.dy = 0;
14 }
15
16 // save cursor position + settings
17 cursorSave(){
18 if (!this.stream.isTTY){
19 return;
20 }
21
22 // save position
23 this.stream.write('\x1B7');
24 }
25
26 // restore last cursor position + settings
27 cursorRestore(){
28 if (!this.stream.isTTY){
29 return;
30 }
31
32 // restore cursor
33 this.stream.write('\x1B8');
34 }
35
36 // show/hide cursor
37 cursor(enabled){
38 if (!this.stream.isTTY){
39 return;
40 }
41
42 if (enabled){
43 this.stream.write('\x1B[?25h');
44 }else{
45 this.stream.write('\x1B[?25l');
46 }
47 }
48
49 // change cursor positionn
50 cursorTo(x=null, y=null){
51 if (!this.stream.isTTY){
52 return;
53 }
54
55 // move cursor absolute
56 _readline.cursorTo(this.stream, x, y);
57 }
58
59 // change relative cursor position
60 cursorRelative(dx=null, dy=null){
61 if (!this.stream.isTTY){
62 return;
63 }
64
65 // store current position
66 this.dy = this.dy + dy;
67
68 // move cursor relative
69 _readline.moveCursor(this.stream, dx, dy);
70 }
71
72 // relative reset
73 cursorRelativeReset(){
74 if (!this.stream.isTTY){
75 return;
76 }
77
78 // move cursor to initial line
79 _readline.moveCursor(this.stream, 0, -this.dy);
80
81 // first char
82 _readline.cursorTo(this.stream, 0, null);
83
84 // reset counter
85 this.dy = 0;
86 }
87
88 // clear to the right from cursor
89 clearRight(){
90 if (!this.stream.isTTY){
91 return;
92 }
93
94 _readline.clearLine(this.stream, 1);
95 }
96
97 // clear the full line
98 clearLine(){
99 if (!this.stream.isTTY){
100 return;
101 }
102
103 _readline.clearLine(this.stream, 0);
104 }
105
106 // clear everyting beyond the current line
107 clearBottom(){
108 if (!this.stream.isTTY){
109 return;
110 }
111
112 _readline.clearScreenDown(this.stream);
113 }
114
115 // add new line; increment counter
116 newline(){
117 this.stream.write('\n');
118 this.dy++;
119 }
120
121 // write content to output stream
122 // @TODO use string-width to strip length
123 write(s){
124 // line wrapping enabled ? trim output
125 if (this.linewrap === true){
126 this.stream.write(s.substr(0, this.getWidth()));
127 }else{
128 this.stream.write(s);
129 }
130 }
131
132 // control line wrapping
133 lineWrapping(enabled){
134 if (!this.stream.isTTY){
135 return;
136 }
137
138 // store state
139 this.linewrap = enabled;
140 if (enabled){
141 this.stream.write('\x1B[?7h');
142 }else{
143 this.stream.write('\x1B[?7l');
144 }
145 }
146
147 // tty environment ?
148 isTTY(){
149 return (this.stream.isTTY === true);
150 }
151
152 // get terminal width
153 getWidth(){
154 // set max width to 80 in tty-mode and 200 in notty-mode
155 return this.stream.columns || (this.stream.isTTY ? 80 : 200);
156 }
157}
158
159module.exports = Terminal;