GithubHelp home page GithubHelp logo

node-argp's Introduction

argp

Node.js project

Command-line option parser

Version: 0.0.9

Inspired by the extremly well-known argp C library, this module parses GNU-style command-line options. Help, usage and version messages are automatically generated and line-wrapped at 80 columns. The module checks for errors, can be easily adapted to your needs thanks to its evented system and also works when Node.js is in debug mode. The module is uncached and nulled once all the data has been parsed, so there's no memory footprint.

This module it's made for you if you want:

  • A robust solution that reads GNU-style parameters.
  • Basic error checking.
  • Nice help messages without caring about indentation, multilines, etc.
  • Zero memory footprint.

A common configuration looks like this:

var argv = require ("argp")
    .description ("Sample app.")
    .email ("[email protected]")
    .body ()
        //The object an argument definition and the text of the help message are
        //configured at the same time
        .group ("Arguments")
        .argument ("arg", { description: "Sample argument" })
        .group ("Options")
        .option ({ short: "o", long: "opt", description: "Sample option" })
        .help ()
        .version ("v1.2.3")
        .end ()
    .argv ();

console.log (argv);

/*
$ node script.js

{
  _debug: false,
  _filename: __filename,
  opt: false,
  help: false,
  version: false,
  arg: false
}

$ node script.js --help

Usage: t.js [OPTIONS] [ARGUMENTS]

Sample app.

 Arguments:
  arg                         Sample argument

 Options:
  -o, --opt                   Sample option
  -h, --help                  Display this help message and exit
  -v, --version               Output version information and exit

Report bugs to <[email protected]>.
*/

If you have a package.json file you can take from it the description, email and version using the readPackage() function. Take into account that this function calls a synchronous fs operation. Doesn't really matter because this module is the first thing you're going to execute.

var argv = require ("argp")
    //If no path is provided, it tries to read the "./package.json" file
    .readPackage ("path/to/package.json")
    .body ()
        .group ("Arguments")
        .argument ("arg", { description: "Sample argument" })
        .group ("Options")
        .option ({ short: "o", long: "opt", description: "Sample option" })
        .help ()
        .end ()
    .argv ();

Installation

npm install argp

Documentation

Objects


Quick examples with no configuration

If an option has not been defined the type of the value is converted automatically from a string to a number, boolean, null or undefined.

By default the parser doesn't allow undefined arguments and options because you typically want to have an absolute control over the calls to your program in order to avoid unexpected behaviours. Allowing undefined arguments and options is as simple as this:

var argv = require ("argv")
    .allowUndefinedArguments ()
    .allowUndefinedOptions ()
    .argv ();
$ node script.js -a -b -c
{ a: true, b: true, c: true }

$ node script.js a b c
{ a: true, b: true, c: true }

$ node script.js -abc null
{ a: true, b: true, c: null }

$ node script.js --a --b 1 --d=e
{ a: true, b: 1, d: "e" }

$ node script.js --no-a b
{ a: false, b: true }

$ node script.js --a -- -b --c d
{ a: true, "-b": true, "--c": true, d: true }

Configuring arguments

Properties:

  • description - String
    The description.
  • hidden - Boolean
    If true, the option is not displayed in the --help and --usage messages. Default is false.
.argument ("arg1")
.argument ("arg2", { description: "..." })
.argument ("arg3", { description: "...", hidden: true })
$ node script.js arg1
{ arg1: true, arg2: false, arg3: false }

Example: options.js.


Configuring options

Considerations:

  1. By default the options are flags. If the option requires a value, the argument property must be defined. This property is a string and can be seen when the --help message is printed. For example,

    $ node script.js --help
    ...
      o, --opt=STR               Sample option
    ...

Where STR is the argument property.

  1. By default, the value of the options is a string. Configure the type property if the value is a number, boolean or array (comma-separated values).

  2. Each option has an id which is used to store the value into the final object. This id is the long name. If the long name has not been configured then the id is the short name.

    .option ({ short: "a", long: "aa" })
    //{ aa: false }
    .option ({ long: "aa" })
    //{ aa: false }
    .option ({ short: "a" })
    //{ a: false }

Common properties between flags and options with value:

  • description - String
    The description.
  • hidden - Boolean
    If true, the option is not displayed in the --help and --usage messages. Default is false.
  • long - String
    The long name, eg: --name. Cannot contain white spaces.
  • short - String
    The short name, eg: -a. It must be an alphanumeric character.

Flags:

  • negate - Boolean
    If true, the flag is negated. The default value is true. Cannot negate a flag with a short name, only the long name can be configured.

     .option ({ short: "n", long: "name", negate: true }) //Error!
     .option ({ long: "name", negate: true })
     $ node script.js
     { a: true }
     
     $ node script.js --no-name
     { a: false }

Options with value:

  • argument - String
    Must be configured if the option requires a value. The string is used when the --help message is printed.

     .option ({ long: "name", argument: "STR" })
     $ node script.js --help
     ...
        --name=STR
    ...
  • optional - Boolean
    If true, the value is optional. Default is false. If the option doesn't receive any value the default value is set and it depends on the value and type properties.

     .option ({ long: "name1", argument: "STR", optional: true })
     .option ({ long: "name2", argument: "NUM", optional: true, type: Number })
     .option ({ long: "name3", argument: "ARR", optional: true, type: Array })
     //Boolean type is rarely used, use a flag instead
     .option ({ long: "name4", argument: "BOOL", optional: true, type: Boolean })
     $ node script.js --name1 --name2 --name3
     # "name1" is null because all the options are strings by default, and the default value of a string is null
     # "name2" is 0 because the default value of a number is 0
     # "name3" is [] because the default value of an array is []
     # "name4" is false because the default value of a boolean is false
     { name1: null, name2: 0, name3: [], name4: false }
     $ node script.js --name1 foo --name2 12 --name3 -12.34,foo,true --name4 true
     { name1: "foo", name2: 12, name3: [-12.34, "foo", true], name4: true }
  • reviver - Function
    The function is executed when the option is parsed. It is similar to the reviver of the JSON.parse() function. This is the right place where you can validate the input data and fail() if is not valid. For example, if the option requires a number you can validate the range here.

     .option ({ long: "name", argument: "STR", reviver: function (value){
       return value + "bar";
     }})
     $ node script.js --name foo
     { name: "foobar" }
     //The reviver is used to validate the range of the number
     .option ({ long: "name", argument: "STR", type: Number,
         reviver: function (value){
     //"value" is already a number
     if (value < 1 || value > 3){
       argp.fail ("Option 'name': invalid range");
     }
     return value;
     }})
     //The reviver can be also used to allow only a few string values, a.k.a. choices.
     .option ({ long: "name", argument: "STR", reviver: function (value){
     if (value !== "a" && value !== "b" && value !== "c"){
       argp.fail ("Option 'name': invalid choice");
     }
     return value;
     }})
  • type - String | Number | Boolean | Array
    The type of the value. Default is a String. If the type is an Array, comma-separated values are automatically stored into an array and each element is converted to the type it represents.

     .option ({ long: "name", argument: "STR", type: Array })
     $ node script.js --name 1,true,foo
     { name: [1, true, "foo"] }
  • value - Object
    The default value.

     .option ({ long: "name", argument: "STR", value: "bar", optional: true })
     $ node script.js
     { name: "bar" }
     
     $ node script.js --name
     { name: "bar" }
     
     $ node script.js --name foo
     { name: "foo" }

Example: options.js.


Full example explained

/*
Avoid storing the module in a variable because when the parser finishes it
is removed from the cache. If you store a reference remember to unreference it
if you want a zero memory footprint.

var argp = require ("argp")
var argv = ...
argp = null;
*/

var argv = require ("./lib")
    //The evented system allows you to fully adapt the module to your needs
    //The "start" and "end" events are useful when you need to initialize or
    //clean up things
    .on ("start", function (argv){
      //Emitted after the default values of the configured options and arguments
			//have been set and before starting the read.
			
			//"argv" is the final object
    })
    .on ("argument", function (argv, argument, ignore){
      //Emitted when an argument is found
			
			//"argv" is the final object
			//"argument" is the argument found
			//"ignore" is a function that when called ignores the argument, hence it
			//it isn't stored in the final object
    })
    .on ("option", function (argv, option, value, long, ignore){
      //Emitted when an option is found
			
			//"argv" is the final object
			//"option" is the name of the option found
			//"value" is the value of the option after calling the reviver, if any
			//"long" is a boolean; true if the option is a long name, otherwise false
			//"ignore" is a function that when called ignores the argument, hence it
			//it isn't stored in the final object
    })
    .on ("end", function (argv){
      //Emitted when all the options and arguments have been read
			
			//"argv" is the final object
    })
    //Wrap lines at 100 columns, default is 80
    .columns (100)
    //If "sort" is enabled, the options are parsed before the arguments, if not,
    //the options and arguments are parsed in the same order they come
    .sort ()
    //Allow undefined arguments
    .allowUndefinedArguments ()
    //Allow undefined options
    .allowUndefinedOptions ()
    //The [ARGUMENTS] part of the "usage" line in the --help and --usage messages can be changed
    //See "custom-usages.js" example
    .usages ([
      "foo",
      "bar"
    ])
    //Print a description at the top of the help message
    .description ("Sample app.")
    //Print a contact email at the end of the help message
    .email ("[email protected]")
    //Configure the body
    .body ()
        //The object an argument definition and the text of the help message are
        //configured at the same time
        //The order of the configuration is important
        
        //Print a paragraph
        .paragraph ("Random paragraph")
			  //Print a line
        .line ("Random line")
        //Print a group line
        .group ("Group 1")
        //After a group line you typically want to print some options or
        //arguments
        .argument ("arg1", { description: "aaa" })
        .argument ("arg2")
        .group ("Group 2")
        .option ({ short: "a", long: "aa", description: "aaa" })
        .option ({ short: "b", long: "bb", type: Number, description: "bbb" })
        .group ("Group 2")
        //Enable the -h, --help option
        .help ()
        //Enable the --usage option
        .usage ()
        //Enable the -v, --version option
        .version ("v1.2.3")
        //Explicit ending
        .end ()
    //Parse the options
    .argv ();

Argp

The module returns an instance of Argp. It inherits from an EventEmitter.

The parser follows the GNU-style rules: -a, -abc, --a, --no-a, --a=b, etc.

If you don't want to configure anything simply require the module, allow undefined arguments and options and call to argv().

var argv = require ("argv")
    .allowUndefinedArguments ()
    .allowUndefinedOptions ()
    .argv ();

Note: If no configuration is provided you cannot join a short name with its value in the same token, eg: -Dvalue, all the characters following a dash, -, are interpreted as individual flags.

The object that argv() returns has 2 special properties: _debug and _filename. _debug is a boolean and it's true if the Node.js process has been started in debug mode, otherwise false (debug mode: $ node debug <script>). _filename is the absolute path of the main script.

Events

With the event system you can fully adapt this module to yours needs. For example, you can create aliases.js, read phases without being surrounded with " (to-upper-case.js), do complex things (mimic npm), etc. Look at the events.js example for further details.

Methods

Objects


argument

Emitted when an argument is found.

Parameters:

  • argv - Object
    The final object.
  • argument - String
    The name of the argument found.
  • ignore - Function
    When the function is called the parser ignores the argument, hence it isn't stored in the final object.

end

Emitted when all the options and arguments have been parsed.

  • argv - Object
    The final object.

option

Emitted when an option is found.

  • argv - Object
    The final object.
  • option - String
    The name of the option found.
  • value - String
    The value of the option after calling the reviver, if any.
  • long - Boolean
    True if the option is a long name, otherwise false.
  • ignore - Function
    When the function is called the parser ignores the argument, hence it isn't stored in the final object.

start

Emitted just before the parser begins to read the input data.

  • argv - Object
    The final object. The default values are already set.

Argp#allowUndefinedArguments() : Argp

Allows undefined arguments.

Argp#allowUndefinedOptions() : Argp

Allows undefined options.

Argp#arguments() : Object

Returns the configured arguments. Look at the internal-data.js example for further details.

Argp#argv() : Object

Parses the process.argv array. It uncaches and nulls the module after parsing the input data.

Argp#body() : Argp

Returns a Body instance.

Argp#columns(columns) : Argp

Sets a maximum line length. By default lines are wrapped at 80 columns.

Argp#description(str) : Argp

Sets a description. The description is printed at the start of the --help message, after the usage lines.

Argp#email(str) : Argp

Sets a contact email. The email is printed at the end of the --help message.

Argp#fail(str[, code]) : undefined

Prints a message to the stderr and exists the program. By default it exists with code 1.

Argp#options([filter]) : Object

Returns the configured options. filter is an object which can be used to return the options with a short name or with a long name.

.options ()
.options ({ short: true })
.options ({ long: true })

Look at the internal-data.js example for further details.

Argp#readPackage([path]) : Argp

Reads a package.json file and configures the parser with the description, email and version. If no path is provided it uses the ./package.json path. It's an fs synchronous operation.

Argp#usages(usages) : Argp

Changes the "usage" line from the --help and --usage messages. usages is an array of strings.

Look at the custom-usages.js example for further details.

Argp#sort() : Argp

If sort() is enabled, the options are parsed before the arguments, if not, the options and arguments are parsed in the same order they come.


Body

The Body instance is returned by Argp#body(). All the following functions print a message in the same order they are configured, this allows you to fully customize the --help message very easily.

The difference among group(), line() and paragraph() are:

  • group() is mainly used to introduce a list of things like arguments or options. The line has an indentation of 1 space and ends with :. A group line always starts in a new paragraph.
  • line() prints text in a new line (the text is prefixed with \n).
  • paragraph() prints text in a new paragraph (the text is prefixed with \n\n).

All the text messages can be split up in multiple lines using \n or \r\n. They will be indented according to the functionality of the caller function.

Look at fully-descriptive-help.js for further details.

Methods

Body#argument(name[, configuration]) : Body

Defines an argument. See Configuring arguments.

Body#columns(column1, column2) : Body

Prints a line with 2 columns. This functionality is used to print the options and arguments.

Body#end() : Argp

Returns the Argp instance. Use it to explicitly end the body configuration.

Body#group(str) : Body

Prints a group line.

Body#help() : Body

Enables the -h, --help option.

Body#line(str[, prefix]) : Body

Prints a line. The prefix is mainly used to indent the line with some spaces.

Body#option(o) : Body

Defines an option. See Configuring options.

Body#paragraph(str[, prefix]) : Body

Prints a paragraph. The prefix is mainly used to indent the paragraph with some spaces.

Body#usage() : Body

Enables the --usage option.

Body#version(str) : Body

Enables the -v, --version option. str is the text to print when the option is called.

node-argp's People

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.