- 1 The fanion ASDF System
- 2 Introduction
- 3 Installing
- 4 Examples
- 5 API reference
- 6 Current issues
- 7 Similar libraries
- 8 Acknowledgments
- Version: 0.1.0
- Description: Exiguous command-line option parser.
- Licence: MIT (Expat)
- Author: Paul A. Patience
- Mailto: [email protected]
- Homepage: https://git.sr.ht/~paulapatience/fanion
- Source control: GIT
Fanion is a Common Lisp library for parsing command-line options. It parses them in the same way as OpenBSD getopt(3), but additionally supports long options, though currently with limitations (see Current issues). In particular, short options may take optional arguments, and options and non-option arguments cannot be mixed. This makes parsing subcommands and their arguments trivial with the existing API.
This library is intentionally spartan in its functionality.
It can parse options and nothing else; it cannot parse non-option
arguments or subcommands, because the comparative ease with which they
can be manually parsed, e.g., via pattern matching or even
DESTRUCTURING-BIND
, makes further complexifying the API unjustified,
especially when considering the myriad ways non-option arguments can be
arranged.
Also, Fanion does not automatically generate usage or help messages, operating under the assumption that there will always be someone (usually me) unhappy with the formatting. Furthermore, I believe that a good help message, just like a good manual page, is best manually written.
However, Fanion's option parsing should be flexible enough to cater to
many use-cases thanks to its option-value reduction (see the REDUCE
argument to FANION:MAKE-OPTION
), which is modeled after
Adopt's.
Fanion is currently under active development and its API is unstable, but it follows Semantic Versioning so breaking changes will be indicated by an appropriate bump in version number.
Why yet another command-line option parsing library, when there are already twenty? (See Similar libraries.) I first started with unix-opts, then migrated to clingon when I saw that it handled subcommands and seemed well-designed, but I was unhappy with the automatic formatting of their help messages and also that they allow options to follow non-option arguments, like GNU getopt_long(3). The catalyst for my decision to write my own library was that I found no way to make clingon options take optional arguments.
The name Fanion comes from the French term for flag in this context.
Fanion is not available on Quicklisp, so you will need to clone it to a location known to ASDF or Quicklisp:
git clone https://git.sr.ht/~paulapatience/fanion
Fanion has no dependencies beyond ASDF/UIOP. It is developed on SBCL, but should be compatible with any conventional Common Lisp implementation.
The Common Lisp files located in Fanion's scripts
directory are good
examples of Fanion being used in practice.
The following is an extract of scripts/build-documentation.lisp
:
(defparameter +options+
(list
(fanion:make-option 'format #\f nil
:value #'parse-format)
(fanion:make-option 'help nil "help")
(fanion:make-option 'output #\o nil
:value #'parse-output
:initial-value uiop:*stdout*)))
(fanion:parse +options+ (uiop:command-line-arguments))
See FANION:MAKE-OPTION
for further examples of its capabilities.
PARSE
is the main entrypoint to the library.
It takes a list of OPTION
s and the command-line arguments to be parsed,
and returns as multiple values a hashtable of parsed options and the
remaining non-option arguments.
Options are parsed in the same way as OpenBSD getopt(3),
except that long options — though currently only boolean long options —
are also supported.
Short options start with one hyphen (-a
), long options with
two (--abc
).
Multiple short options may be joined or separate (-ab -a -b
); their
arguments may be joined or separate (-c1 -c 2
); and they may take
optional arguments, though these if provided must be joined (-d -d1
).
Option parsing ends upon reaching the end of the argument list, the
argument ‘-
’, an argument not starting with ‘-
’, or the argument
‘--
’, which is dropped.
In particular, options and non-option arguments cannot be mixed.
-
[function] PARSE OPTIONS ARGUMENTS
Parse command-line
ARGUMENTS
according toOPTIONS
. Return as multiple values the parsed options as a hashtable whose keys are the options' names, and the list of remaining non-option arguments.OPTIONS
must be a list ofOPTION
s,ARGUMENTS
a list of strings. The list of remaining non-option arguments may share structure withARGUMENTS
.
-
[function] MAKE-OPTION NAME SHORT LONG &KEY (VALUE NIL VALUE-P) OPTIONAL-VALUE INITIAL-VALUE REDUCE FINALLY
Make an
OPTION
namedNAME
identified by at least one ofSHORT
andLONG
.SHORT
may not be#\-
, andLONG
may not contain#\=
.If
VALUE
is non-NIL
, the option takes an argument; ifVALUE
is a function, it is called with the option's argument to produce the option's value. IfOPTIONAL-VALUE
is non-NIL
, the option takes an optional argument.The option's value is initially set to
INITIAL-VALUE
, and each time the option appears in the argument list,REDUCE
is called with, and its result replaces, the option's current value. If the option takes an argument, it is passed asREDUCE
's second argument. The value of boolean options and missing optional arguments isT
. When the options are exhausted,FINALLY
is called with, and its result replaces, the option's value.If
REDUCE
andVALUE
areNIL
,REDUCE
is initialized to(CONSTANTLY T)
. IfREDUCE
isNIL
andVALUE
is not,REDUCE
is initialized to a function which returns its second argument. IfFINALLY
isNIL
, it is initialized toIDENTITY
.Some examples of conventional option styles follow:
(make-option 'verbose #\v nil) ; Boolean short option (make-option 'help nil "help") ; Boolean long option (make-option 'output #\o nil ; Pathname option :value #'uiop:parse-native-namestring :initial-value uiop:*stdout*) (make-option 'formats #\f nil ; List option (in order) :value t :reduce (lambda (a b) (cons b a)) :finally #'nreverse)
-
[class] OPTION STRUCTURE-OBJECT
Command-line option.
This type is exported only for use in type declarations. Its internal representation may change at any time.
Long options are supported, but only as booleans. This will be corrected.
Also, no dedicated FANION-ERROR
class exists for such errors as
unrecognized options and missing arguments.
An error class hierarchy may be added in the future.
In alphabetical order:
-
Adopt with optional Adopt Subcommands
Other lists:
Fanion's option-value reduction, consisting of the VALUE
, REDUCE
and FINALLY
arguments to FANION:MAKE-OPTION
, is modeled after
Adopt's, though in Adopt VALUE
is named KEY
and REDUCE
is
required.