001 /** 002 * jline - Java console input library 003 * Copyright (c) 2002-2006, Marc Prud'hommeaux mwp1@cornell.edu 004 * All rights reserved. 005 * 006 * Redistribution and use in source and binary forms, with or 007 * without modification, are permitted provided that the following 008 * conditions are met: 009 * 010 * Redistributions of source code must retain the above copyright 011 * notice, this list of conditions and the following disclaimer. 012 * 013 * Redistributions in binary form must reproduce the above copyright 014 * notice, this list of conditions and the following disclaimer 015 * in the documentation and/or other materials provided with 016 * the distribution. 017 * 018 * Neither the name of JLine nor the names of its contributors 019 * may be used to endorse or promote products derived from this 020 * software without specific prior written permission. 021 * 022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 023 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 024 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 025 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 026 * EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 027 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 028 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 029 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 030 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 031 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 032 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 033 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 034 * OF THE POSSIBILITY OF SUCH DAMAGE. 035 */ 036 package jline; 037 038 import java.io.*; 039 040 /** 041 * A buffer that can contain ANSI text. 042 * 043 * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a> 044 */ 045 public class ANSIBuffer 046 { 047 private boolean ansiEnabled = true; 048 private final StringBuffer ansiBuffer = new StringBuffer (); 049 private final StringBuffer plainBuffer = new StringBuffer (); 050 051 052 public ANSIBuffer () 053 { 054 } 055 056 057 public ANSIBuffer (final String str) 058 { 059 append (str); 060 } 061 062 063 public void setAnsiEnabled (final boolean ansi) 064 { 065 this.ansiEnabled = ansi; 066 } 067 068 069 public boolean getAnsiEnabled () 070 { 071 return this.ansiEnabled; 072 } 073 074 075 public String getAnsiBuffer () 076 { 077 return ansiBuffer.toString (); 078 } 079 080 081 public String getPlainBuffer () 082 { 083 return plainBuffer.toString (); 084 } 085 086 087 public String toString (final boolean ansi) 088 { 089 return ansi ? getAnsiBuffer () : getPlainBuffer (); 090 } 091 092 093 public String toString () 094 { 095 return toString (ansiEnabled); 096 } 097 098 099 public ANSIBuffer append (final String str) 100 { 101 ansiBuffer.append (str); 102 plainBuffer.append (str); 103 return this; 104 } 105 106 107 public ANSIBuffer attrib (final String str, final int code) 108 { 109 ansiBuffer.append (ANSICodes.attrib (code)) 110 .append (str) 111 .append (ANSICodes.attrib (ANSICodes.OFF)); 112 plainBuffer.append (str); 113 114 return this; 115 } 116 117 118 public ANSIBuffer red (final String str) 119 { 120 return attrib (str, ANSICodes.FG_RED); 121 } 122 123 124 public ANSIBuffer blue (final String str) 125 { 126 return attrib (str, ANSICodes.FG_BLUE); 127 } 128 129 130 public ANSIBuffer green (final String str) 131 { 132 return attrib (str, ANSICodes.FG_GREEN); 133 } 134 135 136 public ANSIBuffer black (final String str) 137 { 138 return attrib (str, ANSICodes.FG_BLACK); 139 } 140 141 142 public ANSIBuffer yellow (final String str) 143 { 144 return attrib (str, ANSICodes.FG_YELLOW); 145 } 146 147 148 public ANSIBuffer magenta (final String str) 149 { 150 return attrib (str, ANSICodes.FG_MAGENTA); 151 } 152 153 154 public ANSIBuffer cyan (final String str) 155 { 156 return attrib (str, ANSICodes.FG_CYAN); 157 } 158 159 160 public ANSIBuffer bold (final String str) 161 { 162 return attrib (str, ANSICodes.BOLD); 163 } 164 165 166 public ANSIBuffer underscore (final String str) 167 { 168 return attrib (str, ANSICodes.UNDERSCORE); 169 } 170 171 172 public ANSIBuffer blink (final String str) 173 { 174 return attrib (str, ANSICodes.BLINK); 175 } 176 177 178 public ANSIBuffer reverse (final String str) 179 { 180 return attrib (str, ANSICodes.REVERSE); 181 } 182 183 184 185 public static class ANSICodes 186 { 187 static final int OFF = 0; 188 static final int BOLD = 1; 189 static final int UNDERSCORE = 4; 190 static final int BLINK = 5; 191 static final int REVERSE = 7; 192 static final int CONCEALED = 8; 193 194 static final int FG_BLACK = 30; 195 static final int FG_RED = 31; 196 static final int FG_GREEN = 32; 197 static final int FG_YELLOW = 33; 198 static final int FG_BLUE = 34; 199 static final int FG_MAGENTA = 35; 200 static final int FG_CYAN = 36; 201 static final int FG_WHITE = 37; 202 static final char ESC = 27; 203 204 205 206 /** 207 * Constructor is private since this is a utility class. 208 */ 209 private ANSICodes () 210 { 211 } 212 213 214 /** 215 * Sets the screen mode. The mode will be one of the following values: 216 * <pre> 217 * mode description 218 * ---------------------------------------- 219 * 0 40 x 148 x 25 monochrome (text) 220 * 1 40 x 148 x 25 color (text) 221 * 2 80 x 148 x 25 monochrome (text) 222 * 3 80 x 148 x 25 color (text) 223 * 4 320 x 148 x 200 4-color (graphics) 224 * 5 320 x 148 x 200 monochrome (graphics) 225 * 6 640 x 148 x 200 monochrome (graphics) 226 * 7 Enables line wrapping 227 * 13 320 x 148 x 200 color (graphics) 228 * 14 640 x 148 x 200 color (16-color graphics) 229 * 15 640 x 148 x 350 monochrome (2-color graphics) 230 * 16 640 x 148 x 350 color (16-color graphics) 231 * 17 640 x 148 x 480 monochrome (2-color graphics) 232 * 18 640 x 148 x 480 color (16-color graphics) 233 * 19 320 x 148 x 200 color (256-color graphics) 234 * </pre> 235 */ 236 public static String setmode (final int mode) 237 { 238 return ESC + "[=" + mode + "h"; 239 } 240 241 /** 242 * Same as setmode () except for mode = 7, which disables line 243 * wrapping (useful for writing the right-most column without 244 * scrolling to the next line). 245 */ 246 public static String resetmode (final int mode) 247 { 248 return ESC + "[=" + mode + "l"; 249 } 250 251 /** 252 * Clears the screen and moves the cursor to the home postition. 253 */ 254 public static String clrscr () 255 { 256 return ESC + "[2J"; 257 } 258 259 /** 260 * Removes all characters from the current cursor position until 261 * the end of the line. 262 */ 263 public static String clreol () 264 { 265 return ESC + "[K"; 266 } 267 268 /** 269 * Moves the cursor n positions to the left. If n is greater or 270 * equal to the current cursor column, the cursor is moved to the 271 * first column. 272 */ 273 public static String left (final int n) 274 { 275 return ESC + "[" + n + "D"; 276 } 277 278 /** 279 * Moves the cursor n positions to the right. If n plus the current 280 * cursor column is greater than the rightmost column, the cursor 281 * is moved to the rightmost column. 282 */ 283 public static String right (final int n) 284 { 285 return ESC + "[" + n + "C"; 286 } 287 288 /** 289 * Moves the cursor n rows up without changing the current column. 290 * If n is greater than or equal to the current row, the cursor is 291 * placed in the first row. 292 */ 293 public static String up (final int n) 294 { 295 return ESC + "[" + n + "A"; 296 } 297 298 /** 299 * Moves the cursor n rows down. If n plus the current row is greater 300 * than the bottom row, the cursor is moved to the bottom row. 301 */ 302 public static String down (final int n) 303 { 304 return ESC + "[" + n + "B"; 305 } 306 307 /* 308 * Moves the cursor to the given row and column. (1,1) represents 309 * the upper left corner. The lower right corner of a usual DOS 310 * screen is (25, 80). 311 */ 312 public static String gotoxy (final int row, final int column) 313 { 314 return ESC + "[" + row + ";" + column + "H"; 315 } 316 317 /** 318 * Saves the current cursor position. 319 */ 320 public static String save () 321 { 322 return ESC + "[s"; 323 } 324 325 /** 326 * Restores the saved cursor position. 327 */ 328 public static String restore () 329 { 330 return ESC + "[u"; 331 } 332 333 /** 334 * Sets the character attribute. It will be 335 * one of the following character attributes: 336 * 337 * <pre> 338 * Text attributes 339 * 0 All attributes off 340 * 1 Bold on 341 * 4 Underscore (on monochrome display adapter only) 342 * 5 Blink on 343 * 7 Reverse video on 344 * 8 Concealed on 345 * 346 * Foreground colors 347 * 30 Black 348 * 31 Red 349 * 32 Green 350 * 33 Yellow 351 * 34 Blue 352 * 35 Magenta 353 * 36 Cyan 354 * 37 White 355 * 356 * Background colors 357 * 40 Black 358 * 41 Red 359 * 42 Green 360 * 43 Yellow 361 * 44 Blue 362 * 45 Magenta 363 * 46 Cyan 364 * 47 White 365 * </pre> 366 * 367 * The attributes remain in effect until the next attribute command 368 * is sent. 369 */ 370 public static String attrib (final int attr) 371 { 372 return ESC + "[" + attr + "m"; 373 } 374 375 /** 376 * Sets the key with the given code to the given value. code must be 377 * derived from the following table, value must 378 * be any semicolon-separated 379 * combination of String (enclosed in double quotes) and numeric values. 380 * For example, to set F1 to the String "Hello F1", followed by a CRLF 381 * sequence, one can use: ANSI.setkey ("0;59", "\"Hello F1\";13;10"). 382 * Heres's the table of key values: 383 * <pre> 384 * Key Code SHIFT+code CTRL+code ALT+code 385 * --------------------------------------------------------------- 386 * F1 0;59 0;84 0;94 0;104 387 * F2 0;60 0;85 0;95 0;105 388 * F3 0;61 0;86 0;96 0;106 389 * F4 0;62 0;87 0;97 0;107 390 * F5 0;63 0;88 0;98 0;108 391 * F6 0;64 0;89 0;99 0;109 392 * F7 0;65 0;90 0;100 0;110 393 * F8 0;66 0;91 0;101 0;111 394 * F9 0;67 0;92 0;102 0;112 395 * F10 0;68 0;93 0;103 0;113 396 * F11 0;133 0;135 0;137 0;139 397 * F12 0;134 0;136 0;138 0;140 398 * HOME (num keypad) 0;71 55 0;119 -- 399 * UP ARROW (num keypad) 0;72 56 (0;141) -- 400 * PAGE UP (num keypad) 0;73 57 0;132 -- 401 * LEFT ARROW (num keypad) 0;75 52 0;115 -- 402 * RIGHT ARROW (num keypad) 0;77 54 0;116 -- 403 * END (num keypad) 0;79 49 0;117 -- 404 * DOWN ARROW (num keypad) 0;80 50 (0;145) -- 405 * PAGE DOWN (num keypad) 0;81 51 0;118 -- 406 * INSERT (num keypad) 0;82 48 (0;146) -- 407 * DELETE (num keypad) 0;83 46 (0;147) -- 408 * HOME (224;71) (224;71) (224;119) (224;151) 409 * UP ARROW (224;72) (224;72) (224;141) (224;152) 410 * PAGE UP (224;73) (224;73) (224;132) (224;153) 411 * LEFT ARROW (224;75) (224;75) (224;115) (224;155) 412 * RIGHT ARROW (224;77) (224;77) (224;116) (224;157) 413 * END (224;79) (224;79) (224;117) (224;159) 414 * DOWN ARROW (224;80) (224;80) (224;145) (224;154) 415 * PAGE DOWN (224;81) (224;81) (224;118) (224;161) 416 * INSERT (224;82) (224;82) (224;146) (224;162) 417 * DELETE (224;83) (224;83) (224;147) (224;163) 418 * PRINT SCREEN -- -- 0;114 -- 419 * PAUSE/BREAK -- -- 0;0 -- 420 * BACKSPACE 8 8 127 (0) 421 * ENTER 13 -- 10 (0 422 * TAB 9 0;15 (0;148) (0;165) 423 * NULL 0;3 -- -- -- 424 * A 97 65 1 0;30 425 * B 98 66 2 0;48 426 * C 99 66 3 0;46 427 * D 100 68 4 0;32 428 * E 101 69 5 0;18 429 * F 102 70 6 0;33 430 * G 103 71 7 0;34 431 * H 104 72 8 0;35 432 * I 105 73 9 0;23 433 * J 106 74 10 0;36 434 * K 107 75 11 0;37 435 * L 108 76 12 0;38 436 * M 109 77 13 0;50 437 * N 110 78 14 0;49 438 * O 111 79 15 0;24 439 * P 112 80 16 0;25 440 * Q 113 81 17 0;16 441 * R 114 82 18 0;19 442 * S 115 83 19 0;31 443 * T 116 84 20 0;20 444 * U 117 85 21 0;22 445 * V 118 86 22 0;47 446 * W 119 87 23 0;17 447 * X 120 88 24 0;45 448 * Y 121 89 25 0;21 449 * Z 122 90 26 0;44 450 * 1 49 33 -- 0;120 451 * 2 50 64 0 0;121 452 * 3 51 35 -- 0;122 453 * 4 52 36 -- 0;123 454 * 5 53 37 -- 0;124 455 * 6 54 94 30 0;125 456 * 7 55 38 -- 0;126 457 * 8 56 42 -- 0;126 458 * 9 57 40 -- 0;127 459 * 0 48 41 -- 0;129 460 * - 45 95 31 0;130 461 * = 61 43 --- 0;131 462 * [ 91 123 27 0;26 463 * ] 93 125 29 0;27 464 * 92 124 28 0;43 465 * ; 59 58 -- 0;39 466 * ' 39 34 -- 0;40 467 * , 44 60 -- 0;51 468 * . 46 62 -- 0;52 469 * / 47 63 -- 0;53 470 * ` 96 126 -- (0;41) 471 * ENTER (keypad) 13 -- 10 (0;166) 472 * / (keypad) 47 47 (0;142) (0;74) 473 * * (keypad) 42 (0;144) (0;78) -- 474 * - (keypad) 45 45 (0;149) (0;164) 475 * + (keypad) 43 43 (0;150) (0;55) 476 * 5 (keypad) (0;76) 53 (0;143) -- 477 */ 478 public static String setkey (final String code, final String value) 479 { 480 return ESC + "[" + code + ";" + value + "p"; 481 } 482 } 483 484 485 public static void main (final String [] args) 486 throws Exception 487 { 488 // sequence, one can use: ANSI.setkey ("0;59", "\"Hello F1\";13;10"). 489 BufferedReader reader = new BufferedReader ( 490 new InputStreamReader (System.in)); 491 System.out.print (ANSICodes.setkey ("97", "97;98;99;13") 492 + ANSICodes.attrib (ANSICodes.OFF)); 493 System.out.flush (); 494 String line; 495 while ((line = reader.readLine ()) != null) 496 { 497 System.out.println ("GOT: " + line); 498 } 499 } 500 } 501