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 * Representation of the input terminal for a platform. Handles
013 * any initialization that the platform may need to perform
014 * in order to allow the {@link ConsoleReader} to correctly handle
015 * input.
016 *
017 * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
018 */
019 public abstract class Terminal implements ConsoleOperations {
020 private static Terminal term;
021
022 /**
023 * @see #setupTerminal
024 */
025 public static Terminal getTerminal() {
026 return setupTerminal();
027 }
028
029 /**
030 * Reset the current terminal to null.
031 */
032 public static void resetTerminal() {
033 term = null;
034 }
035
036 /**
037 * <p>Configure and return the {@link Terminal} instance for the
038 * current platform. This will initialize any system settings
039 * that are required for the console to be able to handle
040 * input correctly, such as setting tabtop, buffered input, and
041 * character echo.</p>
042 *
043 * <p>This class will use the Terminal implementation specified in the
044 * <em>jline.terminal</em> system property, or, if it is unset, by
045 * detecting the operating system from the <em>os.name</em>
046 * system property and instantiating either the
047 * {@link WindowsTerminalTest} or {@link UnixTerminal}.
048 *
049 * @see #initializeTerminal
050 */
051 public static synchronized Terminal setupTerminal() {
052 if (term != null) {
053 return term;
054 }
055
056 final Terminal t;
057
058 String os = System.getProperty("os.name").toLowerCase();
059 String termProp = System.getProperty("jline.terminal");
060
061 if ((termProp != null) && (termProp.length() > 0)) {
062 try {
063 t = (Terminal) Class.forName(termProp).newInstance();
064 } catch (Exception e) {
065 throw (IllegalArgumentException) new IllegalArgumentException(e
066 .toString()).fillInStackTrace();
067 }
068 } else if (os.indexOf("windows") != -1) {
069 t = new WindowsTerminal();
070 } else {
071 t = new UnixTerminal();
072 }
073
074 try {
075 t.initializeTerminal();
076 } catch (Exception e) {
077 e.printStackTrace();
078
079 return term = new UnsupportedTerminal();
080 }
081
082 return term = t;
083 }
084
085 /**
086 * Returns true if the current console supports ANSI
087 * codes.
088 */
089 public boolean isANSISupported() {
090 return true;
091 }
092
093 /**
094 * Read a single character from the input stream. This might
095 * enable a terminal implementation to better handle nuances of
096 * the console.
097 */
098 public int readCharacter(final InputStream in) throws IOException {
099 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 */
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 */
121 public abstract void initializeTerminal() throws Exception;
122
123 /**
124 * Returns the current width of the terminal (in characters)
125 */
126 public abstract int getTerminalWidth();
127
128 /**
129 * Returns the current height of the terminal (in lines)
130 */
131 public abstract int getTerminalHeight();
132
133 /**
134 * Returns true if this terminal is capable of initializing the
135 * terminal to use jline.
136 */
137 public abstract boolean isSupported();
138
139 /**
140 * Returns true if the terminal will echo all characters type.
141 */
142 public abstract boolean getEcho();
143
144 /**
145 * Invokes before the console reads a line with the prompt and mask.
146 */
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 */
154 public void afterReadLine(ConsoleReader reader, String prompt,
155 Character mask) {
156 }
157
158 /**
159 * Returns false if character echoing is disabled.
160 */
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 */
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 */
175 public abstract void disableEcho();
176
177 public InputStream getDefaultBindings() {
178 return Terminal.class.getResourceAsStream("keybindings.properties");
179 }
180 }