unix-options (C) 2009 Andrew Stine

This software is distributed under the terms of the Lisp Lesser GNU 
Public License (http://opensource.franz.com/preamble.html), also 
known as the LLGPL. 

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.

----------------------------------------------------------------------

Unix-options is a small Common Lisp library for parsing unix-style 
command line options. 

This library is very new and not widely tested so suggestions, 
bug-reports and patches (including changes to this document) are
welcome.

Please send any feedback to illuminati (at) beggersandbuskers dot com

----------------------------------------------------------------------
Usage:
 
The library can be loaded through ASDF and used through the package 
'unix-options.'

Exported symbols are:

=| cli-options      - variable
=| &parameters        - symbol
=| &free              - symbol
=| free               - symbol
=| map-parsed-options - function
=| getopt             - function
=| with-cli-options   - macro

An example of usage:

(with-cli-options ()
    (print &parameters in-file out-file)
  (if print
    (with-open-file (in :direction :input)
      (with-open-file (out :direction :output)
        (while (peek-char in)
          (write-char (read-char in) out))))))

$ sample-program -p -i input.txt -o output.txt
=> write input.txt to output.txt

---------------------------------------------------------------------
API:

getopt - An imitation of the Unix 'getopt' command line program

    prototype: (getopt cli-options shortopts longopts)

    details: Getopt accepts three arguments: a list of tokens passed
             in on the CLI, a string detailing available short-form
             options and a list detailing long-form options. Getopt
             breaks the tokens up and sorts them so that they can be
             handled by the calling program more easily.
 
             Cli-options can be any list of strings. Each string
             begging with a single '-' is interpreted as a series of
             short options and any beginning with '--' is interpreted
             as a long option. Others are either free tokens or
             parameters. Any tokens appearing after a token that is
             soley a '--', are interpreted as free tokens.

             Shortopts takes the form: "abf:" where each letter is the
             name of a permissable short option and a ':' following a
             letter signifies that it takes a parameter.

             Longopts takes the form: '("option1" "file=") where each
             string is the name of a long option and a '=' signifies
             that the option takes a parameter.

    example: (getopt '("-ab" "--file" "file.txt" "free")
                     "ab"
                     '("file="))
             => '("a" "b" "file" "file.txt" "--" "free")
             

with-cli-options - A macro that binds values passed in from the command
                   line to local variables

    prototype:  (with-cli-options (&optional (cli-options '(cli-options))
                                             enable-usage-summary)
                                  option-variables &body body)
                                  
    details: With-cli-options takes a list of symbols and attempts to
             bind values passed in on the command line to them according
             to a set of rules. For every symbol named in 
             option-variables, with-cli-options creates a variable to 
             which it binds any long option of the same name. 
             With-cli-options also take the first letter of any symbol
             and bind short options of that letter to that symbol. If
             multiple symbols begin with the same letter, only the first
             in option-variables is bound the short option of the same
             letter; the second is bound to the uppercase version and any
             more must use a long option.
             
             Optionally, each entry in option-variables can be a short
             list the first item being the symbol to be used and the
             second a doc-string for the value to be bound to it.

             In addition, symbols in option-variables are boolean by 
             default; that is, they bound to either t or nil depending on
             whether they are passed in on the cli. Symbols listed after
             &parameters, if it is present, are are considered parameter
             options, that is, they are bound to the next token on the cli
             if the are long options or the same or the rest of the
             current short option group, if they are short options. If
             nothing is passed for this options (ie. if it is the last
             token) it is bound to nil.
             
             Any tokens that aren't options or parameters to options are
             saved into a list of free tokens. This list is bound to 'free'
             unless a different symbol is provided in option-variables
             after &free.
             
             If enable-usage-summary is set, then with-cli-options will be
             able to print out a usage summary (using print-usage-summary)
             based on the options bound in option-varibles. The summary
             will be printed either when an invalid option is specified or
             the user uses '-h' or '--help' as an option. If
             enable-usage-summary is set to a string, that string is passed
             as control string to print-usage-summary. Else, a generic
             string is used.

   example: (with-cli-options ('("-pi" "in" "--out-file" "out" "another"))
                (print &parameters in-file out-file)
              (print print)
              (print in-file)
              (print out-file)
              (print free))
            T
            "in"
            "out"
            ("another")
            => NIL
            
cli-options - returns the list of whitespace separated tokens passed
                on the command line.
                
print-usage-summary - Prints a usage description of the current program

    prototype: (print-usage-summary description option-specs)

    details: Print-usage-summary print a usage summary of options specified
             by options-specs. Each member of the list option-specs is a
             list of specs of the following form:
            
             (short-option(s) long-options(s) parameter description)

             The first item in the list is a string containing all chacters
             used as short options for a specified option. The second item
             is either a string or list of strings each containing the name
             of a possible longform of the same option. The third item is a
             boolean specifying whether an option takes a parameter. It can
             be a string arbitrarily specifying some detail of the 
             parameter. The final item is a description of the option.

             The function takes each option-spec and generates a string
             describing in detail each option. The resulting strings are
             passed as arguments to a call to format. Description is used
             as the control string.

    example: (print-usage-summary "Usage:~%~@{~A~%~}~%end summary"
                                  '(("a" "alpha" nil "A simple option")
                                    ("f" "file" "FILENAME" "A filename")
                                    ("bd" "beta" nil "Another option")))
             Usage:
               -a, --alpha          A simple option
               -f, --file=FILENAME  A filename
               -b, -d, --beta       Another option

             end summary
             =>NIL

map-parsed-options - Function that does the actual parsing of cli tokens

    prototype: (map-parsed-options cli-options bool-options param-options
                                   opt-val-func free-val-func)

    details: Map-parsed-options is the backend function that does most
             of the actual work in parsing cli functions. It is exposed
             to allow more front ends in addition to getopt and
             with-cli-options. Map-parsed-options receives a list of cli
             tokens, as well as two list of options, boolean options and
             options with parameters, respectively. The final two
             arguments are functions, one to handle found options and
             there values, and one to handle free tokens.

    example: (map-parsed-options '("-ab" "value" "free") '("a") '("b")
                                 (lambda (option value)
                                    (format t "option: ~A; value: ~A~%"
                                            option value))
                                 (lambda (free-val)
                                    (format t "free: ~A~%" free-val)))
             option: a; value T
             option: b; value value 
             free: free
             => NIL
