9918f80ae953

adopt: Update site.
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Wed, 17 Apr 2019 10:30:37 -0400
parents c084d84024d0
children c1430240aec7
branches/tags (none)
files adopt/index.html adopt/reference/index.html adopt/usage/index.html

Changes

--- a/adopt/index.html	Thu Mar 07 12:47:45 2019 -0500
+++ b/adopt/index.html	Wed Apr 17 10:30:37 2019 -0400
@@ -12,18 +12,25 @@
         <div class="wrap">
             <header><h1><a href="">Adopt</a></h1></header>
                 <div class="markdown">
-<p>I needed <strong>A</strong> <strong>D</strong>amn <strong>OPT</strong>ion parsing library.</p>
-<p>Adopt is a simple (~150 LOC) UNIX-style option parser in Common Lisp.
-It depends on <a href="https://github.com/sjl/bobbin">Bobbin</a> and <a href="https://www.cliki.net/split-sequence">split-sequence</a>.</p>
-<p>It aims to be simple and powerful enough for the majority of use cases.</p>
+<p>I needed <strong>a</strong> <strong>d</strong>amn <strong>opt</strong>ion parsing library.</p>
+<p>Adopt is a simple UNIX-style option parser in Common Lisp, heavily influenced by
+Python's optparse and argparse.</p>
 <ul>
 <li><strong>License:</strong> MIT</li>
 <li><strong>Documentation:</strong> <a href="https://sjl.bitbucket.io/adopt/">https://sjl.bitbucket.io/adopt/</a></li>
 <li><strong>Mercurial:</strong> <a href="https://bitbucket.org/sjl/adopt/">https://bitbucket.org/sjl/adopt/</a></li>
 <li><strong>Git:</strong> <a href="https://github.com/sjl/adopt/">https://github.com/sjl/adopt/</a></li>
 </ul>
+<p>Adopt aims to be a simple, robust option parser.  It can automatically print
+help information and even generate <code>man</code> pages for you.</p>
 <p>The test suite currently passes in SBCL, CCL, ECL, and ABCL on Ubuntu.  Further
-testing is welcome.</p><h2>Table of Contents</h2><ol class="toc"><li><a href="installation/">Installation</a></li><li><a href="usage/">Usage</a></li><li><a href="reference/"> API Reference</a></li><li><a href="changelog/">Changelog</a></li></ol>
+testing is welcome.</p>
+<p>Adopt is compatible with Quicklisp, but not <em>in</em> Quicklisp (yet).  You can clone
+the repository into your <a href="https://www.quicklisp.org/beta/faq.html#local-project">Quicklisp local-projects directory</a> for now.</p>
+<p>The <code>adopt</code> system contains the core API and depends on <a href="https://github.com/sjl/bobbin">Bobbin</a> and
+<a href="https://www.cliki.net/split-sequence">split-sequence</a>.</p>
+<p>The <code>adopt/test</code> 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.</p><h2>Table of Contents</h2><ol class="toc"><li><a href="usage/">Usage</a></li><li><a href="reference/"> API Reference</a></li><li><a href="changelog/">Changelog</a></li></ol>
                 </div>
             <footer><p><i>Made with Lisp and love by <a href="http://stevelosh.com/">Steve Losh</a>.</i></p>
 <p><a href="http://rochestermade.com" title="Rochester Made"><img src="http://rochestermade.com/media/images/rochester-made-dark-on-light.png" alt="Rochester Made" title="Rochester Made" /></a></p>
--- a/adopt/reference/index.html	Thu Mar 07 12:47:45 2019 -0500
+++ b/adopt/reference/index.html	Wed Apr 17 10:30:37 2019 -0400
@@ -20,26 +20,32 @@
 <div class="toc">
 <ul>
 <li><a href="#package-adopt">Package ADOPT</a><ul>
-<li><a href="#append1-function">APPEND1 (function)</a></li>
 <li><a href="#argv-function">ARGV (function)</a></li>
-<li><a href="#define-interface-macro">DEFINE-INTERFACE (macro)</a></li>
-<li><a href="#latest-function">LATEST (function)</a></li>
+<li><a href="#collect-function">COLLECT (function)</a></li>
+<li><a href="#define-string-macro">DEFINE-STRING (macro)</a></li>
+<li><a href="#discard-option-function">DISCARD-OPTION (function)</a></li>
+<li><a href="#exit-function">EXIT (function)</a></li>
+<li><a href="#first-function">FIRST (function)</a></li>
+<li><a href="#flip-function">FLIP (function)</a></li>
+<li><a href="#last-function">LAST (function)</a></li>
+<li><a href="#make-group-function">MAKE-GROUP (function)</a></li>
+<li><a href="#make-interface-function">MAKE-INTERFACE (function)</a></li>
+<li><a href="#make-option-function">MAKE-OPTION (function)</a></li>
 <li><a href="#parse-options-function">PARSE-OPTIONS (function)</a></li>
-<li><a href="#print-usage-function">PRINT-USAGE (function)</a></li>
+<li><a href="#print-error-and-exit-function">PRINT-ERROR-AND-EXIT (function)</a></li>
+<li><a href="#print-help-function">PRINT-HELP (function)</a></li>
+<li><a href="#print-help-and-exit-function">PRINT-HELP-AND-EXIT (function)</a></li>
+<li><a href="#print-manual-function">PRINT-MANUAL (function)</a></li>
+<li><a href="#supply-new-value-function">SUPPLY-NEW-VALUE (function)</a></li>
+<li><a href="#treat-as-argument-function">TREAT-AS-ARGUMENT (function)</a></li>
+<li><a href="#unrecognized-option-class">UNRECOGNIZED-OPTION (class)</a><ul>
+<li><a href="#slot-problematic-option">Slot PROBLEMATIC-OPTION</a></li>
+</ul>
+</li>
 </ul>
 </li>
 </ul></div>
 <h2 id="package-adopt">Package <code>ADOPT</code></h2>
-<h3 id="append1-function"><code>APPEND1</code> (function)</h3>
-<div class="codehilite"><pre><span/>(APPEND1 LIST EL)
-</pre></div>
-
-
-<p>Append element <code>el</code> to the end of <code>list</code>.</p>
-<p>This is implemented as <code>(append list (list el))</code>.  It is not particularly
-  fast.</p>
-<p>It is useful as a <code>:reduce</code> function when you want to collect all values given
-  for an option.</p>
 <h3 id="argv-function"><code>ARGV</code> (function)</h3>
 <div class="codehilite"><pre><span/>(ARGV)
 </pre></div>
@@ -47,23 +53,92 @@
 
 <p>Return a list of the program name and command line arguments.</p>
 <p>This is not implemented for every Common Lisp implementation.  You can always
-  pass your own values to <code>parse-options</code> and <code>print-usage</code> if it's not
+  pass your own values to <code>parse-options</code> and <code>print-help</code> if it's not
   implemented for your particular Lisp.</p>
-<h3 id="define-interface-macro"><code>DEFINE-INTERFACE</code> (macro)</h3>
-<div class="codehilite"><pre><span/>(DEFINE-INTERFACE NAME USAGE &amp;amp;REST OPTIONS)
+<h3 id="collect-function"><code>COLLECT</code> (function)</h3>
+<div class="codehilite"><pre><span/>(COLLECT LIST EL)
+</pre></div>
+
+
+<p>Append element <code>el</code> to the end of <code>list</code>.</p>
+<p>It is useful as a <code>:reduce</code> function when you want to collect all values given
+  for an option.</p>
+<p>This is implemented as <code>(append list (list el))</code>.  It is not particularly
+  fast.  If you can live with reversed output consider <code>(flip #'cons)</code>  instead.</p>
+<h3 id="define-string-macro"><code>DEFINE-STRING</code> (macro)</h3>
+<div class="codehilite"><pre><span/>(DEFINE-STRING VAR STRING &amp;REST ARGS)
+</pre></div>
+
+
+<p>Convenience macro for <code>(defparameter ,var (format nil ,string ,@args))</code>.</p>
+<h3 id="discard-option-function"><code>DISCARD-OPTION</code> (function)</h3>
+<div class="codehilite"><pre><span/>(DISCARD-OPTION CONDITION)
+</pre></div>
+
+
+<p>Invoke the <code>discard-option</code> restart properly.</p>
+<p>Example:</p>
+<div class="codehilite"><pre><span/>(handler-bind ((unrecognized-option 'discard-option))
+  (multiple-value-bind (arguments options) (parse-options *ui*)
+    (run arguments options)))
 </pre></div>
 
 
-<h3 id="latest-function"><code>LATEST</code> (function)</h3>
-<div class="codehilite"><pre><span/>(LATEST OLD NEW)
+<h3 id="exit-function"><code>EXIT</code> (function)</h3>
+<div class="codehilite"><pre><span/>(EXIT &amp;OPTIONAL (CODE 0))
+</pre></div>
+
+
+<h3 id="first-function"><code>FIRST</code> (function)</h3>
+<div class="codehilite"><pre><span/>(FIRST OLD NEW)
+</pre></div>
+
+
+<p>Return <code>new</code> if <code>old</code> is <code>nil</code>, otherwise return <code>old</code>.</p>
+<p>It is useful as a <code>:reduce</code> function when you want to just keep the
+  first-given value for an option.</p>
+<h3 id="flip-function"><code>FLIP</code> (function)</h3>
+<div class="codehilite"><pre><span/>(FLIP FUNCTION)
+</pre></div>
+
+
+<p>Return a function of two arguments X and Y that calls <code>function</code> with Y and X.</p>
+<p>Useful for wrapping existing functions that expect their arguments in the
+  opposite order.</p>
+<p>Examples:</p>
+<div class="codehilite"><pre><span/>(funcall #'cons 1 2)        ; =&gt; (1 . 2)
+(funcall (flip #'cons) 1 2) ; =&gt; (2 . 1)
+(reduce (flip #'cons) '(1 2 3) :initial-value nil)
+; =&gt; (3 2 1)
+</pre></div>
+
+
+<h3 id="last-function"><code>LAST</code> (function)</h3>
+<div class="codehilite"><pre><span/>(LAST OLD NEW)
 </pre></div>
 
 
 <p>Return <code>new</code>.</p>
 <p>It is useful as a <code>:reduce</code> function when you want to just keep the last-given
   value for an option.</p>
+<h3 id="make-group-function"><code>MAKE-GROUP</code> (function)</h3>
+<div class="codehilite"><pre><span/>(MAKE-GROUP NAME &amp;KEY TITLE HELP MANUAL OPTIONS)
+</pre></div>
+
+
+<h3 id="make-interface-function"><code>MAKE-INTERFACE</code> (function)</h3>
+<div class="codehilite"><pre><span/>(MAKE-INTERFACE &amp;KEY NAME SUMMARY USAGE HELP MANUAL EXAMPLES CONTENTS)
+</pre></div>
+
+
+<h3 id="make-option-function"><code>MAKE-OPTION</code> (function)</h3>
+<div class="codehilite"><pre><span/>(MAKE-OPTION NAME &amp;KEY LONG SHORT HELP MANUAL PARAMETER REDUCE (RESULT-KEY NAME)
+             (INITIAL-VALUE NIL INITIAL-VALUE?) (KEY #'IDENTITY) (FINALLY #'IDENTITY))
+</pre></div>
+
+
 <h3 id="parse-options-function"><code>PARSE-OPTIONS</code> (function)</h3>
-<div class="codehilite"><pre><span/>(PARSE-OPTIONS INTERFACE &amp;amp;OPTIONAL (ARGUMENTS (REST (ARGV))))
+<div class="codehilite"><pre><span/>(PARSE-OPTIONS INTERFACE &amp;OPTIONAL (ARGUMENTS (REST (ARGV))))
 </pre></div>
 
 
@@ -72,29 +147,49 @@
 <ol>
 <li>A fresh list of top-level, unaccounted-for arguments that don't correspond
      to any options defined in <code>interface</code>.</li>
-<li>An <code>EQL</code> hash map of option <code>name</code>s to values.</li>
+<li>An <code>EQL</code> hash table of option keys to values.</li>
 </ol>
-<p>See the full usage documentation for more information.</p>
-<h3 id="print-usage-function"><code>PRINT-USAGE</code> (function)</h3>
-<div class="codehilite"><pre><span/>(PRINT-USAGE INTERFACE &amp;amp;KEY (STREAM *STANDARD-OUTPUT*) (PROGRAM-NAME (FIRST (ARGV))) (WIDTH 80) (OPTION-WIDTH 20))
+<p>See the full documentation for more information.</p>
+<h3 id="print-error-and-exit-function"><code>PRINT-ERROR-AND-EXIT</code> (function)</h3>
+<div class="codehilite"><pre><span/>(PRINT-ERROR-AND-EXIT ERROR &amp;KEY (STREAM *ERROR-OUTPUT*) (EXIT-CODE 1) (PREFIX error: ))
 </pre></div>
 
 
-<p>Print a pretty usage document for <code>interface</code> to <code>stream</code>.</p>
+<p>Print <code>prefix</code> and <code>error</code> to <code>stream</code> and exit.</p>
+<p>Example:</p>
+<div class="codehilite"><pre><span/>(handler-case
+    (multiple-value-bind (arguments options) (parse-options *ui*)
+      (run arguments options))
+  (unrecognized-option (c)
+    (print-error-and-exit c)))
+</pre></div>
+
+
+<h3 id="print-help-function"><code>PRINT-HELP</code> (function)</h3>
+<div class="codehilite"><pre><span/>(PRINT-HELP INTERFACE &amp;KEY (STREAM *STANDARD-OUTPUT*) (PROGRAM-NAME (CAR (ARGV))) (WIDTH 80)
+            (OPTION-WIDTH 20) (INCLUDE-EXAMPLES T))
+</pre></div>
+
+
+<p>Print a pretty help document for <code>interface</code> to <code>stream</code>.</p>
 <p><code>width</code> 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.</p>
 <p><code>option-width</code> 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.</p>
-<p>The result will look something like (assuming a usage string of
-  <code>"[options] FILES"</code>):</p>
-<div class="codehilite"><pre><span/>(print-usage *program-interface* :width 60 :option-width 15)
-; =&amp;gt;
+  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.</p>
+<p>The result will look something like:</p>
+<div class="codehilite"><pre><span/>(print-help *program-interface* :width 60 :option-width 15)
+; =&gt;
+; 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.
@@ -107,6 +202,62 @@
 ;   0.........1.... option-width
 ; 0........1.........2.........3.........4.........5.........6
 </pre></div>
+
+
+<h3 id="print-help-and-exit-function"><code>PRINT-HELP-AND-EXIT</code> (function)</h3>
+<div class="codehilite"><pre><span/>(PRINT-HELP-AND-EXIT INTERFACE &amp;KEY (STREAM *STANDARD-OUTPUT*) (PROGRAM-NAME (CAR (ARGV)))
+                     (WIDTH 80) (OPTION-WIDTH 20) (INCLUDE-EXAMPLES T) (EXIT-CODE 0))
+</pre></div>
+
+
+<p>Print a pretty help document for <code>interface</code> to <code>stream</code> and exit.</p>
+<p>Handy for easily providing --help:</p>
+<div class="codehilite"><pre><span/>(multiple-value-bind (arguments options) (parse-options *ui*)
+  (when (gethash 'help options)
+    (print-help-and-exit *ui*))
+  (run arguments options))
+</pre></div>
+
+
+<h3 id="print-manual-function"><code>PRINT-MANUAL</code> (function)</h3>
+<div class="codehilite"><pre><span/>(PRINT-MANUAL INTERFACE &amp;KEY (STREAM *STANDARD-OUTPUT*) (MANUAL-SECTION 1))
+</pre></div>
+
+
+<h3 id="supply-new-value-function"><code>SUPPLY-NEW-VALUE</code> (function)</h3>
+<div class="codehilite"><pre><span/>(SUPPLY-NEW-VALUE CONDITION VALUE)
+</pre></div>
+
+
+<p>Invoke the <code>supply-new-value</code> restart properly.</p>
+<p>Example:</p>
+<div class="codehilite"><pre><span/>(handler-bind
+    ((unrecognized-option (alexandria:rcurry 'supply-new-value "--foo"))
+  (multiple-value-bind (arguments options) (parse-options *ui*)
+    (run arguments options)))
+</pre></div>
+
+
+<h3 id="treat-as-argument-function"><code>TREAT-AS-ARGUMENT</code> (function)</h3>
+<div class="codehilite"><pre><span/>(TREAT-AS-ARGUMENT CONDITION)
+</pre></div>
+
+
+<p>Invoke the <code>treat-as-argument</code> restart properly.</p>
+<p>Example:</p>
+<div class="codehilite"><pre><span/>(handler-bind ((unrecognized-option 'treat-as-argument))
+  (multiple-value-bind (arguments options) (parse-options *ui*)
+    (run arguments options)))
+</pre></div>
+
+
+<h3 id="unrecognized-option-class"><code>UNRECOGNIZED-OPTION</code> (class)</h3>
+<h4 id="slot-problematic-option">Slot <code>PROBLEMATIC-OPTION</code></h4>
+<ul>
+<li>Allocation: <code>:INSTANCE</code></li>
+<li>Initarg: <code>:PROBLEMATIC-OPTION</code></li>
+<li>Accessor: <code>PROBLEMATIC-OPTION</code></li>
+</ul>
                 </div>
             <footer><p><i>Made with Lisp and love by <a href="http://stevelosh.com/">Steve Losh</a>.</i></p>
 <p><a href="http://rochestermade.com" title="Rochester Made"><img src="http://rochestermade.com/media/images/rochester-made-dark-on-light.png" alt="Rochester Made" title="Rochester Made"/></a></p>
--- a/adopt/usage/index.html	Thu Mar 07 12:47:45 2019 -0500
+++ b/adopt/usage/index.html	Wed Apr 17 10:30:37 2019 -0400
@@ -17,40 +17,310 @@
 <div class="toc">
 <ul>
 <li><a href="#package">Package</a></li>
-<li><a href="#interfaces">Interfaces</a></li>
-<li><a href="#parsing">Parsing</a></li>
+<li><a href="#interfaces">Interfaces</a><ul>
+<li><a href="#creating-an-interface">Creating an Interface</a></li>
+<li><a href="#line-wrapping">Line Wrapping</a></li>
+<li><a href="#examples">Examples</a></li>
+</ul>
+</li>
+<li><a href="#exiting">Exiting</a></li>
 <li><a href="#options">Options</a></li>
-<li><a href="#short-and-long-options">Short and Long Options</a></li>
-<li><a href="#initial-value">Initial Value</a></li>
-<li><a href="#reduce">Reduce</a></li>
-<li><a href="#usage-printing">Usage Printing</a></li>
+<li><a href="#parsing">Parsing</a></li>
+<li><a href="#top-level-structure">Top-Level Structure</a></li>
+<li><a href="#computing-values-with-reduce">Computing Values with Reduce</a></li>
 </ul></div>
 <h2 id="package">Package</h2>
-<p>All core Adopt functions and macros are in the <code>adopt</code> package.  You can <code>:use</code>
-that if you really want to, but it's probably clearer to use namespaced
-<code>adopt:…</code> symbols.</p>
+<p>All core Adopt functions are in the <code>adopt</code> package.  Several of the symbols in
+adopt shadow those in the <code>common-lisp</code> package, so you should probably use
+namespaced <code>adopt:…</code> symbols instead of <code>USE</code>ing the package.</p>
 <h2 id="interfaces">Interfaces</h2>
-<p>define-interface and usage.  nothing else.</p>
-<h2 id="parsing">Parsing</h2>
-<p><code>parse-options</code> with a bare-bones interface.</p>
+<p>To get started with Adopt, you should create an interface with the
+<code>adopt:make-interface</code> function.  This returns an object representing the
+command line interface presented to your users.</p>
+<h3 id="creating-an-interface">Creating an Interface</h3>
+<p>Let's say you're developing a program to search the contents of files (because
+the world certainly needs <em>another</em> <code>grep</code> replacement).  You might start with
+something like:</p>
+<div class="codehilite"><pre><span/>(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."))
+</pre></div>
+
+
+<p>You can now print some help text for your CLI with <code>adopt:print-help</code>:</p>
+<div class="codehilite"><pre><span/>(adopt:print-help *ui*)
+; =&gt;
+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.
+</pre></div>
+
+
+<h3 id="line-wrapping">Line Wrapping</h3>
+<p>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 <code>adopt:make-interface</code> is just a function — you can use <code>format</code> (possibly
+with its <code>~Newline</code> directive) to preprocess the help text argument:</p>
+<div class="codehilite"><pre><span/>(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.")))
+</pre></div>
+
+
+<p>Adopt's line-wrapping library [Bobbin][] will only ever <em>add</em> 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:</p>
+<div class="codehilite"><pre><span/>(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.")))
+</pre></div>
+
+
+<p>If you want to control the width of the help text lines when they are printed,
+<code>adopt:print-help</code> takes a <code>:width</code> argument:</p>
+<div class="codehilite"><pre><span/>(adopt:print-help *ui* :width 50)
+; =&gt;
+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.
+</pre></div>
+
+
+<p><code>adopt:print-help</code> takes a number of other options — see the API Reference for
+more information.</p>
+<h3 id="examples">Examples</h3>
+<p>Describing the CLI in detail is helpful, but users can often learn a lot more by
+seeing a few examples of its usage.  <code>adopt:make-interface</code> can take an
+<code>:examples</code> argument, which should be an alist of <code>(description . example)</code>
+conses:</p>
+<div class="codehilite"><pre><span/>(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)
+; =&gt;
+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 -
+</pre></div>
+
+
+<p>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 <em>you</em> in certain places).</p>
+<h2 id="exiting">Exiting</h2>
+<p>Adopt provides some helpful utility functions to exit out of your program with
+a UNIX exit code.  These do what you think they do:</p>
+<div class="codehilite"><pre><span/>(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)))
+</pre></div>
+
+
+<p>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.</p>
 <h2 id="options">Options</h2>
-<p>talk about the option arguments.</p>
-<h2 id="short-and-long-options">Short and Long Options</h2>
-<p>short versus long arguments.  1+ is required.</p>
-<h2 id="initial-value">Initial Value</h2>
-<p>at this point it's just a default</p>
-<h2 id="reduce">Reduce</h2>
-<p>talk about reducers. mention argparse's:</p>
-<p><code>store_const</code> is <code>(constantly x)</code></p>
-<p><code>store</code> is <code>#'latest</code></p>
-<p><code>store_true</code> is <code>(constantly t)</code></p>
-<p><code>store_false</code> is <code>(constantly nil)</code></p>
-<p><code>append</code> is <code>append1</code></p>
-<p><code>append_const</code> is <code>(rcurry #'append1 x)</code></p>
-<p><code>count</code> is <code>1+</code> with an <code>initial-value</code> of <code>0</code>.</p>
-<p>need to figure out <code>help</code> and <code>version</code>.</p>
-<h2 id="usage-printing">Usage Printing</h2>
-<p>It's <code>(print-usage interface)</code>.</p>
+<p>Now that you know how to create an interface, you can create some options to use
+inside it with <code>adopt:make-option</code>:</p>
+<div class="codehilite"><pre><span/>(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*)))
+</pre></div>
+
+
+<p>Adopt will automatically add the options to the help text:</p>
+<div class="codehilite"><pre><span/>(adopt:print-help *ui*)
+; =&gt;
+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
+</pre></div>
+
+
+<p>The first argument to <code>adopt:make-option</code> is the name of the option, which we'll
+see put to use shortly.  At least one of <code>:short</code> and <code>:long</code> is required, and
+<code>:help</code> text must be specified.  We'll talk more about <code>:reduce</code> in a bit, but
+it too is required.</p>
+<p>I prefer to define each option as its own global variable to keep the call to
+<code>adopt:make-interface</code> from getting too large and unwieldy, but feel free to do
+something like this if you prefer to avoid cluttering your package:</p>
+<div class="codehilite"><pre><span/>(defparameter *ui*
+  (adopt:make-interface
+    …
+    :contents
+    (list (adopt:make-option 'foo …)
+          (adopt:make-option 'bar …)
+          …)))
+</pre></div>
+
+
+<h2 id="parsing">Parsing</h2>
+<p>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:</p>
+<div class="codehilite"><pre><span/>(adopt:parse-options *ui* '("foo.*" "--literal" "a.txt" "b.txt"))
+; =&gt;
+("foo.*" "a.txt" "b.txt")
+#&lt;HASH-TABLE :TEST EQL :COUNT 3 {10103142A3}&gt;
+</pre></div>
+
+
+<p><code>adopt:parse-options</code> returns two values: a list of non-option arguments, and
+a hash table of the option values.</p>
+<p>The keys of the hash table are (by default) the option names given as the first
+argument to <code>adopt:make-option</code>.  We'll see how the option values are determined
+soon.</p>
+<p>From now on I'll use a special pretty printer for hash tables to make it easier
+to see what's inside them:</p>
+<div class="codehilite"><pre><span/>(adopt:parse-options *ui* '("foo.*" "--literal" "a.txt" "b.txt"))
+; =&gt;
+("foo.*" "a.txt" "b.txt")
+{LITERAL: T, VERSION: NIL, HELP: NIL}
+</pre></div>
+
+
+<h2 id="top-level-structure">Top-Level Structure</h2>
+<p>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:</p>
+<div class="codehilite"><pre><span/>(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)
+</pre></div>
+
+
+<p>The <code>toplevel</code> function first uses a <code>handler-case</code> to trap all <code>error</code>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.</p>
+<p>Next we use <code>adopt:parse-options</code> to parse the command line arguments and
+options.  We do some initial checks to see if the user wants <code>--help</code> or
+<code>--version</code> information.  If not, we destructure the arguments into the items we
+expect and call a <code>run</code> function with all the information it needs to do its
+job.</p>
+<p>If the <code>destructuring-bind</code> fails an error will be signaled, and the
+<code>handler-case</code> will print it and exit.  If you want to be a nice person you
+could check that the <code>arguments</code> have the correct shape first, and return
+a friendlier error message to your users if they don't.</p>
+<h2 id="computing-values-with-reduce">Computing Values with Reduce</h2>
                 </div>
             <footer><p><i>Made with Lisp and love by <a href="http://stevelosh.com/">Steve Losh</a>.</i></p>
 <p><a href="http://rochestermade.com" title="Rochester Made"><img src="http://rochestermade.com/media/images/rochester-made-dark-on-light.png" alt="Rochester Made" title="Rochester Made"/></a></p>