use jline instead of java-readline. jline can be added to SVN thanks to its BSD license. plus some small cleanup.

git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@158850 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Daniel Naber 2005-03-23 23:40:50 +00:00
parent 9fcd99dbda
commit 5a59714f4a
7 changed files with 100 additions and 213 deletions

View File

@ -1,2 +1,2 @@
Main-Class: lucli.Lucli Main-Class: lucli.Lucli
Class-Path: lib/libreadline-java.jar lib/lucene.jar Class-Path: lib/jline.jar lib/lucene.jar

View File

@ -1 +0,0 @@
Place libreadline-java.jar.

View File

@ -0,0 +1,33 @@
Copyright (c) 2002, 2003, 2004, 2005, Marc Prud'hommeaux <mwp1@cornell.edu>
All rights reserved.
Redistribution and use in source and binary forms, with or
without modification, are permitted provided that the following
conditions are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with
the distribution.
Neither the name of JLine nor the names of its contributors
may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,2 @@
AnyObjectId[b841cf167aa3ca6c82f2e40ba2fd8732e829525f] was removed in git history.
Apache SVN contains full history.

View File

@ -1,118 +0,0 @@
package lucli;
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache Lucene" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache Lucene", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
import org.gnu.readline.*;
import java.util.Iterator;
import java.util.TreeMap;
/**
* Provide for tab completion
* When the user types a tab do the standard thing: complete the command
* Two tabs show all possible completions.
*/
public class Completer implements ReadlineCompleter {
String[] words; //list of words
int currentPosition = 0; //current position in the array
/**
Default constructor.
*/
public Completer (TreeMap wordMap) {
int size = wordMap.size();
words = new String[size];
Iterator wordIterator = wordMap.keySet().iterator();
for (int ii=0; wordIterator.hasNext(); ii++) {
words[ii] = (String) wordIterator.next();
}
}
/**
Return possible completion. Implements org.gnu.readline.ReadlineCompleter.
*/
public String completer (String text, int state) {
String ret = null; //what we're returning
for (int ii = currentPosition; ii < words.length; ii++) {
if (words[ii].startsWith(text)) {
int next = ii + 1;
if ((next < words.length) && words[next].startsWith(text)) {
//more than one word match
currentPosition = ii + 1; //next time start with next one
ret = words[ii];
break;
} else { //found the last one
if (state == 0) { //if it's the only one
ret = words[ii];
break;
} else {
ret = null; //there were previous ones
break;
}
}
}
}
if (ret == null)
currentPosition = 0; //for next search
//System.out.println("returned:" + ret);
return (ret); //no more matches
}
}

View File

@ -55,8 +55,6 @@ package lucli;
*/ */
import java.io.IOException; import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.Reader; import java.io.Reader;
import java.io.StringReader; import java.io.StringReader;
@ -70,6 +68,8 @@ import java.util.Comparator;
import java.util.Iterator; import java.util.Iterator;
import java.util.Enumeration; import java.util.Enumeration;
import jline.ConsoleReader;
import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.Token; import org.apache.lucene.analysis.Token;
import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.TokenStream;
@ -130,15 +130,14 @@ class LuceneMethods {
} }
public void search(String queryString, boolean explain, boolean showTokens) throws java.io.IOException, org.apache.lucene.queryParser.ParseException { public void search(String queryString, boolean explain, boolean showTokens, ConsoleReader cr)
BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); throws java.io.IOException, org.apache.lucene.queryParser.ParseException {
Hits hits = initSearch(queryString); Hits hits = initSearch(queryString);
System.out.println(hits.length() + " total matching documents"); System.out.println(hits.length() + " total matching documents");
if (explain) { if (explain) {
query = explainQuery(queryString); query = explainQuery(queryString);
} }
final int HITS_PER_PAGE = 10; final int HITS_PER_PAGE = 10;
message("--------------------------------------"); message("--------------------------------------");
for (int start = 0; start < hits.length(); start += HITS_PER_PAGE) { for (int start = 0; start < hits.length(); start += HITS_PER_PAGE) {
@ -158,8 +157,8 @@ class LuceneMethods {
message("#################################################"); message("#################################################");
if (hits.length() > end) { if (hits.length() > end) {
System.out.print("more (y/n) ? "); // TODO: don't let the input end up in the command line history
queryString = in.readLine(); queryString = cr.readLine("more (y/n) ? ");
if (queryString.length() == 0 || queryString.charAt(0) == 'n') if (queryString.length() == 0 || queryString.charAt(0) == 'n')
break; break;
} }

View File

@ -54,18 +54,27 @@ package lucli;
* <http://www.apache.org/>. * <http://www.apache.org/>.
*/ */
import java.io.*; import java.io.File;
import org.gnu.readline.*; import java.io.IOException;
import org.apache.lucene.queryParser.ParseException; import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Set;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.Iterator;
import jline.ArgumentCompletor;
import jline.Completor;
import jline.ConsoleReader;
import jline.FileNameCompletor;
import jline.History;
import jline.SimpleCompletor;
import org.apache.lucene.queryParser.ParseException;
/** /**
* lucli Main class for lucli: the Lucene Command Line Interface * Main class for lucli: the Lucene Command Line Interface.
* This class handles mostly the actual CLI part, command names, help, etc. * This class handles mostly the actual CLI part, command names, help, etc.
*/ */
public class Lucli { public class Lucli {
final static String DEFAULT_INDEX = "index"; //directory "index" under the current directory final static String DEFAULT_INDEX = "index"; //directory "index" under the current directory
@ -87,7 +96,7 @@ public class Lucli {
final static int TOKENS = 8; final static int TOKENS = 8;
final static int EXPLAIN = 9; final static int EXPLAIN = 9;
String fullPath; String historyFile;
TreeMap commandMap = new TreeMap(); TreeMap commandMap = new TreeMap();
LuceneMethods luceneMethods; //current cli class we're using LuceneMethods luceneMethods; //current cli class we're using
boolean enableReadline; //false: use plain java. True: shared library readline boolean enableReadline; //false: use plain java. True: shared library readline
@ -97,16 +106,14 @@ public class Lucli {
application initialization file. application initialization file.
*/ */
public Lucli(String[] args) throws ParseException, IOException { public Lucli(String[] args) throws IOException {
String line; String line;
fullPath = System.getProperty("user.home") + System.getProperty("file.separator") historyFile = System.getProperty("user.home") + File.separator + HISTORYFILE;
+ HISTORYFILE;
/* /*
* Initialize the list of commands * Initialize the list of commands
*/ */
addCommand("info", INFO, "Display info about the current Lucene index. Example: info"); addCommand("info", INFO, "Display info about the current Lucene index. Example: info");
addCommand("search", SEARCH, "Search the current index. Example: search foo", 1); addCommand("search", SEARCH, "Search the current index. Example: search foo", 1);
addCommand("count", COUNT, "Return the number of hits for a search. Example: count foo", 1); addCommand("count", COUNT, "Return the number of hits for a search. Example: count foo", 1);
@ -118,79 +125,64 @@ public class Lucli {
addCommand("tokens", TOKENS, "Does a search and shows the top 10 tokens for each document. Verbose! Example: tokens foo", 1); addCommand("tokens", TOKENS, "Does a search and shows the top 10 tokens for each document. Verbose! Example: tokens foo", 1);
addCommand("explain", EXPLAIN, "Explanation that describes how the document scored against query. Example: explain foo", 1); addCommand("explain", EXPLAIN, "Explanation that describes how the document scored against query. Example: explain foo", 1);
//parse command line arguments //parse command line arguments
parseArgs(args); parseArgs(args);
if (enableReadline) ConsoleReader cr = new ConsoleReader();
org.gnu.readline.Readline.load(ReadlineLibrary.GnuReadline ); //Readline.readHistoryFile(fullPath);
else cr.setHistory(new History(new File(historyFile)));
org.gnu.readline.Readline.load(ReadlineLibrary.PureJava );
Readline.initReadline("lucli"); // init, set app name, read inputrc
Readline.readHistoryFile(fullPath);
// read history file, if available
File history = new File(".rltest_history");
try {
if (history.exists())
Readline.readHistoryFile(history.getName());
} catch (Exception e) {
System.err.println("Error reading history file!");
}
// Set word break characters
try {
Readline.setWordBreakCharacters(" \t;");
}
catch (UnsupportedEncodingException enc) {
System.err.println("Could not set word break characters");
System.exit(0);
}
// set completer with list of words // set completer with list of words
Completor[] comp = new Completor[]{
Readline.setCompleter(new Completer(commandMap)); new SimpleCompletor(getCommandsAsArray()),
new FileNameCompletor()
};
cr.addCompletor (new ArgumentCompletor(comp));
// main input loop // main input loop
luceneMethods = new LuceneMethods(DEFAULT_INDEX); luceneMethods = new LuceneMethods(DEFAULT_INDEX);
while (true) { while (true) {
try { try {
line = Readline.readline("lucli> "); line = cr.readLine("lucli> ");
if (line != null) { if (line != null) {
handleCommand(line); handleCommand(line, cr);
} }
} catch (UnsupportedEncodingException enc) {
System.err.println("caught UnsupportedEncodingException");
break;
} catch (java.io.EOFException eof) { } catch (java.io.EOFException eof) {
System.out.println("");//new line System.out.println("");//new line
exit(); exit();
} catch (UnsupportedEncodingException enc) {
enc.printStackTrace(System.err);
} catch (ParseException pe) {
pe.printStackTrace(System.err);
} catch (IOException ioe) { } catch (IOException ioe) {
ioe.printStackTrace(System.err); ioe.printStackTrace(System.err);
} }
} }
exit();
} }
public static void main(String[] args) throws ParseException, IOException { private String[] getCommandsAsArray() {
Set commandSet = commandMap.keySet();
String[] commands = new String[commandMap.size()];
int i = 0;
for (Iterator iter = commandSet.iterator(); iter.hasNext();) {
String cmd = (String) iter.next();
commands[i++] = cmd;
}
return commands;
}
public static void main(String[] args) throws IOException {
new Lucli(args); new Lucli(args);
} }
private void handleCommand(String line) throws IOException, ParseException { private void handleCommand(String line, ConsoleReader cr) throws IOException, ParseException {
String [] words = tokenizeCommand(line); String [] words = tokenizeCommand(line);
if (words.length == 0) if (words.length == 0)
return; //white space return; //white space
String query = ""; String query = "";
if (line.trim().startsWith("#")) // # = comment
return;
//Command name and number of arguments //Command name and number of arguments
switch (getCommandId(words[0], words.length - 1)) { switch (getCommandId(words[0], words.length - 1)) {
case INFO: case INFO:
@ -200,7 +192,7 @@ public class Lucli {
for (int ii = 1; ii < words.length; ii++) { for (int ii = 1; ii < words.length; ii++) {
query += words[ii] + " "; query += words[ii] + " ";
} }
luceneMethods.search(query, false, false); luceneMethods.search(query, false, false, cr);
break; break;
case COUNT: case COUNT:
for (int ii = 1; ii < words.length; ii++) { for (int ii = 1; ii < words.length; ii++) {
@ -234,13 +226,13 @@ public class Lucli {
for (int ii = 1; ii < words.length; ii++) { for (int ii = 1; ii < words.length; ii++) {
query += words[ii] + " "; query += words[ii] + " ";
} }
luceneMethods.search(query, false, true); luceneMethods.search(query, false, true, cr);
break; break;
case EXPLAIN: case EXPLAIN:
for (int ii = 1; ii < words.length; ii++) { for (int ii = 1; ii < words.length; ii++) {
query += words[ii] + " "; query += words[ii] + " ";
} }
luceneMethods.search(query, true, false); luceneMethods.search(query, true, false, cr);
break; break;
case HELP: case HELP:
help(); help();
@ -248,7 +240,7 @@ public class Lucli {
case NOCOMMAND: //do nothing case NOCOMMAND: //do nothing
break; break;
case UNKOWN: case UNKOWN:
System.out.println("Unknown command:" + words[0] + ". Type help to get a list of commands."); System.out.println("Unknown command: " + words[0] + ". Type help to get a list of commands.");
break; break;
} }
} }
@ -264,13 +256,6 @@ public class Lucli {
} }
private void exit() { private void exit() {
try {
Readline.writeHistoryFile(fullPath);
} catch (IOException ioe) {
error("while saving history:" + ioe);
}
Readline.cleanup();
System.exit(0); System.exit(0);
} }
@ -329,32 +314,19 @@ public class Lucli {
System.out.println(text); System.out.println(text);
} }
/* /*
* Parse command line arguments * Parse command line arguments (currently none)
* Code inspired by http://www.ecs.umass.edu/ece/wireless/people/emmanuel/java/java/cmdLineArgs/parsing.html
*/ */
private void parseArgs(String[] args) { private void parseArgs(String[] args) {
for (int ii = 0; ii < args.length; ii++) { if (args.length > 0) {
// a little overkill for now, but foundation usage();
// for other args System.exit(1);
if (args[ii].startsWith("-")) {
String arg = args[ii];
if (arg.equals("-r")) {
enableReadline = true;
}
else {
usage();
System.exit(1);
}
}
} }
} }
private void usage() { private void usage() {
message("Usage: lucli [-r]"); message("Usage: lucli.Lucli");
message("Arguments:"); message("(currently, no parameters are supported)");
message("\t-r: Provide tab completion and history using the GNU readline shared library ");
} }
private class Command { private class Command {