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 import com.sun.jmx.snmp.ThreadContext;
012
013 /**
014 * Representation of the input terminal for a platform. Handles
015 * any initialization that the platform may need to perform
016 * in order to allow the {@link ConsoleReader} to correctly handle
017 * input.
018 *
019 * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
020 */
021 public abstract class Terminal implements ConsoleOperations {
022 private static Terminal term;
023
024 /**
025 * @see #setupTerminal
026 */
027 public static Terminal getTerminal() {
028 return setupTerminal();
029 }
030
031 /**
032 * Reset the current terminal to null.
033 */
034 public static void resetTerminal() {
035 term = null;
036 }
037
038 /**
039 * <p>Configure and return the {@link Terminal} instance for the
040 * current platform. This will initialize any system settings
041 * that are required for the console to be able to handle
042 * input correctly, such as setting tabtop, buffered input, and
043 * character echo.</p>
044 *
045 * <p>This class will use the Terminal implementation specified in the
046 * <em>jline.terminal</em> system property, or, if it is unset, by
047 * detecting the operating system from the <em>os.name</em>
048 * system property and instantiating either the
049 * {@link WindowsTerminalTest} or {@link UnixTerminal}.
050 *
051 * @see #initializeTerminal
052 */
053 public static synchronized Terminal setupTerminal() {
054 if (term != null) {
055 return term;
056 }
057
058 final Terminal t;
059
060 String os = System.getProperty("os.name").toLowerCase();
061 String termProp = System.getProperty("jline.terminal");
062
063 if ((termProp != null) && (termProp.length() > 0)) {
064 try {
065 t = (Terminal) Class.forName(termProp).newInstance();
066 } catch (Exception e) {
067 throw (IllegalArgumentException) new IllegalArgumentException(e
068 .toString()).fillInStackTrace();
069 }
070 } else if (os.indexOf("windows") != -1) {
071 t = new WindowsTerminal();
072 } else {
073 t = new UnixTerminal();
074 }
075
076 try {
077 t.initializeTerminal();
078 } catch (Exception e) {
079 e.printStackTrace();
080
081 return term = new UnsupportedTerminal();
082 }
083
084 return term = t;
085 }
086
087 /**
088 * Returns true if the current console supports ANSI
089 * codes.
090 */
091 public boolean isANSISupported() {
092 return true;
093 }
094
095 /**
096 * Read a single character from the input stream. This might
097 * enable a terminal implementation to better handle nuances of
098 * the console.
099 */
100 public int readCharacter(final InputStream in) throws IOException {
101 return in.read();
102 }
103
104 /**
105 * Reads a virtual key from the console. Typically, this will
106 * just be the raw character that was entered, but in some cases,
107 * multiple input keys will need to be translated into a single
108 * virtual key.
109 *
110 * @param in the InputStream to read from
111 * @return the virtual key (e.g., {@link ConsoleOperations#VK_UP})
112 */
113 public int readVirtualKey(InputStream in) throws IOException {
114 return readCharacter(in);
115 }
116
117 /**
118 * Initialize any system settings
119 * that are required for the console to be able to handle
120 * input correctly, such as setting tabtop, buffered input, and
121 * character echo.
122 */
123 public abstract void initializeTerminal() throws Exception;
124
125 /**
126 * Returns the current width of the terminal (in characters)
127 */
128 public abstract int getTerminalWidth();
129
130 /**
131 * Returns the current height of the terminal (in lines)
132 */
133 public abstract int getTerminalHeight();
134
135 /**
136 * Returns true if this terminal is capable of initializing the
137 * terminal to use jline.
138 */
139 public abstract boolean isSupported();
140
141 /**
142 * Returns true if the terminal will echo all characters type.
143 */
144 public abstract boolean getEcho();
145
146 /**
147 * Invokes before the console reads a line with the prompt and mask.
148 */
149 public void beforeReadLine(ConsoleReader reader, String prompt,
150 Character mask) {
151 }
152
153 /**
154 * Invokes after the console reads a line with the prompt and mask.
155 */
156 public void afterReadLine(ConsoleReader reader, String prompt,
157 Character mask) {
158 }
159
160 /**
161 * Returns false if character echoing is disabled.
162 */
163 public abstract boolean isEchoEnabled();
164
165
166 /**
167 * Enable character echoing. This can be used to re-enable character
168 * if the ConsoleReader is no longer being used.
169 */
170 public abstract void enableEcho();
171
172
173 /**
174 * Disable character echoing. This can be used to manually re-enable
175 * character if the ConsoleReader has been disabled.
176 */
177 public abstract void disableEcho();
178
179 public InputStream getDefaultBindings() {
180 return getClass().getResourceAsStream("keybindings.properties");
181 }
182 }