开发者

jline multi-argument parsing

开发者 https://www.devze.com 2023-01-22 06:55 出处:网络
I am trying to get JLine to do tab completion so I can enter something like the following: commandname --arg1 value1 --arg2 value2

I am trying to get JLine to do tab completion so I can enter something like the following:

commandname --arg1 value1 --arg2 value2

I am using the following code:

final List<Completor> completors = Arrays.asList(
    new SimpleCompletor("commandname "),
    new SimpleCompleto开发者_如何学编程r("--arg1"),
    new SimpleCompletor("--arg2"),
    new NullCompletor());

consoleReader.addCompletor(new ArgumentCompletor(completors));

But after I type the value2 tab completion stops.

(Suplementary question, can I validate value1 as a date using jline?)


I had the same problem, and I solved it by creating my own classes to complete the commands with jLine. I just needed to implement my own Completor.

I am developing an application that could assist DBAs to type not only the command names, but also the parameters. I am using jLine for just for the Terminal interactions, and I created another Completor.

I have to provide the complete grammar to the Completor, and that is the objective of my application. It is called Zemucan and it is hosted in SourceForge; this application is initially focused to DB2, but any grammar could be incorporated. The example of the Completor I am using is:

public final int complete(final String buffer, final int cursor,
        @SuppressWarnings("rawtypes") final List candidateRaw) {
final List<String> candidates = candidateRaw;

    final String phrase = buffer.substring(0, cursor);
    try {
        // Analyzes the typed phrase. This is my program: Zemucan.
        // ReturnOptions is an object that contains the possible options of the command.
        // It can propose complete the command name, or propose options.
        final ReturnOptions answer = InterfaceCore.analyzePhrase(phrase);

        // The first candidate is the new phrase.
        final String complete = answer.getPhrase().toLowerCase();

        // Deletes extra spaces.
        final String trim = phrase.trim().toLowerCase();

        // Compares if they are equal.
        if (complete.startsWith(trim)) {
            // Takes the difference.
            String diff = complete.substring(trim.length());
            if (diff.startsWith(" ") && phrase.endsWith(" ")) {
                diff = diff.substring(1, diff.length());
            }
            candidates.add(diff);
        } else {
            candidates.add("");
        }

        // There are options or phrases, then add them as
        // candidates. There is not a predefined phrase.
        candidates.addAll(this.fromArrayToColletion(answer.getPhrases()));
        candidates.addAll(this.fromArrayToColletion(answer.getOptions()));
        // Adds a dummy option, in order to prevent that
        // jLine adds automatically the option as a phrase.
        if ((candidates.size() == 2) && (answer.getOptions().length == 1)
                && (answer.getPhrases().length == 0)) {
            candidates.add("");
        }
    } catch (final AbstractZemucanException e) {
        String cause = "";
        if (e.getCause() != null) {
            cause = e.getCause().toString();
        }
        if (e.getCause() != null) {
            final Throwable ex = e.getCause();
        }
        System.exit(InputReader.ASSISTING_ERROR);
    }

    return cursor;

This is an extract of the application. You could do a simple Completor, and you have to provide an array of options. Eventually, you will want to implement your own CompletionHandler to improve the way that the options are presented to the user.

The complete code is available here.


Create 2 completors, then use them to complete arbituary arguments. Note that not all the arguments need to be completed.

List<Completer> completors = new LinkedList<>();

// Completes using the filesystem
completors.add(new FileNameCompleter());

// Completes using random words
completors.add(new StringsCompleter("--arg0", "--arg1", "command"));

// Aggregate the above completors
AggregateCompleter aggComp = new AggregateCompleter(completors);

// Parse the buffer line and complete each token
ArgumentCompleter argComp = new ArgumentCompleter(aggComp);

// Don't require all completors to match
argComp.setStrict(false);

// Add it all together 
conReader.addCompleter(argComp);


Remove the NullCompletor and you will have what you want. NullCompletor makes sure your entire command is only 3 words long.

0

精彩评论

暂无评论...
验证码 换一张
取 消