[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