3
3
package prompt
4
4
5
5
import (
6
- "bytes"
7
- "strconv"
8
6
"syscall"
9
7
)
10
8
11
9
// PosixWriter is a ConsoleWriter implementation for POSIX environment.
12
10
// To control terminal emulator, this outputs VT100 escape sequences.
13
11
type PosixWriter struct {
14
- fd int
15
- buffer []byte
16
- }
17
-
18
- // WriteRaw to write raw byte array
19
- func (w * PosixWriter ) WriteRaw (data []byte ) {
20
- w .buffer = append (w .buffer , data ... )
21
- return
22
- }
23
-
24
- // Write to write safety byte array by removing control sequences.
25
- func (w * PosixWriter ) Write (data []byte ) {
26
- w .WriteRaw (bytes .Replace (data , []byte {0x1b }, []byte {'?' }, - 1 ))
27
- return
28
- }
29
-
30
- // WriteRawStr to write raw string
31
- func (w * PosixWriter ) WriteRawStr (data string ) {
32
- w .WriteRaw ([]byte (data ))
33
- return
34
- }
35
-
36
- // WriteStr to write safety string by removing control sequences.
37
- func (w * PosixWriter ) WriteStr (data string ) {
38
- w .Write ([]byte (data ))
39
- return
12
+ VT100Writer
13
+ fd int
40
14
}
41
15
42
16
// Flush to flush buffer
@@ -49,309 +23,11 @@ func (w *PosixWriter) Flush() error {
49
23
return nil
50
24
}
51
25
52
- /* Erase */
53
-
54
- // EraseScreen erases the screen with the background colour and moves the cursor to home.
55
- func (w * PosixWriter ) EraseScreen () {
56
- w .WriteRaw ([]byte {0x1b , '[' , '2' , 'J' })
57
- return
58
- }
59
-
60
- // EraseUp erases the screen from the current line up to the top of the screen.
61
- func (w * PosixWriter ) EraseUp () {
62
- w .WriteRaw ([]byte {0x1b , '[' , '2' , 'J' })
63
- return
64
- }
65
-
66
- // EraseDown erases the screen from the current line down to the bottom of the screen.
67
- func (w * PosixWriter ) EraseDown () {
68
- w .WriteRaw ([]byte {0x1b , '[' , 'J' })
69
- return
70
- }
71
-
72
- // EraseStartOfLine erases from the current cursor position to the start of the current line.
73
- func (w * PosixWriter ) EraseStartOfLine () {
74
- w .WriteRaw ([]byte {0x1b , '[' , '1' , 'K' })
75
- return
76
- }
77
-
78
- // EraseEndOfLine erases from the current cursor position to the end of the current line.
79
- func (w * PosixWriter ) EraseEndOfLine () {
80
- w .WriteRaw ([]byte {0x1b , '[' , 'K' })
81
- return
82
- }
83
-
84
- // EraseLine erases the entire current line.
85
- func (w * PosixWriter ) EraseLine () {
86
- w .WriteRaw ([]byte {0x1b , '[' , '2' , 'K' })
87
- return
88
- }
89
-
90
- /* Cursor */
91
-
92
- // ShowCursor stops blinking cursor and show.
93
- func (w * PosixWriter ) ShowCursor () {
94
- w .WriteRaw ([]byte {0x1b , '[' , '?' , '1' , '2' , 'l' , 0x1b , '[' , '?' , '2' , '5' , 'h' })
95
- }
96
-
97
- // HideCursor hides cursor.
98
- func (w * PosixWriter ) HideCursor () {
99
- w .WriteRaw ([]byte {0x1b , '[' , '?' , '2' , '5' , 'l' })
100
- return
101
- }
102
-
103
- // CursorGoTo sets the cursor position where subsequent text will begin.
104
- func (w * PosixWriter ) CursorGoTo (row , col int ) {
105
- if row == 0 && col == 0 {
106
- // If no row/column parameters are provided (ie. <ESC>[H), the cursor will move to the home position.
107
- w .WriteRaw ([]byte {0x1b , '[' , 'H' })
108
- return
109
- }
110
- r := strconv .Itoa (row )
111
- c := strconv .Itoa (col )
112
- w .WriteRaw ([]byte {0x1b , '[' })
113
- w .WriteRaw ([]byte (r ))
114
- w .WriteRaw ([]byte {';' })
115
- w .WriteRaw ([]byte (c ))
116
- w .WriteRaw ([]byte {'H' })
117
- return
118
- }
119
-
120
- // CursorUp moves the cursor up by 'n' rows; the default count is 1.
121
- func (w * PosixWriter ) CursorUp (n int ) {
122
- if n == 0 {
123
- return
124
- } else if n < 0 {
125
- w .CursorDown (- n )
126
- return
127
- }
128
- s := strconv .Itoa (n )
129
- w .WriteRaw ([]byte {0x1b , '[' })
130
- w .WriteRaw ([]byte (s ))
131
- w .WriteRaw ([]byte {'A' })
132
- return
133
- }
134
-
135
- // CursorDown moves the cursor down by 'n' rows; the default count is 1.
136
- func (w * PosixWriter ) CursorDown (n int ) {
137
- if n == 0 {
138
- return
139
- } else if n < 0 {
140
- w .CursorUp (- n )
141
- return
142
- }
143
- s := strconv .Itoa (n )
144
- w .WriteRaw ([]byte {0x1b , '[' })
145
- w .WriteRaw ([]byte (s ))
146
- w .WriteRaw ([]byte {'B' })
147
- return
148
- }
149
-
150
- // CursorForward moves the cursor forward by 'n' columns; the default count is 1.
151
- func (w * PosixWriter ) CursorForward (n int ) {
152
- if n == 0 {
153
- return
154
- } else if n < 0 {
155
- w .CursorBackward (- n )
156
- return
157
- }
158
- s := strconv .Itoa (n )
159
- w .WriteRaw ([]byte {0x1b , '[' })
160
- w .WriteRaw ([]byte (s ))
161
- w .WriteRaw ([]byte {'C' })
162
- return
163
- }
164
-
165
- // CursorBackward moves the cursor backward by 'n' columns; the default count is 1.
166
- func (w * PosixWriter ) CursorBackward (n int ) {
167
- if n == 0 {
168
- return
169
- } else if n < 0 {
170
- w .CursorForward (- n )
171
- return
172
- }
173
- s := strconv .Itoa (n )
174
- w .WriteRaw ([]byte {0x1b , '[' })
175
- w .WriteRaw ([]byte (s ))
176
- w .WriteRaw ([]byte {'D' })
177
- return
178
- }
179
-
180
- // AskForCPR asks for a cursor position report (CPR).
181
- func (w * PosixWriter ) AskForCPR () {
182
- // CPR: Cursor Position Request.
183
- w .WriteRaw ([]byte {0x1b , '[' , '6' , 'n' })
184
- w .Flush ()
185
- return
186
- }
187
-
188
- // SaveCursor saves current cursor position.
189
- func (w * PosixWriter ) SaveCursor () {
190
- w .WriteRaw ([]byte {0x1b , '[' , 's' })
191
- return
192
- }
193
-
194
- // UnSaveCursor restores cursor position after a Save Cursor.
195
- func (w * PosixWriter ) UnSaveCursor () {
196
- w .WriteRaw ([]byte {0x1b , '[' , 'u' })
197
- return
198
- }
199
-
200
- /* Scrolling */
201
-
202
- // ScrollDown scrolls display down one line.
203
- func (w * PosixWriter ) ScrollDown () {
204
- w .WriteRaw ([]byte {0x1b , 'D' })
205
- return
206
- }
207
-
208
- // ScrollUp scroll display up one line.
209
- func (w * PosixWriter ) ScrollUp () {
210
- w .WriteRaw ([]byte {0x1b , 'M' })
211
- return
212
- }
213
-
214
- /* Title */
215
-
216
- // SetTitle sets a title of terminal window.
217
- func (w * PosixWriter ) SetTitle (title string ) {
218
- titleBytes := []byte (title )
219
- patterns := []struct {
220
- from []byte
221
- to []byte
222
- }{
223
- {
224
- from : []byte {0x13 },
225
- to : []byte {},
226
- },
227
- {
228
- from : []byte {0x07 },
229
- to : []byte {},
230
- },
231
- }
232
- for i := range patterns {
233
- titleBytes = bytes .Replace (titleBytes , patterns [i ].from , patterns [i ].to , - 1 )
234
- }
235
-
236
- w .WriteRaw ([]byte {0x1b , ']' , '2' , ';' })
237
- w .WriteRaw (titleBytes )
238
- w .WriteRaw ([]byte {0x07 })
239
- return
240
- }
241
-
242
- // ClearTitle clears a title of terminal window.
243
- func (w * PosixWriter ) ClearTitle () {
244
- w .WriteRaw ([]byte {0x1b , ']' , '2' , ';' , 0x07 })
245
- return
246
- }
247
-
248
- /* Font */
249
-
250
- // SetColor sets text and background colors. and specify whether text is bold.
251
- // Deprecated. This interface is not cool, please use SetDisplayAttributes.
252
- func (w * PosixWriter ) SetColor (fg , bg Color , bold bool ) {
253
- if bold {
254
- w .SetDisplayAttributes (fg , bg , DisplayBold )
255
- } else {
256
- w .SetDisplayAttributes (fg , bg , DisplayDefaultFont )
257
- }
258
- return
259
- }
260
-
261
- // SetDisplayAttributes set display attributes (Set colors, blink, bold, italic and so on).
262
- func (w * PosixWriter ) SetDisplayAttributes (fg , bg Color , attrs ... DisplayAttribute ) {
263
- w .WriteRaw ([]byte {0x1b , '[' }) // control sequence introducer
264
- defer w .WriteRaw ([]byte {'m' }) // final character
265
-
266
- var separator byte = ';'
267
- for i := range attrs {
268
- p , ok := displayAttributeParameters [attrs [i ]]
269
- if ! ok {
270
- continue
271
- }
272
- w .WriteRaw (p )
273
- w .WriteRaw ([]byte {separator })
274
- }
275
-
276
- f , ok := foregroundANSIColors [fg ]
277
- if ! ok {
278
- f = foregroundANSIColors [DefaultColor ]
279
- }
280
- w .WriteRaw (f )
281
- w .WriteRaw ([]byte {separator })
282
- b , ok := backgroundANSIColors [bg ]
283
- if ! ok {
284
- b = backgroundANSIColors [DefaultColor ]
285
- }
286
- w .WriteRaw (b )
287
- return
288
- }
289
-
290
- var displayAttributeParameters = map [DisplayAttribute ][]byte {
291
- DisplayReset : {'0' },
292
- DisplayBold : {'1' },
293
- DisplayLowIntensity : {'2' },
294
- DisplayItalic : {'3' },
295
- DisplayUnderline : {'4' },
296
- DisplayBlink : {'5' },
297
- DisplayRapidBlink : {'6' },
298
- DisplayReverse : {'7' },
299
- DisplayInvisible : {'8' },
300
- DisplayCrossedOut : {'9' },
301
- DisplayDefaultFont : {'1' , '0' },
302
- }
303
-
304
- var foregroundANSIColors = map [Color ][]byte {
305
- DefaultColor : {'3' , '9' },
306
-
307
- // Low intensity.
308
- Black : {'3' , '0' },
309
- DarkRed : {'3' , '1' },
310
- DarkGreen : {'3' , '2' },
311
- Brown : {'3' , '3' },
312
- DarkBlue : {'3' , '4' },
313
- Purple : {'3' , '5' },
314
- Cyan : {'3' , '6' },
315
- LightGray : {'3' , '7' },
316
-
317
- // High intensity.
318
- DarkGray : {'9' , '0' },
319
- Red : {'9' , '1' },
320
- Green : {'9' , '2' },
321
- Yellow : {'9' , '3' },
322
- Blue : {'9' , '4' },
323
- Fuchsia : {'9' , '5' },
324
- Turquoise : {'9' , '6' },
325
- White : {'9' , '7' },
326
- }
327
-
328
- var backgroundANSIColors = map [Color ][]byte {
329
- DefaultColor : {'4' , '9' },
330
-
331
- // Low intensity.
332
- Black : {'4' , '0' },
333
- DarkRed : {'4' , '1' },
334
- DarkGreen : {'4' , '2' },
335
- Brown : {'4' , '3' },
336
- DarkBlue : {'4' , '4' },
337
- Purple : {'4' , '5' },
338
- Cyan : {'4' , '6' },
339
- LightGray : {'4' , '7' },
340
-
341
- // High intensity
342
- DarkGray : {'1' , '0' , '0' },
343
- Red : {'1' , '0' , '1' },
344
- Green : {'1' , '0' , '2' },
345
- Yellow : {'1' , '0' , '3' },
346
- Blue : {'1' , '0' , '4' },
347
- Fuchsia : {'1' , '0' , '5' },
348
- Turquoise : {'1' , '0' , '6' },
349
- White : {'1' , '0' , '7' },
350
- }
351
-
352
26
var _ ConsoleWriter = & PosixWriter {}
353
27
354
28
// NewStandardOutputWriter returns ConsoleWriter object to write to stdout.
29
+ // This generates VT100 escape sequences because almost terminal emulators
30
+ // in POSIX OS built on top of a VT100 specification.
355
31
func NewStandardOutputWriter () * PosixWriter {
356
32
return & PosixWriter {
357
33
fd : syscall .Stdout ,
0 commit comments