# HG changeset patch # User Steve Losh # Date 1542863033 18000 # Node ID 152830fa3f854f60a46ce00b1843e8356fa7bf29 # Parent 845fc8785d54b088b019eb212f8a0743e85bcadf Start the docs diff -r 845fc8785d54 -r 152830fa3f85 Makefile --- a/Makefile Wed Nov 21 23:22:18 2018 -0500 +++ b/Makefile Thu Nov 22 00:03:53 2018 -0500 @@ -1,6 +1,9 @@ -.PHONY: test test-sbcl test-ccl test-ecl test-abcl +.PHONY: test test-sbcl test-ccl test-ecl test-abcl pubdocs heading_printer = $(shell which heading || echo 'true') +sourcefiles = $(shell ffind --full-path --literal .lisp) +docfiles = $(shell ls docs/*.markdown) +apidocs = $(shell ls docs/*reference*.markdown) # Testing --------------------------------------------------------------------- test: test-sbcl test-ccl test-ecl test-abcl @@ -20,3 +23,18 @@ test-abcl: $(heading_printer) broadway 'ABCL' abcl --load test/run.lisp + +# Documentation --------------------------------------------------------------- +$(apidocs): $(sourcefiles) + sbcl --noinform --load docs/api.lisp --eval '(quit)' + +docs/build/index.html: $(docfiles) $(apidocs) docs/title + cd docs && ~/.virtualenvs/d/bin/d + +docs: docs/build/index.html + +pubdocs: docs + hg -R ~/src/sjl.bitbucket.org pull -u + rsync --delete -a ./docs/build/ ~/src/sjl.bitbucket.org/adopt + hg -R ~/src/sjl.bitbucket.org commit -Am 'adopt: Update site.' + hg -R ~/src/sjl.bitbucket.org push diff -r 845fc8785d54 -r 152830fa3f85 README.markdown --- a/README.markdown Wed Nov 21 23:22:18 2018 -0500 +++ b/README.markdown Thu Nov 22 00:03:53 2018 -0500 @@ -1,15 +1,18 @@ Adopt ===== -I need **A** **D**amn **OPT**ion parsing library. - +I needed **A** **D**amn **OPT**ion parsing library. -Adopt is a simple (~200 LOC) UNIX-style option parser in Common Lisp. -It depends on `bobbin` and `split-sequence`. +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. +The test suite currently passes in SBCL, CCL, ECL, and ABCL on Debian. Further +testing is welcome. * **License:** MIT * **Documentation:** * **Mercurial:** * **Git:** + +[Bobbin]: https://github.com/sjl/bobbin +[split-sequence]: https://www.cliki.net/split-sequence diff -r 845fc8785d54 -r 152830fa3f85 docs/01-installation.markdown --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/01-installation.markdown Thu Nov 22 00:03:53 2018 -0500 @@ -0,0 +1,17 @@ +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 diff -r 845fc8785d54 -r 152830fa3f85 docs/02-usage.markdown --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/02-usage.markdown Thu Nov 22 00:03:53 2018 -0500 @@ -0,0 +1,56 @@ +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. You can `:use` that if you +really want to, but it's probably clearer to use namespaced `adopt:…` symbols. + +Example +------- + + (define-interface *my-program* "[options] FILES" + (verbosity + "Output extra information." + :short #\v + :long "verbose" + :initial-value 0 + :reduce (constantly 1)) + (verbosity + "Shut up." + :short #\q + :long "quiet" + :reduce (constantly -1)) + (ignore + "Ignore FILE. May be specified multiple times." + :long "ignore" + :parameter "FILE" + :reduce #'append1) + (name + "Your name. May be specified many times, last one wins." + :short #\n + :long "name" + :parameter "NAME" + :reduce #'latest) + (meows + "Meow." + :short #\m + :long "meow" + :initial-value 0 + :reduce #'1+)) + + (pprint + (multiple-value-list + (parse-options *my-program* + '("-vqn" "steve" + "--meow" + "-m" "--meow" "foo" + "--name=sjl" "more" + "--" "--ignore" "bar" + )))) diff -r 845fc8785d54 -r 152830fa3f85 docs/03-reference.markdown --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/03-reference.markdown Thu Nov 22 00:03:53 2018 -0500 @@ -0,0 +1,108 @@ +# 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 + + + diff -r 845fc8785d54 -r 152830fa3f85 docs/04-changelog.markdown --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/04-changelog.markdown Thu Nov 22 00:03:53 2018 -0500 @@ -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. diff -r 845fc8785d54 -r 152830fa3f85 docs/api.lisp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/api.lisp Thu Nov 22 00:03:53 2018 -0500 @@ -0,0 +1,20 @@ +(ql:quickload "cl-d-api") + +(defparameter *header* + "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. + +") + +(d-api:generate-documentation + :adopt + #p"docs/03-reference.markdown" + (list "ADOPT") + *header* + :title "API Reference") + diff -r 845fc8785d54 -r 152830fa3f85 docs/footer.markdown --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/footer.markdown Thu Nov 22 00:03:53 2018 -0500 @@ -0,0 +1,14 @@ +Made with Lisp and love by [Steve Losh][] in Rochester, New York. + +[Steve Losh]: http://stevelosh.com/ + + diff -r 845fc8785d54 -r 152830fa3f85 docs/index.markdown --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/index.markdown Thu Nov 22 00:03:53 2018 -0500 @@ -0,0 +1,17 @@ +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. + +* **License:** MIT +* **Documentation:** +* **Mercurial:** +* **Git:** + +The test suite currently passes in SBCL, CCL, ECL, and ABCL on Debian. Further +testing is welcome. + +[Bobbin]: https://github.com/sjl/bobbin +[split-sequence]: https://www.cliki.net/split-sequence diff -r 845fc8785d54 -r 152830fa3f85 docs/title --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/title Thu Nov 22 00:03:53 2018 -0500 @@ -0,0 +1,1 @@ +Adopt diff -r 845fc8785d54 -r 152830fa3f85 package.lisp --- a/package.lisp Wed Nov 21 23:22:18 2018 -0500 +++ b/package.lisp Thu Nov 22 00:03:53 2018 -0500 @@ -1,3 +1,12 @@ (defpackage :adopt (:use :cl) - (:export :parse-options :print-usage :define-interface)) + (:export + :parse-options + :print-usage + :define-interface + + :argv + + :latest + :append1 + )) diff -r 845fc8785d54 -r 152830fa3f85 src/main.lisp --- a/src/main.lisp Wed Nov 21 23:22:18 2018 -0500 +++ b/src/main.lisp Thu Nov 22 00:03:53 2018 -0500 @@ -2,13 +2,36 @@ ;;;; Utils -------------------------------------------------------------------- (defun 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. + + " (append list (list el))) (defun 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. + + " (declare (ignore old)) new) + (defun 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. + + " #+sbcl sb-ext:*posix-argv* #+ccl ccl:*unprocessed-command-line-arguments* #-(or sbcl ccl) (error "ARGV is not supported on this implementation.")) @@ -126,6 +149,17 @@ (defun 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. + + " (let ((toplevel nil) (results (make-hash-table))) (dolist (option (options interface)) @@ -212,20 +246,19 @@ (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.........10... option-width - 0........10........20........30........40........50........60 width + ; 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 " (assert (> width (+ 2 option-width 2)) (width option-width) @@ -238,45 +271,3 @@ (doc-width (- width doc-column))) (dolist (option (options interface)) (print-option-usage stream option option-column doc-column doc-width)))) - - -;;;; Scratch ------------------------------------------------------------------ -(define-interface *my-program* "[options] FILES" - (verbosity - "Output extra information." - :short #\v - :long "verbose" - :initial-value 0 - :reduce (constantly 1)) - (verbosity - "Shut up." - :short #\q - :long "quiet" - :reduce (constantly -1)) - (ignore - "Ignore FILE. May be specified multiple times." - :long "ignore" - :parameter "FILE" - :reduce #'append1) - (name - "Your name. May be specified many times, last one wins." - :short #\n - :long "name" - :parameter "NAME" - :reduce #'latest) - (meows - "Meow." - :short #\m - :long "meow" - :initial-value 0 - :reduce #'1+)) - -(pprint - (multiple-value-list - (parse-options *my-program* - '("-vqn" "steve" - "--meow" - "-m" "--meow" "foo" - "--name=sjl" "more" - "--" "--ignore" "bar" - ))))