View Javadoc

1   /*
2    * Copyright 2002,2004 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.commons.jelly.tags.interaction;
17  
18  import java.io.BufferedReader;
19  import java.io.IOException;
20  import java.io.InputStreamReader;
21  
22  import java.util.List;
23  import java.util.ArrayList;
24  
25  import jline.ConsoleReader;
26  import jline.History;
27  import jline.SimpleCompletor;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.apache.commons.jelly.TagSupport;
32  import org.apache.commons.jelly.XMLOutput;
33  
34    /***
35    * Jelly Tag that asks the user a question, and puts his answer into a variable,
36    * with the attribute "answer". This variable may be reused further as any other
37    * Jelly variable.
38    * 
39    * @author <a href="mailto:smor@hasgard.net">Stéphane Mor </a>
40     */
41  public class AskTag extends TagSupport {
42  
43      private static Log logger = LogFactory.getLog(AskTag.class);
44  
45      /*** The history of previous user-inputs.*/
46      private static History consoleHistory = new History();
47  
48      /*** The question to ask to the user. */
49      private String question;
50  
51      /***
52       * The variable in which we will stock the user's input.
53       * This defaults to "interact.answer".
54       */
55      private String answer = "interact.answer";
56  
57      /*** The default value, if the user doesn't answer. */
58      private String defaultInput;
59  
60      /*** The prompt to display before the user input. */
61      private String prompt = ">";
62  
63      /*** A list of predefined commands for tab completion. */
64      private List completor;
65      
66      /*** Whether to complete with previous completions as well. */
67      private boolean useHistoryCompletor = true;
68  
69  
70      /***
71       * Sets the question to ask to the user. If a "default" attribute is
72       * present, it will appear inside [].
73       * 
74       * @param question
75       *            The question to ask to the user
76       */
77      public void setQuestion(String question) {
78          this.question = question;
79      }
80  
81      /***
82       * Sets the name of the variable that will hold the answer. 
83       * This defaults to "interact.answer".
84       * 
85       * @param answer
86       *            the name of the variable that will hold the answer
87       */
88      public void setAnswer(String answer) {
89          this.answer = answer;
90      }
91  
92      /***
93       * Sets the default answer to the question. If it is present, it will appear
94       * inside [].
95       * 
96       * @param defaultInput
97       *            the default answer to the question
98       */
99      public void setDefault(String defaultInput) {
100         this.defaultInput = defaultInput;
101     }
102 
103     /***
104      * Sets the prompt that will be displayed before the user's input.
105      * 
106      * @param prompt
107      *            the prompt that will be displayed before the user's input.
108      */
109     public void setPrompt(String prompt) {
110         this.prompt = prompt;
111     }
112 
113     /***
114      * Sets the list of predefined commands.
115      * 
116      * @param list
117      *            the list of commands used for tab completion.
118      */
119     public void setCompletor(List list) {
120         this.completor = list;
121     }
122     
123     /***
124      * Whether the completion should also happen on previously
125      * entered lines (default true).
126      * @param should whether it should
127      */
128     public void setUseHistoryCompletor(boolean should) {
129         this.useHistoryCompletor = should;
130     }
131 
132     /***
133      * Perform functionality provided by the tag.
134      * 
135      * @param output
136      *            the place to write output
137      */
138     public void doTag(XMLOutput output) {
139         if (question != null) {
140             if (defaultInput != null) {
141                 System.out.println(question + " [" + defaultInput + "]");
142             } else {
143                 System.out.println(question);
144             }
145             // The prompt should be just before the user's input,
146             // but it doesn't work ...
147             //System.out.print(prompt + " ");
148         }
149 
150         ConsoleReader consoleReader;
151         String input = null;
152 
153         try {
154             consoleReader = new ConsoleReader();
155         } catch (IOException e) {
156             logger.warn("couldnt create console reader", e);
157             consoleReader = null;
158         }
159 
160 
161         try {
162             if (consoleReader != null
163                     && consoleReader.getTerminal().isSupported()) {
164 
165                 // resue the static history, so our commands are remeberered
166                 consoleReader.setHistory(consoleHistory);
167 
168                 // hate the bell!
169                 consoleReader.setBellEnabled(false);
170 
171                 // add old commands as tab completion history
172                 List oldCommandsAsList = useHistoryCompletor
173                     ? new ArrayList(consoleHistory.getHistoryList()) : new ArrayList(0);
174                 // add predefined commands if given
175                 if (completor != null && !completor.isEmpty()) {
176                     oldCommandsAsList.addAll(completor);
177                 }
178                 String[] oldCommands = new String[oldCommandsAsList.size()];
179                 oldCommandsAsList.toArray(oldCommands);
180                 consoleReader.addCompletor (new SimpleCompletor (oldCommands));
181 
182                 // read the input!
183                 input = consoleReader.readLine();
184                 
185                 // trim the input for tab completion
186                 input = input.trim();
187 
188                 if (defaultInput != null && input.trim().equals("")) {
189                     input = defaultInput;
190                 }
191             } else {
192                 BufferedReader reader = new BufferedReader(
193                         new InputStreamReader(System.in));
194                 input = reader.readLine();
195             }
196 
197         } catch (IOException ex) {
198             logger.warn("error setting up the console reader", ex);
199         }
200 
201         context.setVariable(answer, input);
202     }
203 }