Permalink
Browse files

Documentation, help tests passing

  • Loading branch information...
1 parent f22aaf2 commit 4a08e8dcec18995e3f88f8a435c17cd933d94a61 @frodwith committed Apr 28, 2011
Showing with 363 additions and 161 deletions.
  1. +1 −1 Makefile
  2. +239 −0 README.markdown
  3. +0 −122 README.md
  4. +14 −0 examples/simple.coffee
  5. +25 −15 lib/Help.coffee
  6. +57 −0 lib/getopt.coffee
  7. +1 −0 lib/types.coffee
  8. +2 −2 package.json
  9. +22 −20 test/help.coffee
  10. +2 −1 test/parse.coffee
View
@@ -11,6 +11,6 @@ test: coffee
nodeunit test/*.js
clean:
- rm $(JSFILES)
+ rm -f $(JSFILES)
.PHONY : all test coffee
View
@@ -0,0 +1,239 @@
+Getopt
+======
+
+For the impatient
+-----------------
+If you're in a hurry and you just want to parse your options already:
+
+ getopt = require('getopt');
+ options = getopt.simple({
+ verbose: {
+ type: getopt.flag,
+ short: 'v',
+ },
+ input: {
+ type: getopt.list,
+ short: 'i',
+ },
+ output: {
+ type: getopt.scalar,
+ description: 'output file (- for stdout)',
+ default: '-',
+ short: 'o',
+ required: true,
+ },
+ });
+
+options.verbose is true or false, input is an array (possibly empty), and
+output is a string (or undefined). You also get a --help option for free that
+prints out:
+
+ node myscript.pl [OPTIONS]
+
+ The following options are accepted:
+
+ -h
+ --help Prints this message and exits.
+
+ -v
+ --verbose
+
+
+ -i VAL
+ --input=VAL
+
+ -o VAL
+ --output=VAL output file (- for stdout). Required. Default: -
+
+getopt.simple() doesn't do what I want!
+=======================================
+Yeah, sorry about that. getopt.simple() does what I usually want with a
+minimum of fuss and ceremony, but have a look at the lower level APIs. Very
+probably, you can coerce them into doing what you want, though you might have
+to write try/catch blocks (the horror!) and call process.exit() yourself, and
+so on. The whole API is designed to allow you to use just the parts of it that
+are useful for you. So, read the rest of the documentation :)
+
+Why?
+----
+
+As if Node didn't have enough option parsers. As of this writing, most of them
+are almost good enough for me. None of them quite measures up to the power of
+perl's Getopt::Long though. Getopt::Long's interface sucks, but its parser is
+very flexible. This module aims to have an interface that doesn't suck and
+still be flexible, but you'll be the judge.
+
+Specification
+-------------
+
+The primary way you give information to getopt is through a specification
+object. The keys are the names of targets (keys in the result object), and the
+values are objects with the following keys:
+
+### type
+
+This tells getopt what kind of thing you're trying to parse. It absolutely
+must be one of the following - you cannot pass a string, and there is no
+default.
+
+#### getopt.flag (or getopt.bool)
+
+Just an "on" switch. It'll be true if it was passed, and false if it wasn't.
+All the following forms are valid:
+
+ -vax
+ -v -a -x
+ --verbose --anthropomorphic --xenophobic
+
+#### getopt.scalar (or getopt.string)
+
+Expects one (and only one) value. If present at all, its value will be some
+kind of string. Passing more than one argument for options of this type will
+make getopt throw an error. The following forms are all valid:
+
+ -a42
+ -a 42
+ --answer 42
+ --answer=42
+
+#### getopt.array (or getopt.list)
+
+Expects zero or more values. You'll get an array in the result object of all
+the strings passed for this argument.
+
+ node script.js --foo=one --foo=two --foo=three
+***
+ { foo: ['one', 'two', 'three'] }
+
+#### getopt.object (or getopt.hash)
+
+This one is a little odd: like list, you can pass it multiple times, but the
+result will be an object (or hash) instead of an array, and the value will be
+split into key/value on the = sign. An example will probably explain better:
+
+ define: {
+ type: getopt.object,
+ short: '-D'
+ }
+***
+ node --script.js -Dfoo=bar -Dbar=baz
+***
+ { define: { foo: "bar", bar: "baz" } }
+
+### short
+
+Either a string or an array of strings. All must be one character long (leave
+off the -). This creates short aliases for your argument. The target will be
+the same, though, and aliases can be mixed. In addition, for flag type shorts,
+they can be chained together. No short aliases are created by default.
+
+### long
+
+A list of long names for your option, either a string or an array of strings
+(leave off the --). By default, this is just the name of your target. If you
+do specify some longs, you must also include the name of your target if you
+wish it to be a long alias.
+
+### required
+
+A boolean. This causes getopt.parse to throw an exception if the argument
+wasn't given, and is only valid for scalars and lists. In the list case, at
+least one value must be given.
+
+### default
+
+A default value for your option if none is parsed from the command line.
+Arrays and objects default to empty arrays and objects unless you say
+otherwise.
+
+### description
+
+Purely optional, this should be a string explaining what your option does. The
+help generator makes use of this -- see getopt.help() for details.
+
+Positional Arguments
+--------------------
+Anything that doesn't look like an option will get aggregated into the result
+object's .argv property, in the order it was found in the actual argv. '-' is
+treated as positional, and '--' will cause getopt to stop processing and
+report the rest of the args as positional.
+
+Unrecognized Arguments
+----------------------
+Any options given to the program that aren't specified in the options spec
+will cause an error to be thrown.
+
+API
+===
+
+### getopt.parse(spec, argv)
+
+Processes argv without modifying it and returns a result object, which will
+have an argv property and other properties depending on the option spec. Any
+errors in parsing will throw an exception. If you don't specify argv,
+process.argv (minus the first two elements) will be used.
+
+### getopt.tryParse(spec, argv)
+
+Wraps getopt.parse in a try/catch block. If exceptions are encountered, they
+are printed to stderr and the process will exit with a non-zero code.
+
+### getopt.zero()
+
+Returns the program name (e.g. "node myscript.js"). Useful when generating a
+usage message.
+
+### getopt.usage()
+
+Uses getopt.zero() to generate a usage message of the form:
+"Usage: node myscript.js [OPTIONS]". This is the default message used by
+getopt.simple().
+
+### getopt.help(spec)
+
+Returns a formatted string describing the options specified. Used internally
+by getopt.simple(), but you are encouraged to use it outside that context.
+
+The description field of the spec is examined. If you didn't include a period
+at the end of the description, one will be added. Other bits of explanatory
+text (like "Required", "Default: " or "Can be specified multiple times") will
+be added to the end of the description to keep you from having to duplicate
+spec information in the description.
+
+### getopt.simple(spec, banner, argv)
+
+Behaves similarly to getopt.tryParse(), except that it adds a "help" option
+and then checks for it. If --help is passed, spec will be passed to
+getopt.help() to generate some the help. The given banner will be printed,
+followed by this help. Banner and argv are both optional: banner defaults to
+getopt.usage(), and argv() defaults to process.argv as in getopt.parse().
+
+Errors
+======
+There is a whole heirarchy of error classes, mostly for testing purposes. If
+you don't catch them, node will print a stacktrace for them like the common
+errors. If you do, you can use their "message" member to print out something
+useful to the user.
+
+Any time you create a Parser or Help object (internal classes used by the api
+methods above), an exception will be thrown if there is something inconsistent
+about your option specification. This helps you catch errors sooner. These
+exceptions are instances of getopt.SpecError, but you probably shouldn't try
+to catch them. getopt.tryParse et al will rethrow them.
+
+Calling getopt.parse() an throw exceptions if the user has given bad options
+on the command line. These are generally the ones you want to try to catch and
+print. They are all instances of getopt.ParseError.
+
+I think getopt should behave differently.
+=========================================
+
+I value your opinion, I really do. I also have a job, and it isn't maintaining
+getopt. Please, please either include a patch in your correspondance or send
+me a pull request on github. Otherwise, your issue may or may not be
+addressed, but I'm gonna go out on a limb and say it probably won't be. Thanks
+in advance for your contributions :)
+
+If you insist on not fixing my code for me, though, you can report an issue
+through github. If it's a bug that effects me, it will very likely get fixed.
+If not, perhaps you should reconsider fixing my code for me :)
View
122 README.md
@@ -1,122 +0,0 @@
-special flags
-=============
-A single dash '-' is treated as positional.
-Double dash '--' is removed from the array and stops processing, so that
-everything that comes after it is treated as positional.
-
-the specification object
-========================
-
-keys are target names (what you check for in the result object)
-values are the specification for that target. Keys for the specification are:
-
-short:
- array, each element is a one-character string. If you specify nothing,
- there will be no short alias.
-
-long:
- array, each element is a string. If you specify nothing, the name of the
- target will be used.
-
-type:
- needs to be one of getopt.boolean, getopt.string, getopt.array, or
- getopt.object. See the "types" section.
-
-types
-=====
-
-flag:
- No value is allowed. Short flags can appear in groups such that
- -vax
- is equivalent to
- -v -a -x
-
- Long flags look like:
- --verbose --add --xerox
-
- If the user tries to give a value for a flag with an equals, e.g.
- -v=42
- --verbose=42
- then an error will be thrown. If they try to give one with a space,
- though, , e.g.
- -v 42
- --verbose 42
-
- then -v will be set and 42 will be treated as a positional argument.
-
- A flag can be specified multiple times without error.
-
-scalar:
- A single value is allowed. Not giving a value throws an error. Short
- scalars look like:
- -v 42
- -v=42
-
- Long scalars look like:
- --verbosity 42
- --verbosity=42
-
- Scalars take an additional option, "required" (defaults to false). If this
- is set, an error will be thrown if no value is supplied or the supplied
- value is the empty string. Specifying this will cause "(required)" to be
- appended to your description.
-
- Scalars can also have a "default". This will be the value if none is
- specified, although an empty value can still be specified like
- --verbosity=
-
- Specifying this will cause "(default: value)" to be appended to the
- description.
-
-array:
- The option can be specified zero, one, or many times, and the value will
- be aggregated. This looks like:
-
- --foo one --foo two --foo three
- -f=one -f=two -f=three
- etc.
-
- Arrays can use "required" and "default" just like scalars, except that
- default should be an array. If any values are supplied, the default is not
- used.
-
-object:
- The values supplied must be in the form "name=value". This looks like:
- -D foo=bar --define bar=baz -D=baz=qux --define=qux=quux
-
- Supplying the same key twice will cause an error to be thrown.
-
- Objects can use "default" just like scalars, except
- that default should be an object. If any key/value pairs are supplied, the
- default is ignored.
-
- Objects cannot be "required".
-
-positional arguments
-====================
-
-Anything that doesn't look like an option will be aggregated into the
-"positional" array, and can appear anywhere in the argument list.
-
-unrecognized arguments
-======================
-
-Any options given to the program that aren't specified in the options spec
-will cause an error to be thrown.
-
-errors
-======
-Errors are thrown when you call "parse", and are string exceptions.
-Typical usage would be something like:
-
-parser = new GetOpt(spec)
-
-try {
- parser.parse(process.argv)
-}
-catch (e) {
- console.log(e)
- console.log(parser.usage())
-}
-
-But you can of course do something different.
View
@@ -0,0 +1,14 @@
+getopt = require 'getopt'
+sys = require 'sys'
+
+o = getopt.simple
+ munge:
+ type: getopt.flag
+ description: 'Whether or not to munge'
+ ickiness:
+ type: getopt.scalar
+ default: 1
+ description: 'How icky to make the munging'
+
+if o.munge
+ sys.puts "Munge..." for [1..o.ickiness]
Oops, something went wrong.

0 comments on commit 4a08e8d

Please sign in to comment.