2016-01-25 4 views
6

Ich frage mich, wie ich eine ArgumentCompleter so implementieren könnte, dass, wenn ich einen vollständigen und gültigen Befehl abschließe, würde die Registerkarte für einen neuen Befehl abgeschlossen werden.Verwenden Sie JLine, um mehrere Befehle in einer Zeile zu vervollständigen

Ich hätte angenommen, es so etwas wie diese konstruiert tun könnte:

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(); 

jetzt jedoch diese stoppt, nachdem Reiter arbeiten, um die erste foo bar

completeing Ist jemand vertraut genug mit der Bibliothek, mir zu sagen Wie würde ich das umsetzen? Oder gibt es eine bekannte Möglichkeit, dies zu tun, die ich vermisse? Auch dies verwendet JLine2.

Antwort

4

Das eine schwierige Aufgabe

Es wird von der completer gehandhabt wird Sie verwenden :-)

war. Die complete() Methode des Completers muss nur für die Suche verwenden, was nach dem letzten Leerzeichen kommt.

Wenn Sie zum Beispiel sehen Sie die FileNameCompleter der Bibliothek: dies nicht getan, so haben Sie keine Vollendung finden wird, weil die completer sucht nach <input1> <input2> und nicht nur für <input2> :-)

Sie werden muss eine eigene Implementierung eines Completers durchführen, der Input2 findet.

Zusätzlich muss das CompletionHandler an das anhängen, was Sie bereits eingegeben haben.

Hier ist eine grundlegende Implementierung der Standard FileNameCompleter Wechsel:

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(); 
    } 

Und hier die complete() -Methode des CompletionHandler Änderung der Standard 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 ,. Das wird also einige größere Änderungen erfordern, als ich dachte. Danke für die Einsicht! – flakes

+0

Zumindest scheint es, Sie können es nicht durch einige Config aktivieren. Sie können jedoch eine Standardimplementierung erstellen und sie für Ihre nächsten Klassen übernehmen. –

Verwandte Themen