Command Option & Arguments Listeners

Command Option Listeners

Command option listeners are similar and defined by implementing org.statefive.clic.CommandOptionListener, and must implement the following method:

void option(String command, String option, Object value)

Let's look at implementing this for a top-level command named export, with the same short and long option defined previously; this time we'll just assume that the value type is file/java.io.File:

private String command;
private File filename;

// getters omitted

public void option(String command, String option, Object value) {
	this.command = command;
	switch(command) {
		case "export":
			switch(option) {
				case "f":
				case "file":
					filename = (File) value;
				break;
				// other options omitted
			}
		break;
		// other commands omitted
	}
}

Assigning the value to the member command isn't detailed here but can be used by API callers to determine which command was passed in via the command line. For example, outside of the listener in our main application, we can do something like:

String command = listener.getCommand();
if ("export".equals(command) {
	File fileToExport = listener.getFilename();
	// omitted: Do some export-based things...
}

Like OptionListener, if global.help was defined, each command also need to cater for this for our CommandOptionListener - this will need to be done for each defined command block:

public void option(String command, String option, Object value) {
	this.command = command;
	switch(command) {
		case "export":
			switch(option) {
				case "h":
				case "help":
					System.exit(0);
				break;
				// other options omitted
			}
		break;
		// other commands omitted
	}
}

Command option listeners utilising unary switches should use the same method as defined for OptionListeners, above, i.e. use a boolean value to determine if the switch was defined.

For nested commands, the command parameter will be the path of the command. Let's continue the example by adding a nested command to the export command, named with-meta-data. Since the command is a sub-command of export, then the command path will be export/with-meta-data:

public void option(String command, String option, Object value) {
	this.command = command;
	switch(command) {
		case "export":
			// export-based checks omitted
			break
		case "export/with-meta-data":
			// with-meta-data checks omitted
		break;
	}
}

Command Argument Listeners

To listen for argument updates for commands, implementations must implement the org.statefive.clic.CommandArgsListener interface with the following method:

void argument(String command, String name, int index, Object value);

As per the previous example, if no argument configurations are defined, the name and value will have the same value of the command line argument, and the index will be indexed from 0.

Likewise, if argument configurations are defined, the name will be the argument configuration name.

The rules are the same as command option configurations regarding the command name - i.e., the command name will be the full path to the command being run without leading or trailing forward slashes.

Consider the following argument configuration for an export command:

command.name = export
command.usage = Export all files to the given directory: export <dir> <files...>

args.export-dir.length = 1
args.export-dir.type = dir
args.export-dir.properties = dirType = exists

args.files-to-export.type = file
args.files-to-export.properties = fileType = exists

… And the following argument implementation:

File exportDir;

public void argument(String name, int index, Object value) {
	switch(name) {
		case "export-dir":
			exportDir = (File) value;
		break;
		case "files-to-export":
			File fileToMove = (File) value;
			File moveTo = new File(exportDir, fileToMove.getName());
			if (moveTo.exists()) {
				System.err.println("Cannot move " + fileToMove.getAbsolutePath() + "; " + moveTo.getAbsolutePath() + "already exists");
			} else {
 				fileToMove.renameTo(moveTo);
 			}
		break;
	}
}