View Javadoc
1   package org.cyclopsgroup.jmxterm.cc;
2   
3   import java.util.ArrayList;
4   import java.util.Collections;
5   import java.util.List;
6   
7   import org.apache.commons.lang3.StringUtils;
8   import org.apache.commons.lang3.Validate;
9   import org.cyclopsgroup.jcli.jline.CliCompletor;
10  import org.cyclopsgroup.jmxterm.Command;
11  import org.jline.reader.Candidate;
12  import org.jline.reader.Completer;
13  import org.jline.reader.LineReader;
14  import org.jline.reader.ParsedLine;
15  import org.jline.reader.impl.completer.ArgumentCompleter;
16  import org.slf4j.Logger;
17  import org.slf4j.LoggerFactory;
18  
19  /**
20   * JLine completor that handles tab key
21   *
22   * @author <a href="mailto:jiaqi.guo@gmail.com">Jiaqi Guo</a>
23   */
24  public class ConsoleCompletor implements Completer {
25    private static final Logger LOG = LoggerFactory.getLogger(ConsoleCompletor.class);
26  
27    private final CommandCenter commandCenter;
28  
29    private final List<Candidate> commandNames;
30  
31    public ConsoleCompletor(CommandCenter commandCenter) {
32      Validate.notNull(commandCenter, "Command center can't be NULL");
33      this.commandCenter = commandCenter;
34      List<String> commandNames = new ArrayList<String>(commandCenter.getCommandNames());
35      Collections.sort(commandNames);
36      this.commandNames = new ArrayList<Candidate>(commandNames.size());
37      for (String commandName : commandNames) {
38        this.commandNames.add(new Candidate(commandName));
39      }
40    }
41  
42    @Override
43    public void complete(LineReader reader, ParsedLine line, List<Candidate> candidates) {
44      try {
45        String buffer = line.line();
46        if (StringUtils.isEmpty(buffer) || buffer.indexOf(' ') == -1) {
47          completeCommandName(buffer, candidates);
48        }
49        int separatorPos = buffer.indexOf(' ');
50        String commandName = buffer.substring(0, separatorPos);
51        if (LOG.isDebugEnabled()) {
52          LOG.debug("Command name is [" + commandName + "]");
53        }
54        String commandArguments = buffer.substring(separatorPos + 1);
55        commandArguments.replaceFirst("^\\s*", "");
56        if (LOG.isDebugEnabled()) {
57          LOG.debug("Analyzing commmand arguments [" + commandArguments + "]");
58        }
59        Command cmd = commandCenter.commandFactory.createCommand(commandName);
60        cmd.setSession(commandCenter.session);
61        CliCompletor commandCompletor = new CliCompletor(cmd, commandCenter.argTokenizer);
62        int position = line.cursor();
63        commandCompletor.complete(reader,
64            new ArgumentCompleter.ArgumentLine(commandArguments, position - separatorPos),
65            candidates);
66      } catch (RuntimeException e) {
67        if (LOG.isDebugEnabled()) {
68          LOG.debug("Couldn't complete input", e);
69        }
70      }
71    }
72  
73    private void completeCommandName(String buf, List<Candidate> candidates) {
74      if (buf == null) {
75        // Nothing is there
76        candidates.addAll(commandNames);
77      } else if (buf.indexOf(' ') == -1) {
78        // Partial one word
79        List<Candidate> matchedNames = new ArrayList<Candidate>();
80        for (Candidate commandName : commandNames) {
81          if (commandName.value().startsWith(buf)) {
82            matchedNames.add(commandName);
83          }
84        }
85        candidates.addAll(matchedNames);
86      } else {
87        throw new IllegalStateException("Invalid state");
88      }
89    }
90  }