Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add a showUsage helper #13

Closed
wants to merge 3 commits into from

2 participants

@Filirom1

Nopt is a great tool for option parsing, but I miss a show usage message generator.

I've implemented a very simple one on top of nopt. I hope you will find it useful.

It doesn't change the behaviour of the rest of nopt, and it was implemented in a separate file.

This pull request also solve #7.

Cheers
Romain

@Filirom1

Do you prefer that I publish this feature in npm ?
The name could be nopt-usage.

@isaacs
Owner

Doing this as a separate module would be better.

@isaacs isaacs closed this
@Filirom1 Filirom1 referenced this pull request in Filirom1/findup
Closed

update nopt dependency #2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 8, 2012
  1. @Filirom1

    Add showUsage helper

    Filirom1 authored
  2. @Filirom1

    update the README

    Filirom1 authored
  3. @Filirom1

    fix typo

    Filirom1 authored
This page is out of date. Refresh to see the latest.
Showing with 145 additions and 0 deletions.
  1. +66 −0 README.md
  2. +16 −0 examples/my-program.js
  3. +2 −0  lib/nopt.js
  4. +61 −0 lib/usage.js
View
66 README.md
@@ -208,3 +208,69 @@ That's usually not very useful to you. So they're sliced off by
default. If you want them, then you can pass in `0` as the last
argument, or any other number that you'd like to slice off the start of
the list.
+
+## Show usage
+
+An option parser is great, but it's even better if it generate the
+showUSage message for you.
+
+Everything is done by calling `nopt.usage`
+
+ var nopt = require('nopt');
+ nopt.usage(knownOpts, shortHands, description1, description2, ...)
+
+You could pass as many description objects as you want. Take a look at the following example to understand how it could be used.
+
+
+ #!/usr/bin/env node
+
+ var nopt = require("../lib/nopt")
+ , Stream = require("stream").Stream
+ , path = require("path")
+ , knownOpts = { "foo" : [String, null]
+ , "bar" : [Stream, Number]
+ , "baz" : path
+ , "bloo" : [ "big", "medium", "small" ]
+ , "flag" : Boolean
+ , "pick" : Boolean
+ }
+ , shortHands = { "foofoo" : ["--foo", "Mr. Foo"]
+ , "b7" : ["--bar", "7"]
+ , "m" : ["--bloo", "medium"]
+ , "p" : ["--pick"]
+ , "f" : ["--flag", "true"]
+ , "g" : ["--flag"]
+ , "s" : "--flag"
+ }
+ , description = { "foo" : "Something really foooooooo"
+ , "bar" : "A bar thing"
+ , "baz" : "More or less baz"
+ , "flag" : "Flag it as well"
+ , "pick" : "Or pick something"
+ }
+ , defaults = { "foo" : null
+ , "bar" : 42
+ , "baz" : "/etc/passwd"
+ , "bloo" : "small"
+ , "pick" : false
+ }
+ // everything is optional.
+ // knownOpts and shorthands default to {}
+ // arg list defaults to process.argv
+ // slice defaults to 2
+ , parsed = nopt(knownOpts, shortHands, process.argv, 2)
+ , usage = nopt.usage(knownOpts, shortHands, description, defaults)
+
+ console.log('Usage: ')
+ console.log(usage)
+
+The output is:
+
+ Usage:
+ --foo, -foofoo Something really foooooooo null
+ --bar, -b7 A bar thing 42
+ --baz More or less baz /etc/passwd
+ --bloo, -m small
+ --flag, -f, -g, -s Flag it as well
+ --pick, -p Or pick something false
+
View
16 examples/my-program.js
@@ -21,10 +21,26 @@ var nopt = require("../lib/nopt")
, "g" : ["--flag"]
, "s" : "--flag"
}
+ , description = { "foo" : "Something really foooooooo"
+ , "bar" : "A bar thing"
+ , "baz" : "More or less baz"
+ , "flag" : "Flag it as well"
+ , "pick" : "Or pick something"
+ }
+ , defaults = { "foo" : null
+ , "bar" : 42
+ , "baz" : "/etc/passwd"
+ , "bloo" : "small"
+ , "pick" : false
+ }
// everything is optional.
// knownOpts and shorthands default to {}
// arg list defaults to process.argv
// slice defaults to 2
, parsed = nopt(knownOpts, shortHands, process.argv, 2)
+ , usage = nopt.usage(knownOpts, shortHands, description, defaults)
console.log("parsed =\n"+ require("util").inspect(parsed))
+
+console.log('\nUsage: ')
+console.log(usage)
View
2  lib/nopt.js
@@ -8,9 +8,11 @@ var url = require("url")
, path = require("path")
, Stream = require("stream").Stream
, abbrev = require("abbrev")
+ , usage = require("./usage")
module.exports = exports = nopt
exports.clean = clean
+exports.usage = usage
exports.typeDefs =
{ String : { type: String, validate: validateString }
View
61 lib/usage.js
@@ -0,0 +1,61 @@
+module.exports = function showUsage(knownOpts, shortHands /*, description1, description2, ... */){
+ var descriptions = Array.prototype.slice.call(arguments, 2, arguments.length),
+ knownOptsMaxLen = maxLength(Object.keys(knownOpts)),
+ shortHands2 = {},
+ SPACE = 4;
+
+ // create a shortHands object with the long name as key.
+ Object.keys(shortHands).forEach(function(key){
+ var value = Array.isArray(shortHands[key]) ? shortHands[key][0] : shortHands[key];
+ var option = value.replace('--', '');
+ shortHands2[option] = shortHands2[option] || [];
+ shortHands2[option].push(key);
+ });
+
+ // we can have severals shorthands for one option
+ var shortHandsMaxLength = values(shortHands2).reduce(function(a, b){
+ a = Array.isArray(a) ? a.join(', -').length : a;
+ b = Array.isArray(b) ? b.join(', -').length : b;
+ return ( a > b) ? a : b;
+ });
+
+ // start by writing all known options
+ var out = {};
+ Object.keys(knownOpts).forEach(function(key){
+ var shorts = shortHands2[key] ? ', -' + shortHands2[key].join(', -') : '';
+ var cmd = rpad('', SPACE) + '--' + key + shorts;
+ out[key] = rpad(cmd, knownOptsMaxLen + shortHandsMaxLength + 5 + 2 * SPACE);
+ });
+
+ // then write all the descriptions
+ descriptions.forEach(function(description){
+ var descriptionMaxLen = maxLength(values(description));
+ Object.keys(knownOpts).forEach(function(key){
+ var value = '' + (description[key] !== undefined ? description[key] : '');
+ out[key] += rpad(value, descriptionMaxLen + SPACE);
+ });
+ });
+
+ return values(out).join('\n');
+};
+
+// string right padding helper
+function rpad(str, length) {
+ while (str.length < length)
+ str = str + ' ';
+ return str;
+}
+
+// Object.values
+function values(o){
+ return Object.keys(o).map(function(k){ return o[k]; });
+}
+
+// Return the max length of an array of string.
+function maxLength(arr){
+ return arr.map(function(str){
+ return ('' + str).length;
+ }).reduce(function(a,b){
+ return ( a > b ) ? a : b;
+ });
+}
Something went wrong with that request. Please try again.