Search code examples
javaautocompletejlinejline3

Java : Jline3 : Autocomplete with more than one word


I would like to auto complete using more than one word, for example:

> we can<TAB>
welcome_trashcan  pecan_seaweed  yeswecan  canwest

So all the suggestions should contain both of the keywords. Ideally, it should work for unlimited keywords.

I read the completion wiki, but I don't know which path to follow to achieve this.


Solution

  • I ended up implementing a new Interface (its written in groovy):

    class MatchAnyCompleter implements Completer {
        protected final List<Candidate> candidateList = []
    
        MatchAnyCompleter(List<String> list) {
            assert list
            list.each {
                candidateList << new Candidate(AttributedString.stripAnsi(it), it, null, null, null, null, true)
            }
        }
    
        @Override
        void complete(final LineReader reader, final ParsedLine commandLine, final List<Candidate> selected) {
            assert commandLine != null
            assert selected != null
            selected.addAll(candidateList.findAll {
                Candidate candidate ->
                    commandLine.words().stream().allMatch {
                        String keyword ->
                            candidate.value().contains(keyword)
                    }
            })
        }
    }
    

    Test:

    class MatchAnyCompleterTest extends Specification {
        def "Testing matches"() {
            setup:
                def mac = new MatchAnyCompleter([
                        "somevalue",
                        "welcome_trashcan",
                        "pecan_seaweed",
                        "yeswecan",
                        "canwest",
                        "nomatchhere"
                ])
                def cmdLine = new ParsedLine() {
                    // non-implemented methods were removed for simplicity
                    @Override
                    List<String> words() {
                        return ["we","can"]
                    }
                }
                List<Candidate> selected = []
                mac.complete(null, cmdLine, selected)
            expect:
                selected.each {
                    println it.value()
                }
                assert selected.size() == 4
        }
    }
    

    output:

    welcome_trashcan
    pecan_seaweed
    yeswecan
    canwest