# argv.js Simple yet complete argv parser ## Motivation I needed a new argv parser for a quick and dirty project I was working on and evaluating and selecting the proper existing parser and then learning its API, quirks and adapting the project architecture to it seemed to be more complicated, require more effort and far less fun than putting together a trivial parser myself in a couple of hours. This code is an evolution of that parser. ## Features - Simple / well documented - Supports both the _option_ (a-la `ls`) and _command_ (a-la `git`) paradigms - Nestable parsers can be nested as option/command handlers defining independent nested contexts - Option expansion `-abc` expands to `-a -b -c` if `-abc` is not defined - Option/command value assignment implicit `-a 123` (requires either _definition_ or manual handling) or explicit `-a=123` - Read option/command value defaults from environment variables - Option/command value conversion - Option/command value collection - Multiple option prefix support (by default `-` and `+` are handled) - Dynamic option/command handling - Customizable error and stop condition handling - Reasonable defaults: - Metadata read from `package.json` - `-help` – generate and print help - `-version` – print version - `-quiet` – suppress printing - `-` – stop argument processing - Extensible and self-applicable ### Planned - Run `-` scripts - Option doc grouping (???) ## Contents - [argv.js](#argvjs) - [Motivation](#motivation) - [Features](#features) - [Planned](#planned) - [Contents](#contents) - [Architecture](#architecture) - [Basics and quick start](#basics-and-quick-start) - [Options in more detail](#options-in-more-detail) - [Help and metadata](#help-and-metadata) - [Basic options](#basic-options) - [Commands](#commands) - [Active options/commands](#active-optionscommands) - [Pattern options](#pattern-options) - [Nested parsers](#nested-parsers) - [Stopping](#stopping) - [Error reporting](#error-reporting) - [Before parsing begins](#before-parsing-begins) - [Handling the result](#handling-the-result) - [Calling the script](#calling-the-script) - [Advanced docs](#advanced-docs) - [License](#license) ## Architecture This module provides the following workflow: ``` Parser(..) -> (..) -> ``` - define/declare a parser (parse grammar) ``` Parser() -> ``` - define post-parse callbacks (optional) ``` .then() .stop() .error() ``` - parse ``` (...) -> ``` - arguments are handled in order of occurrence, - argument handlers (defined in ``) are called while parsing, - then/stop/error ``'s are called after the `` is done, - everything is run in the _context_ of the `` object so any data set on it is accessible after parsing is done for further reference. Note that the `` is fully reusable and on each call will produce a new `` object. The `` object has the `` as its `.__proto__`. ## Basics and quick start To install: ```shell_session $ npm install --save ig-argv ``` Create a [bare.js](./examples/bare.js) script and make it runnable ```shell_session $ touch bare.js $ chmod +x bare.js ``` Now for the code ```javascript #!/usr/bin/env node var argv = require('ig-argv') var parser = exports.parser = argv.Parser({ // option definitions... ... }) .then(function(){ // things to do after the options are handled... ... }) // run the parser... __filename == (require.main || {}).filename && parser() ``` This script already knows how to respond to `-help` and friends. ```shell_session $ ./bare.js --help Usage: bare.js [OPTIONS] Options: -h, --help - print this message and exit -v, --version - show bare.js verion and exit -q, --quiet - quiet mode - - stop processing arguments after this point Written by John Smith Varsion: 0.0.1 / License: BSD-3-Clause ``` ## Options in more detail Start by creating an [`options.js`](./examples/options.js) script... ```shell_session $ touch options.js $ chmod +x options.js ``` ...and a parser: ```javascript #!/usr/bin/env node // compatible with both node's and RequireJS' require(..) var argv = require('ig-argv') var parser = argv.Parser({ ``` Now let us populate the option definitions, splitting the job into sections... ### Help and metadata Basic script description ```javascript doc: 'Example script options', ``` Note that `argv.js` exposes [object.js](https://github.com/flynx/object.js)'s [`normalizeIndent(..)` / `normalizeTextIndent(..)`](https://github.com/flynx/object.js#normalizeindent--normalizetextindent) for convenient text/code formatting. Metadata: ```javascript // to make things consistent we'll take the version from package.json version: require('./package.json').version, author: 'John Smith ', license: 'BSD-3-Clause', ``` If not set, `.version`, `.author` and `.license` are acquired from `package.json` located at the same path as the main script. To explicitly set the path of the JSON file from which metadata is read set [`.packageJson`](./ADVANCED.md#parserpackagejson). These basic bits of metadata can be referenced in other `-help` sections, for example: ```javascript footer: 'Written by: $AUTHOR\nVersion: $VERSION / License: $LICENSE', ``` If nested parsers are defined the default `-h` and `--help` will behave differently, the former will print the normal help while `--help` will also print help for each of the nested parsers/commands. To disable this behavior set `'extendedHelp'` to `false`: ```javascript argv.Parser({ ... extendedHelp: false, ... }) ``` To explicitly separate `-h` and `--help` either define custom handlers or alias `--help` directly to `extendedHelp`: ```javascript argv.Parser({ ... '-help': 'extendedHelp', ... }) ``` ### Basic options These, if encountered, simply assign a value to an attribute on the parsed object. This attribute's name is defined by the option name (without the prefix) or by setting [`