--- a/LICENSE.markdown Tue Apr 02 09:51:25 2019 -0400
+++ b/LICENSE.markdown Tue Apr 02 17:58:03 2019 -0400
@@ -1,4 +1,4 @@
-Copyright (c) 2018 Steve Losh and contributors
+Copyright (c) 2019 Steve Losh and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
--- a/README.markdown Tue Apr 02 09:51:25 2019 -0400
+++ b/README.markdown Tue Apr 02 17:58:03 2019 -0400
@@ -1,10 +1,11 @@
Adopt
=====
-I needed **A** **D**amn **OPT**ion parsing library.
+I needed **a** **d**amn **opt**ion parsing library.
-Adopt is a simple UNIX-style option parser in Common Lisp. It depends on
-[Bobbin][] and [split-sequence][].
+Adopt is a simple UNIX-style option parser in Common Lisp, heavily influenced by
+Python's optparse and argparse. It depends on [Bobbin][] and
+[split-sequence][].
* **License:** MIT
* **Documentation:** <https://sjl.bitbucket.io/adopt/>
--- a/docs/01-installation.markdown Tue Apr 02 09:51:25 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-Installation
-============
-
-Adopt is compatible with Quicklisp, but not *in* Quicklisp (yet?). You can
-clone the repository into your [Quicklisp local-projects directory][local] for
-now.
-
-The `adopt` system contains the core API and depends on [Bobbin][] and
-[split-sequence][].
-
-The `adopt.test` system contains the test suite, which uses depends on some
-other systems. You don't need to load this unless you want to run the unit
-tests.
-
-[local]: https://www.quicklisp.org/beta/faq.html#local-project
-[Bobbin]: https://github.com/sjl/bobbin
-[split-sequence]: https://www.cliki.net/split-sequence
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/01-usage.markdown Tue Apr 02 17:58:03 2019 -0400
@@ -0,0 +1,315 @@
+Usage
+=====
+
+Adopt is a simple library for parsing UNIX-style command line arguments in
+Common Lisp. It was made because none of the other libraries did what I needed.
+
+[TOC]
+
+Package
+-------
+
+All core Adopt functions are in the `adopt` package. Several of the symbols in
+adopt shadow those in the `common-lisp` package, so you should probably use
+namespaced `adopt:…` symbols instead of `USE`ing the package.
+
+Interfaces
+----------
+
+To get started with Adopt, you should create an interface with the
+`adopt:make-interface` function. This returns an object representing the
+command line interface presented to your users.
+
+### Creating an Interface
+
+Let's say you're developing a program to search the contents of files (because
+the world certainly needs *another* `grep` replacement). You might start with
+something like:
+
+ (defparameter *ui*
+ (adopt:make-interface
+ :name "search"
+ :summary "search files for a regular expression"
+ :usage "[OPTIONS] PATTERN [FILE]..."
+ :help "Search the contents of each FILE for the regular expression PATTERN. If no files are specified, searches standard input instead."))
+
+You can now print some help text for your CLI with `adopt:print-help`:
+
+ (adopt:print-help *ui*)
+ ; =>
+ search - search files for a regular expression
+
+ USAGE: … [OPTIONS] PATTERN [FILE]...
+
+ Search the contents of each FILE for the regular expression PATTERN. If no
+ files are specified, searches standard input instead.
+
+### Line Wrapping
+
+Adopt will handle line-wrapping your help text, so you don't need to (and
+shouldn't) add extra line breaks when creating your interface. If you want to
+line break the text in your source code to fit nicely in your editor, remember
+that `adopt:make-interface` is just a function — you can use `format` (possibly
+with its `~Newline` directive) to preprocess the help text argument:
+
+ (defparameter *ui*
+ (adopt:make-interface
+ :name "search"
+ :summary "search files for a regular expression"
+ :usage "[OPTIONS] PATTERN [FILE]..."
+ :help (format nil "Search the contents of each FILE for ~
+ the regular expression PATTERN. If ~
+ no files are specified, searches ~
+ standard input instead.")))
+
+Adopt's line-wrapping library [Bobbin][] will only ever *add* line breaks, never
+remove them, which means you can include breaks in the output if you want to
+have multiple paragraphs in your help text:
+
+ (defparameter *ui*
+ (adopt:make-interface
+ :name "search"
+ :summary "search files for a regular expression"
+ :usage "[OPTIONS] PATTERN [FILE]..."
+ :help (format nil
+ "Search the contents of each FILE for the regular expression PATTERN.~@
+ ~@
+ If no files are specified (or if - is given as a file name) standard input will be searched instead.")))
+
+If you want to control the width of the help text lines when they are printed,
+`adopt:print-help` takes a `:width` argument:
+
+ (adopt:print-help *ui* :width 50)
+ ; =>
+ search - search files for a regular expression
+
+ USAGE: … [OPTIONS] PATTERN [FILE]...
+
+ Search the contents of each FILE for the regular
+ expression PATTERN.
+
+ If no files are specified (or if - is given as a
+ file name) standard input will be searched
+ instead.
+
+`adopt:print-help` takes a number of other options — see the API Reference for
+more information.
+
+### Examples
+
+Describing the CLI in detail is helpful, but users can often learn a lot more by
+seeing a few examples of its usage. `adopt:make-interface` can take an
+`:examples` argument, which should be an alist of `(description . example)`
+conses:
+
+ (defparameter *ui*
+ (adopt:make-interface
+ :name "search"
+ :summary "search files for a regular expression"
+ :usage "[OPTIONS] PATTERN [FILE]..."
+ :help …
+ :examples
+ '(("Search foo.txt for the string 'hello':"
+ . "search hello foo.txt")
+ ("Search standard input for lines starting with x:"
+ . "search '^x' -")
+ ("Watch the file log.txt for lines containing the username steve.losh:"
+ . "tail foo/bar/baz/log.txt | search --literal steve.losh -"))))
+
+ (adopt:print-help *ui* :width 50)
+ ; =>
+ search - search files for a regular expression
+
+ USAGE: … [OPTIONS] PATTERN [FILE]...
+
+ Search the contents of each FILE for the regular
+ expression PATTERN.
+
+ If no files are specified (or if - is given as a
+ file name) standard input will be searched
+ instead.
+
+ Examples:
+
+ Search foo.txt for the string 'hello':
+
+ search hello foo.txt
+
+ Search standard input for lines starting with x:
+
+ search '^x' -
+
+ Watch the file log.txt for lines containing the
+ username steve.losh:
+
+ tail foo/bar/baz/log.txt | search --literal steve.losh -
+
+Notice how Adopt line wraps the prose explaining each example, but leaves the
+example itself untouched for easier copying and pasting. In general Adopt tries
+to do the right thing for your users (even when that means making a little more
+work for *you* in certain places).
+
+Exiting
+-------
+
+Adopt provides some helpful utility functions to exit out of your program with
+a UNIX exit code. These do what you think they do:
+
+ (adopt:exit)
+
+ (adopt:exit 1)
+
+ (adopt:print-help-and-exit *ui*)
+
+ (adopt:print-help-and-exit *ui*
+ :stream *error-output*
+ :exit-code 1)
+
+ (handler-case (assert (= 1 0))
+ (error (err)
+ (adopt:print-error-and-exit err)))
+
+These functions are not implemented for every Lisp implementation. PRs are
+welcome, or you can just write the implementation-specific calls in your program
+yourself.
+
+Options
+-------
+
+Now that you know how to create an interface, you can create some options to use
+inside it with `adopt:make-option`:
+
+ (defparameter *option-version*
+ (adopt:make-option 'version
+ :long "version"
+ :help "display version information and exit"
+ :reduce (constantly t)))
+
+ (defparameter *option-help*
+ (adopt:make-option 'help
+ :long "help"
+ :short #\h
+ :help "display help information and exit"
+ :reduce (constantly t)))
+
+ (defparameter *option-literal*
+ (adopt:make-option 'literal
+ :long "literal"
+ :short #\l
+ :help "treat PATTERN as a literal string instead of a regular expression"
+ :reduce (constantly t)))
+
+ (defparameter *ui*
+ (adopt:make-interface
+ :name "search"
+ :summary "search files for a regular expression"
+ :usage "[OPTIONS] PATTERN [FILE]..."
+ :help "Search the contents of …"
+ :contents (list
+ *option-version*
+ *option-help*
+ *option-literal*)))
+
+Adopt will automatically add the options to the help text:
+
+ (adopt:print-help *ui*)
+ ; =>
+ search - search files for a regular expression
+
+ USAGE: /usr/local/bin/sbcl [OPTIONS] PATTERN [FILE]...
+
+ Search the contents of …
+
+ Options:
+ --version display version information and exit
+ -h, --help display help information and exit
+ -l, --literal treat PATTERN as a literal string instead of a regular
+ expression
+
+The first argument to `adopt:make-option` is the name of the option, which we'll
+see put to use shortly. At least one of `:short` and `:long` is required, and
+`:help` text must be specified. We'll talk more about `:reduce` in a bit, but
+it too is required.
+
+I prefer to define each option as its own global variable to keep the call to
+`adopt:make-interface` from getting too large and unwieldy, but feel free to do
+something like this if you prefer to avoid cluttering your package:
+
+ (defparameter *ui*
+ (adopt:make-interface
+ …
+ :contents
+ (list (adopt:make-option 'foo …)
+ (adopt:make-option 'bar …)
+ …)))
+
+Parsing
+-------
+
+At this point we've got an interface with some options, so we can use it to
+parse a list of strings we've received as command line arguments:
+
+ (adopt:parse-options *ui* '("foo.*" "--literal" "a.txt" "b.txt"))
+ ; =>
+ ("foo.*" "a.txt" "b.txt")
+ #<HASH-TABLE :TEST EQL :COUNT 3 {10103142A3}>
+
+`adopt:parse-options` returns two values: a list of non-option arguments, and
+a hash table of the option values.
+
+The keys of the hash table are (by default) the option names given as the first
+argument to `adopt:make-option`. We'll see how the option values are determined
+soon.
+
+From now on I'll use a special pretty printer for hash tables to make it easier
+to see what's inside them:
+
+ (adopt:parse-options *ui* '("foo.*" "--literal" "a.txt" "b.txt"))
+ ; =>
+ ("foo.*" "a.txt" "b.txt")
+ {LITERAL: T, VERSION: NIL, HELP: NIL}
+
+Top-Level Structure
+-------------------
+
+We'll look at how the option values are computed shortly, but first let's see
+the overall structure of the programs you create with Adopt:
+
+ (defun toplevel ()
+ (handler-case
+ (multiple-value-bind (arguments options)
+ (adopt:parse-options *ui*)
+ (when (gethash 'help options)
+ (adopt:print-help-and-exit *ui*))
+ (when (gethash 'version options)
+ (format t "1.0.0~%")
+ (adopt:exit))
+ (destructuring-bind (pattern . files) arguments
+ (run pattern
+ files
+ :literal (gethash 'literal options))))
+ (error (c)
+ (adopt:print-error-and-exit c))))
+
+ (sb-ext:save-lisp-and-die "search" :toplevel #'toplevel)
+
+The `toplevel` function first uses a `handler-case` to trap all `error`s. If
+any error occurs it will print the error message and exit, to avoid confusing
+users by dropping them into a Lisp debugger REPL (which they probably won't
+understand). When you're developing your program yourself you'll want to omit
+this part and let yourself land in the debugger as usual.
+
+Next we use `adopt:parse-options` to parse the command line arguments and
+options. We do some initial checks to see if the user wants `--help` or
+`--version` information. If not, we destructure the arguments into the items we
+expect and call a `run` function with all the information it needs to do its
+job.
+
+If the `destructuring-bind` fails an error will be signaled, and the
+`handler-case` will print it and exit. If you want to be a nice person you
+could check that the `arguments` have the correct shape first, and return
+a friendlier error message to your users if they don't.
+
+Computing Values with Reduce
+----------------------------
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/02-reference.markdown Tue Apr 02 17:58:03 2019 -0400
@@ -0,0 +1,247 @@
+# API Reference
+
+The following is a list of all user-facing parts of adopt.
+
+If there are backwards-incompatible changes to anything listed here, they will
+be noted in the changelog and the author will feel bad.
+
+Anything not listed here is subject to change at any time with no warning, so
+don't touch it.
+
+[TOC]
+
+## Package `ADOPT`
+
+### `ARGV` (function)
+
+ (ARGV)
+
+Return a list of the program name and command line arguments.
+
+ This is not implemented for every Common Lisp implementation. You can always
+ pass your own values to `parse-options` and `print-help` if it's not
+ implemented for your particular Lisp.
+
+
+
+### `COLLECT` (function)
+
+ (COLLECT LIST EL)
+
+Append element `el` to the end of `list`.
+
+ It is useful as a `:reduce` function when you want to collect all values given
+ for an option.
+
+ This is implemented as `(append list (list el))`. It is not particularly
+ fast. If you can live with reversed output consider `(flip #'cons)` instead.
+
+
+
+### `DEFINE-STRING` (macro)
+
+ (DEFINE-STRING VAR STRING &REST ARGS)
+
+Convenience macro for `(defparameter ,var (format nil ,string ,@args))`.
+
+### `DISCARD-OPTION` (function)
+
+ (DISCARD-OPTION CONDITION)
+
+Invoke the `discard-option` restart properly.
+
+ Example:
+
+ (handler-bind ((unrecognized-option 'discard-option))
+ (multiple-value-bind (arguments options) (parse-options *ui*)
+ (run arguments options)))
+
+
+
+### `EXIT` (function)
+
+ (EXIT &OPTIONAL (CODE 0))
+
+### `FIRST` (function)
+
+ (FIRST OLD NEW)
+
+Return `new` if `old` is `nil`, otherwise return `old`.
+
+ It is useful as a `:reduce` function when you want to just keep the
+ first-given value for an option.
+
+
+
+### `FLIP` (function)
+
+ (FLIP FUNCTION)
+
+Return a function of two arguments X and Y that calls `function` with Y and X.
+
+ Useful for wrapping existing functions that expect their arguments in the
+ opposite order.
+
+ Examples:
+
+ (funcall #'cons 1 2) ; => (1 . 2)
+ (funcall (flip #'cons) 1 2) ; => (2 . 1)
+ (reduce (flip #'cons) '(1 2 3) :initial-value nil)
+ ; => (3 2 1)
+
+
+
+### `LAST` (function)
+
+ (LAST OLD NEW)
+
+Return `new`.
+
+ It is useful as a `:reduce` function when you want to just keep the last-given
+ value for an option.
+
+
+
+### `MAKE-GROUP` (function)
+
+ (MAKE-GROUP NAME &KEY TITLE HELP MANUAL OPTIONS)
+
+### `MAKE-INTERFACE` (function)
+
+ (MAKE-INTERFACE &KEY NAME SUMMARY USAGE HELP MANUAL EXAMPLES CONTENTS)
+
+### `MAKE-OPTION` (function)
+
+ (MAKE-OPTION NAME &KEY LONG SHORT HELP MANUAL PARAMETER REDUCE (RESULT-KEY NAME)
+ (INITIAL-VALUE NIL INITIAL-VALUE?) (KEY #'IDENTITY) (FINALLY #'IDENTITY))
+
+### `PARSE-OPTIONS` (function)
+
+ (PARSE-OPTIONS INTERFACE &OPTIONAL (ARGUMENTS (REST (ARGV))))
+
+Parse `arguments` according to `interface`.
+
+ Two values are returned:
+
+ 1. A fresh list of top-level, unaccounted-for arguments that don't correspond
+ to any options defined in `interface`.
+ 2. An `EQL` hash table of option keys to values.
+
+ See the full documentation for more information.
+
+
+
+### `PRINT-ERROR-AND-EXIT` (function)
+
+ (PRINT-ERROR-AND-EXIT ERROR &KEY (STREAM *ERROR-OUTPUT*) (EXIT-CODE 1) (PREFIX error: ))
+
+Print `prefix` and `error` to `stream` and exit.
+
+ Example:
+
+ (handler-case
+ (multiple-value-bind (arguments options) (parse-options *ui*)
+ (run arguments options))
+ (unrecognized-option (c)
+ (print-error-and-exit c)))
+
+
+
+### `PRINT-HELP` (function)
+
+ (PRINT-HELP INTERFACE &KEY (STREAM *STANDARD-OUTPUT*) (PROGRAM-NAME (CAR (ARGV))) (WIDTH 80)
+ (OPTION-WIDTH 20) (INCLUDE-EXAMPLES T))
+
+Print a pretty help document for `interface` to `stream`.
+
+ `width` should be the total width (in characters) for line-wrapping purposes.
+ Care will be taken to ensure lines are no longer than this, though some edge
+ cases (extremely long short/long option names and parameters) may slip
+ through.
+
+ `option-width` should be the width of the column of short/long options (in
+ characters). If the short/long option help is shorter than this, the option's
+ help string will start on the same line. Otherwise the option's help string
+ will start on the next line.
+
+ The result will look something like:
+
+ (print-help *program-interface* :width 60 :option-width 15)
+ ; =>
+ ; foo - do some things and meow
+ ;
+ ; USAGE: /bin/foo [options] FILES
+ ;
+ ; Foo is a program to frobulate some files, meowing as it
+ ; happens.
+ ;
+ ; Options:
+ ; -v, --verbose Output extra information.
+ ; -q, --quiet Shut up.
+ ; --ignore FILE Ignore FILE. May be specified multiple
+ ; times.
+ ; -n NAME, --name NAME
+ ; Your name. May be specified many times,
+ ; last one wins.
+ ; -m, --meow Meow.
+ ; 0.........1.... option-width
+ ; 0........1.........2.........3.........4.........5.........6
+
+
+
+### `PRINT-HELP-AND-EXIT` (function)
+
+ (PRINT-HELP-AND-EXIT INTERFACE &KEY (STREAM *STANDARD-OUTPUT*) (PROGRAM-NAME (CAR (ARGV)))
+ (WIDTH 80) (OPTION-WIDTH 20) (INCLUDE-EXAMPLES T) (EXIT-CODE 0))
+
+Print a pretty help document for `interface` to `stream` and exit.
+
+ Handy for easily providing --help:
+
+ (multiple-value-bind (arguments options) (parse-options *ui*)
+ (when (gethash 'help options)
+ (print-help-and-exit *ui*))
+ (run arguments options))
+
+
+### `PRINT-MANUAL` (function)
+
+ (PRINT-MANUAL INTERFACE &KEY (STREAM *STANDARD-OUTPUT*) (MANUAL-SECTION 1))
+
+### `SUPPLY-NEW-VALUE` (function)
+
+ (SUPPLY-NEW-VALUE CONDITION VALUE)
+
+Invoke the `supply-new-value` restart properly.
+
+ Example:
+
+ (handler-bind
+ ((unrecognized-option (alexandria:rcurry 'supply-new-value "--foo"))
+ (multiple-value-bind (arguments options) (parse-options *ui*)
+ (run arguments options)))
+
+
+
+### `TREAT-AS-ARGUMENT` (function)
+
+ (TREAT-AS-ARGUMENT CONDITION)
+
+Invoke the `treat-as-argument` restart properly.
+
+ Example:
+
+ (handler-bind ((unrecognized-option 'treat-as-argument))
+ (multiple-value-bind (arguments options) (parse-options *ui*)
+ (run arguments options)))
+
+
+
+### `UNRECOGNIZED-OPTION` (class)
+
+#### Slot `PROBLEMATIC-OPTION`
+
+* Allocation: `:INSTANCE`
+* Initarg: `:PROBLEMATIC-OPTION`
+* Accessor: `PROBLEMATIC-OPTION`
+
--- a/docs/02-usage.markdown Tue Apr 02 09:51:25 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-Usage
-=====
-
-Adopt is a simple library for parsing UNIX-style command line arguments in
-Common Lisp. It was made because none of the other libraries did what I needed.
-
-[TOC]
-
-Package
--------
-
-All core Adopt functions and macros are in the `adopt` package. You can `:use`
-that if you really want to, but it's probably clearer to use namespaced
-`adopt:…` symbols.
-
-Interfaces
-----------
-
-define-interface and usage. nothing else.
-
-Parsing
--------
-
-`parse-options` with a bare-bones interface.
-
-Options
--------
-
-talk about the option arguments.
-
-Short and Long Options
-----------------------
-
-short versus long arguments. 1+ is required.
-
-Initial Value
--------------
-
-at this point it's just a default
-
-Reduce
-------
-
-talk about reducers. mention argparse's:
-
-`store_const` is `(constantly x)`
-
-`store` is `#'latest`
-
-`store_true` is `(constantly t)`
-
-`store_false` is `(constantly nil)`
-
-`append` is `append1`
-
-`append_const` is `(rcurry #'append1 x)`
-
-`count` is `1+` with an `initial-value` of `0`.
-
-need to figure out `help` and `version`.
-
-Usage Printing
---------------
-
-It's `(print-usage interface)`.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/03-changelog.markdown Tue Apr 02 17:58:03 2019 -0400
@@ -0,0 +1,11 @@
+Changelog
+=========
+
+Here's the list of changes in each released version.
+
+[TOC]
+
+Current Development Version
+---------------------------
+
+Adopt is still in active development. No promises yet.
--- a/docs/03-reference.markdown Tue Apr 02 09:51:25 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-# API Reference
-
-The following is a list of all user-facing parts of adopt.
-
-If there are backwards-incompatible changes to anything listed here, they will
-be noted in the changelog and the author will feel bad.
-
-Anything not listed here is subject to change at any time with no warning, so
-don't touch it.
-
-[TOC]
-
-## Package `ADOPT`
-
-### `APPEND1` (function)
-
- (APPEND1 LIST EL)
-
-Append element `el` to the end of `list`.
-
- This is implemented as `(append list (list el))`. It is not particularly
- fast.
-
- It is useful as a `:reduce` function when you want to collect all values given
- for an option.
-
-
-
-### `ARGV` (function)
-
- (ARGV)
-
-Return a list of the program name and command line arguments.
-
- This is not implemented for every Common Lisp implementation. You can always
- pass your own values to `parse-options` and `print-usage` if it's not
- implemented for your particular Lisp.
-
-
-
-### `DEFINE-INTERFACE` (macro)
-
- (DEFINE-INTERFACE NAME USAGE &REST OPTIONS)
-
-### `LATEST` (function)
-
- (LATEST OLD NEW)
-
-Return `new`.
-
- It is useful as a `:reduce` function when you want to just keep the last-given
- value for an option.
-
-
-
-### `PARSE-OPTIONS` (function)
-
- (PARSE-OPTIONS INTERFACE &OPTIONAL (ARGUMENTS (REST (ARGV))))
-
-Parse `arguments` according to `interface`.
-
- Two values are returned:
-
- 1. A fresh list of top-level, unaccounted-for arguments that don't correspond
- to any options defined in `interface`.
- 2. An `EQL` hash map of option `name`s to values.
-
- See the full usage documentation for more information.
-
-
-
-### `PRINT-USAGE` (function)
-
- (PRINT-USAGE INTERFACE &KEY (STREAM *STANDARD-OUTPUT*) (PROGRAM-NAME (FIRST (ARGV))) (WIDTH 80) (OPTION-WIDTH 20))
-
-Print a pretty usage document for `interface` to `stream`.
-
- `width` should be the total width (in characters) for line-wrapping purposes.
- Care will be taken to ensure lines are no longer than this, though some edge
- cases (extremely long short/long option names and parameters) may slip
- through.
-
- `option-width` should be the width of the column of short/long options (in
- characters). If the short/long option documentation is shorter than this, the
- option's documentation string will start on the same line. Otherwise the
- option's documentation string will start on the next line.
-
- The result will look something like (assuming a usage string of
- `"[options] FILES"`):
-
- (print-usage *program-interface* :width 60 :option-width 15)
- ; =>
- ; USAGE: /bin/foo [options] FILES
- ;
- ; Options:
- ; -v, --verbose Output extra information.
- ; -q, --quiet Shut up.
- ; --ignore FILE Ignore FILE. May be specified multiple
- ; times.
- ; -n NAME, --name NAME
- ; Your name. May be specified many times,
- ; last one wins.
- ; -m, --meow Meow.
- ; 0.........1.... option-width
- ; 0........1.........2.........3.........4.........5.........6
-
-
-
--- a/docs/04-changelog.markdown Tue Apr 02 09:51:25 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-Changelog
-=========
-
-Here's the list of changes in each released version.
-
-[TOC]
-
-Current Development Version
----------------------------
-
-Adopt is still in active development. No promises yet.
--- a/docs/api.lisp Tue Apr 02 09:51:25 2019 -0400
+++ b/docs/api.lisp Tue Apr 02 17:58:03 2019 -0400
@@ -13,7 +13,7 @@
(d-api:generate-documentation
:adopt
- #p"docs/03-reference.markdown"
+ #p"docs/02-reference.markdown"
(list "ADOPT")
*header*
:title "API Reference")
--- a/docs/index.markdown Tue Apr 02 09:51:25 2019 -0400
+++ b/docs/index.markdown Tue Apr 02 17:58:03 2019 -0400
@@ -1,17 +1,28 @@
-I needed **A** **D**amn **OPT**ion parsing library.
+I needed **a** **d**amn **opt**ion parsing library.
-Adopt is a simple (~150 LOC) UNIX-style option parser in Common Lisp.
-It depends on [Bobbin][] and [split-sequence][].
-
-It aims to be simple and powerful enough for the majority of use cases.
+Adopt is a simple UNIX-style option parser in Common Lisp, heavily influenced by
+Python's optparse and argparse.
* **License:** MIT
* **Documentation:** <https://sjl.bitbucket.io/adopt/>
* **Mercurial:** <https://bitbucket.org/sjl/adopt/>
* **Git:** <https://github.com/sjl/adopt/>
+Adopt aims to be a simple, robust option parser. It can automatically print
+help information and even generate `man` pages for you.
+
The test suite currently passes in SBCL, CCL, ECL, and ABCL on Ubuntu. Further
testing is welcome.
+Adopt is compatible with Quicklisp, but not *in* Quicklisp (yet). You can clone
+the repository into your [Quicklisp local-projects directory][local] for now.
+
+The `adopt` system contains the core API and depends on [Bobbin][] and
+[split-sequence][].
+
+The `adopt/test` system contains the test suite, which depends on some other
+systems. You don't need to load this unless you want to run the unit tests.
+
+[local]: https://www.quicklisp.org/beta/faq.html#local-project
[Bobbin]: https://github.com/sjl/bobbin
[split-sequence]: https://www.cliki.net/split-sequence
--- a/src/main.lisp Tue Apr 02 09:51:25 2019 -0400
+++ b/src/main.lisp Tue Apr 02 17:58:03 2019 -0400
@@ -475,13 +475,14 @@
(format stream (bobbin:wrap (help interface) width))
(format stream "~%")
(dolist (group (groups interface))
- (format stream "~%~A:~%" (or (title group) (name group) "Options"))
- (let* ((option-column 2)
- (option-padding 2)
- (doc-column (+ option-column option-width option-padding))
- (doc-width (- width doc-column)))
- (dolist (option (options group))
- (print-option-help stream option option-column doc-column doc-width))))
+ (when (options group)
+ (format stream "~%~A:~%" (or (title group) (name group) "Options"))
+ (let* ((option-column 2)
+ (option-padding 2)
+ (doc-column (+ option-column option-width option-padding))
+ (doc-width (- width doc-column)))
+ (dolist (option (options group))
+ (print-option-help stream option option-column doc-column doc-width)))))
(let* ((examples (examples interface))
(example-column 2)
(example-width (- width example-column)))