2016-01-25 7 views
6

ArgumentCompleterをどのように実装すれば完全で有効なコマンドを完了すれば、新しいコマンドのためにタブが完成するのかと思いました。JLineを使用して複数のコマンドを1行で完成

私はそれがこのような何かをやって構築することができ想定しているだろう:

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

しかし、今これが最初foo bar

をcompleteingタブの後に働くことを教えするためのライブラリで十分に熟知し、誰です停止します私はこれをどうやって実行するのですか?それとも私が行方不明になっていることを知られている方法はありますか?これはJLine2を使用しています。

それはあなたが使用しているコンプリータによって処理され

:-)かなり作業でした

答えて

4

。コンプリータのcomplete()メソッドは、最後の空白の後ろにあるものだけを検索に使用しなければなりません。

あなたは図書館のFileNameCompleterで例を探している場合:あなたは何の完了を見つけませんので、あなたは意志

:-)これは <input1> <input2>ためのコンプリータ検索するためだけでなく <input2>ため、全く行われていませんinput2を見つけることができるコンプリータの独自の実装を行う必要があります。

さらに、CompletionHandlerは、すでに入力したものに見つかったものを追加する必要があります。ここで

がデフォルト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(); 
    } 

そして、ここでデフォルトCandidateListCompletionHandlerを変更CompletionHandlercomplete()方法 - :

@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

うーん、。だから、これは私が思ったよりも大きな変化を起こすだろう。洞察に感謝します! – flakes

+0

少なくとも、いくつかの設定でそれを有効にすることはできないようです。しかし、標準的な実装を行い、次のクラスのために継承することができます。 –