cli

Overview

The cli object exposes methods for reading command-line arguments, displaying messages to the user, and asking the user for input.

Methods and properties

Reading program arguments

cli.accept(Object definitions)

Reads and parses program arguments according to definitions, and populates cli.args with the resulting values.
For each definition that matches a program argument, the processed value is stored in cli.args, named after the definition's key in definitions.

A definition is an Array with the following values:
  • Identifier list: A space-separated string of possible names or indices that identify the argument. At least one identifier is required. See below for identifier syntax.
  • Type (optional): A type definition to apply to the argument value. Defaults to String.
  • Omit behavior (optional): Either required() or defaultsTo(value). Applied when the argument isn't provided by the user.
  • Description (optional): A description of the argument. Currently unused, but will eventually be displayed to the user when requested.

The argument value is sourced differently depending on the definition's type.
If the type is Boolean, the value is set to true if the argument is present, and otherwise to false.
If the type is other than Boolean, the next program argument is consumed as a value.

An argument identifier can be:
Named
Two dashes followed by a string, such as --name.
Matches an argument if it is exactly the identifier string.
Shorthand
One dash followed by a letter, such as -n.
Matches an argument if it is exactly identifier string, or if it is part of a dash-prefixed group, such as -vn.
Positional
A hash sign followed by a zero-indexed position P, such as #0.
Matches an argument that doesn't already match named or shorthand identifiers, if it is the Pth such one.
Rest
The string #+.
Matches all arguments that didn't match any other identifier, collected in an array.

If there is no definition using a rest identifier, the rest values are implicitely collected in a value named rest.

definitions
A map of argument definitions, by value name.
sample Named argument and shorthand argument
// $ lemon adduser.js -a --name=Rose

cli.accept({
	username: ['--name', String, 'Name of user to add'],
	isAdmin: ['-a', Boolean, 'Make user an admin']
});

return cli.args; // {username: 'Rose', isAdmin: true}
sample Positional arguments
// $ lemon transpile.js -x app.ts build.js

cli.accept({
	sourcePath: ['#0', File, 'Source file'],
	destinationPath: ['#1', File, 'Where to write the transpiled file'],
	overrideExisting: ['-x', Boolean, 'Silently override the destination']
});

return cli.args; // {sourcePath: File('app.ts'), destinationPath: File('build.js'), overrideExisting: true}
sample Rest argument and multiple identifiers
// $ lemon check.js -v --strict catfacts.txt dogfacts.txt

cli.accept({
	paths: ['#+', File, 'Files to check for errors'],
	verbose: ['-v --verbose', Boolean, 'Shows all errors'],
	strictMode: ['-s --strict', Boolean, 'Enable strict checks']
});

return cli.args; // {paths: [File('catfacts.txt'), File('dogfacts.txt')], verbose: true, strictMode: true}
sample Required arguments and default values
// $ lemon delete-big-files.js cat-videos

cli.accept({
	inputFolder: ['#0', Folder, required(), 'The folder to clean up'],
	maximumSize: ['-s --size', Number, defaultsTo(1000), 'The maximum file size in MB'],
	extensionFilter: ['-e --extension', String, 'Only delete files with this extension']
});

return cli.args; // {inputFolder: Folder('cat-videos/'), maximumSize: 1000, extensionFilter: null}

cli.args Object

Holds the processed program arguments. See cli.accept().
Read-only.

Displaying messages

cli.tell(String text)

Displays text to the user by outputting it to stdout.
text
The text to display.
sample Say hi
cli.tell('Hello there!'); // displays “Hello there!”

Promise<Any> cli.tellWhile(String text, Promise asyncOperation)

Displays text to the user by outputting it to stdout, then erases it once asyncOperation resolves.
Returns the resolved value of asyncOperation as a Promise.
text
The text to display while awaiting.
asyncOperation
The Promise to wait for.
sample Wait for a network request to complete
const versionData = await cli.tellWhile(
	'Loading version data...',
	net.getJSON('http://example.org/versions.json')
);

cli.tell(`Latest version is ${versionData.latest}.`);

Asking for input

Promise<Any> cli.ask(String promptText, [TypeDefinition type = String, [Boolean optional = false]])

Displays promptText to the user then waits for input.
Once a value is entered, it is cast and validated with type. If the value is valid, the method returns it as a Promise. If the value is invalid, the user is asked again.
promptText
The prompt to display.
type
The type definition to apply to the entered value.
Defaults to String.
optional
If true, allows the user to enter an empty string, which will result in the value being null.
Defaults to false.
sample Ask for a number
const balloonCount = await cli.ask('How many balloons do you want?', Number);
cli.tell(`Number of balloons requested: ${balloonCount}`);

Promise<Object> cli.askMany(Object definitions)

Calls cli.ask() for each item in definitions, using the item's values for arguments.
Returns a map of all the entered values as a Promise.
definitions
A map of argument arrays for ask(), by value name.
sample Ask for two values
const responses = await cli.askMany({
	flavor: ['What flavor should the cake be?', String],
	deliveryDate: ['When should it be delivered?', moment]
});

const formattedDeliveryDate = format.date(responses.deliveryDate, true);
cli.tell(`Your ${responses.flavor} cake will be delivered ${formattedDeliveryDate}.`);