2016-01-25 23 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

至少它似乎无法通过某些配置激活它。但是你可以制定一个标准的实现并为你的下一个类继承它。 –

相关问题