Anonymous avatar Anonymous committed 6f082eb

added "multiple" as an option setting

Comments (0)

Files changed (1)

 /***************************************************************************
-Author   : Joey Mazzarelli
-Email    : mazzarelli@gmail.com
-Homepage : http://joey.mazzarelli.com/js-opts
-Source   : http://bitbucket.org/mazzarell/js-opts/
-License  : Simplified BSD License
-Version  : 1.0
+ Author   : Joey Mazzarelli
+ Email    : mazzarelli@gmail.com
+ Homepage : http://joey.mazzarelli.com/js-opts
+ Source   : http://bitbucket.org/mazzarell/js-opts/
+ License  : Simplified BSD License
+ Version  : 1.0
 
-Copyright 2010 Joey Mazzarelli. All rights reserved.
+ Copyright 2010 Joey Mazzarelli. All rights reserved.
 
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
 
-   1. Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
 
-   2. Redistributions in binary form must reproduce the above copyright notice,
-      this list of conditions and the following disclaimer in the documentation
-      and/or other materials provided with the distribution.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
 
-THIS SOFTWARE IS PROVIDED BY JOEY MAZZARELLI 'AS IS' AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-EVENT SHALL JOEY MAZZARELLI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ THIS SOFTWARE IS PROVIDED BY JOEY MAZZARELLI 'AS IS' AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ EVENT SHALL JOEY MAZZARELLI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-The views and conclusions contained in the software and documentation are those
-of the authors and should not be interpreted as representing official policies,
-either expressed or implied, of Joey Mazzarelli.
-***************************************************************************/
+ The views and conclusions contained in the software and documentation are those
+ of the authors and should not be interpreted as representing official policies,
+ either expressed or implied, of Joey Mazzarelli.
+ ***************************************************************************/
 
-var puts        = console.log
-  , values      = {}
-  , args        = {}
-  , argv        = []
-  , errors      = []
-  , descriptors = {opts:[], args:[]};
+var puts = console.log
+    , values = {}
+    , args = {}
+    , argv = []
+    , errors = []
+    , descriptors = {opts:[], args:[]};
 
 /**
  * Get some version info out of it
  * building options for a library in addition to the main app.
  */
 exports.add = function (options, namespace) {
-  for (var i=0; i<options.length; i++) {
-    options[i].namespace = namespace;
-    descriptors.opts.push(options[i]);
-  }
+    for (var i = 0; i < options.length; i++) {
+        options[i].namespace = namespace;
+        descriptors.opts.push(options[i]);
+    }
 };
 
 /**
  * @param bool  help     Automatically generate help message, default false
  *
  * ===== Options Docs =====
- * Each option in the array can have the following fields. None are required, 
+ * Each option in the array can have the following fields. None are required,
  * but you should at least provide a short or long name.
  *   {
  *     short       : 'l',
  *     long        : 'list',
  *     description : 'Show a list',
  *     value       : false,  // default false
+ *     multiple    : false,  // default false, if true multiple values are permitted, separated by spaces
  *     required    : true,   // default false
  *     callback    : function (value) { ... },
  *   }
  *   }
  *
  * ===== Arguments Docs =====
- * Arguments are different than options, and simpler. They typically come 
+ * Arguments are different than options, and simpler. They typically come
  * after the options, but the library really doesn't care. Each argument
  * can have the form of:
  *   {
  */
 exports.parse = function (options, params, help) {
 
-  if (params === true) {
-    help = true;
-    params = [];
-  } else if (!params) {
-    params = [];
-  } else {
-    for (var i=0; i<params.length; i++) {
-      descriptors.args.push(params[i]);
+    if (params === true) {
+        help = true;
+    } else if (!params) {
+        params = [];
+    } else {
+        for (var i = 0; i < params.length; i++) {
+            descriptors.args.push(params[i]);
+        }
     }
-  }
 
-  if (help) {
-    options.push({ long        : 'help'
-                 , description : 'Show this help message'
-                 , callback    : exports.help
-                 });
-  }
-  for (var i=0; i<options.length; i++) {
-    descriptors.opts.unshift(options[i]);
-  }
-  options = descriptors.opts;
+    if (help) {
+        options.push({ long:'help', description:'Show this help message', callback:exports.help
+        });
+    }
+    for (var i = 0; i < options.length; i++) {
+        descriptors.opts.unshift(options[i]);
+    }
+    options = descriptors.opts;
 
-  var checkDup = function (opt, type) {
-    var prefix = (type == 'short')? '-': '--';
-    var name = opt[type];
-    if (!opts[prefix + name]) {
-      opts[prefix + name] = opt;
-    } else {
-      if (opt.namespace && !opts[prefix + opt.namespace + '.' + name]) {
-        opts[prefix + opt.namespace + '.' + name] = opt;
-        for (var i=0; i<descriptors.opts.length; i++) {
-          var desc = descriptors.opts[i];
-          if (desc.namespace == opt.namespace) {
-            if (type == 'long' && desc.long == opt.long) {
-                descriptors.opts[i].long = opt.namespace + '.' + opt.long;
-            } else if (type == 'short') {
-              delete descriptors.opts[i].short;
+    var checkDup = function (opt, type) {
+        var prefix = (type == 'short') ? '-' : '--';
+        var name = opt[type];
+        if (!opts[prefix + name]) {
+            opts[prefix + name] = opt;
+        } else {
+            if (opt.namespace && !opts[prefix + opt.namespace + '.' + name]) {
+                opts[prefix + opt.namespace + '.' + name] = opt;
+                for (var i = 0; i < descriptors.opts.length; i++) {
+                    var desc = descriptors.opts[i];
+                    if (desc.namespace == opt.namespace) {
+                        if (type == 'long' && desc.long == opt.long) {
+                            descriptors.opts[i].long = opt.namespace + '.' + opt.long;
+                        } else if (type == 'short') {
+                            delete descriptors.opts[i].short;
+                        }
+                    }
+                }
+            } else {
+                puts('Conflicting flags: ' + prefix + name + '\n');
+                puts(helpString());
+                process.exit(1);
             }
-          }
         }
-      } else {
-        puts('Conflicting flags: ' + prefix + name + '\n');
-        puts(helpString());
-        process.exit(1);
-      }
-    }
-  };
+    };
 
-  var opts = {};
-  for (var i=0; i<options.length; i++) {
-    if (options[i].short) checkDup(options[i], 'short');
-    if (options[i].long) checkDup(options[i], 'long');
-  }
-
-  for (var i=2; i<process.argv.length; i++) {
-    var inp = process.argv[i];
-    if (opts[inp]) {
-      // found a match, process it.
-      var opt = opts[inp];
-      if (!opt.value) {
-        if (opt.callback) opt.callback(true);
+    var missingValue = function (opt) {
+        var flag = opt.short || opt.long;
+        errors.push('Missing value for option: ' + flag);
         if (opt.short) values[opt.short] = true;
         if (opt.long) values[opt.long] = true;
-      } else {
-        var next = process.argv[i+1];
-        if (!next || opts[next]) {
-          var flag = opt.short || opt.long;
-          errors.push('Missing value for option: ' + flag);
-          if (opt.short) values[opt.short] = true;
-          if (opt.long) values[opt.long] = true;
+    };
+
+    var opts = {};
+    for (var i = 0; i < options.length; i++) {
+        if (options[i].short) checkDup(options[i], 'short');
+        if (options[i].long) checkDup(options[i], 'long');
+    }
+
+    for (var i = 2; i < process.argv.length; i++) {
+        var inp = process.argv[i];
+        if (opts[inp]) {
+            // found a match, process it.
+            var opt = opts[inp];
+            if (!opt.value) {
+                if (opt.callback) opt.callback(true);
+                if (opt.short) values[opt.short] = true;
+                if (opt.long) values[opt.long] = true;
+            } else {
+                if (opt.multiple) {
+                    var nextIndex = i + 1,
+                        found = false;
+
+                    //prepare value arrays
+                    if (opt.short) values[opt.short] = [];
+                    if (opt.long) values[opt.long] = [];
+
+                    //no values passed
+                    if (!process.argv[nextIndex]) {
+                        missingValue(opt);
+                    }
+
+                    //continue looking ahead while args exist and the arg is not another option
+                    while (process.argv[nextIndex] && !opts[process.argv[nextIndex]]) {
+                        //not another option, so add to the array
+                        found = true;
+                        if (opt.short) values[opt.short].push( process.argv[nextIndex] );
+                        if (opt.long) values[opt.long].push( process.argv[nextIndex] );
+                        nextIndex++;
+                    }
+
+                    //no value given or arg is another option, and we haven't found a proper value yet
+                    if (!found) {
+                        missingValue(opt);
+                        break;
+                    }
+
+                    //execute the callback if we have found values
+                    if (opt.callback && found) {
+                        opt.callback(values[opt.short].length ? values[opt.short] : values[opt.long]);
+                    }
+
+                    //reset iterator to skip the processed values
+                    i = nextIndex-1;
+
+                } else {
+                    var next = process.argv[i + 1];
+                    if (!next || opts[next]) {
+                        missingValue(opt);
+                    } else {
+                        if (opt.callback) opt.callback(next);
+                        if (opt.short) values[opt.short] = next;
+                        if (opt.long) values[opt.long] = next;
+                        i++;
+                    }
+                }
+
+            }
         } else {
-          if (opt.callback) opt.callback(next);
-          if (opt.short) values[opt.short] = next;
-          if (opt.long) values[opt.long] = next;
-          i++;
+            // No match. If it starts with a dash, show an error. Otherwise
+            // add it to the extra params.
+            if (inp[0] == '-') {
+                puts('Unknown option: ' + inp);
+                if (opts['--help']) puts('Try --help');
+                process.exit(1);
+            } else {
+                argv.push(inp);
+                var arg = params.shift();
+                if (arg) {
+                    args[arg.name] = inp;
+                    if (arg.callback) arg.callback(inp);
+                }
+            }
         }
-      }
-    } else {
-      // No match. If it starts with a dash, show an error. Otherwise
-      // add it to the extra params.
-      if (inp[0] == '-') {
-        puts('Unknown option: ' + inp);
-        if (opts['--help']) puts('Try --help');
+    }
+    for (var i = 0; i < options.length; i++) {
+        var flag = options[i].short || options[i].long;
+        if (options[i].required && !exports.get(flag)) {
+            errors.push('Missing required option: ' + flag);
+        }
+    }
+    for (var i = 0; i < params.length; i++) {
+        if (params[i].required && !args[params[i].name]) {
+            errors.push('Missing required argument: ' + params[i].name);
+        }
+    }
+    if (errors.length) {
+        for (var i = 0; i < errors.length; i++) puts(errors[i]);
+        puts('\n' + helpString());
         process.exit(1);
-      } else {
-        argv.push(inp);
-        var arg = params.shift();
-        if (arg) {
-          args[arg.name] = inp;
-          if (arg.callback) arg.callback(inp);
-        }
-      }
     }
-  }
-  for (var i=0; i<options.length; i++) {
-    var flag = options[i].short || options[i].long;
-    if (options[i].required && !exports.get(flag)) {
-      errors.push('Missing required option: ' + flag);
-    }
-  }
-  for (var i=0; i<params.length; i++) {
-    if (params[i].required && !args[params[i].name]) {
-      errors.push('Missing required argument: ' + params[i].name);
-    }
-  }
-  if (errors.length) {
-    for (var i=0; i<errors.length; i++) puts(errors[i]);
-    puts('\n' + helpString());
-    process.exit(1);
-  }
 };
 
 /**
  * @return string
  */
 exports.get = function (opt) {
-  return values[opt] || values['-' + opt] || values['--' + opt];
+    return values[opt] || values['-' + opt] || values['--' + opt];
 };
 
 /**
  * Get unknown args. Could have special meaning to client
  */
 exports.args = function () {
-  return argv;
+    return argv;
 };
 
 /**
  * @return string Value of arg
  */
 exports.arg = function (name) {
-  //puts(require('sys').inspect(arguments));
-  return args[name];
+    //puts(require('sys').inspect(arguments));
+    return args[name];
 };
 
 /**
  * Print the help message and exit
  */
 exports.help = function () {
-  puts(helpString());
-  process.exit(0);
+    puts(helpString());
+    process.exit(0);
 };
 
 
 // Create the help string
 var helpString = function () {
-  var str = 'Usage: ' + process.argv[0] + ' ' + process.argv[1];
-  if (descriptors.opts.length) str += ' [options]';
-  if (descriptors.args.length) {
-    for (var i=0; i<descriptors.args.length; i++) {
-      if (descriptors.args[i].required) {
-        str += ' ' + descriptors.args[i].name;
-      } else {
-        str += ' [' + descriptors.args[i].name + ']';
-      }
+    var str = 'Usage: ' + process.argv[0] + ' ' + process.argv[1];
+    if (descriptors.opts.length) str += ' [options]';
+    if (descriptors.args.length) {
+        for (var i = 0; i < descriptors.args.length; i++) {
+            if (descriptors.args[i].required) {
+                str += ' ' + descriptors.args[i].name;
+            } else {
+                str += ' [' + descriptors.args[i].name + ']';
+            }
+        }
     }
-  }
-  str += '\n';
-  for (var i=0; i<descriptors.opts.length; i++) {
-    var opt = descriptors.opts[i];
-    if (opt.description) str += (opt.description) + '\n';
-    var line = '';
-    if (opt.short && !opt.long) line += '-' + opt.short;
-    else if (opt.long && !opt.short) line += '--' + opt.long;
-    else line += '-' + opt.short + ', --' + opt.long;
-    if (opt.value) line += ' <value>';
-    if (opt.required) line += ' (required)';
-    str += '    ' + line + '\n';
-  }
-  return str;
+    str += '\n';
+    for (var i = 0; i < descriptors.opts.length; i++) {
+        var opt = descriptors.opts[i];
+        if (opt.description) str += (opt.description) + '\n';
+        var line = '';
+        if (opt.short && !opt.long) line += '-' + opt.short;
+        else if (opt.long && !opt.short) line += '--' + opt.long;
+        else line += '-' + opt.short + ', --' + opt.long;
+        if (opt.value) {
+            line += ' <value>';
+            if(opt.multiple) line += ' <value> <value> ...';
+        }
+        if (opt.required) line += ' (required)';
+        str += '    ' + line + '\n';
+    }
+    return str;
 };
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.