[Pkg-javascript-commits] [node-posix-getopt] 01/03: Imported Upstream version 1.2.0+20150728
Julien Puydt
julien.puydt at laposte.net
Tue Oct 20 05:28:57 UTC 2015
This is an automated email from the git hooks/post-receive script.
jpuydt-guest pushed a commit to branch master
in repository node-posix-getopt.
commit 902533910d7a13150d21d67f99ee0895fa1cb27b
Author: Julien Puydt <julien.puydt at laposte.net>
Date: Sun Oct 18 17:26:49 2015 +0200
Imported Upstream version 1.2.0+20150728
---
LICENSE | 18 +++
README.md | 359 ++++++++++++++++++++++++++++++++++++++++++
examples/basic.js | 72 +++++++++
examples/examples.js | 40 +++++
lib/getopt.js | 305 +++++++++++++++++++++++++++++++++++
package.json | 18 +++
tests/test-getopt.js | 100 ++++++++++++
tests/test-tokenize-optstr.js | 73 +++++++++
8 files changed, 985 insertions(+)
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..280e336
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,18 @@
+Copyright (c) 2013, Joyent, Inc. All rights reserved.
+
+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.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1e1ac42
--- /dev/null
+++ b/README.md
@@ -0,0 +1,359 @@
+
+node-getopt
+==============
+
+Overview
+--------
+
+node-getopt implements the POSIX getopt() function for Node. getopt() provides
+a functional interface for option parsing.
+
+Install the npm package in the usual way:
+
+ $ npm install posix-getopt
+
+Here's how you'd typically use it for a command that takes options "-a" and
+"-b" with no arguments, option "-o" (also called "--output") with one argument,
+and another mandatory argument:
+
+ var mod_getopt = require('posix-getopt');
+ var parser, option;
+
+ parser = new mod_getopt.BasicParser('abo:(output)', process.argv);
+
+ while ((option = parser.getopt()) !== undefined) {
+ switch (option.option) {
+ case 'a':
+ console.log('option "a" is set');
+ break;
+
+ case 'b':
+ console.log('option "b" is set');
+ break;
+
+ case 'o':
+ console.error('option "o" has value "%s"',
+ option.optarg);
+ break;
+
+ default:
+ /* error message already emitted by getopt */
+ mod_assert.equal('?', option.option);
+ break;
+ }
+ }
+
+ if (parser.optind() >= process.argv.length)
+ usage('missing required argument: "input"');
+
+ console.log('input = %s', process.argv[parser.optind()]);
+
+Examples:
+
+ $ cmd
+ error: missing required argument: "input"
+ usage: cmd [-ab] [-o file] input
+
+ $ cmd foo
+ input = foo
+
+ $ cmd -a foo
+ option "a" is set
+ input = foo
+
+ $ cmd -ba foo
+ option "b" is set
+ option "a" is set
+ input = foo
+
+ $ cmd -ba -obar foo
+ option "b" is set
+ option "a" is set
+ option "o" has value "bar"
+ input = foo
+
+ $ cmd -ba --output=bar foo
+ option "b" is set
+ option "a" is set
+ option "o" has value "bar"
+ input = foo
+
+ $ cmd --output= foo
+ option "o" has value ""
+ input = foo
+
+ $ cmd -o
+ option requires an argument -- o
+ error: missing required argument: "input"
+ usage: cmd [-ab] [-o file] input
+
+ $ cmd -- -a
+ input = -a
+
+ $ cmd -q
+ illegal option -- q
+ error: missing required argument: "input"
+ usage: cmd [-ab] [-o file] input
+
+
+Background
+--------
+
+getopt() is a general-purpose command line parser that follows the POSIX
+guidelines for command-line utilities. Using these guidelines encourages
+common conventions among applications, including use of:
+
+- short option names (e.g., "-r")
+- options with arguments (e.g., "-f filename or -ffilename")
+- chaining short option names when options have no arguments (e.g., "-ra")
+
+This implementation mirrors the Solaris getopt() implementation and supports
+long option names (e.g., "--recurse"), potentially with values specified using
+"=" (e.g., "--file=/path/to/file").
+
+Unlike other option parsers available for Node.js, the POSIX getopt() interface
+supports using the same option multiple times (e.g., "-vvv", commonly used to
+indicate level of verbosity).
+
+For further reference on the relevant POSIX standards, see the following:
+
+ http://pubs.opengroup.org/onlinepubs/009695399/functions/getopt.html
+ http://pubs.opengroup.org/onlinepubs/009695399/utilities/getopts.html
+
+The Utility Syntax Guidelines are described here:
+
+ http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html
+
+
+Status
+------
+
+This module is considered complete except that there's minimal automated test
+coverage. There are no known bugs.
+
+
+API
+---
+
+### `new getopt.BasicParser(optstring, argv[, optind])`
+
+Instantiates a new object for parsing the specified arguments using the
+specified option string. This interface is closest to the traditional getopt()
+C function. Callers first instantiate a BasicParser and then invoke the
+getopt() method to iterate the options as they would in C. (This interface
+allows the same option to be specified multiple times.) The optional 3rd
+argument to the constructor `optind` is the number of arguments from `argv` to
+skip. By default `optind` is set to `2`, so the first two arguments in `argv`
+are ignored, since they generally denote the path to the node executable and
+the script being run.
+
+The option string consists of an optional leading ":" (see below) followed by a
+sequence of option-specifiers. Each option-specifier consists of a single
+character denoting the short option name, optionally followed by a colon if the
+option takes an argument and/or a sequence of strings in parentheses
+representing long-option aliases for the option name.
+
+Example option strings:
+
+ ':r' Command takes one option with no args: -r
+ ':ra' Command takes two option with no args: -r and -a
+ ':raf:' Command takes two option with no args: -r and -a
+ and a single option that takes an arg: -f
+ ':f:(file)' Command takes a single option with an argument: -f
+ -f can also be specified as --file
+
+The presence of a leading colon in the option string determines the behavior
+when an argument is not specified for an option which takes an argument. See
+getopt() below. Additionally, if no colon is specified, then error messages are
+printed to stderr when invalid options, options with missing arguments, or
+options with unexpected arguments are encountered.
+
+
+### `parser.optind()`
+
+Returns the next argv-argument to be parsed. When options are specified as
+separate "argv" arguments, this value is incremented with each option parsed.
+When multiple options are specified in the same argv-argument, the returned
+value is unspecified. This matches the variable "OPTIND" from the POSIX
+standard, but is read-only. (If you want to reset OPTIND, you must create a new
+BasicParser instance.) This is most useful after parsing has finished to
+examine the non-option arguments.
+
+This value starts at "2" as described under "Departures from POSIX" below.
+
+
+### `parser.getopt()`
+
+Returns the next argument specified in "argv" (the object's constructor
+argument). The returned value is either undefined or an object with at least
+the following members:
+
+ option single-character option name
+
+The following members may also be present:
+
+ optarg argument value, if any
+
+ optopt option character that caused the error, if any
+
+ error if true, this object represents an error
+
+This function scans "argv" starting at the current value of "optind" and returns
+an object describing the next argument based on the following cases:
+
+- If the end of command line arguments is reached, an undefined value is
+ returned. The end of arguments is signified by a single '-' argument, a
+ single '--' argument, an argument that's neither an option nor a previous
+ option's argument, the end of argv, or an error.
+
+- If an unrecognized command line option is found (i.e. an option character
+ not defined in "optstring"), the returned object's "option" member
+ is just "?". "optopt" is set to the unrecognized option letter. "error"
+ is set to a true value.
+
+- If a known command line option is found and the option takes no arguments
+ then the returned object's "option" member is the option's short name
+ (i.e. the single character specifier in "optstring").
+
+- If a known command line option is found and that option takes an argument
+ and the argument is also found, then the returned object's "option"
+ member is the option's short name and the "optarg" member contains the
+ argument's value.
+
+- If a known command line option is found and that option takes an argument
+ but the argument is not found, then the returned object's "option" member
+ is "?" unless the first character of "optstring" was a colon, in which
+ case the "option" member is set to ":". Either way, the "optopt" member
+ is set to the option character that caused the error and "error" is set to
+ a true value.
+
+
+Departures from POSIX
+--------
+
+- Global state in the C implementation (e.g., optind, optarg, and optopt) is
+ encapsulated in the BasicParser object. optind is available as a method
+ call on the parser object. optarg and optopt are returned directly by
+ getopt().
+
+- Rather than returning an integer or character, getopt() returns an object
+ with the "option" field corresponding to the processed option character
+ and possibly the additional "optarg" and "optopt" fields. If an error
+ occurs on a particular option, "error" is also set. If an error occurs on
+ no particular option or if the end of input is encountered, undefined is
+ returned.
+
+- Long option forms are supported as described above. This introduces an
+ additional error case which is where an argument of the form
+ --option=value is encountered, where "option" does not take a value.
+
+- POSIX starts "optind" at 1, since argv[0] is generally the name of the
+ command and options start at argv[1]. This implementation starts "optind"
+ at 2, since argv[0] is generally the path to the node binary and argv[1]
+ is the path to the script, so options start with argv[2].
+
+
+Examples
+--------
+
+### Example 1: simple short options
+
+ var mod_getopt = require('getopt')
+ var parser, option;
+
+ parser = new mod_getopt.BasicParser('la',
+ ['node', 'script', '-l', '-a', 'stuff']);
+ while ((option = parser.getopt()) !== undefined && !option.error)
+ console.error(option);
+
+outputs:
+
+ { option: 'l' }
+ { option: 'a' }
+
+
+### Example 2: invalid option specified
+
+ var mod_getopt = require('getopt')
+ var parser, option;
+
+ parser = new mod_getopt.BasicParser('la',
+ ['node', 'script', '-l', '-b', 'stuff']);
+ while ((option = parser.getopt()) !== undefined && !option.error)
+ console.error(option);
+ console.error(option);
+
+outputs:
+
+ { option: 'l' }
+ illegal option -- b
+ { option: '?', optopt: 'b', error: true }
+
+
+### Example 3: long options
+
+ var mod_getopt = require('getopt')
+ var parser, option;
+
+ parser = new mod_getopt.BasicParser('lar(recurse)',
+ ['node', 'script', '-l', '--recurse', 'stuff']);
+ while ((option = parser.getopt()) !== undefined && !option.error)
+ console.error(option);
+
+outputs:
+
+ { option: 'l' }
+ { option: 'r' }
+
+
+### Example 4: options with arguments
+
+ var mod_getopt = require('getopt')
+ var parser, option;
+
+ parser = new mod_getopt.BasicParser('f:lad:',
+ ['node', 'script', '-l', '-f', 'filename', '-dtype', 'stuff']);
+ while ((option = parser.getopt()) !== undefined && !option.error)
+ console.error(option);
+
+outputs:
+
+ { option: 'l' }
+ { option: 'f', optarg: 'filename' }
+ { option: 'd', optarg: 'type' }
+
+
+### Example 5: options with missing arguments
+
+ var mod_getopt = require('getopt')
+ var parser, option;
+
+ parser = new mod_getopt.BasicParser('f:la',
+ ['node', 'script', '-l', '-a', '-f']);
+ while ((option = parser.getopt()) !== undefined && !option.error)
+ console.error(option);
+ console.error(option);
+
+outputs:
+
+ { option: 'l' }
+ { option: 'a' }
+ option requires an argument -- f
+ { option: '?', optopt: 'f', error: true }
+
+
+### Example 6: options specified multiple times
+
+ var mod_getopt = require('getopt')
+ var parser, option;
+
+ parser = new mod_getopt.BasicParser('la',
+ ['node', 'script', '-l', '-a', '-l']);
+ while ((option = parser.getopt()) !== undefined && !option.error)
+ console.error(option);
+
+outputs:
+
+ { option: 'l' }
+ { option: 'a' }
+ { option: 'l' }
diff --git a/examples/basic.js b/examples/basic.js
new file mode 100644
index 0000000..90d4a62
--- /dev/null
+++ b/examples/basic.js
@@ -0,0 +1,72 @@
+/*
+ * examples/basic.js: basic example of using node-getopt
+ *
+ * This example parses options for an example command that takes options "a" and
+ * "b" having no arguments, option "o" (with long alias "output") which takes a
+ * mandatory value, and then one mandatory argument. Example valid invocations:
+ *
+ * cmd foo
+ * cmd -a foo
+ * cmd -ab foo
+ * cmd -a -o bar foo
+ * cmd -o bar foo
+ * cmd --output bar foo
+ * cmd --output=bar foo
+ * cmd --output= foo
+ * cmd -- -a (note: "-a" option is NOT set in this case)
+ *
+ * Invalid invocations:
+ *
+ * cmd missing mandatory argument
+ * cmd -o option "-o" requires an argument
+ * cmd -q unknown option "-q"
+ */
+
+var mod_assert = require('assert');
+var mod_getopt = require('..');
+
+function main()
+{
+ var parser, option;
+
+ parser = new mod_getopt.BasicParser('abo:(output)', process.argv);
+
+ while ((option = parser.getopt()) !== undefined) {
+ switch (option.option) {
+ case 'a':
+ console.log('option "a" is set');
+ break;
+
+ case 'b':
+ console.log('option "b" is set');
+ break;
+
+ case 'o':
+ console.error('option "o" has value "%s"',
+ option.optarg);
+ break;
+
+ default:
+ /* error message already emitted by getopt */
+ mod_assert.equal('?', option.option);
+ break;
+ }
+ }
+
+ if (parser.optind() >= process.argv.length)
+ usage('missing required argument: "input"');
+
+ console.log('input = %s', process.argv[parser.optind()]);
+}
+
+function usage(message)
+{
+ if (message)
+ console.error('error: %s', message);
+
+ console.error('usage: %s %s [-ab] [-o file] input',
+ process.argv[0], process.argv[1]);
+ process.exit(2);
+}
+
+main();
diff --git a/examples/examples.js b/examples/examples.js
new file mode 100644
index 0000000..59be146
--- /dev/null
+++ b/examples/examples.js
@@ -0,0 +1,40 @@
+var mod_getopt = require('..');
+var parser, option;
+
+console.error('Example 1: simple short options');
+parser = new mod_getopt.BasicParser('la',
+ ['node', 'script', '-l', '-a', 'stuff']);
+while ((option = parser.getopt()) !== undefined && !option.error)
+ console.error(option);
+
+console.error('Example 2: invalid option specified');
+parser = new mod_getopt.BasicParser('la',
+ ['node', 'script', '-l', '-b', 'stuff']);
+while ((option = parser.getopt()) !== undefined && !option.error)
+ console.error(option);
+console.error(option);
+
+console.error('Example 3: long options');
+parser = new mod_getopt.BasicParser('lar(recurse)',
+ ['node', 'script', '-l', '--recurse', 'stuff']);
+while ((option = parser.getopt()) !== undefined && !option.error)
+ console.error(option);
+
+console.error('Example 4: options with arguments');
+parser = new mod_getopt.BasicParser('f:lad:',
+ ['node', 'script', '-l', '-f', 'filename', '-dtype', 'stuff']);
+while ((option = parser.getopt()) !== undefined && !option.error)
+ console.error(option);
+
+console.error('Example 5: options with missing arguments');
+parser = new mod_getopt.BasicParser('f:la',
+ ['node', 'script', '-l', '-a', '-f']);
+while ((option = parser.getopt()) !== undefined && !option.error)
+ console.error(option);
+console.error(option);
+
+console.error('Example 6: options specified multiple times');
+parser = new mod_getopt.BasicParser('la',
+ ['node', 'script', '-l', '-a', '-l']);
+while ((option = parser.getopt()) !== undefined && !option.error)
+ console.error(option);
diff --git a/lib/getopt.js b/lib/getopt.js
new file mode 100644
index 0000000..15525ba
--- /dev/null
+++ b/lib/getopt.js
@@ -0,0 +1,305 @@
+/*
+ * getopt.js: node.js implementation of POSIX getopt() (and then some)
+ *
+ * Copyright 2011 David Pacheco. All rights reserved.
+ *
+ * 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.
+ */
+
+var ASSERT = require('assert').ok;
+
+function goError(msg)
+{
+ return (new Error('getopt: ' + msg));
+}
+
+/*
+ * The BasicParser is our primary interface to the outside world. The
+ * documentation for this object and its public methods is contained in
+ * the included README.md.
+ */
+function goBasicParser(optstring, argv, optind)
+{
+ var ii;
+
+ ASSERT(optstring || optstring === '', 'optstring is required');
+ ASSERT(optstring.constructor === String, 'optstring must be a string');
+ ASSERT(argv, 'argv is required');
+ ASSERT(argv.constructor === Array, 'argv must be an array');
+
+ this.gop_argv = new Array(argv.length);
+ this.gop_options = {};
+ this.gop_aliases = {};
+ this.gop_optind = optind !== undefined ? optind : 2;
+ this.gop_subind = 0;
+
+ for (ii = 0; ii < argv.length; ii++) {
+ ASSERT(argv[ii].constructor === String,
+ 'argv must be string array');
+ this.gop_argv[ii] = argv[ii];
+ }
+
+ this.parseOptstr(optstring);
+}
+
+exports.BasicParser = goBasicParser;
+
+/*
+ * Parse the option string and update the following fields:
+ *
+ * gop_silent Whether to log errors to stderr. Silent mode is
+ * indicated by a leading ':' in the option string.
+ *
+ * gop_options Maps valid single-letter-options to booleans indicating
+ * whether each option is required.
+ *
+ * gop_aliases Maps valid long options to the corresponding
+ * single-letter short option.
+ */
+goBasicParser.prototype.parseOptstr = function (optstr)
+{
+ var chr, cp, alias, arg, ii;
+
+ ii = 0;
+ if (optstr.length > 0 && optstr[0] == ':') {
+ this.gop_silent = true;
+ ii++;
+ } else {
+ this.gop_silent = false;
+ }
+
+ while (ii < optstr.length) {
+ chr = optstr[ii];
+ arg = false;
+
+ if (!/^[\w\d\u1000-\u1100]$/.test(chr))
+ throw (goError('invalid optstring: only alphanumeric ' +
+ 'characters and unicode characters between ' +
+ '\\u1000-\\u1100 may be used as options: ' + chr));
+
+ if (ii + 1 < optstr.length && optstr[ii + 1] == ':') {
+ arg = true;
+ ii++;
+ }
+
+ this.gop_options[chr] = arg;
+
+ while (ii + 1 < optstr.length && optstr[ii + 1] == '(') {
+ ii++;
+ cp = optstr.indexOf(')', ii + 1);
+ if (cp == -1)
+ throw (goError('invalid optstring: missing ' +
+ '")" to match "(" at char ' + ii));
+
+ alias = optstr.substring(ii + 1, cp);
+ this.gop_aliases[alias] = chr;
+ ii = cp;
+ }
+
+ ii++;
+ }
+};
+
+goBasicParser.prototype.optind = function ()
+{
+ return (this.gop_optind);
+};
+
+/*
+ * For documentation on what getopt() does, see README.md. The following
+ * implementation invariants are maintained by getopt() and its helper methods:
+ *
+ * this.gop_optind Refers to the element of gop_argv that contains
+ * the next argument to be processed. This may
+ * exceed gop_argv, in which case the end of input
+ * has been reached.
+ *
+ * this.gop_subind Refers to the character inside
+ * this.gop_options[this.gop_optind] which begins
+ * the next option to be processed. This may never
+ * exceed the length of gop_argv[gop_optind], so
+ * when incrementing this value we must always
+ * check if we should instead increment optind and
+ * reset subind to 0.
+ *
+ * That is, when any of these functions is entered, the above indices' values
+ * are as described above. getopt() itself and getoptArgument() may both be
+ * called at the end of the input, so they check whether optind exceeds
+ * argv.length. getoptShort() and getoptLong() are called only when the indices
+ * already point to a valid short or long option, respectively.
+ *
+ * getopt() processes the next option as follows:
+ *
+ * o If gop_optind > gop_argv.length, then we already parsed all arguments.
+ *
+ * o If gop_subind == 0, then we're looking at the start of an argument:
+ *
+ * o Check for special cases like '-', '--', and non-option arguments.
+ * If present, update the indices and return the appropriate value.
+ *
+ * o Check for a long-form option (beginning with '--'). If present,
+ * delegate to getoptLong() and return the result.
+ *
+ * o Otherwise, advance subind past the argument's leading '-' and
+ * continue as though gop_subind != 0 (since that's now the case).
+ *
+ * o Delegate to getoptShort() and return the result.
+ */
+goBasicParser.prototype.getopt = function ()
+{
+ if (this.gop_optind >= this.gop_argv.length)
+ /* end of input */
+ return (undefined);
+
+ var arg = this.gop_argv[this.gop_optind];
+
+ if (this.gop_subind === 0) {
+ if (arg == '-' || arg === '' || arg[0] != '-')
+ return (undefined);
+
+ if (arg == '--') {
+ this.gop_optind++;
+ this.gop_subind = 0;
+ return (undefined);
+ }
+
+ if (arg[1] == '-')
+ return (this.getoptLong());
+
+ this.gop_subind++;
+ ASSERT(this.gop_subind < arg.length);
+ }
+
+ return (this.getoptShort());
+};
+
+/*
+ * Implements getopt() for the case where optind/subind point to a short option.
+ */
+goBasicParser.prototype.getoptShort = function ()
+{
+ var arg, chr;
+
+ ASSERT(this.gop_optind < this.gop_argv.length);
+ arg = this.gop_argv[this.gop_optind];
+ ASSERT(this.gop_subind < arg.length);
+ chr = arg[this.gop_subind];
+
+ if (++this.gop_subind >= arg.length) {
+ this.gop_optind++;
+ this.gop_subind = 0;
+ }
+
+ if (!(chr in this.gop_options))
+ return (this.errInvalidOption(chr));
+
+ if (!this.gop_options[chr])
+ return ({ option: chr });
+
+ return (this.getoptArgument(chr));
+};
+
+/*
+ * Implements getopt() for the case where optind/subind point to a long option.
+ */
+goBasicParser.prototype.getoptLong = function ()
+{
+ var arg, alias, chr, eq;
+
+ ASSERT(this.gop_subind === 0);
+ ASSERT(this.gop_optind < this.gop_argv.length);
+ arg = this.gop_argv[this.gop_optind];
+ ASSERT(arg.length > 2 && arg[0] == '-' && arg[1] == '-');
+
+ eq = arg.indexOf('=');
+ alias = arg.substring(2, eq == -1 ? arg.length : eq);
+ if (!(alias in this.gop_aliases))
+ return (this.errInvalidOption(alias));
+
+ chr = this.gop_aliases[alias];
+ ASSERT(chr in this.gop_options);
+
+ if (!this.gop_options[chr]) {
+ if (eq != -1)
+ return (this.errExtraArg(alias));
+
+ this.gop_optind++; /* eat this argument */
+ return ({ option: chr });
+ }
+
+ /*
+ * Advance optind/subind for the argument value and retrieve it.
+ */
+ if (eq == -1)
+ this.gop_optind++;
+ else
+ this.gop_subind = eq + 1;
+
+ return (this.getoptArgument(chr));
+};
+
+/*
+ * For the given option letter 'chr' that takes an argument, assumes that
+ * optind/subind point to the argument (or denote the end of input) and return
+ * the appropriate getopt() return value for this option and argument (or return
+ * the appropriate error).
+ */
+goBasicParser.prototype.getoptArgument = function (chr)
+{
+ var arg;
+
+ if (this.gop_optind >= this.gop_argv.length)
+ return (this.errMissingArg(chr));
+
+ arg = this.gop_argv[this.gop_optind].substring(this.gop_subind);
+ this.gop_optind++;
+ this.gop_subind = 0;
+ return ({ option: chr, optarg: arg });
+};
+
+goBasicParser.prototype.errMissingArg = function (chr)
+{
+ if (this.gop_silent)
+ return ({ option: ':', optopt: chr });
+
+ process.stderr.write('option requires an argument -- ' + chr + '\n');
+ return ({ option: '?', optopt: chr, error: true });
+};
+
+goBasicParser.prototype.errInvalidOption = function (chr)
+{
+ if (!this.gop_silent)
+ process.stderr.write('illegal option -- ' + chr + '\n');
+
+ return ({ option: '?', optopt: chr, error: true });
+};
+
+/*
+ * This error is not specified by POSIX, but neither is the notion of specifying
+ * long option arguments using "=" in the same argv-argument, but it's common
+ * practice and pretty convenient.
+ */
+goBasicParser.prototype.errExtraArg = function (chr)
+{
+ if (!this.gop_silent)
+ process.stderr.write('option expects no argument -- ' +
+ chr + '\n');
+
+ return ({ option: '?', optopt: chr, error: true });
+};
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..4e35435
--- /dev/null
+++ b/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "posix-getopt",
+ "version": "1.2.0",
+ "description": "POSIX-style getopt()",
+ "author": "Dave Pacheco (dap at cs.brown.edu)",
+ "engines": {
+ "node": "*"
+ },
+ "scripts": {
+ "test": "for f in tests/*.js; do echo \"$f\"; node \"$f\" || exit 1; done"
+ },
+ "main": "./lib/getopt",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/davepacheco/node-getopt.git"
+ },
+ "license": "MIT"
+}
diff --git a/tests/test-getopt.js b/tests/test-getopt.js
new file mode 100644
index 0000000..ad32c7f
--- /dev/null
+++ b/tests/test-getopt.js
@@ -0,0 +1,100 @@
+/*
+ * Tests getopt() itself.
+ */
+var mod_getopt = require('..');
+var mod_assert = require('assert');
+
+var test_cases = [ {
+ optstr: '',
+ argv: [],
+ result: []
+}, {
+ optstr: ':',
+ argv: [],
+ result: []
+}, {
+ optstr: ':l',
+ argv: [],
+ result: []
+}, {
+ optstr: ':l:',
+ argv: [],
+ result: []
+}, {
+ optstr: ':las',
+ argv: [],
+ result: []
+}, {
+ optstr: ':l:a:s:',
+ argv: [],
+ result: []
+}, {
+ optstr: ':l(long)',
+ argv: [],
+ result: []
+}, {
+ optstr: ':l:(long)',
+ argv: ['cmd', 'script', '-l', 'arg1', '--long=q', 'b', '--long', 'foo'],
+ result: [
+ { option: 'l', optarg: 'arg1' },
+ { option: 'l', optarg: 'q' }
+ ]
+}, {
+ optstr: 'l:(long)(longer)',
+ argv: [],
+ result: []
+}, {
+ optstr: ':la:r(recurse)(recur)f:(file)(filename)q',
+ argv: [],
+ result: []
+}, {
+ optstr: '\u1000(help)\u1001(version)',
+ argv: ['cmd', 'script', '--help' ],
+ result: [
+ { option: '\u1000' },
+ ]
+}, {
+ optstr: '\u1000(help)\u1001(version)',
+ argv: ['cmd', 'script', '--version' ],
+ result: [
+ { option: '\u1001' },
+ ]
+}, {
+ optstr: '\u1000:(parallel)',
+ argv: ['cmd', 'script', '--parallel=100' ],
+ result: [
+ { option: '\u1000', optarg: 100 },
+ ]
+}, {
+ optstr: 'h',
+ argv: ['-h'],
+ result: [
+ { option: 'h' },
+ ],
+ optind: 0
+}, {
+ optstr: 'hv',
+ argv: ['foo', '-h', '-v' ],
+ result: [
+ { option: 'h' },
+ { option: 'v' },
+ ],
+ optind: 1
+}];
+
+var parser, ii, arg, result;
+for (ii = 0; ii < test_cases.length; ii++) {
+ console.log('test case %s: "%s" with argv = "%s"', ii + 1,
+ test_cases[ii].optstr, test_cases[ii].argv);
+ parser = new mod_getopt.BasicParser(test_cases[ii].optstr,
+ test_cases[ii].argv, test_cases[ii].optind);
+ console.log(parser.gop_tokens);
+
+ result = [];
+ while ((arg = parser.getopt()) !== undefined)
+ result.push(arg);
+
+ mod_assert.deepEqual(test_cases[ii].result, result);
+}
+
+console.log('%s test cases passed', test_cases.length);
diff --git a/tests/test-tokenize-optstr.js b/tests/test-tokenize-optstr.js
new file mode 100644
index 0000000..60c10c6
--- /dev/null
+++ b/tests/test-tokenize-optstr.js
@@ -0,0 +1,73 @@
+/*
+ * Tests internal state of the parser.
+ */
+var mod_path = require('path');
+
+var mod_sys = require('sys');
+var mod_getopt = require('..');
+var mod_assert = require('assert');
+
+var test_cases = [ {
+ optstr: '',
+ silent: false,
+ options: {},
+ aliases: {},
+}, {
+ optstr: ':',
+ silent: true,
+ options: {},
+ aliases: {},
+}, {
+ optstr: ':l',
+ silent: true,
+ options: { l: false },
+ aliases: {},
+}, {
+ optstr: ':l:',
+ silent: true,
+ options: { l: true },
+ aliases: {},
+}, {
+ optstr: ':las',
+ silent: true,
+ options: { l: false, a: false, s: false },
+ aliases: {},
+}, {
+ optstr: ':l:a:s:',
+ silent: true,
+ options: { l: true, a: true, s: true },
+ aliases: {},
+}, {
+ optstr: ':l(long)',
+ silent: true,
+ options: { l: false },
+ aliases: { long: 'l' },
+}, {
+ optstr: ':l:(long)',
+ silent: true,
+ options: { l: true },
+ aliases: { long: 'l' },
+}, {
+ optstr: 'l:(long)(longer)',
+ silent: false,
+ options: { l: true },
+ aliases: { long: 'l', longer: 'l' },
+}, {
+ optstr: ':la:r(recurse)(recur)f:(file)(filename)q',
+ silent: true,
+ options: { l: false, a: true, r: false, f: true, q: false },
+ aliases: { recurse: 'r', recur: 'r', file: 'f', filename: 'f' }
+} ];
+
+var parser, ii;
+for (ii = 0; ii < test_cases.length; ii++) {
+ console.log('test case %s: "%s"', ii + 1, test_cases[ii].optstr);
+ parser = new mod_getopt.BasicParser(test_cases[ii].optstr, []);
+ mod_assert.ok(test_cases[ii].silent === parser.gop_silent);
+ mod_assert.deepEqual(test_cases[ii].options,
+ parser.gop_options);
+ mod_assert.deepEqual(test_cases[ii].aliases,
+ parser.gop_aliases);
+}
+
+console.log('%s test cases passed', test_cases.length);
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-posix-getopt.git
More information about the Pkg-javascript-commits
mailing list