001    /*
002     * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved.
003     *
004     * This software is distributable under the BSD license. See the terms of the
005     * BSD license in the documentation provided with this software.
006     */
007    package jline;
008    
009    import java.io.*;
010    
011    /**
012     *  A buffer that can contain ANSI text.
013     *
014     *  @author  <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
015     */
016    public class ANSIBuffer {
017        private boolean ansiEnabled = true;
018        private final StringBuffer ansiBuffer = new StringBuffer();
019        private final StringBuffer plainBuffer = new StringBuffer();
020    
021        public ANSIBuffer() {
022        }
023    
024        public ANSIBuffer(final String str) {
025            append(str);
026        }
027    
028        public void setAnsiEnabled(final boolean ansi) {
029            this.ansiEnabled = ansi;
030        }
031    
032        public boolean getAnsiEnabled() {
033            return this.ansiEnabled;
034        }
035    
036        public String getAnsiBuffer() {
037            return ansiBuffer.toString();
038        }
039    
040        public String getPlainBuffer() {
041            return plainBuffer.toString();
042        }
043    
044        public String toString(final boolean ansi) {
045            return ansi ? getAnsiBuffer() : getPlainBuffer();
046        }
047    
048        public String toString() {
049            return toString(ansiEnabled);
050        }
051    
052        public ANSIBuffer append(final String str) {
053            ansiBuffer.append(str);
054            plainBuffer.append(str);
055    
056            return this;
057        }
058    
059        public ANSIBuffer attrib(final String str, final int code) {
060            ansiBuffer.append(ANSICodes.attrib(code)).append(str)
061                      .append(ANSICodes.attrib(ANSICodes.OFF));
062            plainBuffer.append(str);
063    
064            return this;
065        }
066    
067        public ANSIBuffer red(final String str) {
068            return attrib(str, ANSICodes.FG_RED);
069        }
070    
071        public ANSIBuffer blue(final String str) {
072            return attrib(str, ANSICodes.FG_BLUE);
073        }
074    
075        public ANSIBuffer green(final String str) {
076            return attrib(str, ANSICodes.FG_GREEN);
077        }
078    
079        public ANSIBuffer black(final String str) {
080            return attrib(str, ANSICodes.FG_BLACK);
081        }
082    
083        public ANSIBuffer yellow(final String str) {
084            return attrib(str, ANSICodes.FG_YELLOW);
085        }
086    
087        public ANSIBuffer magenta(final String str) {
088            return attrib(str, ANSICodes.FG_MAGENTA);
089        }
090    
091        public ANSIBuffer cyan(final String str) {
092            return attrib(str, ANSICodes.FG_CYAN);
093        }
094    
095        public ANSIBuffer bold(final String str) {
096            return attrib(str, ANSICodes.BOLD);
097        }
098    
099        public ANSIBuffer underscore(final String str) {
100            return attrib(str, ANSICodes.UNDERSCORE);
101        }
102    
103        public ANSIBuffer blink(final String str) {
104            return attrib(str, ANSICodes.BLINK);
105        }
106    
107        public ANSIBuffer reverse(final String str) {
108            return attrib(str, ANSICodes.REVERSE);
109        }
110    
111        public static class ANSICodes {
112            static final int OFF = 0;
113            static final int BOLD = 1;
114            static final int UNDERSCORE = 4;
115            static final int BLINK = 5;
116            static final int REVERSE = 7;
117            static final int CONCEALED = 8;
118            static final int FG_BLACK = 30;
119            static final int FG_RED = 31;
120            static final int FG_GREEN = 32;
121            static final int FG_YELLOW = 33;
122            static final int FG_BLUE = 34;
123            static final int FG_MAGENTA = 35;
124            static final int FG_CYAN = 36;
125            static final int FG_WHITE = 37;
126            static final char ESC = 27;
127    
128            /**
129             *  Constructor is private since this is a utility class.
130             */
131            private ANSICodes() {
132            }
133    
134            /**
135              * Sets the screen mode. The mode will be one of the following values:
136              * <pre>
137              * mode     description
138              * ----------------------------------------
139              *   0      40 x 148 x 25 monochrome (text)
140              *   1      40 x 148 x 25 color (text)
141              *   2      80 x 148 x 25 monochrome (text)
142              *   3      80 x 148 x 25 color (text)
143              *   4      320 x 148 x 200 4-color (graphics)
144              *   5      320 x 148 x 200 monochrome (graphics)
145              *   6      640 x 148 x 200 monochrome (graphics)
146              *   7      Enables line wrapping
147              *  13      320 x 148 x 200 color (graphics)
148              *  14      640 x 148 x 200 color (16-color graphics)
149              *  15      640 x 148 x 350 monochrome (2-color graphics)
150              *  16      640 x 148 x 350 color (16-color graphics)
151              *  17      640 x 148 x 480 monochrome (2-color graphics)
152              *  18      640 x 148 x 480 color (16-color graphics)
153              *  19      320 x 148 x 200 color (256-color graphics)
154              * </pre>
155              */
156            public static String setmode(final int mode) {
157                return ESC + "[=" + mode + "h";
158            }
159    
160            /**
161              * Same as setmode () except for mode = 7, which disables line
162              * wrapping (useful for writing the right-most column without
163              * scrolling to the next line).
164              */
165            public static String resetmode(final int mode) {
166                return ESC + "[=" + mode + "l";
167            }
168    
169            /**
170              * Clears the screen and moves the cursor to the home postition.
171              */
172            public static String clrscr() {
173                return ESC + "[2J";
174            }
175    
176            /**
177              * Removes all characters from the current cursor position until
178              * the end of the line.
179              */
180            public static String clreol() {
181                return ESC + "[K";
182            }
183    
184            /**
185              * Moves the cursor n positions to the left. If n is greater or
186              * equal to the current cursor column, the cursor is moved to the
187              * first column.
188              */
189            public static String left(final int n) {
190                return ESC + "[" + n + "D";
191            }
192    
193            /**
194              * Moves the cursor n positions to the right. If n plus the current
195              * cursor column is greater than the rightmost column, the cursor
196              * is moved to the rightmost column.
197              */
198            public static String right(final int n) {
199                return ESC + "[" + n + "C";
200            }
201    
202            /**
203              * Moves the cursor n rows up without changing the current column.
204              * If n is greater than or equal to the current row, the cursor is
205              * placed in the first row.
206              */
207            public static String up(final int n) {
208                return ESC + "[" + n + "A";
209            }
210    
211            /**
212              * Moves the cursor n rows down. If n plus the current row is greater
213              * than the bottom row, the cursor is moved to the bottom row.
214              */
215            public static String down(final int n) {
216                return ESC + "[" + n + "B";
217            }
218    
219            /*
220              * Moves the cursor to the given row and column. (1,1) represents
221              * the upper left corner. The lower right corner of a usual DOS
222              * screen is (25, 80).
223              */
224            public static String gotoxy(final int row, final int column) {
225                return ESC + "[" + row + ";" + column + "H";
226            }
227    
228            /**
229              * Saves the current cursor position.
230              */
231            public static String save() {
232                return ESC + "[s";
233            }
234    
235            /**
236              * Restores the saved cursor position.
237              */
238            public static String restore() {
239                return ESC + "[u";
240            }
241    
242            /**
243              * Sets the character attribute. It will be
244             * one of the following character attributes:
245              *
246              * <pre>
247              * Text attributes
248              *    0    All attributes off
249              *    1    Bold on
250              *    4    Underscore (on monochrome display adapter only)
251              *    5    Blink on
252              *    7    Reverse video on
253              *    8    Concealed on
254              *
255              *   Foreground colors
256              *    30    Black
257              *    31    Red
258              *    32    Green
259              *    33    Yellow
260              *    34    Blue
261              *    35    Magenta
262              *    36    Cyan
263              *    37    White
264              *
265              *   Background colors
266              *    40    Black
267              *    41    Red
268              *    42    Green
269              *    43    Yellow
270              *    44    Blue
271              *    45    Magenta
272              *    46    Cyan
273              *    47    White
274              * </pre>
275              *
276              * The attributes remain in effect until the next attribute command
277              * is sent.
278              */
279            public static String attrib(final int attr) {
280                return ESC + "[" + attr + "m";
281            }
282    
283            /**
284              * Sets the key with the given code to the given value. code must be
285              * derived from the following table, value must
286             * be any semicolon-separated
287              * combination of String (enclosed in double quotes) and numeric values.
288              * For example, to set F1 to the String "Hello F1", followed by a CRLF
289              * sequence, one can use: ANSI.setkey ("0;59", "\"Hello F1\";13;10").
290              * Heres's the table of key values:
291              * <pre>
292              * Key                       Code      SHIFT+code  CTRL+code  ALT+code
293              * ---------------------------------------------------------------
294              * F1                        0;59      0;84        0;94       0;104
295              * F2                        0;60      0;85        0;95       0;105
296              * F3                        0;61      0;86        0;96       0;106
297              * F4                        0;62      0;87        0;97       0;107
298              * F5                        0;63      0;88        0;98       0;108
299              * F6                        0;64      0;89        0;99       0;109
300              * F7                        0;65      0;90        0;100      0;110
301              * F8                        0;66      0;91        0;101      0;111
302              * F9                        0;67      0;92        0;102      0;112
303              * F10                       0;68      0;93        0;103      0;113
304              * F11                       0;133     0;135       0;137      0;139
305              * F12                       0;134     0;136       0;138      0;140
306              * HOME (num keypad)         0;71      55          0;119      --
307              * UP ARROW (num keypad)     0;72      56          (0;141)    --
308              * PAGE UP (num keypad)      0;73      57          0;132      --
309              * LEFT ARROW (num keypad)   0;75      52          0;115      --
310              * RIGHT ARROW (num keypad)  0;77      54          0;116      --
311              * END (num keypad)          0;79      49          0;117      --
312              * DOWN ARROW (num keypad)   0;80      50          (0;145)    --
313              * PAGE DOWN (num keypad)    0;81      51          0;118      --
314              * INSERT (num keypad)       0;82      48          (0;146)    --
315              * DELETE  (num keypad)      0;83      46          (0;147)    --
316              * HOME                      (224;71)  (224;71)    (224;119)  (224;151)
317              * UP ARROW                  (224;72)  (224;72)    (224;141)  (224;152)
318              * PAGE UP                   (224;73)  (224;73)    (224;132)  (224;153)
319              * LEFT ARROW                (224;75)  (224;75)    (224;115)  (224;155)
320              * RIGHT ARROW               (224;77)  (224;77)    (224;116)  (224;157)
321              * END                       (224;79)  (224;79)    (224;117)  (224;159)
322              * DOWN ARROW                (224;80)  (224;80)    (224;145)  (224;154)
323              * PAGE DOWN                 (224;81)  (224;81)    (224;118)  (224;161)
324              * INSERT                    (224;82)  (224;82)    (224;146)  (224;162)
325              * DELETE                    (224;83)  (224;83)    (224;147)  (224;163)
326              * PRINT SCREEN              --        --          0;114      --
327              * PAUSE/BREAK               --        --          0;0        --
328              * BACKSPACE                 8         8           127        (0)
329              * ENTER                     13        --          10         (0
330              * TAB                       9         0;15        (0;148)    (0;165)
331              * NULL                      0;3       --          --         --
332              * A                         97        65          1          0;30
333              * B                         98        66          2          0;48
334              * C                         99        66          3          0;46
335              * D                         100       68          4          0;32
336              * E                         101       69          5          0;18
337              * F                         102       70          6          0;33
338              * G                         103       71          7          0;34
339              * H                         104       72          8          0;35
340              * I                         105       73          9          0;23
341              * J                         106       74          10         0;36
342              * K                         107       75          11         0;37
343              * L                         108       76          12         0;38
344              * M                         109       77          13         0;50
345              * N                         110       78          14         0;49
346              * O                         111       79          15         0;24
347              * P                         112       80          16         0;25
348              * Q                         113       81          17         0;16
349              * R                         114       82          18         0;19
350              * S                         115       83          19         0;31
351              * T                         116       84          20         0;20
352              * U                         117       85          21         0;22
353              * V                         118       86          22         0;47
354              * W                         119       87          23         0;17
355              * X                         120       88          24         0;45
356              * Y                         121       89          25         0;21
357              * Z                         122       90          26         0;44
358              * 1                         49        33          --         0;120
359              * 2                         50        64          0          0;121
360              * 3                         51        35          --         0;122
361              * 4                         52        36          --         0;123
362              * 5                         53        37          --         0;124
363              * 6                         54        94          30         0;125
364              * 7                         55        38          --         0;126
365              * 8                         56        42          --         0;126
366              * 9                         57        40          --         0;127
367              * 0                         48        41          --         0;129
368              * -                         45        95          31         0;130
369              * =                         61        43          ---        0;131
370              * [                         91        123         27         0;26
371              * ]                         93        125         29         0;27
372              *                           92        124         28         0;43
373              * ;                         59        58          --         0;39
374              * '                         39        34          --         0;40
375              * ,                         44        60          --         0;51
376              * .                         46        62          --         0;52
377              * /                         47        63          --         0;53
378              * `                         96        126         --         (0;41)
379              * ENTER (keypad)            13        --          10         (0;166)
380              * / (keypad)                47        47          (0;142)    (0;74)
381              * * (keypad)                42        (0;144)     (0;78)     --
382              * - (keypad)                45        45          (0;149)    (0;164)
383              * + (keypad)                43        43          (0;150)    (0;55)
384              * 5 (keypad)                (0;76)    53          (0;143)    --
385              */
386            public static String setkey(final String code, final String value) {
387                return ESC + "[" + code + ";" + value + "p";
388            }
389        }
390    
391        public static void main(final String[] args) throws Exception {
392            // sequence, one can use: ANSI.setkey ("0;59", "\"Hello F1\";13;10").
393            BufferedReader reader =
394                new BufferedReader(new InputStreamReader(System.in));
395            System.out.print(ANSICodes.setkey("97", "97;98;99;13")
396                             + ANSICodes.attrib(ANSICodes.OFF));
397            System.out.flush();
398    
399            String line;
400    
401            while ((line = reader.readLine()) != null) {
402                System.out.println("GOT: " + line);
403            }
404        }
405    }