Skip to content
Massimiliano Ziccardi edited this page Jan 24, 2017 · 15 revisions

Create an ls command line example

A commons-cli equivalent

In this document. we are going to describe how to create a command line by using the ls example (the example syntax has been taken from the commons-cli documentation.

Usage: ls [OPTION]... [FILE]...
List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuSUX nor --sort.

-a, --all                  do not hide entries starting with .
-A, --almost-all           do not list implied . and ..
-b, --escape               print octal escapes for nongraphic characters
    --block-size=SIZE      use SIZE-byte blocks
-B, --ignore-backups       do not list implied entries ending with ~
-c                         with -lt: sort by, and show, ctime (time of last
                           modification of file status information)
                           with -l: show ctime and sort by name
                           otherwise: sort by ctime
-C                         list entries by columns

The following code can be used to parse this command line with YACLP:

        Parser parser = ParserBuilder
            .forOptionsBasedCli()
            .withOption(
                OptionBuilder
                    .forOption("-a", "--all")
                    .description("do not hide entries starting with .")
                    .build()),
                OptionBuilder
                    .forOption("-A", "--almost-all")
                    .description("do not list implied . and ..")
                    .build(),
                OptionBuilder
                    .forOption("-b", "--escape")
                    .description("print octal escapes for nongraphic characters")
                    .build(),
                OptionBuilder
                    .forOption("--block-size")
                    .description("use SIZE-byte blocks")
                    .argument(ArgumentBuilder.forArgument("SIZE").build())
                    .build(),
                OptionBuilder
                    .forOption("-B", "--ignore-backups")
                    .description("do not list implied entried ending with ~")
                    .build(),
                OptionBuilder
                    .forOption("-c")
                    .description("with -lt: sort by, and show, ctime (time of last "
                        + "modification of file status information) with "
                        + "-l:show ctime and sort by name otherwise: sort "
                        + "by ctime")
                    .build(),
                OptionBuilder
                    .forOption("-C")
                    .description("list entries by columns")
                    .build()
            ).build();

        String[] args = new String[]{ "--block-size", "10"};

        try {
            CommandLine line = parser.parse(args);

            if (line.hasOption("--block-size")) {
                System.out.println (line.getValue("--block-size"));
            }
        } catch (ParsingException pe) {
            System.out.println ("Unexpected exception: " + pe.getMessage());
        }

The above code does exactly the same thing as the commons-cli example.

Let's add some sugar

Mutually exclusive options

It doesn't make sense to pass both -a and -A parameters, so we want to make them mutually exclusive. That can be done with YACLP by changing the code:

    .withOption(
        OptionBuilder
            .forOption("-a", "--all")
            .description("do not hide entries starting with .")
            .build(),
         OptionBuilder
             .forOption("-A", "--almost-all")
             .description("do not list implied . and ..")
             .build()
     )

to

    .withOption(
        OptionBuilder
            .forMutuallyExclusiveOption() // Create a 'mutually exclusive' group of options
            .withOptions(  // Add the mutually exclusive option to the group
                OptionBuilder
                    .forOption("-a", "--all")
                    .description("do not hide entries starting with .")
                    .build(),
                OptionBuilder
                    .forOption("-A", "--almost-all")
                    .description("do not list implied . and ..")
                    .build()
            )
        .build()
    )

We just used the option builder to build a mutually exclusive group and added all the relevant options to it.

Validators

YACLP is bundled with a number of validators for the most common uses:

  • Integer validator
  • String validator
  • File validator They can be used to ensure that the passed in value conforms with some specified rule. For example, in the ls command we have the --block-size parameters that accept a number higher than zero. We can ask YACLP to perform that validation with the following code:
    OptionBuilder
        .forOption("--block-size")
        .description("use SIZE-byte blocks")
        .argument(ArgumentBuilder
                      .forArgument("SIZE")
                      .withValidator(
                          ValidatorBuilder  // Using the validator builder
                              .forInteger() // to add an Integer validator
                              .min(1)       // minimum value must be 1
                              .build()
                      )
                  .build()
                 )
        .build()

Now YACLP will throw a ParsingException if the SIZE argument is not a number or if its value is less then 1.

Complete working example

package it.jnrpe.yaclp.example;

import it.jnrpe.yaclp.*;
import it.jnrpe.yaclp.validators.ValidatorBuilder;

public class ls {
    public static void main(String[] args) {

        Parser parser = ParserBuilder
            .forOptionsBasedCli()
            .withOption(
                OptionBuilder
                    .forMutuallyExclusiveOption()
                    .withOptions(
                        OptionBuilder
                            .forOption("-a", "--all")
                            .description("do not hide entries starting with .")
                            .build(),
                        OptionBuilder
                            .forOption("-A", "--almost-all")
                            .description("do not list implied . and ..")
                            .build()
                    )
                    .build(),
                OptionBuilder
                    .forOption("-b", "--escape")
                    .description("print octal escapes for nongraphic characters")
                    .build(),
                OptionBuilder
                    .forOption("--block-size")
                    .description("use SIZE-byte blocks")
                    .argument(ArgumentBuilder.forArgument("SIZE")
                        .withValidator(
                            ValidatorBuilder
                                .forInteger()
                                .min(1)
                                .build()
                        )
                        .build())
                    .build(),
                OptionBuilder
                    .forOption("-B", "--ignore-backups")
                    .description("do not list implied entried ending with ~")
                    .build(),
                OptionBuilder
                    .forOption("-c")
                    .description("with -lt: sort by, and show, ctime (time of last "
                        + "modification of file status information) with "
                        + "-l:show ctime and sort by name otherwise: sort "
                        + "by ctime")
                    .build(),
                OptionBuilder
                    .forOption("-C")
                    .description("list entries by columns")
                    .build()
            ).build();

        try {
            CommandLine line = parser.parse(args);

            if (line.hasOption("--block-size")) {
                System.out.println (line.getValue("--block-size"));
            }
        } catch (ParsingException pe) {
            System.out.println ("Unexpected exception: " + pe.getMessage());
        }
    }
}