blob: 2d488b64e9d6db66cfe70e48d5725cf02c1fe6d0 [file] [log] [blame]
/*
* Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved.
*
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*/
package jline;
import java.io.*;
import java.util.*;
/**
* <p>
* A simple {@link Completor} implementation that handles a pre-defined
* list of completion words.
* </p>
*
* <p>
* Example usage:
* </p>
* <pre>
* myConsoleReader.addCompletor (new SimpleCompletor (new String [] { "now", "yesterday", "tomorrow" }));
* </pre>
*
* @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
*/
public class SimpleCompletor implements Completor, Cloneable {
/**
* The list of candidates that will be completed.
*/
SortedSet candidates;
/**
* A delimiter to use to qualify completions.
*/
String delimiter;
final SimpleCompletorFilter filter;
/**
* Create a new SimpleCompletor with a single possible completion
* values.
*/
public SimpleCompletor(final String candidateString) {
this(new String[] {
candidateString
});
}
/**
* Create a new SimpleCompletor with a list of possible completion
* values.
*/
public SimpleCompletor(final String[] candidateStrings) {
this(candidateStrings, null);
}
public SimpleCompletor(final String[] strings,
final SimpleCompletorFilter filter) {
this.filter = filter;
setCandidateStrings(strings);
}
/**
* Complete candidates using the contents of the specified Reader.
*/
public SimpleCompletor(final Reader reader) throws IOException {
this(getStrings(reader));
}
/**
* Complete candidates using the whitespearated values in
* read from the specified Reader.
*/
public SimpleCompletor(final InputStream in) throws IOException {
this(getStrings(new InputStreamReader(in)));
}
private static String[] getStrings(final Reader in)
throws IOException {
final Reader reader =
(in instanceof BufferedReader) ? in : new BufferedReader(in);
List words = new LinkedList();
String line;
while ((line = ((BufferedReader) reader).readLine()) != null) {
for (StringTokenizer tok = new StringTokenizer(line);
tok.hasMoreTokens(); words.add(tok.nextToken())) {
;
}
}
return (String[]) words.toArray(new String[words.size()]);
}
public int complete(final String buffer, final int cursor, final List clist) {
String start = (buffer == null) ? "" : buffer;
SortedSet matches = candidates.tailSet(start);
for (Iterator i = matches.iterator(); i.hasNext();) {
String can = (String) i.next();
if (!(can.startsWith(start))) {
break;
}
if (delimiter != null) {
int index = can.indexOf(delimiter, cursor);
if (index != -1) {
can = can.substring(0, index + 1);
}
}
clist.add(can);
}
if (clist.size() == 1) {
clist.set(0, ((String) clist.get(0)) + " ");
}
// the index of the completion is always from the beginning of
// the buffer.
return (clist.size() == 0) ? (-1) : 0;
}
public void setDelimiter(final String delimiter) {
this.delimiter = delimiter;
}
public String getDelimiter() {
return this.delimiter;
}
public void setCandidates(final SortedSet candidates) {
if (filter != null) {
TreeSet filtered = new TreeSet();
for (Iterator i = candidates.iterator(); i.hasNext();) {
String element = (String) i.next();
element = filter.filter(element);
if (element != null) {
filtered.add(element);
}
}
this.candidates = filtered;
} else {
this.candidates = candidates;
}
}
public SortedSet getCandidates() {
return Collections.unmodifiableSortedSet(this.candidates);
}
public void setCandidateStrings(final String[] strings) {
setCandidates(new TreeSet(Arrays.asList(strings)));
}
public void addCandidateString(final String candidateString) {
final String string =
(filter == null) ? candidateString : filter.filter(candidateString);
if (string != null) {
candidates.add(string);
}
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
/**
* Filter for elements in the completor.
*
* @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
*/
public static interface SimpleCompletorFilter {
/**
* Filter the specified String. To not filter it, return the
* same String as the parameter. To exclude it, return null.
*/
public String filter(String element);
}
public static class NoOpFilter implements SimpleCompletorFilter {
public String filter(final String element) {
return element;
}
}
}