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

Это было довольно задача :-)

Он обрабатывается Completer вы используете. Метод метода complete() должен использовать для поиска только то, что приходит после последнего пробела.

Если посмотреть, например, на FileNameCompleter библиотеки: это не будет сделано на всех, так что вы не найдете завершения, потому что поиски Completer для <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(); 
    } 

А вот complete() -метода CompletionHandler меняющегося по умолчанию 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

По крайней мере, кажется, что вы не можете его активировать с помощью какой-либо конфигурации. Но вы можете сделать стандартную реализацию и наследовать ее для своих следующих классов. –

Смежные вопросы