JSPM

  • Created
  • Published
  • Downloads 78
  • Score
    100M100P100Q64739F
  • License MIT

Simple CLI and shell for Node.js based on commander and inquirer.

Package Exports

  • shellcraft

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (shellcraft) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

shellcraft.js

npm version dependencies Build Status ![gitter](https://badges.gitter.im/Join Chat.svg)

Simple CLI and shell for Node.js based on commander and inquirer.

This module provides a way in order to use commander and inquirer together. There are a CLI and a shell mode, and the same commands can be used everywhere.

shellcraft.js supports the command history and the auto-completion (in shell mode).

Documentation

Installation

NPM Badge

$ npm install shellcraft

Hello, World

var shellcraft = require ('shellcraft');

var options = {
  version: '0.1.0'
};

shellcraft.begin (options, function (err, results) {
  if (results) {
    console.log (results);
  }
});

API

There are only two public API in order to play with shellcraft.


shellcraft.begin (options, callback)

✤ options

Some options are available through the option argument.

options = {
  version: '0.1.0',
  prompt: '>',
  promptFixed: false
}

The version is used by Commander with the -V, --version parameter. The default prompt > can be changed by something else. But note that the prompt will always begins by ? , like for example:

? myprompt>

it's because Inquirer has already its own prompt and this one can not be changed easily.

The promptFixed option is experimental and disabled by default. The purpose is to keep the prompt at the bottom even if async console.log outputs are used. In other words, (most) outputs are put before the prompt.

✤ callback (msg)

The callback is called when the shell or the CLI is terminated. Note that currently the msg argument is not consistent between the CLI and the shell. This behavior will change in the future.

Example
shellcraft.begin ({
  version: '0.0.1',
  prompt: 'orc>'
}, function (err, results) {
  if (msg) {
    console.log (results);
  }
});

shell mode

$ node myShell.js
? orc> _
? orc> help
 exit     exit the shell
 help     list of commands
 scope    change scope
? orc> exit
good bye
$ _

CLI mode

$ node myShell.js -h

  Usage: myShell [options]

  Options:

    -h, --help         output usage information
    -V, --version      output the version number
    -s, --scoped       include scoped commands (CLI only)

$ _

shellcraft.registerExtension (shellExt, callback);

There are two builtin commands help and exit. For more commands you must register one or more extensions. An extension must be "requirable" and must export two functions (register() and unregister()).

✤ shellExt

The path on the .js file where the register and unregister methods are exported. An extension argument is passed with the register call. This object has two methods, command and option. It looks like the commander API.

extension
  .command ('foo', 'foo description', options, function (callback, args) {
    /*
     * callback (wizard, function (answers) {})
     *   Is called in order to return to the prompt (or end if CLI). The wizard
     *   argument must be used only in order to process an Inquirer definition
     *   in the shell (or the CLI). Otherwise you must call the callback without
     *   arguments.
     *   The Inquirer answers are retrieved with the second argument.
     *
     * args
     *   Are the arguments provided with the command.
     */
  })
  .option ('-f, --foo', 'foo description', options, function (callback, args) {
    /*
     * callback ()
     *
     * args
     *   This array can not have more than one element.
     */
  });

The options can be (for command):

options : {
  wizard : false,              /* when it's need Inquirer         */
  params : {
    scope: 'goblin',           /* override global scope filter    */
    required: 'argName',       /* a required argument             */
    optional: 'optionals...'   /* several optionals arguments     */
                               /* do not append ... in order to   */
                               /* limit to one optional argument  */
  }
}

The options can be (for option):

options : {
  params : {
    required: 'argName',       /* a required argument             */
  }
}

✤ callback ()

The callback must be called as soon as the extension is registered.

Example

myShellExtension.js

'use strict';

var zog = 'zog';

var cmd = {};
var opt = {};

cmd.hello = function (callback, args) {
  console.log (zog + ' tells "Hello, ' + args.join (' ') + '"');
  callback ();
};

cmd.wizard = function (callback) {
  var wizard = [{
    /* Inquirer definition... */
    type: 'input',
    name: 'zog',
    message: 'tell ' + zog
  }];

  callback (wizard, function (answers) {
    /* stuff on answers */
    if (answers.zog === zog) {
      console.log (zog + ' ' + zog);
    } else {
      console.log ('lokthar?');
    }

    /*
     * You can return false if you must provide several wizard with only
     * one call to this command handler.
     * You can call callback () without argument in order to return to the
     * prompt instead of returning true.
     */
    return true;
  });
};

opt.foobar = function (callback, args) {
  if (args) {
    zog = args[0];
  } else {
    zog = 'lokthar';
  }
  callback ();
};

exports.register = function (extension, callback) {
  extension
    .command ('hello', 'print Hello, John', {
      wizard: false,
      params: {
        required: 'name',
        optional: 'etc...'
      }
    }, cmd.hello)
    .command ('wizard', 'begins a wizard', {
      wizard: true,
      scope: 'warcraft'
    }, cmd.wizard)
    .option ('-f, --foobar', 'zog is foobar', {
      params: {
        required: 'who'
      }
    }, opt.foobar);

  callback ();
};

exports.unregister = function (callback) {
  /* internal stuff */
  callback ();
};

myShell.js

'use strict';

var path       = require ('path');
var shellcraft = require ('../');

var options = {
  version: '0.0.1',
  prompt: 'orc>'
};
var shellExt = path.join (__dirname, 'myShellExtension.js');

shellcraft.registerExtension (shellExt, function () {
  shellcraft.begin (options, function (err, results) {
    if (results) {
      console.log (results);
    }
  });
});

shell mode

$ node myShell.js
? orc> _
? orc> help
 exit                    exit the shell
 help                    list of commands
 scope                   change scope (warcraft)
 hello <name> [etc...]   print Hello, John
? orc> hello Tux
zog tells "Hello, Tux"
? orc> exit
good bye
$ _

CLI mode

$ node myShell.js -h

  Usage: myShell [options] [command]


  Commands:

    *
    hello <name> [etc...]  print Hello, John

  Options:

    -h, --help          output usage information
    -V, --version       output the version number
    -s, --scoped        include scoped commands (CLI only)
    -f, --foobar <who>  zog is foobar

$ _
$ node myShell.js hello Alice
zog tells "Hello, Alice"
$ node myShell.js -f Bob hello Alice
Bob tells "Hello, Alice"
$ _

Note that the commands which are in a different scope (like wizard in this example), are not shown in the global help output.

In order to see all commands, you must pas the -s, --scope argument:

$ node examples/myShell -sh

  Usage: myShell [options] [command]


  Commands:

    *
    hello <name> [etc...]  print Hello, John
    warcraft@wizard        begins a wizard

  Options:

    -h, --help          output usage information
    -V, --version       output the version number
    -s, --scoped        include scoped commands (CLI only)
    -f, --foobar <who>  zog is foobar

$ _

License

The MIT License (MIT)

Copyright (c) 2014-2015 Xcraft mathieu@schroetersa.ch Copyright (c) 2015 Xcraft sam@loup.io

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.