--- /dev/null 2015-04-26 06:51:08.003313989 -0700 +++ new/jdk/src/jdk.jline/share/classes/jdk/internal/jline/console/completer/AggregateCompleter.java 2015-06-18 03:05:16.883897040 -0700 @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jline.console.completer; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import static jline.internal.Preconditions.checkNotNull; + +/** + * Completer which contains multiple completers and aggregates them together. + * + * @author Jason Dillon + * @since 2.3 + */ +public class AggregateCompleter + implements Completer +{ + private final List completers = new ArrayList(); + + public AggregateCompleter() { + // empty + } + + /** + * Construct an AggregateCompleter with the given collection of completers. + * The completers will be used in the iteration order of the collection. + * + * @param completers the collection of completers + */ + public AggregateCompleter(final Collection completers) { + checkNotNull(completers); + this.completers.addAll(completers); + } + + /** + * Construct an AggregateCompleter with the given completers. + * The completers will be used in the order given. + * + * @param completers the completers + */ + public AggregateCompleter(final Completer... completers) { + this(Arrays.asList(completers)); + } + + /** + * Retrieve the collection of completers currently being aggregated. + * + * @return the aggregated completers + */ + public Collection getCompleters() { + return completers; + } + + /** + * Perform a completion operation across all aggregated completers. + * + * @see Completer#complete(String, int, java.util.List) + * @return the highest completion return value from all completers + */ + public int complete(final String buffer, final int cursor, final List candidates) { + // buffer could be null + checkNotNull(candidates); + + List completions = new ArrayList(completers.size()); + + // Run each completer, saving its completion results + int max = -1; + for (Completer completer : completers) { + Completion completion = new Completion(candidates); + completion.complete(completer, buffer, cursor); + + // Compute the max cursor position + max = Math.max(max, completion.cursor); + + completions.add(completion); + } + + // Append candidates from completions which have the same cursor position as max + for (Completion completion : completions) { + if (completion.cursor == max) { + candidates.addAll(completion.candidates); + } + } + + return max; + } + + /** + * @return a string representing the aggregated completers + */ + @Override + public String toString() { + return getClass().getSimpleName() + "{" + + "completers=" + completers + + '}'; + } + + private class Completion + { + public final List candidates; + + public int cursor; + + public Completion(final List candidates) { + checkNotNull(candidates); + this.candidates = new LinkedList(candidates); + } + + public void complete(final Completer completer, final String buffer, final int cursor) { + checkNotNull(completer); + this.cursor = completer.complete(buffer, cursor, candidates); + } + } +}