2016-01-25 24 views
6

我想知道如何實現ArgumentCompleter,這樣如果我完成一個完整而有效的命令,那麼它將開始選項卡完成一個新的命令。使用JLine在一行上完成多個命令

我本來以爲它可以構建做這樣的事情:

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

但是現在這個停止completeing第一foo bar

片後的工作是否有人與庫告訴我再熟悉不過了我將如何去實施這個?還是有一種已知的方式來做到這一點,我失蹤了?這也是使用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(); 
    } 

而這裏CompletionHandlercomplete() - 方法更改默認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

嗯,。所以這需要比我想象的更大的改變。感謝您的洞察! – flakes

+0

至少它似乎無法通過某些配置激活它。但是你可以制定一個標準的實現併爲你的下一個類繼承它。 –

相關問題