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 }