| /* |
| * 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; |
| } |
| } |
| } |