1 /*******************************************************************************
2 
3     Console output
4 
5     Console output classes extending those in ocean.io.Stdout.
6 
7     Additional features are:
8         * clearline() method which erases the rest of the line
9         * bold() method which sets the text output to bold / bright mode
10         * text colour setting methods
11 
12     Copyright:
13         Copyright (c) 2009-2016 dunnhumby Germany GmbH.
14         All rights reserved.
15 
16     License:
17         Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
18         Alternatively, this file may be distributed under the terms of the Tango
19         3-Clause BSD License (see LICENSE_BSD.txt for details).
20 
21 *******************************************************************************/
22 
23 module ocean.io.Stdout;
24 
25 
26 
27 
28 import ocean.meta.types.Qualifiers;
29 
30 import ocean.io.Terminal;
31 
32 import ocean.io.device.Conduit;
33 
34 import ocean.io.stream.Format;
35 
36 import ocean.io.Console;
37 
38 import ocean.text.convert.Formatter;
39 
40 
41 /*******************************************************************************
42 
43     Static output instances
44 
45 *******************************************************************************/
46 
47 public static TerminalOutput Stdout; /// Global standard output.
48 public static TerminalOutput Stderr; /// Global error output.
49 public alias Stdout stdout; /// Alternative.
50 public alias Stderr stderr; /// Alternative.
51 
52 static this ( )
53 {
54     Stdout = new TerminalOutput(Cout.stream);
55     Stderr = new TerminalOutput(Cerr.stream);
56 
57     Stdout.flush = !Cout.redirected;
58     Stdout.redirect = Cout.redirected;
59     Stderr.flush = !Cerr.redirected;
60     Stderr.redirect = Cerr.redirected;
61 }
62 
63 
64 
65 /*******************************************************************************
66 
67     Terminal output class.
68 
69     Derived from FormatOutput in ocean.io.stream.Format, and reimplements
70     methods to return typeof(this), for easy method chaining. Note that not all
71     methods are reimplemented in this way, only those which we commonly use.
72     Others may be added if needed.
73 
74 *******************************************************************************/
75 
76 public class TerminalOutput : FormatOutput
77 {
78     /***************************************************************************
79 
80         Template method to output a CSI sequence
81 
82         Params:
83             seq = csi sequence to output
84 
85     ***************************************************************************/
86 
87     private typeof(this) csiSeq ( istring seq ) ( )
88     {
89         if ( !this.redirect )
90         {
91             this.sink.write(Terminal.CSI);
92             this.sink.write(seq);
93         }
94         return this;
95     }
96 
97 
98     /***************************************************************************
99 
100         True if it's redirected.
101 
102     ***************************************************************************/
103 
104     protected bool redirect;
105 
106 
107     /***************************************************************************
108 
109         Construct a FormatOutput instance, tying the provided stream to a layout
110         formatter.
111 
112     ***************************************************************************/
113 
114     public this (OutputStream output, istring eol = Eol)
115     {
116         super(output, eol);
117     }
118 
119     /// See `FormatOutput.format`
120     public typeof(this) format (Args...) (cstring fmt, Args args)
121     {
122         // FIXME_IN_D2: Use TemplateThisParam in FormatOutput and kill this
123         sformat(&this.emit, fmt, args);
124         return this;
125     }
126 
127     /// See `FormatOutput.formatln`
128     public typeof(this) formatln (Args...) (cstring fmt, Args args)
129     {
130         // FIXME_IN_D2: Use TemplateThisParam in FormatOutput and kill this
131         sformat(&this.emit, fmt, args);
132         this.newline;
133         return this;
134     }
135 
136 
137     /***************************************************************************
138 
139         Output a newline and optionally flush.
140 
141     ***************************************************************************/
142 
143     public typeof(this) newline ( )
144     {
145         super.newline;
146         return this;
147     }
148 
149 
150     /***************************************************************************
151 
152         Emit/purge buffered content.
153 
154     ***************************************************************************/
155 
156     public override typeof(this) flush ( )
157     {
158         super.flush;
159         return this;
160     }
161 
162 
163     /***************************************************************************
164 
165         Control implicit flushing of newline(), where true enables flushing. An
166         explicit flush() will always flush the output.
167 
168     ***************************************************************************/
169 
170     public typeof(this) flush ( bool yes )
171     {
172         super.flush(yes);
173         return this;
174     }
175 
176 
177     /***************************************************************************
178 
179         Output terminal control characters to clear the rest of the line. Note:
180         does not flush. (Flush explicitly if you need to.)
181 
182     ***************************************************************************/
183 
184     public typeof(this) clearline ( )
185     {
186         if ( this.redirect )
187         {
188             return this.newline;
189         }
190         return this.csiSeq!(Terminal.ERASE_REST_OF_LINE);
191     }
192 
193 
194     /***************************************************************************
195 
196         Sets / unsets bold text output.
197 
198         Params:
199             on = bold on / off
200 
201     ***************************************************************************/
202 
203     public typeof(this) bold ( bool on = true )
204     {
205         return on ? this.csiSeq!(Terminal.BOLD) : this.csiSeq!(Terminal.NON_BOLD);
206     }
207 
208 
209     /***************************************************************************
210 
211         Move the current cursor position to the last row of the terminal. This
212         method adapts to changes in the size of the terminal.
213 
214     ***************************************************************************/
215 
216     public typeof(this) endrow ( )
217     {
218         this.sink.write(.format("{}{};1H", Terminal.CSI, Terminal.rows));
219         return this;
220     }
221 
222 
223     /***************************************************************************
224 
225         Carriage return (sends cursor back to the start of the line).
226 
227     ***************************************************************************/
228 
229     public alias csiSeq!("0" ~ Terminal.HORIZONTAL_MOVE_CURSOR) cr;
230 
231 
232     /***************************************************************************
233 
234         Move the cursor up a line
235 
236     ***************************************************************************/
237 
238     public alias csiSeq!("1" ~ Terminal.CURSOR_UP)      up;
239 
240 
241     /***************************************************************************
242 
243         Foreground colour changing methods.
244 
245     ***************************************************************************/
246 
247     public alias csiSeq!(Terminal.Foreground.DEFAULT)   default_colour;
248     public alias csiSeq!(Terminal.Foreground.BLACK)     black;
249     public alias csiSeq!(Terminal.Foreground.RED)       red;
250     public alias csiSeq!(Terminal.Foreground.GREEN)     green;
251     public alias csiSeq!(Terminal.Foreground.YELLOW)    yellow;
252     public alias csiSeq!(Terminal.Foreground.BLUE)      blue;
253     public alias csiSeq!(Terminal.Foreground.MAGENTA)   magenta;
254     public alias csiSeq!(Terminal.Foreground.CYAN)      cyan;
255     public alias csiSeq!(Terminal.Foreground.WHITE)     white;
256 
257 
258     /***************************************************************************
259 
260         Background colour changing methods.
261 
262     ***************************************************************************/
263 
264     public alias csiSeq!(Terminal.Background.DEFAULT)   default_bg;
265     public alias csiSeq!(Terminal.Background.BLACK)     black_bg;
266     public alias csiSeq!(Terminal.Background.RED)       red_bg;
267     public alias csiSeq!(Terminal.Background.GREEN)     green_bg;
268     public alias csiSeq!(Terminal.Background.YELLOW)    yellow_bg;
269     public alias csiSeq!(Terminal.Background.BLUE)      blue_bg;
270     public alias csiSeq!(Terminal.Background.MAGENTA)   magenta_bg;
271     public alias csiSeq!(Terminal.Background.CYAN)      cyan_bg;
272     public alias csiSeq!(Terminal.Background.WHITE)     white_bg;
273 
274 
275     /***************************************************************************
276 
277         Foreground text colour scope class. Resets the default text colour, if
278         it has been changed, when scope exits.
279 
280     ***************************************************************************/
281 
282     public class TextColour
283     {
284         /***********************************************************************
285 
286             Flag set to true when this instance has modified the text colour.
287 
288         ***********************************************************************/
289 
290         private bool colour_set;
291 
292 
293         /***********************************************************************
294 
295             Flag set to true when this instance has modified the text boldness.
296 
297         ***********************************************************************/
298 
299         private bool bold_set;
300 
301 
302         /***********************************************************************
303 
304             Destructor. Resets any modified text settings.
305 
306         ***********************************************************************/
307 
308         ~this ( )
309         {
310             if ( this.colour_set )
311             {
312                 this.outer.default_colour;
313             }
314 
315             if ( this.bold_set )
316             {
317                 this.outer.bold(false);
318             }
319         }
320 
321 
322         /***********************************************************************
323 
324             Sets the text colour and optionally boldness.
325 
326             Params:
327                 method = name of outer class method to call to set the colour
328                 bold = text boldness
329 
330         ***********************************************************************/
331 
332         private void setCol ( istring method ) ( bool bold = false )
333         {
334             this.colour_set = true;
335             mixin("this.outer." ~ method ~ ";");
336 
337             if ( bold )
338             {
339                 this.bold_set = true;
340                 this.outer.bold;
341             }
342         }
343 
344 
345         /***********************************************************************
346 
347             Colour setting methods (all aliases of setCol(), above).
348 
349         ***********************************************************************/
350 
351         public alias setCol!("black") black;
352         public alias setCol!("red") red;
353         public alias setCol!("green") green;
354         public alias setCol!("yellow") yellow;
355         public alias setCol!("blue") blue;
356         public alias setCol!("magenta") magenta;
357         public alias setCol!("cyan") cyan;
358         public alias setCol!("white") white;
359     }
360 
361 
362     /***************************************************************************
363 
364         Background colour class. Resets the default background colour, if
365         it has been changed, when scope exits.
366 
367     ***************************************************************************/
368 
369     public class BackgroundColour
370     {
371         /***********************************************************************
372 
373             Flag set to true when this instance has modified the background
374             colour.
375 
376         ***********************************************************************/
377 
378         private bool colour_set;
379 
380 
381         /***********************************************************************
382 
383             Destructor. Resets any modified text settings.
384 
385         ***********************************************************************/
386 
387         ~this ( )
388         {
389             if ( this.colour_set )
390             {
391                 this.outer.default_bg;
392             }
393         }
394 
395 
396         /***********************************************************************
397 
398             Sets the background colour.
399 
400             Params:
401                 method = name of outer class method to call to set the colour
402 
403         ***********************************************************************/
404 
405         private void setCol ( istring method ) ( )
406         {
407             this.colour_set = true;
408             mixin("this.outer." ~ method ~ ";");
409         }
410 
411 
412         /***********************************************************************
413 
414             Colour setting methods (all aliases of setCol(), above).
415 
416         ***********************************************************************/
417 
418         public alias setCol!("black_bg") black;
419         public alias setCol!("red_bg") red;
420         public alias setCol!("green_bg") green;
421         public alias setCol!("yellow_bg") yellow;
422         public alias setCol!("blue_bg") blue;
423         public alias setCol!("magenta_bg") magenta;
424         public alias setCol!("cyan_bg") cyan;
425         public alias setCol!("white_bg") white;
426     }
427 }