1 /*
2 * Zemucan: A Syntax Assistant for DB2
3 * Copyright (C) 2009, 2010 Andres Gomez Casanova
4 *
5 * This file is part of Zemucan.
6 *
7 * Zemucan is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * Zemucan is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, see <http://www.gnu.org/licenses/>.
19 *
20 * Contact:
21 * a n g o c a at y a h o o dot c o m
22 * Cra. 45 No 61 - 31, Bogota, Colombia.
23 *
24 * Author: $LastChangedBy: angoca $:
25 * Date: $LastChangedDate: 2011-03-06 23:10:20 -0500 (dom, 06 mar 2011) $:
26 * Revision: $LastChangedRevision: 1917 $:
27 * URL: $HeadURL: https://zemucan.svn.sourceforge.net/svnroot/zemucan/branches/zemucan_v1/source-code/uiImplJLine/src/main/java/name/angoca/zemucan/ui/impl/jline/JlineInputReader.java $:
28 */
29 package name.angoca.zemucan.ui.impl.jline;
30
31 import java.awt.event.ActionEvent;
32 import java.awt.event.ActionListener;
33 import java.io.IOException;
34
35 import jline.ConsoleReader;
36 import name.angoca.zemucan.tools.configurator.Configurator;
37 import name.angoca.zemucan.tools.messages.jline.Messages;
38 import name.angoca.zemucan.ui.api.AbstractUIException;
39 import name.angoca.zemucan.ui.api.InputReader;
40 import name.angoca.zemucan.ui.api.InputReaderException;
41
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 /**
46 * Implementation of the input reader using JLine.
47 * <p>
48 * <b>Control Version</b>
49 * <p>
50 * <ul>
51 * <li>0.0.1 Class creation.</li>
52 * <li>0.0.2 'this' to access attributes.</li>
53 * <li>0.0.3 No override.</li>
54 * <li>0.0.4 final.</li>
55 * <li>1.0.0 Moved to version 1.</li>
56 * <li>1.0.1 Validate console.</li>
57 * <li>1.1.0 Exception hierarchy changed.</li>
58 * <li>1.1.1 try catch modified.</li>
59 * <li>1.1.2 Asserts.</li>
60 * <li>1.1.3 Extra line deleted.</li>
61 * <li>1.1.4 Completor renamed.</li>
62 * <li>1.1.5 Completion Handler.</li>
63 * <li>1.1.6 Key binding.</li>
64 * </ul>
65 *
66 * @author Andres Gomez Casanova <a
67 * href="mailto:a n g o c a at y a h o o dot c o m" >(AngocA)</a>
68 * @version 1.1.6 2010-05-24
69 */
70 public final class JlineInputReader implements InputReader {
71 /**
72 * Logger.
73 */
74 private static final Logger LOGGER = LoggerFactory
75 .getLogger(JlineInputReader.class);
76
77 /**
78 * Prompt to show in the console.
79 */
80 private final transient String prompt;
81 /**
82 * JLine console reader.
83 */
84 private final transient ConsoleReader reader;
85
86 /**
87 * Constructor that flushes the stream.
88 *
89 * @param consolePrompt
90 * Prompt to show in each line of the console.
91 * @throws InputReaderException
92 * If there is a problem flushing the stream.
93 */
94 public JlineInputReader(final String/* ! */consolePrompt)
95 throws InputReaderException {
96 assert consolePrompt != null;
97
98 this.prompt = consolePrompt;
99 try {
100 this.reader = new ConsoleReader();
101 } catch (final IOException exception) {
102 throw new InputReaderException(exception);
103 }
104
105 if (this.reader != null) {
106 this.configureConsoleReader();
107 }
108 }
109
110 /**
111 * Configures the console reader.
112 */
113 private void configureConsoleReader() {
114 // Normally, each time a tab is pressed, a beep sounds. It
115 // blocks that.
116 this.reader.setBellEnabled(false);
117
118 // Adds the completor that calls the application's core.
119 this.reader.addCompletor(new ZemucanCompletor());
120
121 // Sets a handler that does not analyzes the candidates, it just
122 // prints them.
123 this.reader.setCompletionHandler(new ZemucanCompletionHandler());
124
125 // Maximum quantity of candidates to show in an assistance.
126 int threshold = -1;
127 try {
128 threshold = Integer
129 .parseInt(Configurator
130 .getInstance()
131 .getProperty(
132 ImplementationJlineInterfaceController.AUTO_PRINT_THRESHOLD_KEY));
133
134 } catch (final NumberFormatException exception) {
135 threshold = ImplementationJlineInterfaceController.AUTO_PRINT_THRESHOLD_VALUE;
136 JlineInputReader.LOGGER.info(Messages.getString("JlineInputReader"
137 + ".InvalidThresholdNumber"), threshold);
138 }
139 this.reader.setAutoprintThreshhold(threshold);
140
141 // Configures the Ctrl + c key to exit from the application.
142 this.reader.addTriggeredAction((char) 3,
143 /**
144 * This class is the listener to exit from the application when the Ctrl
145 * + c keys are pressed.
146 * <p>
147 * This only works for Windows systems. In Linux, it already exists.
148 *
149 * @author Andres Gomez Casanova <a
150 * href="mailto:a n g o c a at y a h o o dot c o m"
151 * >(AngocA)</a>
152 */
153 new ActionListener() {
154 /*
155 * (non-Javadoc)
156 *
157 * @see
158 * java.awt.event.ActionListener#actionPerformed(java.awt.event.
159 * ActionEvent)
160 */
161 @Override
162 public void actionPerformed(final ActionEvent e) {
163 System.exit(0);
164 }
165 });
166 }
167
168 /*
169 * (non-Javadoc)
170 *
171 * @see name.angoca.zemucan.ui.api.InputReader#readString()
172 */
173 @Override
174 public String/* ! */readString() throws AbstractUIException {
175
176 String ret = ""; //$NON-NLS-1$
177 try {
178 ret = this.reader.readLine(this.prompt);
179 } catch (final IOException exception) {
180 throw new InputReaderException(exception);
181 }
182 if (ret == null) {
183 throw new ConsoleProblemException();
184 }
185 return ret;
186 }
187 }