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(
066: e.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: * Enable character echoing. This can be used to re-enable character
165: * if the ConsoleReader is no longer being used.
166: */
167: public abstract void enableEcho();
168:
169: /**
170: * Disable character echoing. This can be used to manually re-enable
171: * character if the ConsoleReader has been disabled.
172: */
173: public abstract void disableEcho();
174:
175: public InputStream getDefaultBindings() {
176: return Terminal.class
177: .getResourceAsStream("keybindings.properties");
178: }
179: }
|