2016-01-25 16 views
6

Zastanawiam się, jak mogę zaimplementować ArgumentCompleter tak, że jeśli wypełnię pełne i poprawne polecenie, to zacznie się wypełniać kartę dla nowego polecenia.Używanie JLine do wykonywania wielu poleceń na jednej linii

bym Zakłada ona mogła być zbudowana robi coś takiego:

final ConsoleReader consoleReader = new ConsoleReader() 

final ArgumentCompleter cyclicalArgument = new ArgumentCompleter(); 
cyclicalArgument.getCompleters().addAll(Arrays.asList(
     new StringsCompleter("foo"), 
     new StringsCompleter("bar"), 
     cyclicalArgument)); 

consoleReader.addCompleter(cyclicalArgument); 
consoleReader.readLine(); 

Jednak teraz to przestaje działać po karcie completeing pierwszy foo bar

Czy ktoś wystarczająco zaznajomieni z biblioteki mi powiedzieć w jaki sposób chciałbym to wdrożyć? Czy istnieje znany sposób na to, że brakuje mi? Również to jest za pomocą JLine2.

Odpowiedz

4

To było nie lada zadaniem :-)

jest obsługiwane przez ukończyły używasz. Metoda wypełniacza musi być używana tylko w wyszukiwaniu po ostatnim pustym polu.

Jeśli spojrzeć na przykład na FileNameCompleter biblioteki: nie jest to w ogóle możliwe, więc nie znajdziesz końca, ponieważ wyszukuje Completer dla <input1> <input2> i nie tylko dla <input2> :-)

Będziesz musicie zrobić własną implementację osoby, która może znaleźć input2.

Dodatkowo CompletionHandler musi dołączyć to, co znalazłeś do tego, co już wpisałeś.

Oto podstawowe wdrożenie zmianę domyślnego FileNameCompleter:

protected int matchFiles(final String buffer, final String translated, final File[] files, 
     final List<CharSequence> candidates) { 
     // THIS IS NEW 
     String[] allWords = translated.split(" "); 
     String lastWord = allWords[allWords.length - 1]; 
     // the lastWord is used when searching the files now 
     // --- 

     if (files == null) { 
     return -1; 
     } 

     int matches = 0; 

     // first pass: just count the matches 
     for (File file : files) { 
     if (file.getAbsolutePath().startsWith(lastWord)) { 
      matches++; 
     } 
     } 
     for (File file : files) { 
     if (file.getAbsolutePath().startsWith(lastWord)) { 
      CharSequence name = file.getName() + (matches == 1 && file.isDirectory() ? this.separator() : " "); 
      candidates.add(this.render(file, name).toString()); 
     } 
     } 

     final int index = buffer.lastIndexOf(this.separator()); 

     return index + this.separator().length(); 
    } 

a tu complete() -Method z CompletionHandler Zmiana domyślnego CandidateListCompletionHandler:

@Override 
    public boolean complete(final ConsoleReader reader, final List<CharSequence> candidates, final int pos) 
     throws IOException { 
     CursorBuffer buf = reader.getCursorBuffer(); 

     // THIS IS NEW 
     String[] allWords = buf.toString().split(" "); 
     String firstWords = ""; 
     if (allWords.length > 1) { 
     for (int i = 0; i < allWords.length - 1; i++) { 
      firstWords += allWords[i] + " "; 
     } 
     } 
     //----- 

     // if there is only one completion, then fill in the buffer 
     if (candidates.size() == 1) { 
     String value = Ansi.stripAnsi(candidates.get(0).toString()); 

     if (buf.cursor == buf.buffer.length() && this.printSpaceAfterFullCompletion && !value.endsWith(" ")) { 
      value += " "; 
     } 

     // fail if the only candidate is the same as the current buffer 
     if (value.equals(buf.toString())) { 
      return false; 
     } 

     CandidateListCompletionHandler.setBuffer(reader, firstWords + " " + value, pos); 

     return true; 
     } else if (candidates.size() > 1) { 
     String value = this.getUnambiguousCompletions(candidates); 
     CandidateListCompletionHandler.setBuffer(reader, value, pos); 
     } 

     CandidateListCompletionHandler.printCandidates(reader, candidates); 

     // redraw the current console buffer 
     reader.drawLine(); 

     return true; 
    } 
+0

Hmm ,. więc zajmie to trochę większe zmiany, niż myślałem. Dzięki za wgląd! – flakes

+0

Przynajmniej wydaje się, że nie można go aktywować za pomocą jakiejś konfiguracji. Ale możesz wykonać standardową implementację i odziedziczyć ją dla kolejnych klas. –