NOTICE: add Alexandre Blondin Massé
[nit.git] / lib / console.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Defines some ANSI Terminal Control Escape Sequences.
16 module console
17
18 # A ANSI/VT100 escape sequence.
19 abstract class TermEscape
20 # The US-ASCII ESC character.
21 protected fun esc: Char do return 27.ascii
22
23 # The Control Sequence Introducer (CSI).
24 protected fun csi: String do return "{esc}["
25 end
26
27 # Abstract class of the ANSI/VT100 escape sequences for directional moves.
28 abstract class TermDirectionalMove
29 super TermEscape
30
31 # The length of the move.
32 var magnitude: Int = 1 is protected writable
33
34 redef fun to_s do
35 if magnitude == 1 then return "{csi}{code}"
36 return "{csi}{magnitude}{code}"
37 end
38
39 # The code of the command.
40 protected fun code: String is abstract
41 end
42
43 # ANSI/VT100 code to move the cursor up by `magnitude` rows (CUU).
44 class TermMoveUp
45 super TermDirectionalMove
46
47 init do end
48
49 # Move by the specified number of cells.
50 init by(magnitude: Int) do self.magnitude = magnitude
51
52 redef fun code do return "A"
53 end
54
55 # ANSI/VT100 code to move the cursor down by `magnitude` rows (CUD).
56 class TermMoveDown
57 super TermDirectionalMove
58
59 init do end
60
61 # Move by the specified number of cells.
62 init by(magnitude: Int) do self.magnitude = magnitude
63
64 redef fun code do return "B"
65 end
66
67 # ANSI/VT100 code to move the cursor foward by `magnitude` columns (CUF).
68 class TermMoveFoward
69 super TermDirectionalMove
70
71 init do end
72
73 # Move by the specified number of cells.
74 init by(magnitude: Int) do self.magnitude = magnitude
75
76 redef fun code do return "C"
77 end
78
79 # ANSI/VT100 code to move the cursor backward by `magnitude` columns (CUB).
80 class TermMoveBackward
81 super TermDirectionalMove
82
83 init do end
84
85 # Move by the specified number of cells.
86 init by(magnitude: Int) do self.magnitude = magnitude
87
88 redef fun code do return "D"
89 end
90
91 # ANSI/VT100 code to move the cursor at the specified position (CUP).
92 class TermMove
93 super TermEscape
94
95 # Vertical position.
96 #
97 # 1 is the top.
98 var row: Int = 1
99
100 # Horizontal position.
101 #
102 # 1 is the left.
103 var column: Int = 1
104
105 init do end
106
107 # Move at the specified position.
108 #
109 # (1, 1) is the top-left corner of the display.
110 init at(row: Int, column: Int) do
111 self.row = row
112 self.column = column
113 end
114
115 redef fun to_s do
116 if row == 1 then
117 if column == 1 then return "{csi}H"
118 return "{csi};{column}H"
119 else
120 if column == 1 then return "{csi}{row}H"
121 return "{csi}{row};{column}H"
122 end
123 end
124 end
125
126 # ANSI/VT100 code to clear from the cursor to the end of the screen (ED 0).
127 class TermEraseDisplayDown
128 super TermEscape
129 redef fun to_s do return "{csi}J"
130 end
131
132 # ANSI/VT100 code to clear from the cursor to the beginning of the screen (ED 1).
133 class TermEraseDisplayUp
134 super TermEscape
135 redef fun to_s do return "{csi}1J"
136 end
137
138 # ANSI/VT100 code to clear the entire display and move the cursor to the top left of screen (ED 2).
139 #
140 # Note: Some terminals always move the cursor when the screen is cleared. So we
141 # force this behaviour to ensure interoperability of the code.
142 class TermClearDisplay
143 super TermEscape
144 redef fun to_s do return "{csi}2J{csi}H"
145 end
146
147 # ANSI/VT100 code to erase anything after the cursor in the line (EL 0).
148 class TermEraseLineFoward
149 super TermEscape
150 redef fun to_s do return "{csi}K"
151 end
152
153 # ANSI/VT100 code to erase anything before the cursor in the line (EL 1).
154 class TermEraseLineBackward
155 super TermEscape
156 redef fun to_s do return "{csi}1K"
157 end
158
159 # ANSI/VT100 code to clear everything in the current line (EL 2).
160 class TermClearLine
161 super TermEscape
162 redef fun to_s do return "{csi}2K"
163 end
164
165 # ANSI/VT100 code to save the current cursor position (SCP).
166 class TermSaveCursor
167 super TermEscape
168 redef fun to_s do return "{csi}s"
169 end
170
171 # ANSI/VT100 code to restore the current cursor position (RCP).
172 class TermRestoreCursor
173 super TermEscape
174 redef fun to_s do return "{csi}u"
175 end
176
177 # ANSI/VT100 code to change character look (SGR).
178 #
179 # By default, resets everything to the terminal’s defaults.
180 #
181 # Note:
182 #
183 # The escape sequence inserted at the end of the string by terminal-related
184 # methods of `String` resets all character attributes to the terminal’s
185 # defaults. So, when combining format `a` and `b`, something like
186 # `("foo".a + " bar").b` will not work as expected, but `"foo".a.b + " bar".b`
187 # will. You may also use `TermCharFormat` (this class).
188 #
189 # Usage example:
190 #
191 # print "{(new TermCharFormat).yellow_fg.bold}a{(new TermCharFormat).yellow_fg}b{new TermCharFormat}"
192 class TermCharFormat
193 super TermEscape
194
195 private var attributes: Array[String] = new Array[String]
196
197 # Copies the attributes from the specified format.
198 init from(format: TermCharFormat) do
199 attributes.add_all(format.attributes)
200 end
201
202 redef fun to_s: String do return "{csi}{attributes.join(";")}m"
203
204 # Apply the specified SGR and return `self`.
205 private fun apply(sgr: String): TermCharFormat do
206 attributes.add(sgr)
207 return self
208 end
209
210 # Apply normal (default) format and return `self`.
211 fun default: TermCharFormat do return apply("0")
212
213 # Apply bold weight and return `self`.
214 fun bold: TermCharFormat do return apply("1")
215
216 # Apply underlining and return `self`.
217 fun underline: TermCharFormat do return apply("4")
218
219 # Apply blinking or bold weight and return `self`.
220 fun blink: TermCharFormat do return apply("5")
221
222 # Apply reverse video and return `self`.
223 fun inverse: TermCharFormat do return apply("7")
224
225 # Apply normal weight and return `self`.
226 fun normal_weight: TermCharFormat do return apply("22")
227
228 # Add the attribute that disable inderlining and return `self`.
229 fun not_underlined: TermCharFormat do return apply("24")
230
231 # Add the attribute that disable blinking and return `self`.
232 fun steady: TermCharFormat do return apply("25")
233
234 # Add the attribute that disable reverse video and return `self`.
235 fun positive: TermCharFormat do return apply("27")
236
237 # Apply a black foreground and return `self`.
238 fun black_fg: TermCharFormat do return apply("30")
239
240 # Apply a red foreground and return `self`.
241 fun red_fg: TermCharFormat do return apply("31")
242
243 # Apply a green foreground and return `self`.
244 fun green_fg: TermCharFormat do return apply("32")
245
246 # Apply a yellow foreground and return `self`.
247 fun yellow_fg: TermCharFormat do return apply("33")
248
249 # Apply a blue foreground and return `self`.
250 fun blue_fg: TermCharFormat do return apply("34")
251
252 # Apply a mangenta foreground and return `self`.
253 fun magenta_fg: TermCharFormat do return apply("35")
254
255 # Apply a cyan foreground and return `self`.
256 fun cyan_fg: TermCharFormat do return apply("36")
257
258 # Apply a white foreground and return `self`.
259 fun white_fg: TermCharFormat do return apply("37")
260
261 # Apply the default foreground and return `self`.
262 fun default_fg: TermCharFormat do return apply("39")
263
264 # Apply a black backgroud and return `self`.
265 fun black_bg: TermCharFormat do return apply("40")
266
267 # Apply a red backgroud and return `self`.
268 fun red_bg: TermCharFormat do return apply("41")
269
270 # Apply a green backgroud and return `self`.
271 fun green_bg: TermCharFormat do return apply("42")
272
273 # Apply a yellow backgroud and return `self`.
274 fun yellow_bg: TermCharFormat do return apply("43")
275
276 # Apply a blue backgroud and return `self`.
277 fun blue_bg: TermCharFormat do return apply("44")
278
279 # Apply a mangenta backgroud and return `self`.
280 fun magenta_bg: TermCharFormat do return apply("45")
281
282 # Apply a cyan backgroud and return `self`.
283 fun cyan_bg: TermCharFormat do return apply("46")
284
285 # Apply a white backgroud and return `self`.
286 fun white_bg: TermCharFormat do return apply("47")
287
288 # Apply the default backgroud and return `self`.
289 fun default_bg: TermCharFormat do return apply("49")
290 end
291
292 # Redefine the `String` class to add functions to color the string.
293 redef class String
294 private fun apply_format(f: TermCharFormat): String do
295 return "{f}{self}{normal}"
296 end
297
298 private fun normal: TermCharFormat do return new TermCharFormat
299
300 # Make the text appear in dark gray (or black) in a ANSI/VT100 terminal.
301 #
302 # WARNING: SEE: `TermCharFormat`
303 fun gray: String do return apply_format(normal.black_fg)
304
305 # Make the text appear in red in a ANSI/VT100 terminal.
306 #
307 # WARNING: SEE: `TermCharFormat`
308 fun red: String do return apply_format(normal.red_fg)
309
310 # Make the text appear in green in a ANSI/VT100 terminal.
311 #
312 # WARNING: SEE: `TermCharFormat`
313 fun green: String do return apply_format(normal.green_fg)
314
315 # Make the text appear in yellow in a ANSI/VT100 terminal.
316 #
317 # WARNING: SEE: `TermCharFormat`
318 fun yellow: String do return apply_format(normal.yellow_fg)
319
320 # Make the text appear in blue in a ANSI/VT100 terminal.
321 #
322 # WARNING: SEE: `TermCharFormat`
323 fun blue: String do return apply_format(normal.blue_fg)
324
325 # Make the text appear in mangenta in a ANSI/VT100 terminal.
326 #
327 # WARNING: SEE: `TermCharFormat`
328 fun purple: String do return apply_format(normal.magenta_fg)
329
330 # Make the text appear in cyan in a ANSI/VT100 terminal.
331 #
332 # WARNING: SEE: `TermCharFormat`
333 fun cyan: String do return apply_format(normal.cyan_fg)
334
335 # Make the text appear in light gray (or white) in a ANSI/VT100 terminal.
336 #
337 # WARNING: SEE: `TermCharFormat`
338 fun light_gray: String do return apply_format(normal.white_fg)
339
340 # Make the text appear in bold in a ANSI/VT100 terminal.
341 #
342 # WARNING: SEE: `TermCharFormat`
343 fun bold: String do return apply_format(normal.bold)
344
345 # Make the text underlined in a ANSI/VT100 terminal.
346 #
347 # WARNING: SEE: `TermCharFormat`
348 fun underline: String do return apply_format(normal.underline)
349 end