Rápido
Rápido is an extensible command line interface that enables rapid development for any technology stack.
Rápido is written in JavaScript and is built on top of Node.js and npm.
Features
- Custom commands and stacks
- Scaffolding
- Command line argument parsing
- Configuration loading
- User input
- Colorized output
- Command-line auto-completion
Screenshot
Installation
The only prerequisite for Rápido is Node. After Node has been installed, Rápido should be installed as a
global script using npm
as shown below:
$ npm install rapido --global
Overview
Commands
Rápido is extensible and supports any number of commands that can easily be invoked from the command line.
Commands are bundled as part of "stacks" and new stacks can easily be installed using npm
(described later).
Based on the arguments passed to the Rápido command line interface, Rápido will delegate the work to the
appropriate command handler. A simple command invocation is shown below:
$ rap create component ui/buttons/Button --no-testing
In the above example, "create component"
is the command name and "ui/buttons/Button"
and "--no-testing"
are additional
arguments to the command handler.
NOTE: Rápido uses rap
by default, but you can change it to whatever you want. See Custom Command Line Tools using Rápido
Details on creating your own commands are described in the "Creating Custom Commands" section below.
Stacks
A stack is a collection of commands that are all related to a particular technology stack. Rápido supports
using multiple stacks, and new stacks can easily be installed using npm
.
When running a command, the command is searched for in the stacks that are currently enabled.
Installing Stacks
A new stack should be installed just like any other Node module using npm
. For example:
$ npm install rapido-raptorjs
Stacks can also be installed globally using the --global
switch for npm
(e.g. npm install rapido-raptorjs --global
). When launched, Rápido
will search for Rápido stacks and commands in all of the first-level Node modules found in any of the available
node_modules
directories. Rápido uses the same module search path that Node uses and will begin its
search in the current working directory and ending in the global node_modules
direcotry.
A Rápido stack is indicated by the existence of a rapido-stack.json
configuration
file in the root directory of the module.
Enabling Stacks
Stacks can be enabled and disabled using the rap use
command as shown in the sample below:
$ rap use raptorjs
It is also possible to enable multiple stacks:
$ rap use raptorjs jquery backbone
NOTE: If multiple enabled stacks support the same command then you will be prompted to choose a stack when invoking
the ambiguous command.
NOTE: The currently enabled stacks are stored in the rapido.json
configuration that is discovered first
(see the "Configuration" section below). If a rapido.json
file is not found, one is created in
the current directory.
Listing Commands and Stacks
To get a list of available commands for the currently enabled stacks, simply run the following command:
$ rap list
To get a list of all commamnds for all stacks that have been installed (not just the ones that are enabled), the
following command should be used:
$ rap list all
Configuration
Rápido, and all of the commands, can be configured using rapido.json
files that can be loaded
from multiple locations.
Sample rapido.json config file:
{
"scaffold.component.dir": "scaffolds/component",
"scaffold.page.dir": "scaffolds/page",
"scaffold.webapp.dir": "scaffolds/webapp",
"modules.dir": "modules",
"components.base.dir": "modules",
"pages.base.dir": "modules/pages",
"app.rtld.file": "modules/taglibs/app/app.rtld"
}
NOTE: Any configuration properties that have the suffix "file" or "dir" will result in a property value of type
raptor/file/File that
references the file resolved relative to the directory containing the rapido.json
file that the
configuration property is defined in.
Configuration files are merged together, and Rápido supports configuration
overrides at the directory/project-level and at the user or system level using a simple configuration search path.
Rápido will look for a rapido.json
file in the current working directory, and then search in the parent directory,
all the way up to the root. It will then search in the home directory. Lastly, Rápido will search
for rapido-stack.json
files in all of the node_modules
directories using the same search
path that Node uses to find and load modules (starting in the current working directory).
Creating a Stack
Rápido provides commands for creating stacks and commands. To create a new stack simply do the following:
$ mkdir my-stack
$ cd my-stack
$ rap create stack
You will be prompted for information about the new stack, and the command then will generate all of the files
for your stack in the current directory. Stacks are defined in a rapido-stack.json
file as shown in the following
sample code:
{
"name": "raptorjs",
"description": "Commands for the RaptorJS Toolkit",
"commands": {
"create component": {
"description": "Create a RaptorJS UI component",
"file": "command-create-component.js"
},
"create page": {
"description": "Create a RaptorJS page",
"file": "command-create-page.js"
},
"rename component": {
"description": "Rename an existing UI component",
"file": "command-rename-component.js"
}
}
}
You can then share your stack by publishing it to the npm repository by simply running npm publish
.
Creating a Command
New commands can be added to a stack using the rap create command
. You will be prompted for
some information about the command, and then the command implementation will be created
and automatically registered in the stack by updating the rapido-stack.json
for the stack.
A command handler is implemented as a CommonJS module as shown in the following sample code:
module.exports = {
usage: 'Usage: $0 say hello <name>',
options: {
'upper-case': {
describe: 'Convert name to upper case'
}
},
validate: function(args, rapido) {
var name = args._[0];
if (!name) {
throw 'name is required';
}
return {
name: name,
upperCase: args['upper-case']
};
},
run: function(args, config, rapido) {
var name = args.name;
if (args.upperCase) {
name = name.toUpperCase();
}
rapido.log.success('Command says: ' + name);
}
}
Command Line Argument Parsing
A command should declare which options it allows using the options
property of the exported
command module as shown in the previous section. In addition, the usage
property should be
used to provide basic information for the command.
Internally, Rápido uses the optimist module to
parse the command line arguments using the option definitions. Please see the documentation for
the optimist
module on the format for defining options.
Reading Configuration Properties
The loaded configuration is passed as the second argument to the run
method exported by
a command. Configuration properties can easily be read as shown in the following sample code:
module.exports = {
...
run: function(args, config, rapido) {
var scaffoldDir = config["scaffold.page.dir"];
if (!scaffoldDir) {
throw new Error('"scaffold.page.dir" not defined in "' + rapido.configFilename + '" config file');
}
...
}
}
Scaffolding
Rápido provides support for scaffolding which allows for commands to generate a set of files
from a template directory. Rápido uses dust-linkedin to
support variables, conditionals and other structural logic inside template files. Only files with
the ".dust" extension will be treated as Dust templates and other files will be copied directly
to the output directory. In addition,
variables are supported in filenames using _<var-name>_
syntax. If a variable inside a filename
resolves to a false
value then the file will be ignored, thus allowing for conditional files.
The generation of files using a scaffold can be done as shown in the following sample code:
rapido.scaffold({
scaffoldDir: scaffoldDir,
outputDir: outputDir,
overwrite: true,
data: {
name: 'Frank',
count: 30
},
beforeFile: function(outputFile, content) {
return true;
},
afterFile: function(outputFile) {
}
});
User Input
Rápido makes it easy to accept user input from the command line using the prompt
module for Node as shown in the following sample code:
var prompt = rapido.prompt;
prompt.start();
prompt.get(
{
properties: {
'name': {
description: 'Name',
required: false
},
'count': {
description: 'Count',
required: false
},
}
}
,
function (err, result) {
if (err) {
rapido.log.error(err);
return;
}
var name = result.name || 'Default';
var count = result.count || 0;
});
Colorized Output
The following commands should be used to produce colorized output:
rapido.log.success('Completed successfully');
rapido.log.success('success', 'Completed successfully');
rapido.log.info('Some info message');
rapido.log.info('info', 'Some info message');
rapido.log.warn('Some warning message');
rapido.log.warn('warn', 'Some warning message');
rapido.log.error('Some error message');
rapido.log.error('error', 'Some error message');
rapido.log('Message with no color');
Command-line Auto-Completion
Rápido provides support for auto-completion in a shell. Auto-completion allows the TAB character to be used
to complete a command name or a command option. To enable this feature, the following command must
be added to your shell initialization scripts (typically ~/.profile
) after installing Rápido globally.
complete -C rap rap
The above command will use the rap
command itself to handle auto-completion. The rap
script detects
when it is being invoked in the context of auto-completion based on special environment variables
that get set by the shell. For more info, please see Bash: Programmable Completion Builtins.
Custom Command Line Tools using Rápido
Don't like the name rap
or what to create your own custom command line tool
that utilizes the power or Rápido? No problem! Just add a Node bin script to project similar to the following:
#!/usr/bin/env node
var path = require('path');
var rapido = require('rapido').create();
rapido.configFilename = "raptor.json";
rapido.title = 'RaptorJS Command Line Tools';
rapido.addNodeModulesDir(path.join(__dirname, '../node_modules'));
rapido.enableStack('raptorjs');
rapido.addStackDir(path.join(__dirname, '..'));
rapido.exclusiveStackCommands('raptorjs');
rapido.hideCommand('another-stack', 'useless command');
rapido.run(process.argv);
You'll then want to register your script in the package.json
file for your Node module so that it
can be installed globally:
{
"bin": {
"raptor": "bin/raptor",
...
}
...
}
Your command line tool is ready to be installed:
npm install raptor --global
Now, when you launch your custom script, you will be shown something similar to the following: