pargv

Examples

A list of examples demonstrating features of Pargv. You will notice some examples omit calling .parse() or .exec() which is required to either parsed the args or parse and execute a matching action. This is done for brevity sake and to help focus on the primary purpose of the example.

You can view a Video Tutorial on YouTube also which may also help.

Import or Require

ES6 or TypeScript

import { Pargv } from 'pargv';

ES5

const Pargv = require('pargv').Pargv;

Create the Instance

const pargv = new Pargv(/* your options */);

Simple command and action:

pargv.command('download <url>')
  .action((url, parsed, cmd) => {
    // do something with the url, parsed result or command instance.
  });
pargv.exec(['download', 'http://someurl.com']);

Just parse don’t execute action:

const parsed = pargv.command('download <url>')
  .parse(['download', 'http://someurl.com']);

Using Pargv without a command:

A command is not required to use Pargv just envoke the default instance and then you can define your config and simply use Pargv as a straight parser leveraging all it’s good ness.

const parsed =
  pargv.command()
    .option('-x')
    .option('-y')
    .option('-z')
    .when('-x', '-y')
    .demand('-z')
    .parse();

Adding some meta data for help text:

const parsed =
  pargv.command()
    .name('My App')
    .description('My awesome CLI app.')
    .version('1.0.0')
    .license('ISC');

You can also create fancy text for your program name by way of Figlet fonts. Below we’re adding some color and a custom font. The below will now display in help as blue text using the Doom font. Cool right?

const parsed =
  pargv.command()
    .name('My App', 'blue', 'Doom');

Multiple args spread in callback:

pargv.command('download <url> <savedir>')
  .action((url, savedir, parsed, cmd) => {
    // notice we now have two arguments in our
    // action callback before parsed result and
    // command instance.
  });
pargv.exec(['download', 'http://someurl.com']);

// NOTE: both .parse() & .exec() can accept rest params or array of args.
// The following is also valid.
pargv.exec('download', 'http://someurl.com');

Specify type for command or option:

Supported types: “date, number, integer, float, regexp, array, boolean, json, object”

pargv.command('download <url> <timeout:number>')
  .action((url, timeout, parsed, cmd) => {
    // timeout here will be a number.
  });
pargv.exec(['download', 'http://someurl.com']);

Specify a default inline:

Define a default value inline in our command. In this example “deadpool” is the default username. The syntax is as follows:

[key : type : default]

Each segement or part must have a value. If you have a default but do not need to ensure a type you can set the type segment to “string” or “auto”. Meaning the “default” can’t be the second arg in the segments.

const result = pargv.command('download <url> --username [username:string:deadpool]')
  .parse('download', 'http://someurl.com');

Require min or max:

// Require 2 commands
pargv.command('download <url>')
  .min.commands(2);

// Require 2 options.
pargv.command('download <url>')
  .min.options(2);

// Allow a max of 2 commands.
pargv.command('download <url>')
  .max.commands(2);

// Allow a max of 2 options.
pargv.command('download <url>')
  .max.commands(2);

Adding option with description:

pargv.command('download <url>')
  .option('--directory, -dir <dir>', 'Saves to directory.');

Adding option with description default value:

pargv.command('download <url>')
  .option('--directory, -dir <dir>', 'Saves to directory.', './downloads');

Adding option with description where dir is value in RegExp:

The directory string must be a value in the defined RegExp

pargv.command('download <url>')
  .option('--directory, -dir <dir>', 'Saves to directory.', null, /^(downloads|saved|temp)$/);

Adding option with description where dir is value in list:

A bit redundant but you can also use a simple list for matching or restricting values. This will do the same as above. Up to you!

pargv.command('download <url>')
  .option('--directory, -dir <dir>', 'Saves to directory.', null, 'dowloads, saved, temp');

Adding an alias:

Notice we enter ‘–dir’ to denote which key to add our alias for. We could also have used ‘–directory’. Pargv will just figure it out. Behind the scenes the longer key is alwways the primary in this case ‘–directory’.

pargv.command('download <url>')
  .option('--directory, -dir <dir>', 'Saves to directory.')
  .alias('--dir', '-d');

Adding a describe:

The directory string must be a value in the defined RegExp

pargv.command('download <url>')
  .option('--dir, -d <dir>')
  .describe('--dir', 'Saves to the specified directory');

Adding a demand:

Notice that we init the option with [dir] using [] instead of <> indicates that it is optional. When we then call demand for that key we are essentially changing it to <dir>.

pargv.command('download <url>')
  .option('--dir, -d [dir]')
  .demand('--dir');

Adding a when:

We’ve intentially set password to optional here but then ensure password is present when –username is called by using the “when” method.

pargv.command('login --username <username> --password [password]')
  .when('--username', '--password');

Adding a default value:

pargv.command('login --username <username> --password [password]')
  .default('--username', 'jsmith');

Restrict to min or max commands:

pargv.command('download <url>')
  .min.commands(1); // this is redundant but ensures <url> is provided.
pargv.command('download <url>')
  .max.commands(1); // ensure only <url> is allowed.
// for example if your cli command was: $ download /some/path other_variable
// max command error would be thrown.

Restrict to min or max options:

pargv.command('download <url>')
  .option('--force, -f')
  .option('--other, -o')
  .min.options(1); // would ensure either --force or --other is provided.
pargv.command('download <url>')
  .option('--force, -f')
  .option('--other, -o')
  .max.options(1); // would allow only --force or --other.

Variadic Command Args

Default: When setting a default for variadic args these values are not merged meaning the default is triggered ONLY when the variadic arg contains no values.

Coerce: Unlike above default, the coerce method will be run against EACH value in the array of variadic values.

pargv.command('download <url> [others...]')
  .default('others', ['url1', 'url2'])
  .action((url, others, parsed, cmd) => {
    // others will be array of values.
  });

External Commands:

Pargv supports executing any external command. To define a command as external the command must be prefixed with an @. This tells Pargv that @some_program should be executed externally as opposed to calling a callback action.

Basic Usage

This example would be synonymous with calling $ git push in your terminal.

pargv.command('@git push')

This could be called in the following manner where “app” is the name of your program that is using Pargv and has been added to your path.

$ app push

You could also call it directly via full path to Pargv config.

$ node /some/path/to/pargv/config push

Full Path

You can also specify a full path to an executable file. The below would result in a command name of run. However Pargv will auto create aliases to the full path and the full path without an extension.

pargv.command('@some/full/path/run.sh [arg1]')
$ app run arg1

Or call with full path, however the above would be best practice!

$ app some/full/path/run.sh arg1 arg2...

External Command Only

You can also just specify the external command by itself which essentially creates a wrapper if you will. This may not seem very useful at first but it allows you to create your own config and constraints on the external command. In the below example you must have at least two –flag type options.

pargv.command('@git')
  .min.options(2);

This will allow you to pass whatever you wish to the git command now wrapped into your application.

$ app git ...args

Handle Spawn Manually

If you specify “spawnAction” Pargv will do it’s parsing then provide the parsed result as wel as a config that can be handed off to spawn. You may then set any other options you wish then execute the method. If you return from this value Pargv will wire up handlers for catching errors as well as closing.

pargv.command('@ls', 'Lists files in directory')
  .spawnAction((spawn, config, parsed, cmd) => {

    // spawn - a wrapper to Node's spawn which allows passing
    //    command, args, options or the config object below itself.

    // config - object containing the following
    //    command: the command to be spawned in this case "ls".
    //    args: an array of arguments to be passed to command.
    //    options: the SpawnOptions object for Node's ChildProcess.

    // parsed - the Pargv Parsed Result.
    // cmd - the Pargv Command.

    const child = spwan(config.command, config.args, config.options);

    // OR

    const child = spawn(config);

    // You could handle close event yourself here
    // or return the child process below for Pargv
    // to do so for you.
    child.on('close', () => {
      // handle clean up here.
    });

    // OR

    // returning here allows Pargv to handle errors
    // for you but is NOT required.
    return child;

  });

Setup completions:

pargv.command('login --username <username> --password [password]')
  .completion(); // auto adds command 'completions'

Or define custom command name for completions.

pargv.command('login --username <username> --password [password]')
  .completion('comps');

Or define custom tab completions handler

pargv.command('login --username <username> --password [password]')
  .completion('completions', (current: string, argv: any[], done?: CompletionHandlerCallback) => {
    // current - the current argument for completions.
    // argv - the array of all arguments in stream.
    // done - optional callback for async completions.
    //        done handler accepts 1 arg (completions: any[])
  });
  // Pargv is pretty good with tab completions unless you have a really
  // special need and have the time to sort it out it is suggested to
  // use built in tab completions. They work pretty good!

Install completions:

The following assume your “completions” command is named “completions” and your program name is called “app”.

$ app completions --install

Or (with custom path)

$ app completions --install ~/.bash_profile

Or (manual redirect to path)

$ app completions >> ~/.bash_profile

Or (call without options prints to screen)

$ app completions

Adding custom completions for:

pargv.command('login --username <username> --password [password]')
  .completionFor('--username', 'jsmith', 'bjones');

Adding an example for your help text:

Nothing exciting here just adds examples that are displayed in help texts below its commands and options. The second param is an optional description.

pargv.example('login --username jsmith --password changeme', 'Logs in a user.');

Or you can add as a tuple.

pargv.example([
  ['your example', 'your optional description'],
  ['your other example without description']
])

Custom log handler:

pargv
  .onLog((message) => {
    // Do something with log message.
  });

Custom error handler:

pargv
  .onError((err) => {
    // Do something with error.
    process.exit(1);
  });

Custom help handler:

pargv
  .onHelp((command, commands) => {
    // command - optional value if help was called with a specific command.
    // commands - contains all commands that have been configured.
    // using command and commands build out your own help text.
  });

Parsing Objects

$ app --user.name Joe --user.age 35

OR

$ app --user.name=Joe --user.age=35

OR

$ app --user name:Joe|age:35

Result:

const result = {
  user: {
    name: 'Joe',
    age: 35
  }
};

Parsing Arrays

By default csv strings are converted to Arrays.

$ app --size 'small, medium,large, xl'

Result:

const result = {
  size: ['small', 'medium', 'large', 'xl']
};

To disable auto cast to array of csv strings set to type “string”.

// forces string instead of auto convert to array.
pargv.command('--size, -s [size:string]')

Parsing Date

$ app --start-date 01/01/2018

Result:

const result = {
  size: 2018-01-01T08:00:00.000Z // JavaScript Date object.
};

More Examples

Take a look at test.spec.ts to see internal tests. May give you a few ideas. Will try to add more as time permits.