Skip to content

Commit

Permalink
Improve ordering of candidates and groups, fixes #205 and fixes #210
Browse files Browse the repository at this point in the history
  • Loading branch information
gnodet committed Jan 23, 2018
1 parent fc728fc commit a3a115b
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 12 deletions.
39 changes: 28 additions & 11 deletions reader/src/main/java/org/jline/reader/impl/LineReaderImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,10 @@
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.function.Function;
import java.util.function.IntBinaryOperator;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -3828,8 +3824,7 @@ protected boolean doComplete(CompletionType lst, boolean useMenu, boolean prefix
int errors = getInt(ERRORS, DEFAULT_ERRORS);

// Build a list of sorted candidates
NavigableMap<String, List<Candidate>> sortedCandidates =
new TreeMap<>(caseInsensitive ? String.CASE_INSENSITIVE_ORDER : null);
Map<String, List<Candidate>> sortedCandidates = new HashMap<>();
for (Candidate cand : candidates) {
sortedCandidates
.computeIfAbsent(AttributedString.fromAnsi(cand.value()).toString(), s -> new ArrayList<>())
Expand Down Expand Up @@ -3993,6 +3988,15 @@ else if (isSet(Option.RECOGNIZE_EXACT)) {
return true;
}

protected Comparator<Candidate> getCandidateComparator(boolean caseInsensitive, String word) {
String wdi = caseInsensitive ? word.toLowerCase() : word;
ToIntFunction<String> wordDistance = w -> distance(wdi, caseInsensitive ? w.toLowerCase() : w);
return Comparator
.comparing(Candidate::value, Comparator.comparingInt(wordDistance))
.thenComparing(Candidate::value, Comparator.comparingInt(String::length))
.thenComparing(Comparator.naturalOrder());
}

protected String getOthersGroupName() {
return getString(OTHERS_GROUP_NAME, DEFAULT_OTHERS_GROUP_NAME);
}
Expand All @@ -4001,6 +4005,12 @@ protected String getOriginalGroupName() {
return getString(ORIGINAL_GROUP_NAME, DEFAULT_ORIGINAL_GROUP_NAME);
}


protected Comparator<String> getGroupComparator() {
return Comparator.<String>comparingInt(s -> getOthersGroupName().equals(s) ? 1 : getOriginalGroupName().equals(s) ? -1 : 0)
.thenComparing(String::toLowerCase, Comparator.naturalOrder());
}

private void mergeCandidates(List<Candidate> possible) {
// Merge candidates if the have the same key
Map<String, List<Candidate>> keyedCandidates = new HashMap<>();
Expand Down Expand Up @@ -4335,9 +4345,12 @@ protected boolean doList(List<Candidate> possible, String completed, boolean run
.filter(c -> caseInsensitive
? c.value().toLowerCase().startsWith(current.toLowerCase())
: c.value().startsWith(current))
.sorted(getCandidateComparator(caseInsensitive, current))
.collect(Collectors.toList());
} else {
cands = possible;
cands = possible.stream()
.sorted(getCandidateComparator(caseInsensitive, current))
.collect(Collectors.toList());
}
post = () -> {
AttributedString t = insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>());
Expand Down Expand Up @@ -4423,13 +4436,17 @@ protected PostResult computePost(List<Candidate> possible, Candidate selection,
protected PostResult computePost(List<Candidate> possible, Candidate selection, List<Candidate> ordered, String completed, Function<String, Integer> wcwidth, int width, boolean autoGroup, boolean groupName, boolean rowsFirst) {
List<Object> strings = new ArrayList<>();
if (groupName) {
LinkedHashMap<String, TreeMap<String, Candidate>> sorted = new LinkedHashMap<>();
Comparator<String> groupComparator = getGroupComparator();
Map<String, Map<String, Candidate>> sorted;
sorted = groupComparator != null
? new TreeMap<>(groupComparator)
: new LinkedHashMap<>();
for (Candidate cand : possible) {
String group = cand.group();
sorted.computeIfAbsent(group != null ? group : "", s -> new TreeMap<>())
sorted.computeIfAbsent(group != null ? group : "", s -> new LinkedHashMap<>())
.put(cand.value(), cand);
}
for (Map.Entry<String, TreeMap<String, Candidate>> entry : sorted.entrySet()) {
for (Map.Entry<String, Map<String, Candidate>> entry : sorted.entrySet()) {
String group = entry.getKey();
if (group.isEmpty() && sorted.size() > 1) {
group = getOthersGroupName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public void testListAndMenu() throws IOException {
assertFalse(reader.list);
assertFalse(reader.menu);

assertBuffer("foo", new TestBuffer("fo\t\t"));
assertBuffer("foobar", new TestBuffer("fo\t\t"));
assertFalse(reader.list);
assertTrue(reader.menu);

Expand Down

0 comments on commit a3a115b

Please sign in to comment.