1 /* 2 * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. 3 * 4 * This software is distributable under the BSD license. See the terms of the 5 * BSD license in the documentation provided with this software. 6 */ 7 package jline; 8 9 import java.io.*; 10 11 /** 12 * Representation of the input terminal for a platform. Handles 13 * any initialization that the platform may need to perform 14 * in order to allow the {@link ConsoleReader} to correctly handle 15 * input. 16 * 17 * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a> 18 */ 19 public abstract class Terminal implements ConsoleOperations { 20 private static Terminal term; 21 22 /** 23 * @see #setupTerminal 24 */ getTerminal()25 public static Terminal getTerminal() { 26 return setupTerminal(); 27 } 28 29 /** 30 * Reset the current terminal to null. 31 */ resetTerminal()32 public static void resetTerminal() { 33 term = null; 34 } 35 36 /** 37 * <p>Configure and return the {@link Terminal} instance for the 38 * current platform. This will initialize any system settings 39 * that are required for the console to be able to handle 40 * input correctly, such as setting tabtop, buffered input, and 41 * character echo.</p> 42 * 43 * <p>This class will use the Terminal implementation specified in the 44 * <em>jline.terminal</em> system property, or, if it is unset, by 45 * detecting the operating system from the <em>os.name</em> 46 * system property and instantiating either the 47 * {@link WindowsTerminalTest} or {@link UnixTerminal}. 48 * 49 * @see #initializeTerminal 50 */ setupTerminal()51 public static synchronized Terminal setupTerminal() { 52 if (term != null) { 53 return term; 54 } 55 56 final Terminal t; 57 58 String os = System.getProperty("os.name").toLowerCase(); 59 String termProp = System.getProperty("jline.terminal"); 60 61 if ((termProp != null) && (termProp.length() > 0)) { 62 try { 63 t = (Terminal) Class.forName(termProp).newInstance(); 64 } catch (Exception e) { 65 throw (IllegalArgumentException) new IllegalArgumentException(e 66 .toString()).fillInStackTrace(); 67 } 68 } else if (os.indexOf("windows") != -1) { 69 t = new WindowsTerminal(); 70 } else { 71 t = new UnixTerminal(); 72 } 73 74 try { 75 t.initializeTerminal(); 76 } catch (Exception e) { 77 e.printStackTrace(); 78 79 return term = new UnsupportedTerminal(); 80 } 81 82 return term = t; 83 } 84 85 /** 86 * Returns true if the current console supports ANSI 87 * codes. 88 */ isANSISupported()89 public boolean isANSISupported() { 90 return true; 91 } 92 93 /** 94 * Read a single character from the input stream. This might 95 * enable a terminal implementation to better handle nuances of 96 * the console. 97 */ readCharacter(final InputStream in)98 public int readCharacter(final InputStream in) throws IOException { 99 return in.read(); 100 } 101 102 /** 103 * Reads a virtual key from the console. Typically, this will 104 * just be the raw character that was entered, but in some cases, 105 * multiple input keys will need to be translated into a single 106 * virtual key. 107 * 108 * @param in the InputStream to read from 109 * @return the virtual key (e.g., {@link ConsoleOperations#VK_UP}) 110 */ readVirtualKey(InputStream in)111 public int readVirtualKey(InputStream in) throws IOException { 112 return readCharacter(in); 113 } 114 115 /** 116 * Initialize any system settings 117 * that are required for the console to be able to handle 118 * input correctly, such as setting tabtop, buffered input, and 119 * character echo. 120 */ initializeTerminal()121 public abstract void initializeTerminal() throws Exception; 122 123 /** 124 * Returns the current width of the terminal (in characters) 125 */ getTerminalWidth()126 public abstract int getTerminalWidth(); 127 128 /** 129 * Returns the current height of the terminal (in lines) 130 */ getTerminalHeight()131 public abstract int getTerminalHeight(); 132 133 /** 134 * Returns true if this terminal is capable of initializing the 135 * terminal to use jline. 136 */ isSupported()137 public abstract boolean isSupported(); 138 139 /** 140 * Returns true if the terminal will echo all characters type. 141 */ getEcho()142 public abstract boolean getEcho(); 143 144 /** 145 * Invokes before the console reads a line with the prompt and mask. 146 */ beforeReadLine(ConsoleReader reader, String prompt, Character mask)147 public void beforeReadLine(ConsoleReader reader, String prompt, 148 Character mask) { 149 } 150 151 /** 152 * Invokes after the console reads a line with the prompt and mask. 153 */ afterReadLine(ConsoleReader reader, String prompt, Character mask)154 public void afterReadLine(ConsoleReader reader, String prompt, 155 Character mask) { 156 } 157 158 /** 159 * Returns false if character echoing is disabled. 160 */ isEchoEnabled()161 public abstract boolean isEchoEnabled(); 162 163 164 /** 165 * Enable character echoing. This can be used to re-enable character 166 * if the ConsoleReader is no longer being used. 167 */ enableEcho()168 public abstract void enableEcho(); 169 170 171 /** 172 * Disable character echoing. This can be used to manually re-enable 173 * character if the ConsoleReader has been disabled. 174 */ disableEcho()175 public abstract void disableEcho(); 176 getDefaultBindings()177 public InputStream getDefaultBindings() { 178 // Mac bindings are slightly different from Unix/Linux. 179 // For instance, the Delete key behavior is different between them. 180 return Terminal.class.getResourceAsStream( 181 System.getProperty("os.name").toLowerCase().startsWith("mac") ? 182 "keybindings-mac.properties" : "keybindings.properties"); 183 } 184 } 185