1.1.2 • Published 6 years ago

clhoe v1.1.2

Weekly downloads
3
License
ISC
Repository
github
Last release
6 years ago

clhoe

This is an npm module that provides simple, yet powerful, routing for command line interfaces, in a similar fashion to mainstream HTTP routing.

Installation

$ npm install clhoe

Usage

In order to do antyhing with Clhoe, we first need to include her. Yes, the name is one heck of a pun on the actual name.

const Clhoe = require('clhoe')

Basic Routing

Routing is done by calling the route function on Clhoe. The defined routes will be executed automatically once all routes have been added.

Clhoe.route((command) => {
	// TODO: add routes
})

Inside the closure passed to route, we get the opportunity to define command routes. The command parameter passed to the closure we provided, is a function that when called, creates a new route: it takes the form command(path, callback), whereas the callback will be executed if the path matches with what is entered into the terminal.

Command Route Syntax

For an example, let us create a command that creates a new project:

command('new project', () => {
	console.log('Creating a new project...')
})

The callback will be called, if an only if, the passed arguments from the terminal are in the following order:

$ mycommand new project
Creating a new project...

Otherwise, nothing will be matched. How to add default behavior if no route was matched will be discussed once all the syntax has been covered.

Variable Captures

The above example is quite dull on its own. At the very least, it would be nice if the user could specify the name they want for their project:

command('new [project]', ({ project }) => {
	console.log('Creating a new project ' + project + '...')
})

The [] enclosed area captures whatever is typed in by the user and stores that in a variable, which we are able to extract from an object passed along to the callback provided to the command.

If the following is executed:

$ mycommand new monkeys
Creating a new project monkeys...

You can see we also specified a name for that project.

Optional Groups

Let us elaborate upon what we have and take it even further. For instance, let us say we wanted to have a means of specifying the type of the project, but we want it to be optional.

This can be accomplished by introducing an optional group, for which we can use the {} syntax:

command('new [project] {--type [type]}', ({ project, type }) => {
	type = type || 'default'
	
	if (!['default', 'amazing'].includes(type))
		throw new Error('Invalid type!')
	
	console.log('Creating a new ' + type + ' project ' + project + '...')
})

The type property on the variables object will be undefined if the user did not enter it, as such we are making sure it is given a default value.

$ mycommand new monkeys --type amazing
Creating a new amazing project monkeys...

Verbose Flag

Using what we know, let us implement an optional flag -v for the same program that will print additional information regarding the process of setting our project up.

command('new [project] {--type [type]} {-v}', ({ project, type }, groups) => {
	type = type || 'default'
	
	if (!['default', 'amazing'].includes(type))
		throw new Error('Invalid type!')
	
	console.log('Creating a new ' + type + ' project ' + project + '...')
	
	if (groups.includes('-v'))
	{
		// TODO: implement verbose mode
	}
})

We can check if an optional group was used by seeing if its name is available in the groups array added to the callback. If -v is included, we wish to create our example application in verbose mode.

Variable Captures Varargs

It is also possible to capture a varargs number of strings from the command the user typed in:

command('new [project] [...args]', ({ project, args }) => {
	console.log('Creating project ' + project + ' with:')
	
	for (let arg of args)
		console.log(arg)
})

The args we extracted will always be in the form of an array, as such on running the command, we might get something like this:

$ mycommand new monkeys lots of strings
Creating project monkeys with:
lots
of
strings

It is possible to use optional groups at the same time as using varargs, as optional groups are always evaluated first, before anything else is evaluated.

Default Command

If no route was matched, a default callback (if provided) will be called:

Clhoe.route((command) => {
	// ...
}).else(() => {
	console.log('No command was matched!')
})

The chained else function will add such a callback.

Help Command

Let us have a look at how a help command might be implemented:

let help = () => {
	console.log('Help command!')
}

Clhoe.route((command) => {
	// Full match: 'help'
	command('help', help)
	
	// ...
}).else(help)

Thus, either if $ mycommand help is successfully matched, or no match at all occurred, the help closure will be called:

$ mycommand help
Help command!

$ mycommand i will not match a route
Help command!

License

This module, and the code therein, is licensed under ISC.