1 Introduction

-*- outline -*-
* Copyright (C) 2010, 2011, 2015 Didier Verna
This file is part of Clon.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved.
* Introduction
In the Lisp family of languages, one of the key components is the so-called
REPL, the Read-Eval-Print Loop, which blends the runtime, compilation and
development phases together, allowing for a very high level of interaction
with the program. The importance of this paradigm explains why it is still
rare to find "standalone" applications written in Lisp: most Lisp application
clients are lispers themselves, and they prefer to live in the REPL.
On the other hand, many contemporary Common Lisp compilers provide ways of
creating standalone Common Lisp programs, using either shebang technology or
by directly dumping executables. This process is getting easier to achieve
every day. For instance, with SBCL, all it takes is one function call
(save-lisp-and-die) and one command-line option to the compiler (--script).
The (big) size of a Lisp image has been considered a showstopper in creating
standalone applications for a long time, but nowadays, it doesn't really
matter anymore (if you are not convinced, just figure out the average size of
an application bundle under Mac OS X). This, along with the fact that Common
Lisp compilers can generate very efficient code today, makes the perspective
of standalone Common Lisp applications very tempting again.
When it comes to preserving interaction with the user, one of the key
components in a standalone application is the handling of the command-line.
Clon is a library designed to do just that.
* Overview
Clon provides traditional features one might expect from a command-line
options management library, but what makes it somewhat unique in its
conception is that it has been designed with both the application developer
and the application user in mind: many aspects of the command-line management
usually imposed by the program are in fact under the control of the
application user. The idea is that all Clon-enabled applications behave in a
uniform way, and that it is the user who gets to decide, not the developper.
The most important features of Clon are listed below.
** Command-Line Syntax
Clon imposes a particular yet flexible syntax for the command-line. Options
have short and/or long names, beginning with either one or two dashes. Options
may take an argument. In that case, the argument may be optional or mandatory.
Option names may be abbreviated and one-character options may be grouped
together in a single call. There is an additional call syntax for Boolean or
Boolean-based options. Finally, the command-line may have a "postfix", that
is, a non-option part.
** Option Types
Clon comes with a set of predefined option types, including "flags" (option
without arguments), "switches" (Boolean options), simple Lisp objects, simple
strings, enumerations, pathnames etc. Clon is also extensible: it is possible
to define new option types, either from scratch or by subclassing an existing
one.
** Value Retrieval
The traditional approach to command-line analysis is to process it
sequentially, and Clon lets you do that. However, Clon also provides an
explicit retrieval mechanism by which you can directly request the value of a
specific option, regardless of its position, or even its presence on the
command-line. An option's value can be retrieved from different sources: a
command-line argument, a "fallback" value (for optional arguments), a default
value or an environment variable associated with the option. The retrieval
process is completely automated, hence removing this burden from the
developer's shoulders.
** Error Management
Another cumbersome task already taken care of is error management. Clon
provides two built-in error management schemes, in case something is wrong on
the command-line. The simplest one is to quit the application with an
informative error message. The other one is to enter an interactive dialog
with the user, in which it is possible to fix the problem (correct a typo,
discard an option call, provide a missing argument or value etc.). A unique
feature of Clon is that the application user may choose his or her preferred
error management scheme.
** Help String Contents
The "help string" is typically what you expect from the output of a --help
option. Maintaining an up-to-date help string is a very boring task, so Clon
completely automates this for you (another burden removed from the developer's
shoulders). However, the application programmer still has control over the
help string's contents, notably the order in which options are displayed, and
also by having the possibility of grouping options together and inserting
arbitrary text in the output.
** Help String Format
Clon also completely automates the help string typesetting process. For
instance, it can automatically format the output for 80 columns, but it is
also aware of the tty geometry and will use it when appropriate. Clon also
supports help string "fontification" (or "highlighting") through ISO/IEC 6429
SGR escape sequences on tty's that support it. Another unique feature of Clon
is that the exact format and highlight specification for the help string is
under the control of the application user, via the notion of "theme". Clon
comes with a set of predefined themes (for instance, standard, with heavy
fontification, refcard for quick reference etc.) and application users can
define their own. As a matter of fact, a theme not only controls the format
and highlight of the help string, but also its contents.

2.1 net.didierverna.clon

Clon is a library for command-line option management.
It is intended to ease the creation of standalone Common Lisp applications by
providing a powerful and uniform command-line option interface.
The most important features of Clon are the following.
- [from the programmer’s point of view] Centralized command-line options
specification and management, including automatic generation of help
strings, conversion from command-line / environment strings to
application-level option values, global or on-demand option retrieval, and
extensibility (the programmer can define his own option types).
- [from the end-user’s point of view] Uniform command-line option syntax
across Clon applications, customization of the help strings layout
(with optional ISO6429 coloring on terminals that support it),
possibly abbreviated option calls and short/long syntax.

2.2 net.didierverna.clon.termio

Clon is a library for command-line option management.
The termio feature provides ISO6429 coloring on terminals that support it.
For a more complete description of Clon, see the net.didierverna.clon system.

6.1.2 Macros

Macro: defgroup(&rest KEYS &key HEADER HIDDEN) &body FORMS

Define a new group.
KEYS are initargs to MAKE-GROUP (currently, only :header).
Each form in FORMS will be treated as a new :item.
The CAR of each form is the name of the operation to perform: TEXT, GROUP, or
an option class name. The rest are the arguments to the MAKE-<OP> function or
the DEFGROUP macro.

Dump a standalone executable named NAME starting with FUNCTION.
ARGS may be any arguments understood by the underlying implementation’s
dumping facility. They will simply be passed along. Note that DUMP already
passes some such arguments. Some of them are critical for the dumping facility
(e.g. :executable) and cannot be overridden. Some others, however, will be if
you provide them as well (e.g. :load-init-file).

Since executable dumping is not available in all supported implementations,
this function behaves differently in some cases, as described below.

- ECL doesn’t create executables by dumping a Lisp image, but relies on having
toplevel code to execute instead, so this macro simply expands to a call to
FUNCTION. This also means that ARGS is unused.
- ABCL can’t dump executables at all because of the underlying Java
implementation, so this macro expands to just (PROGN) but creates a Java
class file with a main function that creates an interpreter, loads
the file in which this macro call appears and calls FUNCTION. This also
means that ARGS is unused.

6.1.3 Functions

Function: cmdline()

Get the current application’s command-line.
This command-line is not supposed to contain any Lisp implementation specific
option; only user-level ones. When a standalone executable is dumped, this is
always the case. When used interactively, this depends on the underlying Lisp
implementation. See appendix A.5 of the user manual for more information.

Get the next command-line option in CONTEXT.
When there is no next command-line option, return nil.
Otherwise, return four values:
- the option object,
- the option’s name used on the command-line,
- the retrieved value,
- the value source.

Make a new context.
- SYNOPSIS is the program synopsis to use in that context.
It defaults to *SYNOPSIS*.
- CMDLINE is the argument list (strings) to process.
It defaults to a POSIX conformant argv.
- If MAKE-CURRENT, make the new context current.

Make a new enum option.
- SHORT-NAME is the option’s short name (without the dash).
It defaults to nil.
- LONG-NAME is the option’s long name (without the double-dash).
It defaults to nil.
- DESCRIPTION is the option’s description appearing in help strings.
It defaults to nil.
- ARGUMENT-NAME is the option’s argument name appearing in help strings.
- ARGUMENT-TYPE is one of :required, :mandatory or :optional (:required and
:mandatory are synonyms).
It defaults to :optional.
- ENUM is the set of possible values.
- ENV-VAR is the option’s associated environment variable.
It defaults to nil.
- FALLBACK-VALUE is the option’s fallback value (for missing optional
arguments), if any.
- DEFAULT-VALUE is the option’s default value, if any.
- When HIDDEN, the option doesn’t appear in help strings.

Make a new flag.
- SHORT-NAME is the option’s short name (without the dash).
It defaults to nil.
- LONG-NAME is the option’s long name (without the double-dash).
It defaults to nil.
- DESCRIPTION is the option’s description appearing in help strings.
It defaults to nil.
- ENV-VAR is the flag’s associated environment variable.
It defaults to nil.
- When HIDDEN, the option doesn’t appear in help strings.

Make a new lispobj option.
- SHORT-NAME is the option’s short name (without the dash).
It defaults to nil.
- LONG-NAME is the option’s long name (without the double-dash).
It defaults to nil.
- DESCRIPTION is the option’s description appearing in help strings.
It defaults to nil.
- ARGUMENT-NAME is the option’s argument name appearing in help strings.
- ARGUMENT-TYPE is one of :required, :mandatory or :optional (:required and
:mandatory are synonyms).
It defaults to :optional.
- ENV-VAR is the option’s associated environment variable.
It defaults to nil.
- TYPESPEC is a type specifier the option’s value should satisfy.
- FALLBACK-VALUE is the option’s fallback value (for missing optional
arguments), if any.
- DEFAULT-VALUE is the option’s default value, if any.
- When HIDDEN, the option doesn’t appear in help strings.

Make a new path option.
- SHORT-NAME is the option’s short name (without the dash).
It defaults to nil.
- LONG-NAME is the option’s long name (without the double-dash).
It defaults to nil.
- DESCRIPTION is the option’s description appearing in help strings.
It defaults to nil.
- ARGUMENT-NAME is the option’s argument name appearing in help strings.
- ARGUMENT-TYPE is one of :required, :mandatory or :optional (:required and
:mandatory are synonyms).
It defaults to :optional.
- ENV-VAR is the option’s associated environment variable.
It defaults to nil.
- FALLBACK-VALUE is the option’s fallback value (for missing optional
arguments), if any.
- DEFAULT-VALUE is the option’s default value, if any.
- TYPE is the pathname type. It can be one of :file, :directory, :file-list,
:directory-list or nil meaning that everything is allowed.
- When HIDDEN, the option doesn’t appear in help strings.

Make a new string option.
- SHORT-NAME is the option’s short name (without the dash).
It defaults to nil.
- LONG-NAME is the option’s long name (without the double-dash).
It defaults to nil.
- DESCRIPTION is the option’s description appearing in help strings.
It defaults to nil.
- ARGUMENT-NAME is the option’s argument name appearing in help strings.
- ARGUMENT-TYPE is one of :required, :mandatory or :optional (:required and
:mandatory are synonyms).
It defaults to :optional.
- ENV-VAR is the option’s associated environment variable.
It defaults to nil.
- FALLBACK-VALUE is the option’s fallback value (for missing optional
arguments), if any.
- DEFAULT-VALUE is the option’s default value, if any.
- When HIDDEN, the option doesn’t appear in help strings.

Make a new switch.
- SHORT-NAME is the switch’s short name (without the dash).
It defaults to nil.
- LONG-NAME is the switch’s long name (without the double-dash).
It defaults to nil.
- DESCRIPTION is the switch’s description appearing in help strings.
It defaults to nil.
- ARGUMENT-STYLE is the switch’s argument display style. It can be one of
:yes/no, :on/off, :true/false, :yup/nope or :yeah/nah.
It defaults to :yes/no.
- ARGUMENT-TYPE is one of :required, :mandatory or :optional (:required and
:mandatory are synonyms).
It defaults to :optional.
- ENV-VAR is the switch’s associated environment variable.
It defaults to nil.
- DEFAULT-VALUE is the switch’s default value, if any.
- When HIDDEN, the option doesn’t appear in help strings.

Make a new xswitch.
- SHORT-NAME is the xswitch’s short name (without the dash).
It defaults to nil.
- LONG-NAME is the xswitch’s long name (without the double-dash).
It defaults to nil.
- DESCRIPTION is the xswitch’s description appearing in help strings.
It defaults to nil.
- ARGUMENT-NAME is the option’s argument name appearing in help strings.
- ARGUMENT-TYPE is one of :required, :mandatory or :optional (:required and
:mandatory are synonyms).
It defaults to :optional.
- ENUM is the set of possible non-boolean values.
- ENV-VAR is the xswitch’s associated environment variable.
It defaults to nil.
- DEFAULT-VALUE is the xswitch’s default value, if any.
- When HIDDEN, the option doesn’t appear in help strings.

6.2.2 Macros

Accumulate BODY forms in a list beginning with INITIAL-VALUE.
INITIAL-VALUE is not evaluated. BODY forms are accumulated only when their
value is non-nil.
If nothing to accumulate, then return nil instead of the list of
INITIAL-VALUE.

Restartably throw an invalid-negated-syntax error.
The error relates to the command-line use of OPTION.
BODY constitutes the body of the only restart available,
use-short-call, and should act as if OPTION had been normally called by short
name.

Restartably throw a spurious-cmdline-argument error.
The error relates to the command-line use of OPTION called by NAME with
ARGUMENT.
BODY constitutes the body of the only restart available, discard-argument, and
should act as if ARGUMENT had not been provided.

Set SYMBOL’s indentation to INDENT in (X)Emacs.
This function sets SYMBOL’s common-lisp-indent-function property.
If INDENT is a symbol, use its indentation definition.
Otherwise, INDENT is considered as an indentation definition.

Convert CMDLINE-ARGUMENT to VALUED-OPTION’s value.
This function is used when the conversion comes from a command-line usage of
VALUED-OPTION, called by CMDLINE-NAME, and intercepts invalid-argument errors
to raise the higher level invalid-cmdline-argument error instead.

Convert ENV-VAL to VALUED-OPTION’s value.
This function is used when the conversion comes from an environment variable
associated with VALUED-OPTION, and intercepts invalid-argument errors
to raise the higher level invalid-environment-value error instead.

Make a new internal (Clon-specific) enum option.
- LONG-NAME is the option’s long-name, sans the ’clon-’ prefix.
(Internal options don’t have short names.)
- DESCRIPTION is the options’s description.
- ARGUMENT-NAME is the option’s argument name appearing in help strings.
- ARGUMENT-TYPE is one of :required, :mandatory or :optional (:required and
:mandatory are synonyms).
It defaults to :optional.
- ENUM is the set of possible values.
- ENV-VAR is the option’s associated environment variable, sans the ’CLON_’
prefix. It defaults to nil.
- FALLBACK-VALUE is the option’s fallback value (for missing optional
arguments), if any.
- DEFAULT-VALUE is the option’s default value, if any.
- When HIDDEN, the option doesn’t appear in help strings.

Make a new internal (Clon-specific) flag.
- LONG-NAME is the flag’s long-name, sans the ’clon-’ prefix.
(Internal options don’t have short names.)
- DESCRIPTION is the flag’s description.
- ENV-VAR is the flag’s associated environment variable, sans the ’CLON_’
prefix. It default to nil.
- When HIDDEN, the option doesn’t appear in help strings.

Make a new internal (Clon-specific) string option.
- LONG-NAME is the option’s long-name, sans the ’clon-’ prefix.
(Internal options don’t have short names.)
- DESCRIPTION is the options’s description.
- ARGUMENT-NAME is the option’s argument name appearing in help strings.
- ARGUMENT-TYPE is one of :required, :mandatory or :optional (:required and
:mandatory are synonyms).
It defaults to :optional.
- ENV-VAR is the option’s associated environment variable, sans the ’CLON_’
prefix. It defaults to nil.
- TYPESPEC is a type specifier the option’s value should satisfy.
- FALLBACK-VALUE is the option’s fallback value (for missing optional
arguments), if any.
- DEFAULT-VALUE is the option’s default value, if any.
- When HIDDEN, the option doesn’t appear in help strings.

Make a new internal (Clon-specific) path option.
- LONG-NAME is the option’s long-name, sans the ’clon-’ prefix.
(Internal options don’t have short names.)
- DESCRIPTION is the options’s description.
- ARGUMENT-NAME is the option’s argument name appearing in help strings.
- ARGUMENT-TYPE is one of :required, :mandatory or :optional (:required and
:mandatory are synonyms).
It defaults to :optional.
- ENV-VAR is the option’s associated environment variable, sans the ’CLON_’
prefix. It defaults to nil.
- FALLBACK-VALUE is the option’s fallback value (for missing optional
arguments), if any.
- DEFAULT-VALUE is the option’s default value, if any.
- TYPE is the pathname type. It can be one of :file, :directory, :file-list,
:directory-list or nil meaning that everything is allowed.
- When HIDDEN, the option doesn’t appear in help strings.

Make a new internal (Clon-specific) string option.
- LONG-NAME is the option’s long-name, sans the ’clon-’ prefix.
(Internal options don’t have short names.)
- DESCRIPTION is the options’s description.
- ARGUMENT-NAME is the option’s argument name appearing in help strings.
- ARGUMENT-TYPE is one of :required, :mandatory or :optional (:required and
:mandatory are synonyms).
It defaults to :optional.
- ENV-VAR is the option’s associated environment variable, sans the ’CLON_’
prefix. It defaults to nil.
- FALLBACK-VALUE is the option’s fallback value (for missing optional
arguments), if any.
- DEFAULT-VALUE is the option’s default value, if any.
- When HIDDEN, the option doesn’t appear in help strings.

Make a new internal (Clon-specific) switch.
- LONG-NAME is the switch’s long-name, sans the ’clon-’ prefix.
(Internal options don’t have short names.)
- DESCRIPTION is the switch’s description.
- ARGUMENT-STYLE is the switch’s argument display style. It can be one of
:yes/no, :on/off, :true/false, :yup/nope or :yeah/nah.
It defaults to :yes/no.
- ARGUMENT-TYPE is one of :required, :mandatory or :optional (:required and
:mandatory are synonyms).
It defaults to :optional.
- ENV-VAR is the switch’s associated environment variable, sans the ’CLON_’
prefix. It defaults to nil.
- DEFAULT-VALUE is the switch’s default value, if any.
- When HIDDEN, the option doesn’t appear in help strings.

Make a new internal (Clon-specific) xswitch.
- LONG-NAME is the xswitch’s long-name, sans the ’clon-’ prefix.
(Internal options don’t have short names.)
- DESCRIPTION is the xswitch’s description.
- ARGUMENT-NAME is the option’s argument name appearing in help strings.
- ARGUMENT-TYPE is one of :required, :mandatory or :optional (:required and
:mandatory are synonyms).
It defaults to :optional.
- ENUM is the set of possible non-boolean values.
- ENV-VAR is the xswitch’s associated environment variable, sans the ’CLON_’
prefix. It defaults to nil.
- DEFAULT-VALUE is the xswitch’s default value, if any.
- When HIDDEN, the option doesn’t appear in help strings.

Return FACE’s parent generation for PARENT-NAME.
That is, 1 if PARENT-NAME names FACE’s parent, 2 if it names its grand-parent
etc. If PARENT-NAME does not name one of FACE’s ancestors, trigger an error.

Princ CHAR on SHEET’s stream and increment the column position.
The effect of printing CHAR must be exactly to move right by one column, so
control characters, as well as newlines and tabs are forbidden here.

Princ STRING on SHEET’s stream and update the column position.
The effect of printing STRING must be exactly to move right by the
corresponding string length, so control characters, as well as newlines and
tabs are forbidden here.

Return a new property list from KEYS with REPLACEMENT.
REPLACEMENT can take the following forms:
- :KEY
The effect is to remove :KEY from KEYS, as per REMOVE-KEYS.
- (:KEY :NEW-KEY)
The effect is to replace :KEY with :NEW-KEY, leaving the values unchanged.
- (:KEY :NEW-KEY (VAL-OR-VALS NEW-VAL)*), with VAL-OR-VALS being
either a value or a list of values. The effect is to replace :KEY with
:NEW-KEY and a value matching one of the VAL-OR-VALS with the
corresponding NEW-VAL. Values not matching any VAL-OR-VALS remain unchanged.
- (:KEY (VAL-OR-VALS :NEW-KEY NEW-VAL...)*), with VAL-OR-VALS as above. The
effect is the same as above, but :NEW-KEY additionally depends on the
matched value. If multiple :NEW-KEY NEW-VAL couples are provided, that many
new keys are inserted along with their values. For values not matching any
VAL-OR-VALS, :KEY and its value remain unchanged.

Search for a branch of faces named NAMES starting at FACE.
The branch is searched for as a direct subbranch of FACE, or as a direct
subbranch of FACE’s ancestors.
If a branch is found, return its leaf face. Otherwise return nil.

Search for a face named NAME starting at FACE.
The face is looked for as a direct subface of FACE (in which case it is simply
returned), or up in the hierarchy and by successive upper branches (in which
case it is copied and attached to FACE).
If ERROR-ME, trigger an error if no face is found; otherwise, return nil.

Search for an option in CONTEXT.
The search is done with SHORT-NAME, LONG-NAME, or PARTIAL-NAME.
In case of a PARTIAL-NAME search, look for an option the long name of which
begins with it.
In case of multiple matches by PARTIAL-NAME, the longest match is selected.
When such an option exists, return wo values:
- the option itself,
- the name used to find the option, possibly completed if partial.

Search for a sticky option in CONTEXT, matching NAMEARG.
NAMEARG is the concatenation of the option’s short name and its argument.
In case of multiple matches, the option with the longest name is selected.
When such an option exists, return two values:
- the option itself,
- the argument part of NAMEARG.

The face bottom padding.
This property can take the following forms:
- nil: the next output can start right at the end of this face’s,
- 0: the next output should start on the next line,
- N>0: there should be N empty lines before the next output.

The face left padding.
This property can take the following forms:
- <NUMBER>: the padding is relative to the enclosing face,
- SELF: the padding is set to wherever the face happens to be opened,
- (<NUMBER> ABSOLUTE): the padding is set in absolute value,
- (<NUMBER> :RELATIVE-TO <FACE-NAME>): the padding is set relatively to a
parent face named FACE-NAME.

Retrieve OPTION’s value from a long call.
CMDLINE-NAME is the name used on the command-line.
CMDLINE-ARGUMENT is a potentially already parsed cmdline argument.
Otherwise, CMDLINE is where to find an argument.
This function returns three values:
- the retrieved value,
- the value source,
- the new command-line (possibly with the first item popped if the option
requires an argument).

Retrieve OPTION’s value from a short call.
CMDLINE-ARGUMENT is a potentially already parsed cmdline argument.
Otherwise, CMDLINE is where to find an argument.
This function returns three values:
- the retrieved value,
- the value source,
- the new command-line (possibly with the first item popped if the option
requires an argument).

The face right padding.
This property can take the following forms:
- <NUMBER>: the padding is relative to the enclosing face,
- SELF: the padding is set to wherever the face happens to be closed,
- (<NUMBER> ABSOLUTE): the padding is set in absolute value,
- (<NUMBER> :RELATIVE-TO <FACE-NAME>): the padding is set relatively to a
parent face named FACE-NAME.

The face top padding.
This property can take the following forms:
- nil: the output can start right away,
- 0: the output should start on the next line,
- N>0: there should be N empty lines before the output.

The face left padding.
This property can take the following forms:
- <NUMBER>: the padding is relative to the enclosing face,
- SELF: the padding is set to wherever the face happens to be opened,
- (<NUMBER> ABSOLUTE): the padding is set in absolute value,
- (<NUMBER> :RELATIVE-TO <FACE-NAME>): the padding is set relatively to a
parent face named FACE-NAME.

The face right padding.
This property can take the following forms:
- <NUMBER>: the padding is relative to the enclosing face,
- SELF: the padding is set to wherever the face happens to be closed,
- (<NUMBER> ABSOLUTE): the padding is set in absolute value,
- (<NUMBER> :RELATIVE-TO <FACE-NAME>): the padding is set relatively to a
parent face named FACE-NAME.

The face top padding.
This property can take the following forms:
- nil: the output can start right away,
- 0: the output should start on the next line,
- N>0: there should be N empty lines before the output.

The face bottom padding.
This property can take the following forms:
- nil: the next output can start right at the end of this face’s,
- 0: the next output should start on the next line,
- N>0: there should be N empty lines before the next output.