001 /*
002 * Copyright (c) 2002-2006, 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 * <p>Configure and return the {@link Terminal} instance for the
031 * current platform. This will initialize any system settings
032 * that are required for the console to be able to handle
033 * input correctly, such as setting tabtop, buffered input, and
034 * character echo.</p>
035 *
036 * <p>This class will use the Terminal implementation specified in the
037 * <em>jline.terminal</em> system property, or, if it is unset, by
038 * detecting the operating system from the <em>os.name</em>
039 * system property and instantiateing either the
040 * {@link WindowsTerminal} or {@link UnixTerminal}.
041 *
042 * @see #initializeTerminal
043 */
044 public static synchronized Terminal setupTerminal() {
045 if (term != null) {
046 return term;
047 }
048
049 final Terminal t;
050
051 String os = System.getProperty("os.name").toLowerCase();
052 String termProp = System.getProperty("jline.terminal");
053
054 if ((termProp != null) && (termProp.length() > 0)) {
055 try {
056 t = (Terminal) Class.forName(termProp).newInstance();
057 } catch (Exception e) {
058 throw (IllegalArgumentException) new IllegalArgumentException(e
059 .toString())
060 .fillInStackTrace();
061 }
062 } else if (os.indexOf("windows") != -1) {
063 t = new WindowsTerminal();
064 } else {
065 t = new UnixTerminal();
066 }
067
068 try {
069 t.initializeTerminal();
070 } catch (Exception e) {
071 e.printStackTrace();
072
073 return term = new UnsupportedTerminal();
074 }
075
076 return term = t;
077 }
078
079 /**
080 * Returns true if the current console supports ANSI
081 * codes.
082 */
083 public boolean isANSISupported() {
084 return true;
085 }
086
087 /**
088 * Read a single character from the input stream. This might
089 * enable a terminal implementation to better handle nuances of
090 * the console.
091 */
092 public int readCharacter(final InputStream in) throws IOException {
093 return in.read();
094 }
095
096 /**
097 * Reads a virtual key from the console. Typically, this will
098 * just be the raw character that was entered, but in some cases,
099 * multiple input keys will need to be translated into a single
100 * virtual key.
101 *
102 * @param in the InputStream to read from
103 * @return the virtual key (e.g., {@link ConsoleOperations#VK_UP})
104 */
105 public int readVirtualKey(InputStream in) throws IOException {
106 return readCharacter(in);
107 }
108
109 /**
110 * Initialize any system settings
111 * that are required for the console to be able to handle
112 * input correctly, such as setting tabtop, buffered input, and
113 * character echo.
114 */
115 public abstract void initializeTerminal() throws Exception;
116
117 /**
118 * Returns the current width of the terminal (in characters)
119 */
120 public abstract int getTerminalWidth();
121
122 /**
123 * Returns the current height of the terminal (in lines)
124 */
125 public abstract int getTerminalHeight();
126
127 /**
128 * Returns true if this terminal is capable of initializing the
129 * terminal to use jline.
130 */
131 public abstract boolean isSupported();
132
133 /**
134 * Returns true if the terminal will echo all characters type.
135 */
136 public abstract boolean getEcho();
137
138 /**
139 * Invokes before the console reads a line with the prompt and mask.
140 */
141 public void beforeReadLine(ConsoleReader reader, String prompt,
142 Character mask) {
143 }
144
145 /**
146 * Invokes after the console reads a line with the prompt and mask.
147 */
148 public void afterReadLine(ConsoleReader reader, String prompt,
149 Character mask) {
150 }
151 }