The clingon Reference Manual

Table of Contents

Next: , Previous: , Up: (dir)   [Contents][Index]

The clingon Reference Manual

This is the clingon Reference Manual, version 0.3.5, generated automatically by Declt version 3.0 "Montgomery Scott" on Sun May 15 04:24:50 2022 GMT+0.


Next: , Previous: , Up: Top   [Contents][Index]

1 Introduction

* clingon

=clingon= is a command-line options parser system for Common Lisp.

A summary of the features supported by =clingon= is provided below.

- Native support for sub-commands
- Support for command aliases
- Short and long option names support
- Related options may be grouped into categories
- Short options may be collapsed as a single argument, e.g. =-xyz=
- Long options support both notations - =--long-opt arg= and
  =--long-opt=arg=.
- Automatic generation of help/usage information for commands and
  sub-commands
- Out of the box support for =--version= and =--help= flags
- Support for various kinds of options like /string/, /integer/,
  /boolean/, /switches/, /enums/, /list/, /counter/, /filepath/, etc.
- Sub-commands can lookup global options and flags defined in parent
  commands
- Support for options, which may be required
- Options can be initialized via environment variables
- Single interface for creating options using =CLINGON:MAKE-OPTION=
- Generate documentation for your command-line app
- Support for =pre-hook= and =post-hook= actions for commands, which
  allows invoking functions before and after the respective handler of
  the command is executed
- Support for Bash and Zsh shell completions
- =clingon= is extensible, so if you don't find something you need you
  can extend it by developing a new option kind, or even new mechanism
  for initializing options, e.g. by looking up an external key/value
  store.

Scroll to the demo section in order to see some examples of =clingon=
in action.

Other Common Lisp option parser systems, which you might consider
checking out.

- [[https://github.com/libre-man/unix-opts][unix-opts]]
- [[https://github.com/sjl/adopt/][adopt]]
- [[https://github.com/didierverna/clon][clon]]

* Quick Example

Here's a really quick example of a simple CLI application, which
greets people.

#+begin_src lisp
(in-package :cl-user)
(defpackage :clingon.example.greet
  (:use :cl)
  (:import-from :clingon)
  (:export
   :main))
(in-package :clingon.example.greet)

(defun greet/options ()
  "Returns the options for the `greet' command"
  (list
   (clingon:make-option
    :string
    :description "Person to greet"
    :short-name #\u
    :long-name "user"
    :initial-value "stranger"
    :env-vars '("USER")
    :key :user)))

(defun greet/handler (cmd)
  "Handler for the `greet' command"
  (let ((who (clingon:getopt cmd :user)))
    (format t "Hello, ~A!~%" who)))

(defun greet/command ()
  "A command to greet someone"
  (clingon:make-command
   :name "greet"
   :description "greets people"
   :version "0.1.0"
   :authors '("John Doe  (ql:register-local-projects)
#+end_src

** Building the Demo App

You can build the demo app using SBCL with the following command.

#+begin_src shell
LISP=sbcl make demo
#+end_src

Build the demo app using Clozure CL:

#+begin_src shell
LISP=ccl make demo
#+end_src

In order to build the demo app using ECL you need to follow these
instructions, which are ECL-specific. See [[https://common-lisp.net/project/ecl/static/manual/System-building.html#Compiling-with-ASDF][Compiling with ASDF from the
ECL manual]] for more details. First, load the =:clingon.demo= system.

#+begin_src lisp
(ql:quickload :clingon.demo)
#+end_src

And now build the binary with ECL:

#+begin_src lisp
(asdf:make-build :clingon.demo
                 :type :program
                 :move-here #P"./"
                 :epilogue-code '(clingon.demo:main))
#+end_src

This will create a new executable =clingon-demo=, which you can now
execute.

Optionally, you can also enable the bash completions support.

#+begin_src shell
APP=clingon-demo source extras/completions.bash
#+end_src

In order to activate the Zsh completions, install the completions
script in your =~/.zsh-completions= directory (or anywhere else you
prefer) and update your =~/.zshrc= file, so that the completions are
loaded.

Make sure that you have these lines in your =~/.zshrc= file.

#+begin_src shell
  fpath=(~/.zsh-completions $fpath)
  autoload -U compinit
  compinit
#+end_src

The following command will generate the Zsh completions script.

#+begin_src shell
  ./clingon-demo zsh-completion > ~/.zsh-completions/_clingon-demo
#+end_src

Use the =--help= flag to see some usage information about the demo
application.

#+begin_src shell
./clingon-demo --help
#+end_src

* Requirements

- [[https://www.quicklisp.org/beta/][Quicklisp]]

* Installation

The =clingon= system is not yet part of Quicklisp, so for now
you need to install it in your local Quicklisp projects.

Clone the repo in your [[https://www.quicklisp.org/beta/faq.html][Quicklisp local-projects]] directory.

#+begin_src lisp
(ql:register-local-projects)
#+end_src

Then load the system.

#+begin_src lisp
(ql:quickload :clingon)
#+end_src

* Step By Step Guide

In this section we will implement a simple CLI application, and
explain at each step what and why we do the things we do.

Once you are done with it, you should have a pretty good understanding
of the =clingon= system and be able to further extend the sample
application on your own.

We will be developing the application interactively and in the
REPL. Finally we will create an ASDF system for our CLI app, so we can
build it and ship it.

The code we develop as part of this section will reside in a file
named =intro.lisp=. Anything we write will be sent to the Lisp REPL, so
we can compile it and get quick feedback about the things we've done
so far.

You can find the complete code we'll develop in this section in the
=clingon/examples/intro= directory.

** Start the REPL

Start up your REPL session and let's load the =clingon= system.

#+begin_src lisp
CL-USER> (ql:quickload :clingon)
To load "clingon":
  Load 1 ASDF system:
    clingon
; Loading "clingon"

(:CLINGON)
#+end_src

** Create a new package

First, we will define a new package for our application and switch to
it.

#+begin_src lisp
(in-package :cl-user)
(defpackage :clingon.intro
  (:use :cl)
  (:import-from :clingon)
  (:export :main))
(in-package :clingon.intro)
#+end_src

We have our package, so now we can proceed to the next section and
create our first command.

** Creating a new command

The first thing we'll do is to create a new command. Commands are
created using the =CLINGON:MAKE-COMMAND= function.

Each command has a name, description, any options that
the command accepts, any sub-commands the command knows about, etc.

The command in =clingon= is represented by the =CLINGON:COMMAND=
class, which contains many other slots as well, which you can lookup.

#+begin_src lisp
(defun top-level/command ()
  "Creates and returns the top-level command"
  (clingon:make-command
   :name "clingon-intro"
   :description "my first clingon cli app"
   :version "0.1.0"
   :license "BSD 2-Clause"
   :authors '("John Doe ")))
#+end_src

This is how our simple command looks like. For now it doesn't do much,
and in fact it won't execute anything, but we will fix that as we go.

What is important to note, is that we are using a convention here
to make things easier to understand and organize our code base.

Functions that return new commands will be named =/command=.  A
similar approach is taken when we define options for a given command,
e.g. =/options= and for sub-commands we use
=/sub-commands=. Handlers will use the =/handler=
notation.

This makes things easier later on, when we introduce new sub-commands,
and when we need to wire things up we can refer to our commands using
the established naming convention. Of course, it's up to you to decide
which approach to take, so feel free to adjust the layout of the code
to your personal preferences. In this guide we will use the afore
mentioned approach.

Commands can be linked together in order to form a tree of commands
and sub-commands. We will talk about that one in more details in the
later sections of this guide.

** Adding options

Next, we will add a couple of options. Similar to the previous section
we will define a new function, which simply returns a list of valid
options. Defining it in the following way would make it easier to
re-use these options later on, in case you have another command, which
uses the exact same set of options.

=clingon= exposes a single interface for creating options via the
=CLINGON:MAKE-OPTION= generic function. This unified interface will
allow developers to create and ship new option kinds, and still have
their users leverage a common interface for the options via the
=CLINGON:MAKE-OPTION= interface.

#+begin_src lisp
(defun top-level/options ()
  "Creates and returns the options for the top-level command"
  (list
   (clingon:make-option
    :counter
    :description "verbosity level"
    :short-name #\v
    :long-name "verbose"
    :key :verbose)
   (clingon:make-option
    :string
    :description "user to greet"
    :short-name #\u
    :long-name "user"
    :initial-value "stranger"
    :env-vars '("USER")
    :key :user)))
#+end_src

Let's break things down a bit and explain what we just did.

We've defined two options -- one of =:COUNTER= kind and another one,
which is of =:STRING= kind. Each option specifies a short and long
name, along with a description of what the option is meant for.

Another important thing we did is to specify a =:KEY= for our options.
This is the key which we will later use in order to get the value
associated with our option, when we use =CLINGON:GETOPT=.

And we have also defined that our =--user= option can be initialized
via environment variables. We can specify multiple environment variables,
if we need to, and the first one that resolves to something will be used
as the initial value for the option.

If none of the environment variables are defined, the option will be
initialized with the value specified by the =:INITIAL-VALUE= initarg.

Before we move to the next section of this guide we will update the
definition of our =TOP-LEVEL/COMMAND= function, so that we include our
options.

#+begin_src lisp
(defun top-level/command ()
  "Creates and returns the top-level command"
  (clingon:make-command
   :name "clingon-intro"
   ...
   :usage "[-v] [-u ]"      ;; <- new code
   :options (top-level/options))) ;; <- new code
#+end_src

** Defining a handler

A /handler/ in =clingon= is a function, which accepts an instance of
=CLINGON:COMMAND= and is responsible for performing some work.

The single argument a handler receives will be used to inspect the
values of parsed options and any free arguments that were provided on the
command-line.

A command may or may not specify a handler. Some commands may be used
purely as /namespaces/ for other sub-commands, and it might make no
sense to have a handler for such commands. In other situations you may
still want to provide a handler for the parent commands.

Let's define the handler for our /top-level/ command.

#+begin_src lisp
(defun top-level/handler (cmd)
  "The top-level handler"
  (let ((args (clingon:command-arguments cmd))
        (user (clingon:getopt cmd :user))
        (verbose (clingon:getopt cmd :verbose)))
    (format t "Hello, ~A!~%" user)
    (format t "The current verbosity level is set to ~A~%" verbose)
    (format t "You have provided ~A arguments~%" (length args))
    (format t "Bye.~%")))
#+end_src

We are introducing a couple of new functions, which we haven't
described before.

We are using =CLINGON:COMMAND-ARGUMENTS=, which will give us the free
arguments we've provided to our command, when we invoke it on the
command-line.

We also use the =CLINGON:GETOPT= function to lookup the values
associated with our options. Remember the =:KEY= initarg we've used in
=CLINGON:MAKE-OPTION= when defining our options?

And we will again update our =TOP-LEVEL/COMMAND= definition, this time
with our handler included.

#+begin_src lisp
(defun top-level/command ()
  "Creates and returns the top-level command"
  (clingon:make-command
   :name "clingon-intro"
   ...
   :handler #'top-level/handler)) ;; <- new code
#+end_src

At this point we are basically done with our simple application. But
before we move to the point where build our binary and start playing
with it on the command-line we can test things out on the REPL, just
to make sure everything works as expected.

** Testing things out on the REPL

Create a new instance of our command and bind it to some variable.

#+begin_src lisp
INTRO> (defparameter *app* (top-level/command))
*APP*
#+end_src

Inspecting the returned instance would give you something like this.

#+begin_src lisp
#
--------------------
Class: #
--------------------
 Group slots by inheritance [ ]
 Sort slots alphabetically  [X]

All Slots:
[ ]  ARGS-TO-PARSE    = NIL
[ ]  ARGUMENTS        = NIL
[ ]  AUTHORS          = ("John Doe ")
[ ]  CONTEXT          = #
[ ]  DESCRIPTION      = "my first clingon cli app"
[ ]  EXAMPLES         = NIL
[ ]  HANDLER          = #
[ ]  LICENSE          = "BSD 2-Clause"
[ ]  LONG-DESCRIPTION = NIL
[ ]  NAME             = "clingon-intro"
[ ]  OPTIONS          = (# # # # #)
[ ]  PARENT           = NIL
[ ]  SUB-COMMANDS     = NIL
[ ]  USAGE            = "[-v] [-u ]"
[ ]  VERSION          = "0.1.0"

[set value]  [make unbound]
#+end_src

You might also notice that besides the options we've defined ourselves,
there are few additional options, that we haven't defined at all.

These options are automatically added by =clingon= itself for each new
command and provide flags for =--help=, =--version= and
=--bash-completions= for you automatically, so you don't have to deal
with them manually.

Before we dive into testing out our application, first we will check
that we have a correct help information for our command.

#+begin_src lisp
INTRO> (clingon:print-usage *app* t)
NAME:
  clingon-intro - my first clingon cli app

USAGE:
  clingon-intro [-v] [-u ]

OPTIONS:
      --help              display usage information and exit
      --version           display version and exit
  -u, --user       user to greet [default: stranger] [env: $USER]
  -v, --verbose           verbosity level [default: 0]

AUTHORS:
  John Doe 

LICENSE:
  BSD 2-Clause

NIL
#+end_src

This help information will make it easier for our users, when they
need to use it. And that is automatically handled for you, so you
don't have to manually maintain an up-to-date usage information, each
time you introduce a new option.

Time to test out our application on the REPL. In order to test things
out you can use the =CLINGON:PARSE-COMMAND-LINE= function by passing
it an instance of your command, along with any arguments that need to
be parsed. Let's try it out without any command-line arguments.

#+begin_src lisp
INTRO> (clingon:parse-command-line *app* nil)
#
#+end_src

The =CLINGON:PARSE-COMMAND-LINE= function will (as the name suggests)
parse the given arguments against the options associated with our
command. Finally it will return an instance of =CLINGON:COMMAND=.

In our simple CLI application, that would be the same instance as our
=*APP*=, but things look differently when we have sub-commands.

When we start adding new sub-commands, the result of
=CLINGON:PARSE-COMMAND-LINE= will be different based on the arguments
it needs to parse. That means that if our input matches a sub-command
you will receive an instance of the sub-command that matched the given
arguments.

Internally the =clingon= system maintains a tree data structure,
describing the relationships between commands. This allows a command
to be related to some other command, and this is how the command and
sub-commands support is implemented in =clingon=.

Each command in =clingon= is associated with a /context/.  The
/context/ or /environment/ provides the options and their values with
respect to the command itself. This means that a parent command and a
sub-command may have exactly the same set of options defined, but they
will reside in different contexts. Depending on how you use it,
sub-commands may /shadow/ a parent command option, but it also means
that a sub-command can refer to an option defined in a global command.

The /context/ of a command in =clingon= is available via the
=CLINGON:COMMAND-CONTEXT= accessor. We will use the context in order
to lookup our options and the values associated with them.

The function that operates on command's context and retrieves
values from it is called =CLINGON:GETOPT=.

Let's see what we've got for our options.

#+begin_src lisp
INTRO> (let ((c (clingon:parse-command-line *app* nil)))
         (clingon:getopt c :user))
"dnaeon"
T
#+end_src

The =CLINGON:GETOPT= function returns multiple values -- first one
specifies the value of the option, if it had any. And the second one
indicates whether or not that option has been set at all on the
command-line.

If you need to simply test things out and tell whether an option has
been set at all you can use the =CLINGON:OPT-IS-SET-P= function
instead.

Let's try it out with a different input.

#+begin_src lisp
INTRO> (let ((c (clingon:parse-command-line *app* (list "-vvv" "--user" "foo"))))
         (format t "Verbose is ~A~%" (clingon:getopt c :verbose))
         (format t "User is ~A~%" (clingon:getopt c :user)))
Verbose is 3
User is foo
#+end_src

Something else, which is important to mention here. The default
precedence list for options is:

- The value provided by the =:INITIAL-VALUE= initarg
- The value of the first environment variable, which successfully resolved,
  provided by the =:ENV-VARS= initarg
- The value provided on the command-line when invoking the application.

Play with it using different command-line arguments. If you specify
invalid or unknown options =clingon= will signal a condition and
provide you a few recovery options. For example, if you specify an
invalid flag like this:

#+begin_src lisp
INTRO> (clingon:parse-command-line *app* (list "--invalid-flag"))
#+end_src

We will be dropped into the debugger and be provided with restarts we
can choose from, e.g.

#+begin_src lisp
Unknown option --invalid-flag of kind LONG
   [Condition of type CLINGON.CONDITIONS:UNKNOWN-OPTION]

Restarts:
 0: [DISCARD-OPTION] Discard the unknown option
 1: [TREAT-AS-ARGUMENT] Treat the unknown option as a free argument
 2: [SUPPLY-NEW-VALUE] Supply a new value to be parsed
 3: [RETRY] Retry SLY mREPL evaluation request.
 4: [ABORT] Return to sly-db level 1.
 5: [RETRY] Retry SLY mREPL evaluation request.
 --more--
...
#+end_src

This is similar to the way other Common Lisp options parsing systems
behave such as [[https://github.com/sjl/adopt][adopt]] and [[https://github.com/libre-man/unix-opts][unix-opts]].

Also worth mentioning again here is that =CLINGON:PARSE-COMMAND-LINE= is
meant to be used within the REPL, and not called directly by handlers.

** Adding a sub-command

Sub-commands are no different than regular commands, and in fact are
created exactly the way we did it for our /top-level/ command.

#+begin_src lisp
(defun shout/handler (cmd)
  "The handler for the `shout' command"
  (let ((args (mapcar #'string-upcase (clingon:command-arguments cmd)))
        (user (clingon:getopt cmd :user))) ;; <- a global option
    (format t "HEY, ~A!~%" user)
    (format t "~A!~%" (clingon:join-list args #\Space))))

(defun shout/command ()
  "Returns a command which SHOUTS back anything we write on the command-line"
  (clingon:make-command
   :name "shout"
   :description "shouts back anything you write"
   :usage "[options] [arguments ...]"
   :handler #'shout/handler))
#+end_src

And now, we will wire up our sub-command making it part of the
/top-level/ command we have so far.

#+begin_src lisp
(defun top-level/command ()
  "Creates and returns the top-level command"
  (clingon:make-command
   :name "clingon-intro"
   ...
   :sub-commands (list (shout/command)))) ;; <- new code
#+end_src

You should also notice here that within the =SHOUT/HANDLER= we are
actually referencing an option, which is defined somewhere else.  This
option is actually defined on our top-level command, but thanks's to
the automatic management of relationships that =clingon= provides we
can now refer to global options as well.

Let's move on to the final section of this guide, where we will create
a system definition for our application and build it.

** Packaging it up

One final piece which remains to be added to our code is to provide an
entrypoint for our application, so let's do it now.

#+begin_src lisp
(defun main ()
  (let ((app (top-level/command)))
    (clingon:run app)))
#+end_src

This is the entrypoint which will be used when we invoke our
application on the command-line, which we'll set in our ASDF
definition.

And here's a simple system definition for the application we've
developed so far.

#+begin_src lisp
(defpackage :clingon-intro-system
  (:use :cl :asdf))
(in-package :clingon-intro-system)

(defsystem "clingon.intro"
  :name "clingon.intro"
  :long-name "clingon.intro"
  :description "An introduction to the clingon system"
  :version "0.1.0"
  :author "John Doe "
  :license "BSD 2-Clause"
  :depends-on (:clingon)
  :components ((:module "intro"
                :pathname #P"examples/intro/"
                :components ((:file "intro"))))
  :build-operation "program-op"
  :build-pathname "clingon-intro"
  :entry-point "clingon.intro:main")
#+end_src

Now we can build our application and start using it on the
command-line.

#+begin_src shell
sbcl --eval '(ql:quickload :clingon.intro)' \
     --eval '(asdf:make :clingon.intro)' \
     --eval '(quit)'
#+end_src

This will produce a new binary called =clingon-intro= in the directory
of the =clingon.intro= system.

** Testing it out on the command-line

Time to check things up on the command-line.

#+begin_src shell
$ ./clingon-intro --help
NAME:
  clingon-intro - my first clingon cli app

USAGE:
  clingon-intro [-v] [-u ]

OPTIONS:
      --help              display usage information and exit
      --version           display version and exit
  -u, --user       user to greet [default: stranger] [env: $USER]
  -v, --verbose           verbosity level [default: 0]

COMMANDS:
  shout  shouts back anything you write

AUTHORS:
  John Doe 

LICENSE:
  BSD 2-Clause
#+end_src

Let's try out our commands.

#+begin_src shell
$ ./clingon-intro -vvv --user Lisper
Hello, Lisper!
The current verbosity level is set to 3
You have provided 0 arguments
Bye.
#+end_src

And let's try our sub-command as well.

#+begin_src shell
$ ./clingon-intro --user stranger shout why are yelling at me?
HEY, stranger!
WHY ARE YELLING AT ME?!
#+end_src

You can find the full code we've developed in this guide in the
[[https://github.com/dnaeon/clingon/tree/master/examples][clingon/examples]] directory of the repo.

* Exiting

When a command needs to exit with a given status code you can use the
=CLINGON:EXIT= function.

* Handling SIGINT (CTRL-C) signals

=clingon= by default will provide a handler for =SIGINT= signals,
which when detected will cause the application to immediately exit
with status code =130=.

If your commands need to provide some cleanup logic as part of their
job, e.g. close out all open files, TCP session, etc., you could wrap
your =clingon= command handlers in [[http://www.lispworks.com/documentation/HyperSpec/Body/s_unwind.htm][UNWIND-PROTECT]] to make sure that
your cleanup tasks are always executed.

However, using [[http://www.lispworks.com/documentation/HyperSpec/Body/s_unwind.htm][UNWIND-PROTECT]] may not be appropriate in all cases,
since the cleanup forms will always be executed, which may or may not
be what you need.

For example if you are developing a =clingon= application, which
populates a database in a transaction you would want to use
[[http://www.lispworks.com/documentation/HyperSpec/Body/s_unwind.htm][UNWIND-PROTECT]], but only for releasing the database connection itself.

If the application is interrupted while it inserts or updates records,
what you want to do is to rollback the transaction as well, so your
database is left in a consistent state.

In those situations you would want to use the [[https://github.com/compufox/with-user-abort][WITH-USER-ABORT]] system,
so that your =clingon= command can detect the =SIGINT= signal and act
upon it, e.g. taking care of rolling back the transaction.

* Generating Documentation

=clingon= can generate documentation for your application by using the
=CLINGON:PRINT-DOCUMENTATION= generic function.

Currently the documentation generator supports only the /Markdown/
format, but other formats can be developed as separate extensions to
=clingon=.

Here's how you can generate the Markdown documentation for the
=clingon-demo= application from the REPL.

#+begin_src lisp
CL-USER> (ql:quickload :clingon.demo)
CL-USER> (in-package :clingon.demo)
DEMO> (with-open-file (out #P"clingon-demo.md" :direction :output)
        (clingon:print-documentation :markdown (top-level/command) out))
#+end_src

You can also create a simple command, which can be added to your
=clingon= apps and have it generate the documentation for you, e.g.

#+begin_src lisp
(defun print-doc/command ()
  "Returns a command which will print the app's documentation"
  (clingon:make-command
   :name "print-doc"
   :description "print the documentation"
   :usage ""
   :handler (lambda (cmd)
              ;; Print the documentation starting from the parent
              ;; command, so we can traverse all sub-commands in the
              ;; tree.
              (clingon:print-documentation :markdown (clingon:command-parent cmd) t))))
#+end_src

Above command can be wired up anywhere in your application.

Make sure to also check the =clingon-demo= app, which provides a
=print-doc= sub-command, which operates on the /top-level/ command and
generates the documentation for all sub-commands.

You can also find the generated documentation for the =clingon-demo=
app in the =docs/= directory of the =clingon= repo.

* Command Hooks

=clingon= allows you to associate =pre= and =post= hooks with a
command.

The =pre= and =post= hooks are functions which will be invoked before
and after the respective command handler is executed. They are useful
in cases when you need to set up or tear things down before executing
the command's handler.

An example of a =pre-hook= might be to configure the logging level of
your application based on the value of a global flag. A =post-hook=
might be responsible for shutting down any active connections, etc.

The =pre-hook= and =post-hook= functions accept a single argument,
which is an instance of =CLINGON:COMMAND=. That way the hooks can
examine the command's context and lookup any flags or options.

Hooks are also hierachical in the sense that they will be executed
based on the command's lineage.

Consider the following example, where we have a CLI app with three
commands.

#+begin_src text
  main -> foo -> bar
#+end_src

In above example the =bar= command is a sub-command of =foo=, which in
turn is a sub-command of =main=. Also, consider that we have added
pre- and post-hooks to each command.

If a user executed the following on the command-line:

#+begin_src shell
  $ main foo bar
#+end_src

Based on the above command-line =clingon= would do the following:

- Execute any =pre-hook= functions starting from the least-specific up to the
  most-specific node from the commands' lineage
- Execute the command's handler
- Execute any =post-hook= functions starting from the most-specific down to the
  least-specific node from the command's lineage

In above example that would be:

#+begin_src text
  > main (pre-hook)
  >> foo (pre-hook)
  >>> bar (pre-hook)
  >>>> bar (handler)
  >>> bar (post-hook)
  >> foo (post-hook)
  > main (post-hook)
#+end_src

Associating hooks with commands is done during instantiation of a
command. The following example creates a new command with a =pre-hook=
and =post-hook=.

#+begin_src lisp
  (defun foo/pre-hook (cmd)
    "The pre-hook for `foo' command"
    (declare (ignore cmd))
    (format t "foo pre-hook has been invoked~&"))

  (defun foo/post-hook (cmd)
    "The post-hook for `foo' command"
    (declare (ignore cmd))
    (format t "foo post-hook has been invoked~&"))

  (defun foo/handler (cmd)
    (declare (ignore cmd))
    (format t "foo handler has been invoked~&"))

  (defun foo/command ()
    "Returns the `foo' command"
    (clingon:make-command
     :name "foo"
     :description "the foo command"
     :authors '("John Doe ")
     :handler #'foo/handler
     :pre-hook #'foo/pre-hook
     :post-hook #'foo/post-hook
     :options nil
     :sub-commands nil))
#+end_src

If we have executed above command we would see the following output.

#+begin_src shell
  foo pre-hook has been invoked
  foo handler has been invoked
  foo post-hook has been invoked
#+end_src

* Options

The =clingon= system supports various kinds of options, each of which
is meant to serve a specific purpose.

Each builtin option can be initialized via environment variables, and
new mechanisms for initializing options can be developed, if needed.

Options are created via the single =CLINGON:MAKE-OPTION= interface.

The supported option kinds include:

- =counter=
- =integer=
- =string=
- =boolean=
- =boolean/true=
- =boolean/false=
- =choice=
- =enum=
- =list=
- =list/integer=
- =filepath=
- =list/filepath=
- etc.

** Counters Options

A =counter= is an option kind, which increments every time it is set
on the command-line.

A good example for =counter= options is to provide a flag, which
increases the verbosity level, depending on the number of times the
flag was provided, similar to the way =ssh(1)= does it, e.g.

#+begin_src shell
ssh -vvv user@host
#+end_src

Here's an example of creating a =counter= option.

#+begin_src lisp
(clingon:make-option
 :counter
 :short-name #\v
 :long-name "verbose"
 :description "how noisy we want to be"
 :key :verbose)
#+end_src

The default =step= for counters is set to =1=, but you can change
that, if needed.

#+begin_src lisp
(clingon:make-option
 :counter
 :short-name #\v
 :long-name "verbose"
 :description "how noisy we want to be"
 :step 42
 :key :verbose)
#+end_src

** Boolean Options

The following boolean option kinds are supported by =clingon=.

The =:boolean= kind is an option which expects an argument, which
represents a boolean value.

Arguments =true= and =1= map to =T= in Lisp, anything else is
considered a falsey value and maps to =NIL=.

#+begin_src lisp
(clingon:make-option
 :boolean
 :description "my boolean"
 :short-name #\b
 :long-name "my-boolean"
 :key :boolean)
#+end_src

This creates an option =-b, --my-boolean =, which can be
provided on the command-line, where == should be =true= or =1=
for truthy values, and anything else maps to =NIL=.

The =:boolean/true= option kind creates a flag, which always returns
=T=.

The =:boolean/false= option kind creates a flag, which always returns
=NIL=.

The =:flag= option kind is an alias for =:boolean/true=.

** Integer Options

Here's an example of creating an option, which expects an integer
argument.

#+begin_src lisp
(clingon:make-option
 :integer
 :description "my integer opt"
 :short-name #\i
 :long-name "int"
 :key :my-int
 :initial-value 42)
#+end_src

** Choice Options

=choice= options are useful when you have to limit the arguments
provided on the command-line to a specific set of values.

For example:

#+begin_src lisp
(clingon:make-option
 :choice
 :description "log level"
 :short-name #\l
 :long-name "log-level"
 :key :choice
 :items '("info" "warn" "error" "debug"))
#+end_src

With this option defined, you can now set the logging level only to
=info=, =warn=, =error= or =debug=, e.g.

#+begin_src shell
-l, --log-level [info|warn|error|debug]
#+end_src

** Enum Options

Enum options are similar to the =choice= options, but instead of
returning the value itself they can be mapped to something else.

For example:

#+begin_src lisp
(clingon:make-option
 :enum
 :description "enum option"
 :short-name #\e
 :long-name "my-enum"
 :key :enum
 :items '(("one" . 1)
          ("two" . 2)
          ("three" . 3)))
#+end_src

If a user specifies =--my-enum=one= on the command-line the option
will be have the value =1= associated with it, when being looked up
via =CLINGON:GETOPT=.

The values you associate with the enum variant, can be any object.

This is one of the options being used by the /clingon-demo/
application, which maps user input to Lisp functions, in order to
perform some basic math operations.

#+begin_src lisp
(clingon:make-option
 :enum
 :description "operation to perform"
 :short-name #\o
 :long-name "operation"
 :required t
 :items `(("add" . ,#'+)
          ("sub" . ,#'-)
          ("mul" . ,#'*)
          ("div" . ,#'/))
 :key :math/operation)
#+end_src

** List / Accumulator Options

The =:list= option kind accumulates each argument it is given on the
command-line into a list.

For example:

#+begin_src lisp
(clingon:make-option
 :list
 :description "files to process"
 :short-name #\f
 :long-name "file"
 :key :files)
#+end_src

If you invoke an application, which uses a similar option like the one
above using the following command-line arguments:

#+begin_src shell
$ my-app --file foo --file bar --file baz
#+end_src

When you retrieve the value associated with your option, you will get a
list of all the files specified on the command-line, e.g.

#+begin_src lisp
(clingon:getopt cmd :files) ;; => '("foo" "bar" "baz")
#+end_src

A similar option exists for integer values using the =:list/integer=
option, e.g.

#+begin_src lisp
(clingon:make-option
 :list/integer
 :description "list of integers"
 :short-name #\l
 :long-name "int"
 :key :integers)
#+end_src

** Switch Options

=:SWITCH= options are a variation of =:BOOLEAN= options with an
associated list of known states that can turn a switch /on/ or
/off/.

Here is an example of a =:SWITCH= option.

#+begin_src lisp
(clingon:make-option
 :switch
 :description "my switch option"
 :short-name #\s
 :long-name "state"
 :key :switch)
#+end_src

The default states for a switch to be considered as /on/ are:

- /on/, /yes/, /true/, /enable/ and /1/

The default states considered to turn the switch /off/ are:

- /off/, /no/, /false/, /disable/ and /0/

You can customize the list of /on/ and /off/ states by specifying them
using the =:ON-STATES= and =:OFF-STATES= initargs, e.g.

#+begin_src lisp
(clingon:make-option
 :switch
 :description "engine switch option"
 :short-name #\s
 :long-name "state"
 :on-states '("start")
 :off-states '("stop")
 :key :engine)
#+end_src

These sample command-line arguments will turn a switch on and off.

#+begin_src shell
my-app --engine=start --engine=stop
#+end_src

The final value of the =:engine= option will be =NIL= in the above
example.

* Generic Functions Operating on Options

If the existing options provided by =clingon= are not enough for you,
and you need something a bit more specific for your use case, then you
can always implement a new option kind.

The following generic functions operate on options and are exported by
the =clingon= system.

- =CLINGON:INITILIAZE-OPTION=
- =CLINGON:FINALIZE-OPTION=
- =CLINGON:DERIVE-OPTION-VALUE=
- =CLINGON:OPTION-USAGE-DETAILS=
- =CLINGON:OPTION-DESCRIPTION-DETAILS=
- =CLINGON:MAKE-OPTION=

New option kinds should inherit from the =CLINGON:OPTION= class, which
implements all of the above generic functions. If you need to
customize the behaviour of your new option, you can still override the
default implementations.

** CLINGON:INITIALIZE-OPTION

The =CLINGON:INITIALIZE-OPTION= as the name suggests is being used to
initialize an option.

The default implementation of this generic function supports
initialization from environment variables, but implementors
can choose to support other initialization methods, e.g.
be able to initialize an option from a key/value store like
/Redis/, /Consul/ or /etcd/ for example.

** CLINGON:FINALIZE-OPTION

The =CLINGON:FINALIZE-OPTION= generic function is called after
all command-line arguments have been processed and values for them
have been derived already.

=CLINGON:FINALIZE-OPTION= is meant to /finalize/ the option's value,
e.g. transform it to another object, if needed.

For example the =:BOOLEAN= option kind transforms user-provided input
like =true=, =false=, =1= and =0= into their respective Lisp counterparts
like =T= and =NIL=.

Another example where you might want to customize the behaviour of
=CLINGON:FINALIZE-OPTION= is to convert a string option provided on
the command-line, which represents a database connection string into
an actual session object for the database.

The default implementation of this generic function simply returns the
already set value, e.g. calls =#'IDENTITY= on the last derived value.

** CLINGON:DERIVE-OPTION-VALUE

The =CLINGON:DERIVE-OPTION-VALUE= is called whenever an option is
provided on the command-line.

If that option accepts an argument, it will be passed the respective
value from the command-line, otherwise it will be called with a =NIL=
argument.

Responsibility of the option is to derive a value from the given input
and return it to the caller. The returned value will be set by the
parser and later on it will be used to produce a final value, by
calling the =CLINGON:FINALIZE-OPTION= generic function.

Different kinds of options implement this one different -- for example
the =:LIST= option kind accumulates each given argument, while others
ignore any previously derived values and return the last provided
argument.

The =:ENUM= option kind for example will derive a value from a
pre-defined list of allowed values.

If an option fails to derive a value (e.g. invalid value has been
provided) the implementation of this generic function should signal a
=CLINGON:OPTION-DERIVE-ERROR= condition, so that =clingon= can provide
appropriate restarts.

** CLINGON:OPTION-USAGE-DETAILS

This generic function is used to provide a pretty-printed usage format
for the given option. It will be used when printing usage information
on the command-line for the respective commands.

** CLINGON:OPTION-DESCRIPTION-DETAILS

This generic function is meant to enrich the description of the option
by providing as much details as possible for the given option, e.g.
listing the available values that an option can accept.

** CLINGON:MAKE-OPTION

The =CLINGON:MAKE-OPTION= generic function is the primary way for
creating new options. Implementors of new option kinds should simply
provide an implementation of this generic function, along with the
respective option kind.

Additional option kinds may be implemented as separate sub-systems,
but still follow the same principle by providing a single and
consistent interface for option creation.

* Developing New Options

This section contains short guides explaining how to develop new
options for =clingon=.

** Developing an Email Option

The option which we'll develop in this section will be used for
specifying email addresses.

Start up your Lisp REPL session and do let's some work. Load the
=:clingon= and =:cl-ppcre= systems, since we will need them.

#+begin_src lisp
CL-USER> (ql:quickload :clingon)
CL-USER> (ql:quickload :cl-ppcre)
#+end_src

We will first create a new package for our extension and import the
symbols we will need from the =:clingon= and =:cl-ppcre= systems.

#+begin_src lisp
(defpackage :clingon.extensions/option-email
  (:use :cl)
  (:import-from
   :cl-ppcre
   :scan)
  (:import-from
   :clingon
   :option
   :initialize-option
   :derive-option-value
   :make-option
   :option-value
   :option-derive-error)
  (:export
   :option-email))
(in-package :clingon.extensions/option-email)
#+end_src

Then lets define the class, which will represent an email address
option.

#+begin_src lisp
(defclass option-email (option)
  ((pattern
    :initarg :pattern
    :initform "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"
    :reader option-email-pattern
    :documentation "Pattern used to match for valid email addresses"))
  (:default-initargs
   :parameter "EMAIL")
  (:documentation "An option used to represent an email address"))
#+end_src

Now we will implement =CLINGON:INITIALIZE-OPTION= for our new
option. We will keep the default initialization logic as-is, but also
add an additional step to validate the email address, if we have any
initial value at all.

#+begin_src lisp
(defmethod initialize-option ((option option-email) &key)
  "Initializes our new email address option"
  ;; Make sure to invoke our parent initialization method first, so
  ;; various things like setting up initial value from environment
  ;; variables can still be applied.
  (call-next-method)

  ;; If we don't have any value set, there's nothing else to
  ;; initialize further here.
  (unless (option-value option)
    (return-from initialize-option))

  ;; If we get to this point, that means we've got some initial value,
  ;; which is either set as a default, or via environment
  ;; variables. Next thing we need to do is make sure we've got a good
  ;; initial value, so let's derive a value from it.
  (let ((current (option-value option)))
    (setf (option-value option)
          (derive-option-value option current))))
#+end_src

Next we will implement =CLINGON:DERIVE-OPTION-VALUE= for our new
option kind.

#+begin_src lisp
(defmethod derive-option-value ((option option-email) arg &key)
  "Derives a new value based on the given argument.
   If the given ARG represents a valid email address according to the
   pattern we know of we consider this as a valid email address."
  (unless (scan (option-email-pattern option) arg)
    (error 'option-derive-error :reason (format nil "~A is not a valid email address" arg)))
  arg)
#+end_src

Finally, lets register our new option as a valid kind by implemeting
the =CLINGON:MAKE-OPTION= generic function.

#+begin_src lisp
(defmethod make-option ((kind (eql :email)) &rest rest)
  (apply #'make-instance 'option-email rest))
#+end_src

We can test things out now. Go back to your REPL and try these
expressions out. First we make a new instance of our new option.

#+begin_src lisp
(defparameter *opt*
  (make-option :email :short-name #\e :description "email opt" :key :email))
#+end_src

And now, lets validate a couple of good email addresses.

#+begin_src lisp
EXTENSIONS/OPTION-EMAIL> (derive-option-value *opt* "test@example.com")
"test@example.com"
EXTENSIONS/OPTION-EMAIL> (derive-option-value *opt* "foo@bar.com")
"foo@bar.com"
#+end_src

If we try deriving a value from a bad email address we will have a
condition of type =CLINGON:OPTION-DERIVE-ERROR= signalled.

#+begin_src lisp
EXTENSIONS/OPTION-EMAIL> (derive-option-value opt "bad-email-address-here")
; Debugger entered on #
...
bad-email-address-here is not a valid email address
   [Condition of type OPTION-DERIVE-ERROR]
#+end_src

Good, we can catch invalid email addresses as well. Whenever an option
fails to derive a new value from a given argument, and we signal
=CLINGON:OPTION-DERIVE-ERROR= condition we can recover by providing
new values or discarding them completely, thanks to the Common Lisp
Condition System.

Last thing to do is actually package this up as an extension system
and register it in Quicklisp. That way everyone else can benefit from
the newly developed option.

* Shell Completions

=clingon= provides support for Bash and Zsh shell completions.

** Bash Completions

In order to enable the Bash completions for your =clingon= app,
follow these instructions.

#+begin_src shell
APP=app-name source extras/completions.bash
#+end_src

Make sure to set =APP= to your correct application name.

The [[https://github.com/dnaeon/clingon/blob/master/extras/completions.bash][completions.bash]] script will dynamically provide completions by
invoking the =clingon= app with the =--bash-completions= flag. This
builtin flag when provided on the command-line will return completions
for the sub-commands and the available flags.

** Zsh Completions

When developing your CLI app with =clingon= you can provide an
additional command, which will take care of generating the Zsh
completion script for your users.

The following code can be used in your app and added as a sub-command
to your top-level command.

#+begin_src lisp
  (defun zsh-completion/command ()
    "Returns a command for generating the Zsh completion script"
    (clingon:make-command
     :name "zsh-completion"
     :description "generate the Zsh completion script"
     :usage ""
     :handler (lambda (cmd)
                ;; Use the parent command when generating the completions,
                ;; so that we can traverse all sub-commands in the tree.
                (let ((parent (clingon:command-parent cmd)))
                  (clingon:print-documentation :zsh-completions parent t)))))
#+end_src

You can also check out the =clingon-demo= app for a fully working CLI
app with Zsh completions support.

[[./images/clingon-zsh-completions.gif]]

* Ideas For Future Improvements

** Additional Documentation Generators

As of now =clingon= supports generating documentation only in /Markdown/
format.

Would be nice to have additional documentation generators, e.g.
/man pages/, /HTML/, etc.

** Performance Notes

=clingon= has been developed and tested on a GNU/Linux system using
SBCL.

Performance of the resulting binaries with SBCL seem to be good,
although I have noticed better performance when the binaries have been
produced with Clozure CL. And by better I mean better in terms of
binary size and speed (startup + run time).

Although you can enable compression on the image when using SBCL you
have to pay the extra price for the startup time.

Here are some additional details. Build the =clingon-demo= app with
SBCL.

#+begin_src shell
$ LISP=sbcl make demo
sbcl --eval '(ql:quickload :clingon.demo)' \
        --eval '(asdf:make :clingon.demo)' \
                --eval '(quit)'
This is SBCL 2.1.7, an implementation of ANSI Common Lisp.
More information about SBCL is available at .

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
To load "clingon.demo":
  Load 1 ASDF system:
    clingon.demo
; Loading "clingon.demo"
[package clingon.utils]...........................
[package clingon.conditions]......................
[package clingon.options].........................
[package clingon.command].........................
[package clingon].................................
[package clingon.demo]
[undoing binding stack and other enclosing state... done]
[performing final GC... done]
[defragmenting immobile space... (fin,inst,fdefn,code,sym)=1118+969+19070+19610+26536... done]
[saving current Lisp image into /home/dnaeon/Projects/lisp/clingon/clingon-demo:
writing 0 bytes from the read-only space at 0x50000000
writing 736 bytes from the static space at 0x50100000
writing 31391744 bytes from the dynamic space at 0x1000000000
writing 2072576 bytes from the immobile space at 0x50200000
writing 12341248 bytes from the immobile space at 0x52a00000
done]
#+end_src

Now, build it using Clozure CL.

#+begin_src shell
$ LISP=ccl make demo
ccl --eval '(ql:quickload :clingon.demo)' \
        --eval '(asdf:make :clingon.demo)' \
                --eval '(quit)'
To load "clingon.demo":
  Load 1 ASDF system:
    clingon.demo
; Loading "clingon.demo"
[package clingon.utils]...........................
[package clingon.conditions]......................
[package clingon.options].........................
[package clingon.command].........................
[package clingon].................................
[package clingon.demo].
#+end_src

In terms of file size the binaries produced by Clozure CL are smaller.

#+begin_src shell
$ ls -lh clingon-demo*
-rwxr-xr-x 1 dnaeon dnaeon 33M Aug 20 12:56 clingon-demo.ccl
-rwxr-xr-x 1 dnaeon dnaeon 45M Aug 20 12:55 clingon-demo.sbcl
#+end_src

Generating the Markdown documentation for the demo app when using the
SBCL executable looks like this.

#+begin_src shell
$ time ./clingon-demo.sbcl print-doc > /dev/null

real    0m0.098s
user    0m0.071s
sys     0m0.027s
#+end_src

And when doing the same thing with the executable produced by Clozure
CL we see these results.

#+begin_src shell
$ time ./clingon-demo.ccl print-doc > /dev/null

real    0m0.017s
user    0m0.010s
sys     0m0.007s
#+end_src

* Tests

The =clingon= tests are provided as part of the =:clingon.test= system.

In order to run the tests you can evaluate the following expressions.

#+begin_src lisp
CL-USER> (ql:quickload :clingon.test)
CL-USER> (asdf:test-system :clingon.test)
#+end_src

Or you can run the tests using the =run-tests.sh= script instead, e.g.

#+begin_src shell
LISP=sbcl ./run-tests.sh
#+end_src

Here's how to run the tests against SBCL, CCL and ECL for example.

#+begin_src shell
for lisp in sbcl ccl ecl; do
    echo "Running tests using ${lisp} ..."
    LISP=${lisp} make test > ${lisp}-tests.out
done
#+end_src

* Docker Images

A few Docker images are available.

Build and run the tests in a container.

#+begin_src shell
docker build -t clingon.test:latest -f Dockerfile.tests .
docker run --rm clingon.test:latest
#+end_src

Build and run the =clingon-intro= application.

#+begin_src shell
docker build -t clingon.intro:latest -f Dockerfile.intro .
docker run --rm clingon.intro:latest
#+end_src

Build and run the =clingon.demo= application.

#+begin_src lisp
docker build -t clingon.demo:latest -f Dockerfile.demo .
docker run --rm clingon.demo:latest
#+end_src

* Contributing

=clingon= is hosted on [[https://github.com/dnaeon/clingon][Github]]. Please contribute by reporting issues,
suggesting features or by sending patches using pull requests.

* License

This project is Open Source and licensed under the [[http://opensource.org/licenses/BSD-2-Clause][BSD License]].

* Authors

- Marin Atanasov Nikolov 



Next: , Previous: , Up: Top   [Contents][Index]

2 Systems

The main system appears first, followed by any subsystem dependency.


Previous: , Up: Systems   [Contents][Index]

2.1 clingon

Long Name

clingon

Maintainer

Marin Atanasov Nikolov <dnaeon@gmail.com>

Author

Marin Atanasov Nikolov <dnaeon@gmail.com>

Home Page

https://github.com/dnaeon/clingon

Source Control

https://github.com/dnaeon/clingon

Bug Tracker

https://github.com/dnaeon/clingon

License

BSD 2-Clause

Description

Command-line options parser system for Common Lisp

Long Description

* clingon

=clingon= is a command-line options parser system for Common Lisp.

A summary of the features supported by =clingon= is provided below.

- Native support for sub-commands
- Support for command aliases
- Short and long option names support
- Related options may be grouped into categories
- Short options may be collapsed as a single argument, e.g. =-xyz=
- Long options support both notations - =–long-opt arg= and
=–long-opt=arg=.
- Automatic generation of help/usage information for commands and
sub-commands
- Out of the box support for =–version= and =–help= flags
- Support for various kinds of options like /string/, /integer/,
/boolean/, /switches/, /enums/, /list/, /counter/, /filepath/, etc.
- Sub-commands can lookup global options and flags defined in parent
commands
- Support for options, which may be required
- Options can be initialized via environment variables
- Single interface for creating options using =CLINGON:MAKE-OPTION=
- Generate documentation for your command-line app
- Support for =pre-hook= and =post-hook= actions for commands, which
allows invoking functions before and after the respective handler of
the command is executed
- Support for Bash and Zsh shell completions
- =clingon= is extensible, so if you don’t find something you need you
can extend it by developing a new option kind, or even new mechanism
for initializing options, e.g. by looking up an external key/value
store.

Scroll to the demo section in order to see some examples of =clingon=
in action.

Other Common Lisp option parser systems, which you might consider
checking out.

- [[https://github.com/libre-man/unix-opts][unix-opts]]
- [[https://github.com/sjl/adopt/][adopt]]
- [[https://github.com/didierverna/clon][clon]]

* Quick Example

Here’s a really quick example of a simple CLI application, which
greets people.

#+begin_src lisp
(in-package :cl-user)
(defpackage :clingon.example.greet
(:use :cl)
(:import-from :clingon)
(:export
:main))
(in-package :clingon.example.greet)

(defun greet/options ()
"Returns the options for the ‘greet’ command"
(list
(clingon:make-option
:string
:description "Person to greet"
:short-name #\u
:long-name "user"
:initial-value "stranger"
:env-vars ’("USER")
:key :user)))

(defun greet/handler (cmd)
"Handler for the ‘greet’ command"
(let ((who (clingon:getopt cmd :user)))
(format t "Hello, ~A!~%" who)))

(defun greet/command ()
"A command to greet someone"
(clingon:make-command
:name "greet"
:description "greets people"
:version "0.1.0"
:authors ’("John Doe <john.doe@example.org")
:license "BSD 2-Clause"
:options (greet/options)
:handler #’greet/handler))

(defun main ()
"The main entrypoint of our CLI program"
(let ((app (greet/command)))
(clingon:run app)))
#+end_src

This small example shows a lot of details about how apps are
structured with =clingon=.

You can see there’s a =main= function, which will be the entrypoint
for our ASDF system. Then you can find the =greet/command= function,
which creates and returns a new command.

The =greet/options= functions returns the options associated with our
sample command.

And we also have the =greet/handler= function, which is the function
that will be invoked when users run our command-line app.

This way of organizing command, options and handlers makes it easy to
re-use common options, or even handlers, and wire up any sub-commands
anyway you prefer.

You can find additional examples included in the test suite for
=clingon=.

* Demo

You can also build and run the =clingon= demo application, which
includes the =greet= command introduced in the previous section, along
with other examples.

[[./images/clingon-demo.gif]]

Clone the [[https://github.com/dnaeon/clingon][clingon]] repo in your [[https://www.quicklisp.org/beta/faq.html][Quicklisp local-projects]] directory.

#+begin_src shell
git clone https://github.com/dnaeon/clingon
#+end_src

Register it to your local Quicklisp projects.

#+begin_src lisp
CL-USER> (ql:register-local-projects)
#+end_src

** Building the Demo App

You can build the demo app using SBCL with the following command.

#+begin_src shell
LISP=sbcl make demo
#+end_src

Build the demo app using Clozure CL:

#+begin_src shell
LISP=ccl make demo
#+end_src

In order to build the demo app using ECL you need to follow these
instructions, which are ECL-specific. See [[https://common-lisp.net/project/ecl/static/manual/System-building.html#Compiling-with-ASDF][Compiling with ASDF from the
ECL manual]] for more details. First, load the =:clingon.demo= system.

#+begin_src lisp
(ql:quickload :clingon.demo)
#+end_src

And now build the binary with ECL:

#+begin_src lisp
(asdf:make-build :clingon.demo
:type :program
:move-here #P"./"
:epilogue-code ’(clingon.demo:main))
#+end_src

This will create a new executable =clingon-demo=, which you can now
execute.

Optionally, you can also enable the bash completions support.

#+begin_src shell
APP=clingon-demo source extras/completions.bash
#+end_src

In order to activate the Zsh completions, install the completions
script in your =~/.zsh-completions= directory (or anywhere else you
prefer) and update your =~/.zshrc= file, so that the completions are
loaded.

Make sure that you have these lines in your =~/.zshrc= file.

#+begin_src shell
fpath=(~/.zsh-completions $fpath)
autoload -U compinit
compinit
#+end_src

The following command will generate the Zsh completions script.

#+begin_src shell
./clingon-demo zsh-completion > ~/.zsh-completions/_clingon-demo
#+end_src

Use the =–help= flag to see some usage information about the demo
application.

#+begin_src shell
./clingon-demo –help
#+end_src

* Requirements

- [[https://www.quicklisp.org/beta/][Quicklisp]]

* Installation

The =clingon= system is not yet part of Quicklisp, so for now
you need to install it in your local Quicklisp projects.

Clone the repo in your [[https://www.quicklisp.org/beta/faq.html][Quicklisp local-projects]] directory.

#+begin_src lisp
(ql:register-local-projects)
#+end_src

Then load the system.

#+begin_src lisp
(ql:quickload :clingon)
#+end_src

* Step By Step Guide

In this section we will implement a simple CLI application, and
explain at each step what and why we do the things we do.

Once you are done with it, you should have a pretty good understanding
of the =clingon= system and be able to further extend the sample
application on your own.

We will be developing the application interactively and in the
REPL. Finally we will create an ASDF system for our CLI app, so we can
build it and ship it.

The code we develop as part of this section will reside in a file
named =intro.lisp=. Anything we write will be sent to the Lisp REPL, so
we can compile it and get quick feedback about the things we’ve done
so far.

You can find the complete code we’ll develop in this section in the
=clingon/examples/intro= directory.

** Start the REPL

Start up your REPL session and let’s load the =clingon= system.

#+begin_src lisp
CL-USER> (ql:quickload :clingon)
To load "clingon":
Load 1 ASDF system:
clingon
; Loading "clingon"

(:CLINGON)
#+end_src

** Create a new package

First, we will define a new package for our application and switch to
it.

#+begin_src lisp
(in-package :cl-user)
(defpackage :clingon.intro
(:use :cl)
(:import-from :clingon)
(:export :main))
(in-package :clingon.intro)
#+end_src

We have our package, so now we can proceed to the next section and
create our first command.

** Creating a new command

The first thing we’ll do is to create a new command. Commands are
created using the =CLINGON:MAKE-COMMAND= function.

Each command has a name, description, any options that
the command accepts, any sub-commands the command knows about, etc.

The command in =clingon= is represented by the =CLINGON:COMMAND=
class, which contains many other slots as well, which you can lookup.

#+begin_src lisp
(defun top-level/command ()
"Creates and returns the top-level command"
(clingon:make-command
:name "clingon-intro"
:description "my first clingon cli app"
:version "0.1.0"
:license "BSD 2-Clause"
:authors ’("John Doe <john.doe@example.com>")))
#+end_src

This is how our simple command looks like. For now it doesn’t do much,
and in fact it won’t execute anything, but we will fix that as we go.

What is important to note, is that we are using a convention here
to make things easier to understand and organize our code base.

Functions that return new commands will be named =<name>/command=. A
similar approach is taken when we define options for a given command,
e.g. =<name>/options= and for sub-commands we use
=<name>/sub-commands=. Handlers will use the =<name>/handler=
notation.

This makes things easier later on, when we introduce new sub-commands,
and when we need to wire things up we can refer to our commands using
the established naming convention. Of course, it’s up to you to decide
which approach to take, so feel free to adjust the layout of the code
to your personal preferences. In this guide we will use the afore
mentioned approach.

Commands can be linked together in order to form a tree of commands
and sub-commands. We will talk about that one in more details in the
later sections of this guide.

** Adding options

Next, we will add a couple of options. Similar to the previous section
we will define a new function, which simply returns a list of valid
options. Defining it in the following way would make it easier to
re-use these options later on, in case you have another command, which
uses the exact same set of options.

=clingon= exposes a single interface for creating options via the
=CLINGON:MAKE-OPTION= generic function. This unified interface will
allow developers to create and ship new option kinds, and still have
their users leverage a common interface for the options via the
=CLINGON:MAKE-OPTION= interface.

#+begin_src lisp
(defun top-level/options ()
"Creates and returns the options for the top-level command"
(list
(clingon:make-option
:counter
:description "verbosity level"
:short-name #\v
:long-name "verbose"
:key :verbose)
(clingon:make-option
:string
:description "user to greet"
:short-name #\u
:long-name "user"
:initial-value "stranger"
:env-vars ’("USER")
:key :user)))
#+end_src

Let’s break things down a bit and explain what we just did.

We’ve defined two options – one of =:COUNTER= kind and another one,
which is of =:STRING= kind. Each option specifies a short and long
name, along with a description of what the option is meant for.

Another important thing we did is to specify a =:KEY= for our options.
This is the key which we will later use in order to get the value
associated with our option, when we use =CLINGON:GETOPT=.

And we have also defined that our =–user= option can be initialized
via environment variables. We can specify multiple environment variables,
if we need to, and the first one that resolves to something will be used
as the initial value for the option.

If none of the environment variables are defined, the option will be
initialized with the value specified by the =:INITIAL-VALUE= initarg.

Before we move to the next section of this guide we will update the
definition of our =TOP-LEVEL/COMMAND= function, so that we include our
options.

#+begin_src lisp
(defun top-level/command ()
"Creates and returns the top-level command"
(clingon:make-command
:name "clingon-intro"
...
:usage "[-v] [-u <USER>]" ;; <- new code
:options (top-level/options))) ;; <- new code
#+end_src

** Defining a handler

A /handler/ in =clingon= is a function, which accepts an instance of
=CLINGON:COMMAND= and is responsible for performing some work.

The single argument a handler receives will be used to inspect the
values of parsed options and any free arguments that were provided on the
command-line.

A command may or may not specify a handler. Some commands may be used
purely as /namespaces/ for other sub-commands, and it might make no
sense to have a handler for such commands. In other situations you may
still want to provide a handler for the parent commands.

Let’s define the handler for our /top-level/ command.

#+begin_src lisp
(defun top-level/handler (cmd)
"The top-level handler"
(let ((args (clingon:command-arguments cmd))
(user (clingon:getopt cmd :user))
(verbose (clingon:getopt cmd :verbose)))
(format t "Hello, ~A!~%" user)
(format t "The current verbosity level is set to ~A~%" verbose)
(format t "You have provided ~A arguments~%" (length args))
(format t "Bye.~%")))
#+end_src

We are introducing a couple of new functions, which we haven’t
described before.

We are using =CLINGON:COMMAND-ARGUMENTS=, which will give us the free
arguments we’ve provided to our command, when we invoke it on the
command-line.

We also use the =CLINGON:GETOPT= function to lookup the values
associated with our options. Remember the =:KEY= initarg we’ve used in
=CLINGON:MAKE-OPTION= when defining our options?

And we will again update our =TOP-LEVEL/COMMAND= definition, this time
with our handler included.

#+begin_src lisp
(defun top-level/command ()
"Creates and returns the top-level command"
(clingon:make-command
:name "clingon-intro"
...
:handler #’top-level/handler)) ;; <- new code
#+end_src

At this point we are basically done with our simple application. But
before we move to the point where build our binary and start playing
with it on the command-line we can test things out on the REPL, just
to make sure everything works as expected.

** Testing things out on the REPL

Create a new instance of our command and bind it to some variable.

#+begin_src lisp
INTRO> (defparameter *app* (top-level/command))
*APP*
#+end_src

Inspecting the returned instance would give you something like this.

#+begin_src lisp
#<CLINGON.COMMAND:COMMAND {1004648293}>
——————–
Class: #<STANDARD-CLASS CLINGON.COMMAND:COMMAND>
——————–
Group slots by inheritance [ ]
Sort slots alphabetically [X]

All Slots:
[ ] ARGS-TO-PARSE = NIL
[ ] ARGUMENTS = NIL
[ ] AUTHORS = ("John Doe <john.doe@example.com>")
[ ] CONTEXT = #<HASH-TABLE :TEST EQUAL :COUNT 0 {1004648433}>
[ ] DESCRIPTION = "my first clingon cli app"
[ ] EXAMPLES = NIL
[ ] HANDLER = #<FUNCTION TOP-LEVEL/HANDLER>
[ ] LICENSE = "BSD 2-Clause"
[ ] LONG-DESCRIPTION = NIL
[ ] NAME = "clingon-intro"
[ ] OPTIONS = (#<CLINGON.OPTIONS:OPTION-BOOLEAN-TRUE short=NIL long=bash-completions> #<CLINGON.OPTIONS:OPTION-BOOLEAN-TRUE short=NIL long=version> #<CLINGON.OPTIONS:OPTION-BOOLEAN-TRUE short=NIL long=help> #<CLINGON.OPTIONS:OPTION-COUNTER short=v long=verbose> #<CLINGON.OPTIONS::OPTION-STRING short=u long=user>) [ ] PARENT = NIL
[ ] SUB-COMMANDS = NIL
[ ] USAGE = "[-v] [-u <USER>]"
[ ] VERSION = "0.1.0"

[set value] [make unbound]
#+end_src

You might also notice that besides the options we’ve defined ourselves,
there are few additional options, that we haven’t defined at all.

These options are automatically added by =clingon= itself for each new
command and provide flags for =–help=, =–version= and
=–bash-completions= for you automatically, so you don’t have to deal
with them manually.

Before we dive into testing out our application, first we will check
that we have a correct help information for our command.

#+begin_src lisp
INTRO> (clingon:print-usage *app* t)
NAME:
clingon-intro - my first clingon cli app

USAGE:
clingon-intro [-v] [-u <USER>]

OPTIONS:
–help display usage information and exit
–version display version and exit
-u, –user <VALUE> user to greet [default: stranger] [env: $USER]
-v, –verbose verbosity level [default: 0]

AUTHORS:
John Doe <john.doe@example.com>

LICENSE:
BSD 2-Clause

NIL
#+end_src

This help information will make it easier for our users, when they
need to use it. And that is automatically handled for you, so you
don’t have to manually maintain an up-to-date usage information, each
time you introduce a new option.

Time to test out our application on the REPL. In order to test things
out you can use the =CLINGON:PARSE-COMMAND-LINE= function by passing
it an instance of your command, along with any arguments that need to
be parsed. Let’s try it out without any command-line arguments.

#+begin_src lisp
INTRO> (clingon:parse-command-line *app* nil)
#<CLINGON.COMMAND:COMMAND name=clingon-intro options=5 sub-commands=0>
#+end_src

The =CLINGON:PARSE-COMMAND-LINE= function will (as the name suggests)
parse the given arguments against the options associated with our
command. Finally it will return an instance of =CLINGON:COMMAND=.

In our simple CLI application, that would be the same instance as our
=*APP*=, but things look differently when we have sub-commands.

When we start adding new sub-commands, the result of
=CLINGON:PARSE-COMMAND-LINE= will be different based on the arguments
it needs to parse. That means that if our input matches a sub-command
you will receive an instance of the sub-command that matched the given
arguments.

Internally the =clingon= system maintains a tree data structure,
describing the relationships between commands. This allows a command
to be related to some other command, and this is how the command and
sub-commands support is implemented in =clingon=.

Each command in =clingon= is associated with a /context/. The
/context/ or /environment/ provides the options and their values with
respect to the command itself. This means that a parent command and a
sub-command may have exactly the same set of options defined, but they
will reside in different contexts. Depending on how you use it,
sub-commands may /shadow/ a parent command option, but it also means
that a sub-command can refer to an option defined in a global command.

The /context/ of a command in =clingon= is available via the
=CLINGON:COMMAND-CONTEXT= accessor. We will use the context in order
to lookup our options and the values associated with them.

The function that operates on command’s context and retrieves
values from it is called =CLINGON:GETOPT=.

Let’s see what we’ve got for our options.

#+begin_src lisp
INTRO> (let ((c (clingon:parse-command-line *app* nil)))
(clingon:getopt c :user))
"dnaeon"
T
#+end_src

The =CLINGON:GETOPT= function returns multiple values – first one
specifies the value of the option, if it had any. And the second one
indicates whether or not that option has been set at all on the
command-line.

If you need to simply test things out and tell whether an option has
been set at all you can use the =CLINGON:OPT-IS-SET-P= function
instead.

Let’s try it out with a different input.

#+begin_src lisp
INTRO> (let ((c (clingon:parse-command-line *app* (list "-vvv" "–user" "foo"))))
(format t "Verbose is ~A~%" (clingon:getopt c :verbose))
(format t "User is ~A~%" (clingon:getopt c :user)))
Verbose is 3
User is foo
#+end_src

Something else, which is important to mention here. The default
precedence list for options is:

- The value provided by the =:INITIAL-VALUE= initarg
- The value of the first environment variable, which successfully resolved,
provided by the =:ENV-VARS= initarg
- The value provided on the command-line when invoking the application.

Play with it using different command-line arguments. If you specify
invalid or unknown options =clingon= will signal a condition and
provide you a few recovery options. For example, if you specify an
invalid flag like this:

#+begin_src lisp
INTRO> (clingon:parse-command-line *app* (list "–invalid-flag"))
#+end_src

We will be dropped into the debugger and be provided with restarts we
can choose from, e.g.

#+begin_src lisp
Unknown option –invalid-flag of kind LONG
[Condition of type CLINGON.CONDITIONS:UNKNOWN-OPTION]

Restarts:
0: [DISCARD-OPTION] Discard the unknown option
1: [TREAT-AS-ARGUMENT] Treat the unknown option as a free argument
2: [SUPPLY-NEW-VALUE] Supply a new value to be parsed
3: [RETRY] Retry SLY mREPL evaluation request.
4: [ABORT] Return to sly-db level 1.
5: [RETRY] Retry SLY mREPL evaluation request.
–more–
...
#+end_src

This is similar to the way other Common Lisp options parsing systems
behave such as [[https://github.com/sjl/adopt][adopt]] and [[https://github.com/libre-man/unix-opts][unix-opts]].

Also worth mentioning again here is that =CLINGON:PARSE-COMMAND-LINE= is
meant to be used within the REPL, and not called directly by handlers.

** Adding a sub-command

Sub-commands are no different than regular commands, and in fact are
created exactly the way we did it for our /top-level/ command.

#+begin_src lisp
(defun shout/handler (cmd)
"The handler for the ‘shout’ command"
(let ((args (mapcar #’string-upcase (clingon:command-arguments cmd)))
(user (clingon:getopt cmd :user))) ;; <- a global option
(format t "HEY, ~A!~%" user)
(format t "~A!~%" (clingon:join-list args #\Space))))

(defun shout/command ()
"Returns a command which SHOUTS back anything we write on the command-line"
(clingon:make-command
:name "shout"
:description "shouts back anything you write"
:usage "[options] [arguments ...]"
:handler #’shout/handler))
#+end_src

And now, we will wire up our sub-command making it part of the
/top-level/ command we have so far.

#+begin_src lisp
(defun top-level/command ()
"Creates and returns the top-level command"
(clingon:make-command
:name "clingon-intro"
...
:sub-commands (list (shout/command)))) ;; <- new code
#+end_src

You should also notice here that within the =SHOUT/HANDLER= we are
actually referencing an option, which is defined somewhere else. This
option is actually defined on our top-level command, but thanks’s to
the automatic management of relationships that =clingon= provides we
can now refer to global options as well.

Let’s move on to the final section of this guide, where we will create
a system definition for our application and build it.

** Packaging it up

One final piece which remains to be added to our code is to provide an
entrypoint for our application, so let’s do it now.

#+begin_src lisp
(defun main ()
(let ((app (top-level/command)))
(clingon:run app)))
#+end_src

This is the entrypoint which will be used when we invoke our
application on the command-line, which we’ll set in our ASDF
definition.

And here’s a simple system definition for the application we’ve
developed so far.

#+begin_src lisp
(defpackage :clingon-intro-system
(:use :cl :asdf))
(in-package :clingon-intro-system)

(defsystem "clingon.intro"
:name "clingon.intro"
:long-name "clingon.intro"
:description "An introduction to the clingon system"
:version "0.1.0"
:author "John Doe <john.doe@example.org>"
:license "BSD 2-Clause"
:depends-on (:clingon)
:components ((:module "intro"
:pathname #P"examples/intro/"
:components ((:file "intro"))))
:build-operation "program-op"
:build-pathname "clingon-intro"
:entry-point "clingon.intro:main")
#+end_src

Now we can build our application and start using it on the
command-line.

#+begin_src shell
sbcl –eval ’(ql:quickload :clingon.intro)’ \
–eval ’(asdf:make :clingon.intro)’ \
–eval ’(quit)’
#+end_src

This will produce a new binary called =clingon-intro= in the directory
of the =clingon.intro= system.

** Testing it out on the command-line

Time to check things up on the command-line.

#+begin_src shell
$ ./clingon-intro –help
NAME:
clingon-intro - my first clingon cli app

USAGE:
clingon-intro [-v] [-u <USER>]

OPTIONS:
–help display usage information and exit
–version display version and exit
-u, –user <VALUE> user to greet [default: stranger] [env: $USER]
-v, –verbose verbosity level [default: 0]

COMMANDS:
shout shouts back anything you write

AUTHORS:
John Doe <john.doe@example.com>

LICENSE:
BSD 2-Clause
#+end_src

Let’s try out our commands.

#+begin_src shell
$ ./clingon-intro -vvv –user Lisper
Hello, Lisper!
The current verbosity level is set to 3
You have provided 0 arguments
Bye.
#+end_src

And let’s try our sub-command as well.

#+begin_src shell
$ ./clingon-intro –user stranger shout why are yelling at me?
HEY, stranger!
WHY ARE YELLING AT ME?!
#+end_src

You can find the full code we’ve developed in this guide in the
[[https://github.com/dnaeon/clingon/tree/master/examples][clingon/examples]] directory of the repo.

* Exiting

When a command needs to exit with a given status code you can use the
=CLINGON:EXIT= function.

* Handling SIGINT (CTRL-C) signals

=clingon= by default will provide a handler for =SIGINT= signals,
which when detected will cause the application to immediately exit
with status code =130=.

If your commands need to provide some cleanup logic as part of their
job, e.g. close out all open files, TCP session, etc., you could wrap
your =clingon= command handlers in [[http://www.lispworks.com/documentation/HyperSpec/Body/s_unwind.htm][UNWIND-PROTECT]] to make sure that
your cleanup tasks are always executed.

However, using [[http://www.lispworks.com/documentation/HyperSpec/Body/s_unwind.htm][UNWIND-PROTECT]] may not be appropriate in all cases,
since the cleanup forms will always be executed, which may or may not
be what you need.

For example if you are developing a =clingon= application, which
populates a database in a transaction you would want to use
[[http://www.lispworks.com/documentation/HyperSpec/Body/s_unwind.htm][UNWIND-PROTECT]], but only for releasing the database connection itself.

If the application is interrupted while it inserts or updates records,
what you want to do is to rollback the transaction as well, so your
database is left in a consistent state.

In those situations you would want to use the [[https://github.com/compufox/with-user-abort][WITH-USER-ABORT]] system,
so that your =clingon= command can detect the =SIGINT= signal and act
upon it, e.g. taking care of rolling back the transaction.

* Generating Documentation

=clingon= can generate documentation for your application by using the
=CLINGON:PRINT-DOCUMENTATION= generic function.

Currently the documentation generator supports only the /Markdown/
format, but other formats can be developed as separate extensions to
=clingon=.

Here’s how you can generate the Markdown documentation for the
=clingon-demo= application from the REPL.

#+begin_src lisp
CL-USER> (ql:quickload :clingon.demo)
CL-USER> (in-package :clingon.demo)
DEMO> (with-open-file (out #P"clingon-demo.md" :direction :output)
(clingon:print-documentation :markdown (top-level/command) out))
#+end_src

You can also create a simple command, which can be added to your
=clingon= apps and have it generate the documentation for you, e.g.

#+begin_src lisp
(defun print-doc/command ()
"Returns a command which will print the app’s documentation"
(clingon:make-command
:name "print-doc"
:description "print the documentation"
:usage ""
:handler (lambda (cmd)
;; Print the documentation starting from the parent
;; command, so we can traverse all sub-commands in the
;; tree.
(clingon:print-documentation :markdown (clingon:command-parent cmd) t))))
#+end_src

Above command can be wired up anywhere in your application.

Make sure to also check the =clingon-demo= app, which provides a
=print-doc= sub-command, which operates on the /top-level/ command and
generates the documentation for all sub-commands.

You can also find the generated documentation for the =clingon-demo=
app in the =docs/= directory of the =clingon= repo.

* Command Hooks

=clingon= allows you to associate =pre= and =post= hooks with a
command.

The =pre= and =post= hooks are functions which will be invoked before
and after the respective command handler is executed. They are useful
in cases when you need to set up or tear things down before executing
the command’s handler.

An example of a =pre-hook= might be to configure the logging level of
your application based on the value of a global flag. A =post-hook=
might be responsible for shutting down any active connections, etc.

The =pre-hook= and =post-hook= functions accept a single argument,
which is an instance of =CLINGON:COMMAND=. That way the hooks can
examine the command’s context and lookup any flags or options.

Hooks are also hierachical in the sense that they will be executed
based on the command’s lineage.

Consider the following example, where we have a CLI app with three
commands.

#+begin_src text
main -> foo -> bar
#+end_src

In above example the =bar= command is a sub-command of =foo=, which in
turn is a sub-command of =main=. Also, consider that we have added
pre- and post-hooks to each command.

If a user executed the following on the command-line:

#+begin_src shell
$ main foo bar
#+end_src

Based on the above command-line =clingon= would do the following:

- Execute any =pre-hook= functions starting from the least-specific up to the
most-specific node from the commands’ lineage
- Execute the command’s handler
- Execute any =post-hook= functions starting from the most-specific down to the
least-specific node from the command’s lineage

In above example that would be:

#+begin_src text
> main (pre-hook)
>> foo (pre-hook)
>>> bar (pre-hook)
>>>> bar (handler)
>>> bar (post-hook)
>> foo (post-hook)
> main (post-hook)
#+end_src

Associating hooks with commands is done during instantiation of a
command. The following example creates a new command with a =pre-hook=
and =post-hook=.

#+begin_src lisp
(defun foo/pre-hook (cmd)
"The pre-hook for ‘foo’ command"
(declare (ignore cmd))
(format t "foo pre-hook has been invoked~&"))

(defun foo/post-hook (cmd)
"The post-hook for ‘foo’ command"
(declare (ignore cmd))
(format t "foo post-hook has been invoked~&"))

(defun foo/handler (cmd)
(declare (ignore cmd))
(format t "foo handler has been invoked~&"))

(defun foo/command ()
"Returns the ‘foo’ command"
(clingon:make-command
:name "foo"
:description "the foo command"
:authors ’("John Doe <john.doe@example.org>")
:handler #’foo/handler
:pre-hook #’foo/pre-hook
:post-hook #’foo/post-hook
:options nil
:sub-commands nil))
#+end_src

If we have executed above command we would see the following output.

#+begin_src shell
foo pre-hook has been invoked
foo handler has been invoked
foo post-hook has been invoked
#+end_src

* Options

The =clingon= system supports various kinds of options, each of which
is meant to serve a specific purpose.

Each builtin option can be initialized via environment variables, and
new mechanisms for initializing options can be developed, if needed.

Options are created via the single =CLINGON:MAKE-OPTION= interface.

The supported option kinds include:

- =counter=
- =integer=
- =string=
- =boolean=
- =boolean/true=
- =boolean/false=
- =choice=
- =enum=
- =list=
- =list/integer=
- =filepath=
- =list/filepath=
- etc.

** Counters Options

A =counter= is an option kind, which increments every time it is set
on the command-line.

A good example for =counter= options is to provide a flag, which
increases the verbosity level, depending on the number of times the
flag was provided, similar to the way =ssh(1)= does it, e.g.

#+begin_src shell
ssh -vvv user@host
#+end_src

Here’s an example of creating a =counter= option.

#+begin_src lisp
(clingon:make-option
:counter
:short-name #\v
:long-name "verbose"
:description "how noisy we want to be"
:key :verbose)
#+end_src

The default =step= for counters is set to =1=, but you can change
that, if needed.

#+begin_src lisp
(clingon:make-option
:counter
:short-name #\v
:long-name "verbose"
:description "how noisy we want to be"
:step 42
:key :verbose)
#+end_src

** Boolean Options

The following boolean option kinds are supported by =clingon=.

The =:boolean= kind is an option which expects an argument, which
represents a boolean value.

Arguments =true= and =1= map to =T= in Lisp, anything else is
considered a falsey value and maps to =NIL=.

#+begin_src lisp
(clingon:make-option
:boolean
:description "my boolean"
:short-name #\b
:long-name "my-boolean"
:key :boolean)
#+end_src

This creates an option =-b, –my-boolean <VALUE>=, which can be
provided on the command-line, where =<VALUE>= should be =true= or =1=
for truthy values, and anything else maps to =NIL=.

The =:boolean/true= option kind creates a flag, which always returns
=T=.

The =:boolean/false= option kind creates a flag, which always returns
=NIL=.

The =:flag= option kind is an alias for =:boolean/true=.

** Integer Options

Here’s an example of creating an option, which expects an integer
argument.

#+begin_src lisp
(clingon:make-option
:integer
:description "my integer opt"
:short-name #\i
:long-name "int"
:key :my-int
:initial-value 42)
#+end_src

** Choice Options

=choice= options are useful when you have to limit the arguments
provided on the command-line to a specific set of values.

For example:

#+begin_src lisp
(clingon:make-option
:choice
:description "log level"
:short-name #\l
:long-name "log-level"
:key :choice
:items ’("info" "warn" "error" "debug"))
#+end_src

With this option defined, you can now set the logging level only to
=info=, =warn=, =error= or =debug=, e.g.

#+begin_src shell
-l, –log-level [info|warn|error|debug]
#+end_src

** Enum Options

Enum options are similar to the =choice= options, but instead of
returning the value itself they can be mapped to something else.

For example:

#+begin_src lisp
(clingon:make-option
:enum
:description "enum option"
:short-name #\e
:long-name "my-enum"
:key :enum
:items ’(("one" . 1)
("two" . 2)
("three" . 3)))
#+end_src

If a user specifies =–my-enum=one= on the command-line the option
will be have the value =1= associated with it, when being looked up
via =CLINGON:GETOPT=.

The values you associate with the enum variant, can be any object.

This is one of the options being used by the /clingon-demo/
application, which maps user input to Lisp functions, in order to
perform some basic math operations.

#+begin_src lisp
(clingon:make-option
:enum
:description "operation to perform"
:short-name #\o
:long-name "operation"
:required t
:items ‘(("add" . ,#’+)
("sub" . ,#’-)
("mul" . ,#’*)
("div" . ,#’/))
:key :math/operation)
#+end_src

** List / Accumulator Options

The =:list= option kind accumulates each argument it is given on the
command-line into a list.

For example:

#+begin_src lisp
(clingon:make-option
:list
:description "files to process"
:short-name #\f
:long-name "file"
:key :files)
#+end_src

If you invoke an application, which uses a similar option like the one
above using the following command-line arguments:

#+begin_src shell
$ my-app –file foo –file bar –file baz
#+end_src

When you retrieve the value associated with your option, you will get a
list of all the files specified on the command-line, e.g.

#+begin_src lisp
(clingon:getopt cmd :files) ;; => ’("foo" "bar" "baz")
#+end_src

A similar option exists for integer values using the =:list/integer=
option, e.g.

#+begin_src lisp
(clingon:make-option
:list/integer
:description "list of integers"
:short-name #\l
:long-name "int"
:key :integers)
#+end_src

** Switch Options

=:SWITCH= options are a variation of =:BOOLEAN= options with an
associated list of known states that can turn a switch /on/ or
/off/.

Here is an example of a =:SWITCH= option.

#+begin_src lisp
(clingon:make-option
:switch
:description "my switch option"
:short-name #\s
:long-name "state"
:key :switch)
#+end_src

The default states for a switch to be considered as /on/ are:

- /on/, /yes/, /true/, /enable/ and /1/

The default states considered to turn the switch /off/ are:

- /off/, /no/, /false/, /disable/ and /0/

You can customize the list of /on/ and /off/ states by specifying them
using the =:ON-STATES= and =:OFF-STATES= initargs, e.g.

#+begin_src lisp
(clingon:make-option
:switch
:description "engine switch option"
:short-name #\s
:long-name "state"
:on-states ’("start")
:off-states ’("stop")
:key :engine)
#+end_src

These sample command-line arguments will turn a switch on and off.

#+begin_src shell
my-app –engine=start –engine=stop
#+end_src

The final value of the =:engine= option will be =NIL= in the above
example.

* Generic Functions Operating on Options

If the existing options provided by =clingon= are not enough for you,
and you need something a bit more specific for your use case, then you
can always implement a new option kind.

The following generic functions operate on options and are exported by
the =clingon= system.

- =CLINGON:INITILIAZE-OPTION=
- =CLINGON:FINALIZE-OPTION=
- =CLINGON:DERIVE-OPTION-VALUE=
- =CLINGON:OPTION-USAGE-DETAILS=
- =CLINGON:OPTION-DESCRIPTION-DETAILS=
- =CLINGON:MAKE-OPTION=

New option kinds should inherit from the =CLINGON:OPTION= class, which
implements all of the above generic functions. If you need to
customize the behaviour of your new option, you can still override the
default implementations.

** CLINGON:INITIALIZE-OPTION

The =CLINGON:INITIALIZE-OPTION= as the name suggests is being used to
initialize an option.

The default implementation of this generic function supports
initialization from environment variables, but implementors
can choose to support other initialization methods, e.g.
be able to initialize an option from a key/value store like
/Redis/, /Consul/ or /etcd/ for example.

** CLINGON:FINALIZE-OPTION

The =CLINGON:FINALIZE-OPTION= generic function is called after
all command-line arguments have been processed and values for them
have been derived already.

=CLINGON:FINALIZE-OPTION= is meant to /finalize/ the option’s value,
e.g. transform it to another object, if needed.

For example the =:BOOLEAN= option kind transforms user-provided input
like =true=, =false=, =1= and =0= into their respective Lisp counterparts
like =T= and =NIL=.

Another example where you might want to customize the behaviour of
=CLINGON:FINALIZE-OPTION= is to convert a string option provided on
the command-line, which represents a database connection string into
an actual session object for the database.

The default implementation of this generic function simply returns the
already set value, e.g. calls =#’IDENTITY= on the last derived value.

** CLINGON:DERIVE-OPTION-VALUE

The =CLINGON:DERIVE-OPTION-VALUE= is called whenever an option is
provided on the command-line.

If that option accepts an argument, it will be passed the respective
value from the command-line, otherwise it will be called with a =NIL=
argument.

Responsibility of the option is to derive a value from the given input
and return it to the caller. The returned value will be set by the
parser and later on it will be used to produce a final value, by
calling the =CLINGON:FINALIZE-OPTION= generic function.

Different kinds of options implement this one different – for example
the =:LIST= option kind accumulates each given argument, while others
ignore any previously derived values and return the last provided
argument.

The =:ENUM= option kind for example will derive a value from a
pre-defined list of allowed values.

If an option fails to derive a value (e.g. invalid value has been
provided) the implementation of this generic function should signal a
=CLINGON:OPTION-DERIVE-ERROR= condition, so that =clingon= can provide
appropriate restarts.

** CLINGON:OPTION-USAGE-DETAILS

This generic function is used to provide a pretty-printed usage format
for the given option. It will be used when printing usage information
on the command-line for the respective commands.

** CLINGON:OPTION-DESCRIPTION-DETAILS

This generic function is meant to enrich the description of the option
by providing as much details as possible for the given option, e.g.
listing the available values that an option can accept.

** CLINGON:MAKE-OPTION

The =CLINGON:MAKE-OPTION= generic function is the primary way for
creating new options. Implementors of new option kinds should simply
provide an implementation of this generic function, along with the
respective option kind.

Additional option kinds may be implemented as separate sub-systems,
but still follow the same principle by providing a single and
consistent interface for option creation.

* Developing New Options

This section contains short guides explaining how to develop new
options for =clingon=.

** Developing an Email Option

The option which we’ll develop in this section will be used for
specifying email addresses.

Start up your Lisp REPL session and do let’s some work. Load the
=:clingon= and =:cl-ppcre= systems, since we will need them.

#+begin_src lisp
CL-USER> (ql:quickload :clingon)
CL-USER> (ql:quickload :cl-ppcre)
#+end_src

We will first create a new package for our extension and import the
symbols we will need from the =:clingon= and =:cl-ppcre= systems.

#+begin_src lisp
(defpackage :clingon.extensions/option-email
(:use :cl)
(:import-from
:cl-ppcre
:scan)
(:import-from
:clingon
:option
:initialize-option
:derive-option-value
:make-option
:option-value
:option-derive-error)
(:export
:option-email))
(in-package :clingon.extensions/option-email)
#+end_src

Then lets define the class, which will represent an email address
option.

#+begin_src lisp
(defclass option-email (option)
((pattern
:initarg :pattern
:initform "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"
:reader option-email-pattern
:documentation "Pattern used to match for valid email addresses"))
(:default-initargs
:parameter "EMAIL")
(:documentation "An option used to represent an email address"))
#+end_src

Now we will implement =CLINGON:INITIALIZE-OPTION= for our new
option. We will keep the default initialization logic as-is, but also
add an additional step to validate the email address, if we have any
initial value at all.

#+begin_src lisp
(defmethod initialize-option ((option option-email) &key)
"Initializes our new email address option"
;; Make sure to invoke our parent initialization method first, so
;; various things like setting up initial value from environment
;; variables can still be applied.
(call-next-method)

;; If we don’t have any value set, there’s nothing else to
;; initialize further here.
(unless (option-value option)
(return-from initialize-option))

;; If we get to this point, that means we’ve got some initial value,
;; which is either set as a default, or via environment
;; variables. Next thing we need to do is make sure we’ve got a good
;; initial value, so let’s derive a value from it.
(let ((current (option-value option)))
(setf (option-value option)
(derive-option-value option current))))
#+end_src

Next we will implement =CLINGON:DERIVE-OPTION-VALUE= for our new
option kind.

#+begin_src lisp
(defmethod derive-option-value ((option option-email) arg &key)
"Derives a new value based on the given argument.
If the given ARG represents a valid email address according to the
pattern we know of we consider this as a valid email address."
(unless (scan (option-email-pattern option) arg)
(error ’option-derive-error :reason (format nil "~A is not a valid email address" arg)))
arg)
#+end_src

Finally, lets register our new option as a valid kind by implemeting
the =CLINGON:MAKE-OPTION= generic function.

#+begin_src lisp
(defmethod make-option ((kind (eql :email)) &rest rest)
(apply #’make-instance ’option-email rest))
#+end_src

We can test things out now. Go back to your REPL and try these
expressions out. First we make a new instance of our new option.

#+begin_src lisp
(defparameter *opt*
(make-option :email :short-name #\e :description "email opt" :key :email))
#+end_src

And now, lets validate a couple of good email addresses.

#+begin_src lisp
EXTENSIONS/OPTION-EMAIL> (derive-option-value *opt* "test@example.com")
"test@example.com"
EXTENSIONS/OPTION-EMAIL> (derive-option-value *opt* "foo@bar.com")
"foo@bar.com"
#+end_src

If we try deriving a value from a bad email address we will have a
condition of type =CLINGON:OPTION-DERIVE-ERROR= signalled.

#+begin_src lisp
EXTENSIONS/OPTION-EMAIL> (derive-option-value opt "bad-email-address-here")
; Debugger entered on #<OPTION-DERIVE-ERROR {1002946463}>
...
bad-email-address-here is not a valid email address
[Condition of type OPTION-DERIVE-ERROR]
#+end_src

Good, we can catch invalid email addresses as well. Whenever an option
fails to derive a new value from a given argument, and we signal
=CLINGON:OPTION-DERIVE-ERROR= condition we can recover by providing
new values or discarding them completely, thanks to the Common Lisp
Condition System.

Last thing to do is actually package this up as an extension system
and register it in Quicklisp. That way everyone else can benefit from
the newly developed option.

* Shell Completions

=clingon= provides support for Bash and Zsh shell completions.

** Bash Completions

In order to enable the Bash completions for your =clingon= app,
follow these instructions.

#+begin_src shell
APP=app-name source extras/completions.bash
#+end_src

Make sure to set =APP= to your correct application name.

The [[https://github.com/dnaeon/clingon/blob/master/extras/completions.bash][completions.bash]] script will dynamically provide completions by
invoking the =clingon= app with the =–bash-completions= flag. This
builtin flag when provided on the command-line will return completions
for the sub-commands and the available flags.

** Zsh Completions

When developing your CLI app with =clingon= you can provide an
additional command, which will take care of generating the Zsh
completion script for your users.

The following code can be used in your app and added as a sub-command
to your top-level command.

#+begin_src lisp
(defun zsh-completion/command ()
"Returns a command for generating the Zsh completion script"
(clingon:make-command
:name "zsh-completion"
:description "generate the Zsh completion script"
:usage ""
:handler (lambda (cmd)
;; Use the parent command when generating the completions,
;; so that we can traverse all sub-commands in the tree.
(let ((parent (clingon:command-parent cmd)))
(clingon:print-documentation :zsh-completions parent t)))))
#+end_src

You can also check out the =clingon-demo= app for a fully working CLI
app with Zsh completions support.

[[./images/clingon-zsh-completions.gif]]

* Ideas For Future Improvements

** Additional Documentation Generators

As of now =clingon= supports generating documentation only in /Markdown/
format.

Would be nice to have additional documentation generators, e.g.
/man pages/, /HTML/, etc.

** Performance Notes

=clingon= has been developed and tested on a GNU/Linux system using
SBCL.

Performance of the resulting binaries with SBCL seem to be good,
although I have noticed better performance when the binaries have been
produced with Clozure CL. And by better I mean better in terms of
binary size and speed (startup + run time).

Although you can enable compression on the image when using SBCL you
have to pay the extra price for the startup time.

Here are some additional details. Build the =clingon-demo= app with
SBCL.

#+begin_src shell
$ LISP=sbcl make demo
sbcl –eval ’(ql:quickload :clingon.demo)’ \
–eval ’(asdf:make :clingon.demo)’ \
–eval ’(quit)’
This is SBCL 2.1.7, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
To load "clingon.demo":
Load 1 ASDF system:
clingon.demo
; Loading "clingon.demo"
[package clingon.utils]...........................
[package clingon.conditions]......................
[package clingon.options].........................
[package clingon.command].........................
[package clingon].................................
[package clingon.demo]
[undoing binding stack and other enclosing state... done]
[performing final GC... done]
[defragmenting immobile space... (fin,inst,fdefn,code,sym)=1118+969+19070+19610+26536... done]
[saving current Lisp image into /home/dnaeon/Projects/lisp/clingon/clingon-demo:
writing 0 bytes from the read-only space at 0x50000000
writing 736 bytes from the static space at 0x50100000
writing 31391744 bytes from the dynamic space at 0x1000000000
writing 2072576 bytes from the immobile space at 0x50200000
writing 12341248 bytes from the immobile space at 0x52a00000
done]
#+end_src

Now, build it using Clozure CL.

#+begin_src shell
$ LISP=ccl make demo
ccl –eval ’(ql:quickload :clingon.demo)’ \
–eval ’(asdf:make :clingon.demo)’ \
–eval ’(quit)’
To load "clingon.demo":
Load 1 ASDF system:
clingon.demo
; Loading "clingon.demo"
[package clingon.utils]...........................
[package clingon.conditions]......................
[package clingon.options].........................
[package clingon.command].........................
[package clingon].................................
[package clingon.demo].
#+end_src

In terms of file size the binaries produced by Clozure CL are smaller.

#+begin_src shell
$ ls -lh clingon-demo*
-rwxr-xr-x 1 dnaeon dnaeon 33M Aug 20 12:56 clingon-demo.ccl
-rwxr-xr-x 1 dnaeon dnaeon 45M Aug 20 12:55 clingon-demo.sbcl
#+end_src

Generating the Markdown documentation for the demo app when using the
SBCL executable looks like this.

#+begin_src shell
$ time ./clingon-demo.sbcl print-doc > /dev/null

real 0m0.098s
user 0m0.071s
sys 0m0.027s
#+end_src

And when doing the same thing with the executable produced by Clozure
CL we see these results.

#+begin_src shell
$ time ./clingon-demo.ccl print-doc > /dev/null

real 0m0.017s
user 0m0.010s
sys 0m0.007s
#+end_src

* Tests

The =clingon= tests are provided as part of the =:clingon.test= system.

In order to run the tests you can evaluate the following expressions.

#+begin_src lisp
CL-USER> (ql:quickload :clingon.test)
CL-USER> (asdf:test-system :clingon.test)
#+end_src

Or you can run the tests using the =run-tests.sh= script instead, e.g.

#+begin_src shell
LISP=sbcl ./run-tests.sh
#+end_src

Here’s how to run the tests against SBCL, CCL and ECL for example.

#+begin_src shell
for lisp in sbcl ccl ecl; do
echo "Running tests using ${lisp} ..."
LISP=${lisp} make test > ${lisp}-tests.out
done
#+end_src

* Docker Images

A few Docker images are available.

Build and run the tests in a container.

#+begin_src shell
docker build -t clingon.test:latest -f Dockerfile.tests .
docker run –rm clingon.test:latest
#+end_src

Build and run the =clingon-intro= application.

#+begin_src shell
docker build -t clingon.intro:latest -f Dockerfile.intro .
docker run –rm clingon.intro:latest
#+end_src

Build and run the =clingon.demo= application.

#+begin_src lisp
docker build -t clingon.demo:latest -f Dockerfile.demo .
docker run –rm clingon.demo:latest
#+end_src

* Contributing

=clingon= is hosted on [[https://github.com/dnaeon/clingon][Github]]. Please contribute by reporting issues,
suggesting features or by sending patches using pull requests.

* License

This project is Open Source and licensed under the [[http://opensource.org/licenses/BSD-2-Clause][BSD License]].

* Authors

- Marin Atanasov Nikolov <dnaeon@gmail.com>

Version

0.3.5

Dependencies
Source

clingon.asd (file)

Components

Next: , Previous: , Up: Top   [Contents][Index]

3 Modules

Modules are listed depth-first from the system components tree.


Next: , Previous: , Up: Modules   [Contents][Index]

3.1 clingon/utils

Parent

clingon (system)

Location

src/

Component

utils.lisp (file)


Next: , Previous: , Up: Modules   [Contents][Index]

3.2 clingon/core

Dependency

utils (module)

Parent

clingon (system)

Location

src/

Components

Previous: , Up: Modules   [Contents][Index]

3.3 clingon/client-package

Dependency

core (module)

Parent

clingon (system)

Location

src/

Component

package.lisp (file)


Next: , Previous: , Up: Top   [Contents][Index]

4 Files

Files are sorted by type and then listed depth-first from the systems components trees.


Previous: , Up: Files   [Contents][Index]

4.1 Lisp


Next: , Previous: , Up: Lisp files   [Contents][Index]

4.1.1 clingon.asd

Location

clingon.asd

Systems

clingon (system)

Packages

clingon-system


Next: , Previous: , Up: Lisp files   [Contents][Index]

4.1.2 clingon/utils/utils.lisp

Parent

utils (module)

Location

src/utils.lisp

Packages

clingon.utils

Exported Definitions
Internal Definitions

argv (function)


Next: , Previous: , Up: Lisp files   [Contents][Index]

4.1.3 clingon/core/conditions.lisp

Parent

core (module)

Location

src/conditions.lisp

Packages

clingon.conditions

Exported Definitions

Next: , Previous: , Up: Lisp files   [Contents][Index]

4.1.4 clingon/core/options.lisp

Parent

core (module)

Location

src/options.lisp

Packages

clingon.options

Exported Definitions
Internal Definitions

Next: , Previous: , Up: Lisp files   [Contents][Index]

4.1.5 clingon/core/command.lisp

Dependencies
Parent

core (module)

Location

src/command.lisp

Packages

clingon.command

Exported Definitions
Internal Definitions

Previous: , Up: Lisp files   [Contents][Index]

4.1.6 clingon/client-package/package.lisp

Parent

client-package (module)

Location

src/package.lisp

Packages

clingon


Next: , Previous: , Up: Top   [Contents][Index]

5 Packages

Packages are listed by definition order.


Next: , Previous: , Up: Packages   [Contents][Index]

5.1 clingon-system

Source

clingon.asd

Use List

Next: , Previous: , Up: Packages   [Contents][Index]

5.2 clingon.utils

Source

utils.lisp (file)

Use List

common-lisp

Exported Definitions
Internal Definitions

argv (function)


Next: , Previous: , Up: Packages   [Contents][Index]

5.3 clingon.conditions

Source

conditions.lisp (file)

Use List

common-lisp

Exported Definitions

Next: , Previous: , Up: Packages   [Contents][Index]

5.4 clingon.options

Source

options.lisp (file)

Use List

common-lisp

Exported Definitions
Internal Definitions

Next: , Previous: , Up: Packages   [Contents][Index]

5.5 clingon.command

Source

command.lisp (file)

Use List

common-lisp

Exported Definitions
Internal Definitions

Previous: , Up: Packages   [Contents][Index]

5.6 clingon

Source

package.lisp (file)

Use List

common-lisp


Next: , Previous: , Up: Top   [Contents][Index]

6 Definitions

Definitions are sorted by export status, category, package, and then by lexicographic order.


Next: , Previous: , Up: Definitions   [Contents][Index]

6.1 Exported definitions


Next: , Previous: , Up: Exported definitions   [Contents][Index]

6.1.1 Special variables

Special Variable: *end-of-options-marker*

A marker specifying the end of options

Package

clingon.options

Source

options.lisp (file)


Next: , Previous: , Up: Exported definitions   [Contents][Index]

6.1.2 Macros

Macro: with-command-tree (NODE TOP-LEVEL) &body BODY

Evaluates BODY for each node in the command’s tree starting from TOP-LEVEL

Package

clingon.command

Source

command.lisp (file)


Next: , Previous: , Up: Exported definitions   [Contents][Index]

6.1.3 Functions

Function: discard-option CONDITION

A handler which can be used to invoke the ‘discard-option’ restart

Package

clingon.command

Source

command.lisp (file)

Function: end-of-options-p ARG

A predicate which returns T if the given argument specifies end of options

Package

clingon.options

Source

options.lisp (file)

Function: exit &optional CODE

Exit the program returning the given status code

Package

clingon.utils

Source

utils.lisp (file)

Function: git-rev-parse &key SHORT REV PATH

Returns the git revision with the given REV

Package

clingon.utils

Source

utils.lisp (file)

Function: group-by SEQUENCE PREDICATE

Groups the items from SEQUENCE based on the result from PREDICATE

Package

clingon.utils

Source

utils.lisp (file)

Function: hashtable-keys HTABLE

Returns the keys from the given hashtable

Package

clingon.utils

Source

utils.lisp (file)

Function: hashtable-values HTABLE

Returns the values from the given hashtable

Package

clingon.utils

Source

utils.lisp (file)

Function: join-list LIST SEPARATOR

Returns a string representing the items in the given LIST with SEPARATOR between each item

Package

clingon.utils

Source

utils.lisp (file)

Function: long-option-p ARG

A predicate which returns T if the given argument is a long option

Package

clingon.options

Source

options.lisp (file)

Function: make-command &rest REST

Creates a new COMMAND instance

Package

clingon.command

Source

command.lisp (file)

Function: missing-option-argument-p VALUE
Package

clingon.conditions

Source

conditions.lisp (file)

Function: option-derive-error-p VALUE
Package

clingon.conditions

Source

conditions.lisp (file)

Function: short-option-p ARG

A predicate which returns T if the given argument is a short option

Package

clingon.options

Source

options.lisp (file)

Function: treat-as-argument CONDITION

A handler which can be used to invoke the ‘treat-as-argument’ restart

Package

clingon.command

Source

command.lisp (file)

Function: unknown-option-p VALUE
Package

clingon.conditions

Source

conditions.lisp (file)

Function: walk ROOT NEIGHBORS-FUNC &key ORDER

Walks a tree structure starting from ROOT. Neighbors of each node are discovered by invoking the NEIGHBORS-FUNC function, which should accept a single argument – the node we are currently visiting, and should return a list of adjacent nodes.

The ORDER should be either :dfs or :bfs for Depth-First Search or Breadth-First Search respectively.

Package

clingon.utils

Source

utils.lisp (file)


Next: , Previous: , Up: Exported definitions   [Contents][Index]

6.1.4 Generic functions

Generic Function: apply-hooks KIND COMMAND &key

Applies any hooks associated with the given COMMAND

Package

clingon.command

Source

command.lisp (file)

Methods
Method: apply-hooks (KIND (eql post)) (COMMAND command) &key

Applies the post-hooks associated with command’s lineage
starting from the most-specific node down to the least-specific one

Method: apply-hooks (KIND (eql pre)) (COMMAND command) &key

Applies any pre-hooks associated with the command’s lineage starting from the least-specific node up to the most-specific one.

Generic Function: circular-dependency-items CONDITION
Package

clingon.conditions

Methods
Method: circular-dependency-items (CONDITION circular-dependency)
Source

conditions.lisp (file)

Generic Function: command-aliases OBJECT
Package

clingon.command

Methods
Method: command-aliases (COMMAND command)

Aliases of the command

Source

command.lisp (file)

Generic Function: command-args-to-parse OBJECT
Generic Function: (setf command-args-to-parse) NEW-VALUE OBJECT
Package

clingon.command

Methods
Method: command-args-to-parse (COMMAND command)
Method: (setf command-args-to-parse) NEW-VALUE (COMMAND command)

Arguments to be parsed based on the command options

Source

command.lisp (file)

Generic Function: command-arguments OBJECT
Generic Function: (setf command-arguments) NEW-VALUE OBJECT
Package

clingon.command

Methods
Method: command-arguments (COMMAND command)
Method: (setf command-arguments) NEW-VALUE (COMMAND command)

Discovered free arguments after parsing the options

Source

command.lisp (file)

Generic Function: command-authors OBJECT
Package

clingon.command

Methods
Method: command-authors (COMMAND command)

Authors of the command

Source

command.lisp (file)

Generic Function: command-description OBJECT
Package

clingon.command

Methods
Method: command-description (COMMAND command)

Short description of what the command does

Source

command.lisp (file)

Generic Function: command-examples OBJECT
Package

clingon.command

Methods
Method: command-examples (COMMAND command)

A list of examples describing how to use the command

Source

command.lisp (file)

Generic Function: command-full-name COMMAND
Package

clingon.command

Methods
Method: command-full-name (COMMAND command)

Returns a string representing the full name of the command

Source

command.lisp (file)

Generic Function: command-full-path COMMAND
Package

clingon.command

Methods
Method: command-full-path (COMMAND command)

Returns the full path to the command

Source

command.lisp (file)

Generic Function: command-handler OBJECT
Package

clingon.command

Methods
Method: command-handler (COMMAND command)

A function which accepts a single argument. The
argument is an instance of the COMMAND class, which provides the context and environment for options.

Source

command.lisp (file)

Generic Function: command-is-top-level-p TOP-LEVEL
Package

clingon.command

Methods
Method: command-is-top-level-p (TOP-LEVEL command)

Returns T if the command is a top-level command, NIL otherwise

Source

command.lisp (file)

Generic Function: command-license OBJECT
Package

clingon.command

Methods
Method: command-license (COMMAND command)

License for the command

Source

command.lisp (file)

Generic Function: command-lineage COMMAND
Package

clingon.command

Methods
Method: command-lineage (COMMAND command)

Returns the lineage of the command up to the root

Source

command.lisp (file)

Generic Function: command-long-description OBJECT
Package

clingon.command

Methods
Method: command-long-description (COMMAND command)

Long description of what the command does

Source

command.lisp (file)

Generic Function: command-name OBJECT
Package

clingon.command

Methods
Method: command-name (COMMAND command)

Command name

Source

command.lisp (file)

Generic Function: command-options OBJECT
Generic Function: (setf command-options) NEW-VALUE OBJECT
Package

clingon.command

Methods
Method: command-options (COMMAND command)
Method: (setf command-options) NEW-VALUE (COMMAND command)

Command options

Source

command.lisp (file)

Generic Function: command-parent OBJECT
Generic Function: (setf command-parent) NEW-VALUE OBJECT
Package

clingon.command

Methods
Method: command-parent (COMMAND command)
Method: (setf command-parent) NEW-VALUE (COMMAND command)

Parent command. This one will be automatically set during instantiation.

Source

command.lisp (file)

Generic Function: command-post-hook OBJECT
Package

clingon.command

Methods
Method: command-post-hook (COMMAND command)

A post-hook is a function which will be invoked
after the command handler is executed. The function must accept a single argument, which is an instance of the COMMAND class.

Source

command.lisp (file)

Generic Function: command-pre-hook OBJECT
Package

clingon.command

Methods
Method: command-pre-hook (COMMAND command)

A pre-hook is a function which will be invoked
before the command handler is executed. The function must accept a single argument, which is an instance of the COMMAND class.

Source

command.lisp (file)

Generic Function: command-sub-commands OBJECT
Package

clingon.command

Methods
Method: command-sub-commands (COMMAND command)

Sub-commands for the command

Source

command.lisp (file)

Generic Function: command-tree TOP-LEVEL
Package

clingon.command

Methods
Method: command-tree (TOP-LEVEL command)

Collects the nodes representing the command’s tree starting from TOP-LEVEL

Source

command.lisp (file)

Generic Function: command-usage OBJECT
Package

clingon.command

Methods
Method: command-usage (COMMAND command)

Usage information for the command

Source

command.lisp (file)

Generic Function: command-usage-string COMMAND
Package

clingon.command

Methods
Method: command-usage-string (COMMAND command)

Returns the usage string for the given command

Source

command.lisp (file)

Generic Function: command-version OBJECT
Package

clingon.command

Methods
Method: command-version (COMMAND command)

Version of the command

Source

command.lisp (file)

Generic Function: derive-option-value OPTION VALUE &key

Derives a new value for the option based on the given string VALUE

Package

clingon.options

Source

options.lisp (file)

Methods
Method: derive-option-value (OPTION option-switch) ARG &key
Method: derive-option-value (OPTION option-enum) ARG &key
Method: derive-option-value (OPTION option-choice) ARG &key
Method: derive-option-value (OPTION option-list-integer) ARG &key
Method: derive-option-value (OPTION option-integer) ARG &key
Method: derive-option-value (OPTION option-list) ARG &key
Method: derive-option-value (OPTION option-counter) ARG &key
Method: derive-option-value (OPTION option-boolean-false) ARG &key
Method: derive-option-value (OPTION option-boolean-true) ARG &key
Method: derive-option-value (OPTION option-boolean) ARG &key
Method: derive-option-value (OPTION option) ARG &key
Generic Function: duplicate-command-items CONDITION
Package

clingon.conditions

Methods
Method: duplicate-command-items (CONDITION duplicate-commands)
Source

conditions.lisp (file)

Generic Function: duplicate-option-items CONDITION
Package

clingon.conditions

Methods
Method: duplicate-option-items (CONDITION duplicate-options)
Source

conditions.lisp (file)

Generic Function: duplicate-option-kind CONDITION
Package

clingon.conditions

Methods
Method: duplicate-option-kind (CONDITION duplicate-options)
Source

conditions.lisp (file)

Generic Function: duplicate-option-name CONDITION
Package

clingon.conditions

Methods
Method: duplicate-option-name (CONDITION duplicate-options)
Source

conditions.lisp (file)

Generic Function: finalize-command COMMAND &key

Finalizes a command and derives the set of reduced options

Package

clingon.command

Source

command.lisp (file)

Methods
Method: finalize-command (COMMAND command) &key

Finalizes the command and derives the reduced set of option values

Generic Function: finalize-option OPTION &key

Finalizes an option, e.g. performs any value transformations

Package

clingon.options

Source

options.lisp (file)

Methods
Method: finalize-option (OPTION option-list) &key
Method: finalize-option (OPTION option-boolean) &key
Method: finalize-option (OPTION option) &key

Finalizes the value of the option

Generic Function: find-option KIND OBJECT NAME &key

Returns the option of the given KIND and NAME, or NIL otherwise

Package

clingon.command

Source

command.lisp (file)

Methods
Method: find-option (KIND (eql long)) (COMMAND command) NAME &key

Finds the option with the given long name

Method: find-option (KIND (eql short)) (COMMAND command) NAME &key

Finds the option with the given short name

Generic Function: find-sub-command COMMAND NAME &key
Package

clingon.command

Methods
Method: find-sub-command (COMMAND command) NAME &key

Returns the sub-command with the given name or alias

Source

command.lisp (file)

Generic Function: getopt COMMAND OPT-KEY &optional DEFAULT
Package

clingon.command

Methods
Method: getopt (COMMAND command) OPT-KEY &optional DEFAULT

Returns the value of the option with the given OPT-KEY,
by traversing the lineage of the given COMMAND,
starting from the most-specific to least-specific command.

Make sure to call GETOPT on a command, which has been
finalized.

For example, if we have the following command line:

$ my-app –verbose –some-flag foo-command –foo-flag bar-command –bar-flag –some-flag

Where ‘cmd’ is bound to the command named ‘bar-command’ then
the result of the following expression:

(clingon:getopt cmd :verbose)

Will return the global flag ‘–verbose’, which is associated with the
top-level ‘my-app’ command.

However, if we request the value of the ‘–some-flag’ option, which
is defined on both – ‘my-app’ and ‘bar-command’ then the following
expression:

(clingon:getopt cmd :bar-flag)

Will return the most-specific flag, which in this case is the one
defined on ‘bar-command’.

This approach allows sub-commands to re-use already defined global
flags and options, which are defined by other commands from their
lineage.

Source

command.lisp (file)

Generic Function: initialize-command COMMAND &key

Initializes a command

Package

clingon.command

Source

command.lisp (file)

Methods
Method: initialize-command (COMMAND command) &key

Initializes the command and the options associated with it.

Generic Function: initialize-option OPTION &key

Initializes an option, e.g. sets initial option value

Package

clingon.options

Source

options.lisp (file)

Methods
Method: initialize-option (OPTION option-switch) &key

Initializes the switch option kind

Method: initialize-option (OPTION option-enum) &key
Method: initialize-option (OPTION option-choice) &key
Method: initialize-option (OPTION option-list-integer) &key
Method: initialize-option (OPTION option-integer) &key

Initializes the integer option. In case the option was
first initialized by other means, such as environment variables, we make sure that the provided value is a valid integer.

Method: initialize-option (OPTION option-list) &key

Initializes a list option. If the option has been initialized via environment variables, the initial value for the list would be represented as a string. This method will ensure that if the option is initialized from a string source it is represented as a valid list before deriving any other values for the option.

Method: initialize-option (OPTION option) &key

Initialize the value of the option.

Environment variables take precedence over any initial-value configured for the option.

The first environment variable that resolves to a non-NIL result will be used to set the option.

Generic Function: invalid-option-item CONDITION
Package

clingon.conditions

Methods
Method: invalid-option-item (CONDITION invalid-option)
Source

conditions.lisp (file)

Generic Function: invalid-option-reason CONDITION
Package

clingon.conditions

Methods
Method: invalid-option-reason (CONDITION invalid-option)
Source

conditions.lisp (file)

Generic Function: make-option KIND &rest REST

Creates a new option of the given kind

Package

clingon.options

Source

options.lisp (file)

Methods
Method: make-option (KIND (eql switch)) &rest REST
Method: make-option (KIND (eql enum)) &rest REST
Method: make-option (KIND (eql choice)) &rest REST
Method: make-option (KIND (eql list/integer)) &rest REST
Method: make-option (KIND (eql integer)) &rest REST
Method: make-option (KIND (eql list/filepath)) &rest REST
Method: make-option (KIND (eql list)) &rest REST
Method: make-option (KIND (eql counter)) &rest REST
Method: make-option (KIND (eql boolean/false)) &rest REST
Method: make-option (KIND (eql flag)) &rest REST
Method: make-option (KIND (eql boolean/true)) &rest REST
Method: make-option (KIND (eql boolean)) &rest REST
Method: make-option (KIND (eql filepath)) &rest REST
Method: make-option (KIND (eql string)) &rest REST
Method: make-option (KIND (eql generic)) &rest REST

Creates a generic option

Generic Function: missing-option-argument-command CONDITION
Package

clingon.conditions

Methods
Method: missing-option-argument-command (CONDITION missing-option-argument)
Source

conditions.lisp (file)

Generic Function: missing-option-argument-item CONDITION
Package

clingon.conditions

Methods
Method: missing-option-argument-item (CONDITION missing-option-argument)
Source

conditions.lisp (file)

Generic Function: missing-required-option-value-command CONDITION
Package

clingon.conditions

Methods
Method: missing-required-option-value-command (CONDITION missing-required-option-value)
Source

conditions.lisp (file)

Generic Function: missing-required-option-value-item CONDITION
Package

clingon.conditions

Methods
Method: missing-required-option-value-item (CONDITION missing-required-option-value)
Source

conditions.lisp (file)

Generic Function: opt-is-set-p COMMAND OPT-KEY
Package

clingon.command

Methods
Method: opt-is-set-p (COMMAND command) OPT-KEY

Returns T if the OPT-KEY is defined anywhere in the command’s lineage

Source

command.lisp (file)

Generic Function: option-category OBJECT
Package

clingon.options

Methods
Method: option-category (OPTION option)

Category for the option. Options with the same category will be grouped together

Source

options.lisp (file)

Generic Function: option-choice-items OBJECT
Package

clingon.options

Methods
Method: option-choice-items (OPTION-CHOICE option-choice)

The available choices

Source

options.lisp (file)

Generic Function: option-counter-step OBJECT
Package

clingon.options

Methods
Method: option-counter-step (OPTION-COUNTER option-counter)

Numeric value to increase the counter with

Source

options.lisp (file)

Generic Function: option-derive-error-reason CONDITION
Package

clingon.conditions

Methods
Method: option-derive-error-reason (CONDITION option-derive-error)
Source

conditions.lisp (file)

Generic Function: option-description OBJECT
Package

clingon.options

Methods
Method: option-description (OPTION option)

Short description of the option

Source

options.lisp (file)

Generic Function: option-description-details KIND OBJECT &key

Returns a formatted and probably enriched content of the option’s description

Package

clingon.options

Source

options.lisp (file)

Methods
Method: option-description-details (KIND (eql zsh-option-spec)) (OPTION option-switch) &key
Method: option-description-details (KIND (eql zsh-option-spec)) (OPTION option-enum) &key
Method: option-description-details (KIND (eql default)) (OPTION option-enum) &key
Method: option-description-details (KIND (eql zsh-option-spec)) (OPTION option-choice) &key
Method: option-description-details (KIND (eql default)) (OPTION option-choice) &key
Method: option-description-details (KIND (eql zsh-option-spec)) (OPTION option-filepath) &key
Method: option-description-details (KIND (eql zsh-option-spec)) (OPTION option) &key
Method: option-description-details (KIND (eql default)) (OPTION option) &key
Generic Function: option-enum-items OBJECT
Package

clingon.options

Methods
Method: option-enum-items (OPTION-ENUM option-enum)

The enum variants and their associated values

Source

options.lisp (file)

Generic Function: option-env-vars OBJECT
Package

clingon.options

Methods
Method: option-env-vars (OPTION option)

List of env vars which can set the option value

Source

options.lisp (file)

Generic Function: option-hidden-p OBJECT
Package

clingon.options

Methods
Method: option-hidden-p (OPTION option)

Whether or not this option will be hidden on the usage pages

Source

options.lisp (file)

Generic Function: option-initial-value OBJECT
Package

clingon.options

Methods
Method: option-initial-value (OPTION option)

Initial value for the option

Source

options.lisp (file)

Generic Function: option-integer-radix OBJECT
Package

clingon.options

Methods
Method: option-integer-radix (OPTION-LIST-INTEGER option-list-integer)

automatically generated reader method

Source

options.lisp (file)

Method: option-integer-radix (OPTION-INTEGER option-integer)

automatically generated reader method

Source

options.lisp (file)

Generic Function: option-is-set-p OBJECT
Generic Function: (setf option-is-set-p) NEW-VALUE OBJECT
Package

clingon.options

Methods
Method: option-is-set-p (OPTION option)
Method: (setf option-is-set-p) NEW-VALUE (OPTION option)

Predicate which returns T if the option was set

Source

options.lisp (file)

Generic Function: option-key OBJECT
Package

clingon.options

Methods
Method: option-key (OPTION option)

Key used to associate the option with it’s value

Source

options.lisp (file)

Generic Function: option-list-separator OBJECT
Package

clingon.options

Methods
Method: option-list-separator (OPTION-LIST option-list)

Character used to separate items in a list represented as a string

Source

options.lisp (file)

Generic Function: option-long-name OBJECT
Package

clingon.options

Methods
Method: option-long-name (OPTION option)

Long option name

Source

options.lisp (file)

Generic Function: option-parameter OBJECT
Package

clingon.options

Methods
Method: option-parameter (OPTION option)

Option takes a parameter identified by the given name

Source

options.lisp (file)

Generic Function: option-required-p OBJECT
Package

clingon.options

Methods
Method: option-required-p (OPTION option)

Mark the option as required. Only valid if the option takes a parameter

Source

options.lisp (file)

Generic Function: option-short-name OBJECT
Package

clingon.options

Methods
Method: option-short-name (OPTION option)

Short option name

Source

options.lisp (file)

Generic Function: option-switch-off-states OBJECT
Package

clingon.options

Methods
Method: option-switch-off-states (OPTION-SWITCH option-switch)

The list of states considered to ‘deactivate’ the switch

Source

options.lisp (file)

Generic Function: option-switch-on-states OBJECT
Package

clingon.options

Methods
Method: option-switch-on-states (OPTION-SWITCH option-switch)

The list of states considered to ‘activate’ the switch

Source

options.lisp (file)

Generic Function: option-usage-details KIND OBJECT &key

Returns the usage details for the option as a
string. The returned string will be used for formatting and displaying the option as part of help pages.

Package

clingon.options

Source

options.lisp (file)

Methods
Method: option-usage-details (KIND (eql zsh-option-spec)) (OPTION option-list) &key

List options may be repeated on the command-line

Method: option-usage-details (KIND (eql zsh-option-spec)) (OPTION option-counter) &key

Counter options may be repeated on the command-line

Method: option-usage-details (KIND (eql zsh-option-spec)) (OPTION option) &key
Method: option-usage-details (KIND (eql default)) (OPTION option) &key
Generic Function: option-value OBJECT
Generic Function: (setf option-value) NEW-VALUE OBJECT
Package

clingon.options

Methods
Method: option-value (OPTION option)
Method: (setf option-value) NEW-VALUE (OPTION option)

Computed value after finalizing the option

Source

options.lisp (file)

Generic Function: parse-command-line TOP-LEVEL ARGUMENTS
Package

clingon.command

Methods
Method: parse-command-line (TOP-LEVEL command) ARGUMENTS

Parses the arguments for the given top-level command and returns the most-specific command that is matched against the given arguments. The returned command contains the environment for the command handler to be executed with already populated options.

Source

command.lisp (file)

Generic Function: parse-option KIND OBJECT &key

Parses an option of the given KIND

Package

clingon.command

Source

command.lisp (file)

Methods
Method: parse-option (KIND (eql long)) (COMMAND command) &key

Parses a long option

Method: parse-option (KIND (eql short)) (COMMAND command) &key

Parses a short option

Method: parse-option (KIND (eql free-argument)) (COMMAND command) &key

Consume the option and treat it as a free argument

Method: parse-option (KIND (eql consume-all-arguments)) (COMMAND command) &key

Consumes all arguments after the end-of-options flag

Generic Function: print-bash-completions COMMAND STREAM
Package

clingon.command

Methods
Method: print-bash-completions (COMMAND command) STREAM

Prints the bash completions for the given command

Source

command.lisp (file)

Generic Function: print-bash-completions-and-exit COMMAND STREAM
Package

clingon.command

Methods
Method: print-bash-completions-and-exit (COMMAND command) STREAM

Prints the bash completions for the given command and exits

Source

command.lisp (file)

Generic Function: print-documentation KIND COMMAND STREAM &key WRAP-AT

Prints the documentation of the given top-level command

Package

clingon.command

Source

command.lisp (file)

Methods
Method: print-documentation (KIND (eql zsh-completions)) (TOP-LEVEL command) STREAM &key

Prints the Zsh completion script for the given top-level command

Method: print-documentation (KIND (eql markdown)) (TOP-LEVEL command) STREAM &key WRAP-AT

Prints the documentation for the given TOP-LEVEL command in Markdown format

Generic Function: print-options-usage COMMAND STREAM &key WRAP-AT-WIDTH
Package

clingon.command

Methods
Method: print-options-usage (COMMAND command) STREAM &key WRAP-AT-WIDTH

Prints the usage information about the options for the given command

Source

command.lisp (file)

Generic Function: print-sub-commands-info COMMAND STREAM &key WRAP-AT-WIDTH
Package

clingon.command

Methods
Method: print-sub-commands-info (COMMAND command) STREAM &key WRAP-AT-WIDTH

Prints a summary of the sub-commands available for the command

Source

command.lisp (file)

Generic Function: print-usage COMMAND STREAM &key WRAP-AT

Prints the usage information of the command

Package

clingon.command

Source

command.lisp (file)

Methods
Method: print-usage (COMMAND command) STREAM &key WRAP-AT
Generic Function: print-usage-and-exit COMMAND STREAM
Package

clingon.command

Methods
Method: print-usage-and-exit (COMMAND command) STREAM
Source

command.lisp (file)

Generic Function: print-version-and-exit COMMAND STREAM
Package

clingon.command

Methods
Method: print-version-and-exit (COMMAND command) STREAM
Source

command.lisp (file)

Generic Function: run TOP-LEVEL &optional ARGUMENTS
Package

clingon.command

Methods
Method: run (TOP-LEVEL command) &optional ARGUMENTS

Runs the specified top-level command

Source

command.lisp (file)

Generic Function: unknown-option-kind CONDITION
Package

clingon.conditions

Methods
Method: unknown-option-kind (CONDITION unknown-option)
Source

conditions.lisp (file)

Generic Function: unknown-option-name CONDITION
Package

clingon.conditions

Methods
Method: unknown-option-name (CONDITION unknown-option)
Source

conditions.lisp (file)

Generic Function: validate-top-level-command TOP-LEVEL
Package

clingon.command

Methods
Method: validate-top-level-command (TOP-LEVEL command)

Validates the top-level command and it’s sub-commands

Source

command.lisp (file)

Generic Function: visible-options COMMAND
Package

clingon.command

Methods
Method: visible-options (COMMAND command)

Returns the list of visible options for the given command

Source

command.lisp (file)


Next: , Previous: , Up: Exported definitions   [Contents][Index]

6.1.5 Conditions

Condition: circular-dependency ()

A condition which is signalled when a circular dependency is detected

Package

clingon.conditions

Source

conditions.lisp (file)

Direct superclasses

simple-error (condition)

Direct methods

circular-dependency-items (method)

Direct slots
Slot: items
Initargs

:items

Initform

(quote (error "must specify items"))

Readers

circular-dependency-items (generic function)

Condition: duplicate-commands ()

A condition which is signalled when a command provides duplicate sub-commands

Package

clingon.conditions

Source

conditions.lisp (file)

Direct superclasses

simple-error (condition)

Direct methods

duplicate-command-items (method)

Direct slots
Slot: items
Initargs

:items

Initform

(quote (error "must specify duplicate items"))

Readers

duplicate-command-items (generic function)

Condition: duplicate-options ()

A condition which is signalled when a command provides duplicate options

Package

clingon.conditions

Source

conditions.lisp (file)

Direct superclasses

simple-error (condition)

Direct methods
Direct slots
Slot: kind
Initargs

:kind

Initform

(quote (error "must specify option kind"))

Readers

duplicate-option-kind (generic function)

Slot: items
Initargs

:items

Initform

(quote (error "must specify option items"))

Readers

duplicate-option-items (generic function)

Slot: name
Initargs

:name

Initform

(quote (error "must specify option name"))

Readers

duplicate-option-name (generic function)

Condition: invalid-option ()

A condition which is signalled when an option is identified as invalid

Package

clingon.conditions

Source

conditions.lisp (file)

Direct superclasses

simple-error (condition)

Direct methods
Direct slots
Slot: item

The option which is identified as invalid

Initargs

:item

Initform

(quote (error "must specify option item"))

Readers

invalid-option-item (generic function)

Slot: reason

The reason why this option is invalid

Initargs

:reason

Initform

(quote (error "must specify reason"))

Readers

invalid-option-reason (generic function)

Condition: missing-option-argument ()

A condition which is signalled when an option expects an argument, but none was provided

Package

clingon.conditions

Source

conditions.lisp (file)

Direct superclasses

simple-error (condition)

Direct methods
Direct slots
Slot: item
Initargs

:item

Initform

(quote (error "must specify option item"))

Readers

missing-option-argument-item (generic function)

Slot: command
Initargs

:command

Initform

(quote (error "must specify command"))

Readers

missing-option-argument-command (generic function)

Condition: missing-required-option-value ()

A condition which is signalled when a required option value was not set

Package

clingon.conditions

Source

conditions.lisp (file)

Direct superclasses

simple-error (condition)

Direct methods
Direct slots
Slot: item

The option item which requires a value

Initargs

:item

Initform

(quote (error "must specify option item"))

Readers

missing-required-option-value-item (generic function)

Slot: command

The command to which the option is associated

Initargs

:command

Initform

(quote (error "must specify command"))

Readers

missing-required-option-value-command (generic function)

Condition: option-derive-error ()

A condition which is signalled when deriving an option’s value has failed

Package

clingon.conditions

Source

conditions.lisp (file)

Direct superclasses

simple-error (condition)

Direct methods

option-derive-error-reason (method)

Direct slots
Slot: reason

Reason for which deriving a value failed

Initargs

:reason

Initform

(quote (error "must specify reason"))

Readers

option-derive-error-reason (generic function)

Condition: unknown-option ()

A condition which is signalled when an unknown option is seen

Package

clingon.conditions

Source

conditions.lisp (file)

Direct superclasses

error (condition)

Direct methods
Direct slots
Slot: name
Initargs

:name

Initform

(quote (error "must specify option name"))

Readers

unknown-option-name (generic function)

Slot: kind
Initargs

:kind

Initform

(quote (error "must specify option kind"))

Readers

unknown-option-kind (generic function)


Previous: , Up: Exported definitions   [Contents][Index]

6.1.6 Classes

Class: command ()

A class to represent a command to be handled

Package

clingon.command

Source

command.lisp (file)

Direct superclasses

standard-object (class)

Direct methods
Direct slots
Slot: name

Command name

Initargs

:name

Initform

(error "must specify command name")

Readers

command-name (generic function)

Slot: options

Command options

Initargs

:options

Readers

command-options (generic function)

Writers

(setf command-options) (generic function)

Slot: handler

A function which accepts a single argument. The
argument is an instance of the COMMAND class, which provides the context and environment for options.

Initargs

:handler

Readers

command-handler (generic function)

Slot: pre-hook

A pre-hook is a function which will be invoked
before the command handler is executed. The function must accept a single argument, which is an instance of the COMMAND class.

Initargs

:pre-hook

Readers

command-pre-hook (generic function)

Slot: post-hook

A post-hook is a function which will be invoked
after the command handler is executed. The function must accept a single argument, which is an instance of the COMMAND class.

Initargs

:post-hook

Readers

command-post-hook (generic function)

Slot: sub-commands

Sub-commands for the command

Initargs

:sub-commands

Readers

command-sub-commands (generic function)

Slot: parent

Parent command. This one will be automatically set during instantiation.

Initargs

:parent

Readers

command-parent (generic function)

Writers

(setf command-parent) (generic function)

Slot: args-to-parse

Arguments to be parsed based on the command options

Initargs

:args-to-parse

Readers

command-args-to-parse (generic function)

Writers

(setf command-args-to-parse) (generic function)

Slot: arguments

Discovered free arguments after parsing the options

Initargs

:arguments

Readers

command-arguments (generic function)

Writers

(setf command-arguments) (generic function)

Slot: context

The context contains the reduced set of options for the command

Initargs

:context

Initform

(make-hash-table :test (function equal))

Readers

command-context (generic function)

Writers

(setf command-context) (generic function)

Slot: version

Version of the command

Initargs

:version

Readers

command-version (generic function)

Slot: authors

Authors of the command

Initargs

:authors

Readers

command-authors (generic function)

Slot: license

License for the command

Initargs

:license

Readers

command-license (generic function)

Slot: description

Short description of what the command does

Initargs

:description

Readers

command-description (generic function)

Slot: long-description

Long description of what the command does

Initargs

:long-description

Readers

command-long-description (generic function)

Slot: examples

A list of examples describing how to use the command

Initargs

:examples

Readers

command-examples (generic function)

Slot: aliases

Aliases of the command

Initargs

:aliases

Readers

command-aliases (generic function)

Slot: usage

Usage information for the command

Initargs

:usage

Readers

command-usage (generic function)

Class: option ()

A class representing a command-line option

Package

clingon.options

Source

options.lisp (file)

Direct superclasses

standard-object (class)

Direct subclasses
Direct methods
Direct slots
Slot: parameter

Option takes a parameter identified by the given name

Initargs

:parameter

Readers

option-parameter (generic function)

Slot: required

Mark the option as required. Only valid if the option takes a parameter

Initargs

:required

Readers

option-required-p (generic function)

Slot: short-name

Short option name

Initargs

:short-name

Readers

option-short-name (generic function)

Slot: long-name

Long option name

Initargs

:long-name

Readers

option-long-name (generic function)

Slot: description

Short description of the option

Initargs

:description

Initform

(error "must specify description")

Readers

option-description (generic function)

Slot: category

Category for the option. Options with the same category will be grouped together

Initargs

:category

Initform

""

Readers

option-category (generic function)

Slot: env-vars

List of env vars which can set the option value

Initargs

:env-vars

Readers

option-env-vars (generic function)

Slot: initial-value

Initial value for the option

Initargs

:initial-value

Readers

option-initial-value (generic function)

Slot: key

Key used to associate the option with it’s value

Initargs

:key

Initform

(error "must specify option key")

Readers

option-key (generic function)

Slot: is-set-p

Predicate which returns T if the option was set

Initargs

:is-set-p

Readers

option-is-set-p (generic function)

Writers

(setf option-is-set-p) (generic function)

Slot: hidden

Whether or not this option will be hidden on the usage pages

Initargs

:hidden

Readers

option-hidden-p (generic function)

Slot: value

Computed value after finalizing the option

Initargs

:value

Readers

option-value (generic function)

Writers

(setf option-value) (generic function)

Class: option-boolean ()

An option which represents a boolean flag

Package

clingon.options

Source

options.lisp (file)

Direct superclasses

option (class)

Direct subclasses
Direct methods
Direct Default Initargs
InitargValue
:parameter"value"
Class: option-boolean-false ()

A boolean option which always returns false

Package

clingon.options

Source

options.lisp (file)

Direct superclasses

option-boolean (class)

Direct methods

derive-option-value (method)

Direct Default Initargs
InitargValue
:parameternil
Class: option-boolean-true ()

A boolean option which always returns true

Package

clingon.options

Source

options.lisp (file)

Direct superclasses

option-boolean (class)

Direct methods

derive-option-value (method)

Direct Default Initargs
InitargValue
:parameternil
Class: option-choice ()

An option which allows selecting an item from a predefined list

Package

clingon.options

Source

options.lisp (file)

Direct superclasses

option (class)

Direct methods
Direct slots
Slot: items

The available choices

Initargs

:items

Initform

(error "must specify available items")

Readers

option-choice-items (generic function)

Direct Default Initargs
InitargValue
:parameter"choice"
Class: option-counter ()

An option which increments every time it is set

Package

clingon.options

Source

options.lisp (file)

Direct superclasses

option (class)

Direct methods
Direct slots
Slot: step

Numeric value to increase the counter with

Initargs

:step

Initform

1

Readers

option-counter-step (generic function)

Direct Default Initargs
InitargValue
:initial-value0
Class: option-enum ()

An option which represents an enum with variants and associated values

Package

clingon.options

Source

options.lisp (file)

Direct superclasses

option (class)

Direct methods
Direct slots
Slot: items

The enum variants and their associated values

Initargs

:items

Initform

(error "must specify available variants")

Readers

option-enum-items (generic function)

Direct Default Initargs
InitargValue
:parameter"variant"
Class: option-filepath ()

An option which represents a filepath

Package

clingon.options

Source

options.lisp (file)

Direct superclasses

option (class)

Direct subclasses

option-list-filepath (class)

Direct methods

option-description-details (method)

Direct Default Initargs
InitargValue
:parameter"path"
Class: option-integer ()

An option class to represent an integer

Package

clingon.options

Source

options.lisp (file)

Direct superclasses

option (class)

Direct methods
Direct slots
Slot: radix
Initargs

:radix

Initform

10

Readers

option-integer-radix (generic function)

Direct Default Initargs
InitargValue
:parameter"int"
Class: option-list ()

An option which collects values into a list

Package

clingon.options

Source

options.lisp (file)

Direct superclasses

option (class)

Direct subclasses
Direct methods
Direct slots
Slot: separator

Character used to separate items in a list represented as a string

Initargs

:separator

Initform

#\,

Readers

option-list-separator (generic function)

Direct Default Initargs
InitargValue
:initial-valuenil
:parameter"item"
Class: option-list-filepath ()

An option which represents a list of filepaths

Package

clingon.options

Source

options.lisp (file)

Direct superclasses
Direct Default Initargs
InitargValue
:parameter"path"
Class: option-list-integer ()

An option which collects integers into a list

Package

clingon.options

Source

options.lisp (file)

Direct superclasses

option-list (class)

Direct methods
Direct slots
Slot: radix
Initargs

:radix

Initform

10

Readers

option-integer-radix (generic function)

Class: option-switch ()

An option which represents a switch with a state

Package

clingon.options

Source

options.lisp (file)

Direct superclasses

option-boolean (class)

Direct methods
Direct slots
Slot: on-states

The list of states considered to ‘activate’ the switch

Initargs

:on-states

Initform

(quote ("on" "yes" "true" "enable" "1"))

Readers

option-switch-on-states (generic function)

Slot: off-states

The list of states considered to ‘deactivate’ the switch

Initargs

:off-states

Initform

(quote ("off" "no" "false" "disable" "0"))

Readers

option-switch-off-states (generic function)

Direct Default Initargs
InitargValue
:parameter"state"

Previous: , Up: Definitions   [Contents][Index]

6.2 Internal definitions


Next: , Previous: , Up: Internal definitions   [Contents][Index]

6.2.1 Special variables

Special Variable: *default-bash-completions-flag*

The default ‘–bash-completions’ flag

Package

clingon.command

Source

command.lisp (file)

Special Variable: *default-help-flag*

The default ‘–help’ flag

Package

clingon.command

Source

command.lisp (file)

Special Variable: *default-options*

A list of default options to add to each sub-command

Package

clingon.command

Source

command.lisp (file)

Special Variable: *default-version-flag*

The default ‘–version’ flag

Package

clingon.command

Source

command.lisp (file)

Special Variable: *zsh-compfunc-with-sub-commands*

Template for a Zsh completion function which contains sub-commands

Package

clingon.command

Source

command.lisp (file)

Special Variable: *zsh-compfunc-without-sub-commands*

Template for a Zsh completion function without sub-commands

Package

clingon.command

Source

command.lisp (file)


Next: , Previous: , Up: Internal definitions   [Contents][Index]

6.2.2 Functions

Function: argv ()

Returns the list of command-line arguments

Package

clingon.utils

Source

utils.lisp (file)

Function: parse-integer-or-lose VALUE &key RADIX
Package

clingon.options

Source

options.lisp (file)


Next: , Previous: , Up: Internal definitions   [Contents][Index]

6.2.3 Generic functions

Generic Function: command-context OBJECT
Generic Function: (setf command-context) NEW-VALUE OBJECT
Package

clingon.command

Methods
Method: command-context (COMMAND command)
Method: (setf command-context) NEW-VALUE (COMMAND command)

The context contains the reduced set of options for the command

Source

command.lisp (file)

Generic Function: derive-option-with-restarts COMMAND OPTION OPTARG
Package

clingon.command

Methods
Method: derive-option-with-restarts (COMMAND command) (OPTION option) OPTARG

Provides possible restarts when deriving an option’s value

Source

command.lisp (file)

Generic Function: ensure-unique-options COMMAND
Package

clingon.command

Methods
Method: ensure-unique-options (COMMAND command)

Ensures that the given COMMAND does not contain duplicate options

Source

command.lisp (file)

Generic Function: ensure-unique-sub-commands COMMAND
Package

clingon.command

Methods
Method: ensure-unique-sub-commands (COMMAND command)

Ensure that the given COMMAND does not contain duplicate sub-command names

Source

command.lisp (file)

Generic Function: handle-missing-argument-with-restarts COMMAND OPTION
Package

clingon.command

Methods
Method: handle-missing-argument-with-restarts (COMMAND command) (OPTION option)

Provides possible restarts when an option requires an argument, but none was provided

Source

command.lisp (file)

Generic Function: handle-unknown-option-with-restarts COMMAND KIND FULL-NAME
Package

clingon.command

Methods
Method: handle-unknown-option-with-restarts (COMMAND command) KIND FULL-NAME

Provides possible restarts when an unknown option is detected

Source

command.lisp (file)

Generic Function: parse-command-line% COMMAND
Package

clingon.command

Methods
Method: parse-command-line% (COMMAND command)
Source

command.lisp (file)

Generic Function: zsh-sub-command-dispatch-items COMMAND
Package

clingon.command

Methods
Method: zsh-sub-command-dispatch-items (COMMAND command)

Returns a list of of command-name -> function-name dispatch strings, which will be used for populating into the Zsh completion function.

Source

command.lisp (file)

Generic Function: zsh-sub-command-items COMMAND
Package

clingon.command

Methods
Method: zsh-sub-command-items (COMMAND command)

Returns the sub-command items, which will be populated in the Zsh completion function

Source

command.lisp (file)


Previous: , Up: Internal definitions   [Contents][Index]

6.2.4 Classes

Class: option-string ()

An option which represents a string

Package

clingon.options

Source

options.lisp (file)

Direct superclasses

option (class)

Direct Default Initargs
InitargValue
:parameter"value"

Previous: , Up: Top   [Contents][Index]

Appendix A Indexes


Next: , Previous: , Up: Indexes   [Contents][Index]

A.1 Concepts

Jump to:   C   F   L   M  
Index Entry  Section

C
clingon.asd: The clingon․asd file
clingon/client-package: The clingon/client-package module
clingon/client-package/package.lisp: The clingon/client-package/package․lisp file
clingon/core: The clingon/core module
clingon/core/command.lisp: The clingon/core/command․lisp file
clingon/core/conditions.lisp: The clingon/core/conditions․lisp file
clingon/core/options.lisp: The clingon/core/options․lisp file
clingon/utils: The clingon/utils module
clingon/utils/utils.lisp: The clingon/utils/utils․lisp file

F
File, Lisp, clingon.asd: The clingon․asd file
File, Lisp, clingon/client-package/package.lisp: The clingon/client-package/package․lisp file
File, Lisp, clingon/core/command.lisp: The clingon/core/command․lisp file
File, Lisp, clingon/core/conditions.lisp: The clingon/core/conditions․lisp file
File, Lisp, clingon/core/options.lisp: The clingon/core/options․lisp file
File, Lisp, clingon/utils/utils.lisp: The clingon/utils/utils․lisp file

L
Lisp File, clingon.asd: The clingon․asd file
Lisp File, clingon/client-package/package.lisp: The clingon/client-package/package․lisp file
Lisp File, clingon/core/command.lisp: The clingon/core/command․lisp file
Lisp File, clingon/core/conditions.lisp: The clingon/core/conditions․lisp file
Lisp File, clingon/core/options.lisp: The clingon/core/options․lisp file
Lisp File, clingon/utils/utils.lisp: The clingon/utils/utils․lisp file

M
Module, clingon/client-package: The clingon/client-package module
Module, clingon/core: The clingon/core module
Module, clingon/utils: The clingon/utils module

Jump to:   C   F   L   M  

Next: , Previous: , Up: Indexes   [Contents][Index]

A.2 Functions

Jump to:   (  
A   C   D   E   F   G   H   I   J   L   M   O   P   R   S   T   U   V   W   Z  
Index Entry  Section

(
(setf command-args-to-parse): Exported generic functions
(setf command-args-to-parse): Exported generic functions
(setf command-arguments): Exported generic functions
(setf command-arguments): Exported generic functions
(setf command-context): Internal generic functions
(setf command-context): Internal generic functions
(setf command-options): Exported generic functions
(setf command-options): Exported generic functions
(setf command-parent): Exported generic functions
(setf command-parent): Exported generic functions
(setf option-is-set-p): Exported generic functions
(setf option-is-set-p): Exported generic functions
(setf option-value): Exported generic functions
(setf option-value): Exported generic functions

A
apply-hooks: Exported generic functions
apply-hooks: Exported generic functions
apply-hooks: Exported generic functions
argv: Internal functions

C
circular-dependency-items: Exported generic functions
circular-dependency-items: Exported generic functions
command-aliases: Exported generic functions
command-aliases: Exported generic functions
command-args-to-parse: Exported generic functions
command-args-to-parse: Exported generic functions
command-arguments: Exported generic functions
command-arguments: Exported generic functions
command-authors: Exported generic functions
command-authors: Exported generic functions
command-context: Internal generic functions
command-context: Internal generic functions
command-description: Exported generic functions
command-description: Exported generic functions
command-examples: Exported generic functions
command-examples: Exported generic functions
command-full-name: Exported generic functions
command-full-name: Exported generic functions
command-full-path: Exported generic functions
command-full-path: Exported generic functions
command-handler: Exported generic functions
command-handler: Exported generic functions
command-is-top-level-p: Exported generic functions
command-is-top-level-p: Exported generic functions
command-license: Exported generic functions
command-license: Exported generic functions
command-lineage: Exported generic functions
command-lineage: Exported generic functions
command-long-description: Exported generic functions
command-long-description: Exported generic functions
command-name: Exported generic functions
command-name: Exported generic functions
command-options: Exported generic functions
command-options: Exported generic functions
command-parent: Exported generic functions
command-parent: Exported generic functions
command-post-hook: Exported generic functions
command-post-hook: Exported generic functions
command-pre-hook: Exported generic functions
command-pre-hook: Exported generic functions
command-sub-commands: Exported generic functions
command-sub-commands: Exported generic functions
command-tree: Exported generic functions
command-tree: Exported generic functions
command-usage: Exported generic functions
command-usage: Exported generic functions
command-usage-string: Exported generic functions
command-usage-string: Exported generic functions
command-version: Exported generic functions
command-version: Exported generic functions

D
derive-option-value: Exported generic functions
derive-option-value: Exported generic functions
derive-option-value: Exported generic functions
derive-option-value: Exported generic functions
derive-option-value: Exported generic functions
derive-option-value: Exported generic functions
derive-option-value: Exported generic functions
derive-option-value: Exported generic functions
derive-option-value: Exported generic functions
derive-option-value: Exported generic functions
derive-option-value: Exported generic functions
derive-option-value: Exported generic functions
derive-option-with-restarts: Internal generic functions
derive-option-with-restarts: Internal generic functions
discard-option: Exported functions
duplicate-command-items: Exported generic functions
duplicate-command-items: Exported generic functions
duplicate-option-items: Exported generic functions
duplicate-option-items: Exported generic functions
duplicate-option-kind: Exported generic functions
duplicate-option-kind: Exported generic functions
duplicate-option-name: Exported generic functions
duplicate-option-name: Exported generic functions

E
end-of-options-p: Exported functions
ensure-unique-options: Internal generic functions
ensure-unique-options: Internal generic functions
ensure-unique-sub-commands: Internal generic functions
ensure-unique-sub-commands: Internal generic functions
exit: Exported functions

F
finalize-command: Exported generic functions
finalize-command: Exported generic functions
finalize-option: Exported generic functions
finalize-option: Exported generic functions
finalize-option: Exported generic functions
finalize-option: Exported generic functions
find-option: Exported generic functions
find-option: Exported generic functions
find-option: Exported generic functions
find-sub-command: Exported generic functions
find-sub-command: Exported generic functions
Function, argv: Internal functions
Function, discard-option: Exported functions
Function, end-of-options-p: Exported functions
Function, exit: Exported functions
Function, git-rev-parse: Exported functions
Function, group-by: Exported functions
Function, hashtable-keys: Exported functions
Function, hashtable-values: Exported functions
Function, join-list: Exported functions
Function, long-option-p: Exported functions
Function, make-command: Exported functions
Function, missing-option-argument-p: Exported functions
Function, option-derive-error-p: Exported functions
Function, parse-integer-or-lose: Internal functions
Function, short-option-p: Exported functions
Function, treat-as-argument: Exported functions
Function, unknown-option-p: Exported functions
Function, walk: Exported functions

G
Generic Function, (setf command-args-to-parse): Exported generic functions
Generic Function, (setf command-arguments): Exported generic functions
Generic Function, (setf command-context): Internal generic functions
Generic Function, (setf command-options): Exported generic functions
Generic Function, (setf command-parent): Exported generic functions
Generic Function, (setf option-is-set-p): Exported generic functions
Generic Function, (setf option-value): Exported generic functions
Generic Function, apply-hooks: Exported generic functions
Generic Function, circular-dependency-items: Exported generic functions
Generic Function, command-aliases: Exported generic functions
Generic Function, command-args-to-parse: Exported generic functions
Generic Function, command-arguments: Exported generic functions
Generic Function, command-authors: Exported generic functions
Generic Function, command-context: Internal generic functions
Generic Function, command-description: Exported generic functions
Generic Function, command-examples: Exported generic functions
Generic Function, command-full-name: Exported generic functions
Generic Function, command-full-path: Exported generic functions
Generic Function, command-handler: Exported generic functions
Generic Function, command-is-top-level-p: Exported generic functions
Generic Function, command-license: Exported generic functions
Generic Function, command-lineage: Exported generic functions
Generic Function, command-long-description: Exported generic functions
Generic Function, command-name: Exported generic functions
Generic Function, command-options: Exported generic functions
Generic Function, command-parent: Exported generic functions
Generic Function, command-post-hook: Exported generic functions
Generic Function, command-pre-hook: Exported generic functions
Generic Function, command-sub-commands: Exported generic functions
Generic Function, command-tree: Exported generic functions
Generic Function, command-usage: Exported generic functions
Generic Function, command-usage-string: Exported generic functions
Generic Function, command-version: Exported generic functions
Generic Function, derive-option-value: Exported generic functions
Generic Function, derive-option-with-restarts: Internal generic functions
Generic Function, duplicate-command-items: Exported generic functions
Generic Function, duplicate-option-items: Exported generic functions
Generic Function, duplicate-option-kind: Exported generic functions
Generic Function, duplicate-option-name: Exported generic functions
Generic Function, ensure-unique-options: Internal generic functions
Generic Function, ensure-unique-sub-commands: Internal generic functions
Generic Function, finalize-command: Exported generic functions
Generic Function, finalize-option: Exported generic functions
Generic Function, find-option: Exported generic functions
Generic Function, find-sub-command: Exported generic functions
Generic Function, getopt: Exported generic functions
Generic Function, handle-missing-argument-with-restarts: Internal generic functions
Generic Function, handle-unknown-option-with-restarts: Internal generic functions
Generic Function, initialize-command: Exported generic functions
Generic Function, initialize-option: Exported generic functions
Generic Function, invalid-option-item: Exported generic functions
Generic Function, invalid-option-reason: Exported generic functions
Generic Function, make-option: Exported generic functions
Generic Function, missing-option-argument-command: Exported generic functions
Generic Function, missing-option-argument-item: Exported generic functions
Generic Function, missing-required-option-value-command: Exported generic functions
Generic Function, missing-required-option-value-item: Exported generic functions
Generic Function, opt-is-set-p: Exported generic functions
Generic Function, option-category: Exported generic functions
Generic Function, option-choice-items: Exported generic functions
Generic Function, option-counter-step: Exported generic functions
Generic Function, option-derive-error-reason: Exported generic functions
Generic Function, option-description: Exported generic functions
Generic Function, option-description-details: Exported generic functions
Generic Function, option-enum-items: Exported generic functions
Generic Function, option-env-vars: Exported generic functions
Generic Function, option-hidden-p: Exported generic functions
Generic Function, option-initial-value: Exported generic functions
Generic Function, option-integer-radix: Exported generic functions
Generic Function, option-is-set-p: Exported generic functions
Generic Function, option-key: Exported generic functions
Generic Function, option-list-separator: Exported generic functions
Generic Function, option-long-name: Exported generic functions
Generic Function, option-parameter: Exported generic functions
Generic Function, option-required-p: Exported generic functions
Generic Function, option-short-name: Exported generic functions
Generic Function, option-switch-off-states: Exported generic functions
Generic Function, option-switch-on-states: Exported generic functions
Generic Function, option-usage-details: Exported generic functions
Generic Function, option-value: Exported generic functions
Generic Function, parse-command-line: Exported generic functions
Generic Function, parse-command-line%: Internal generic functions
Generic Function, parse-option: Exported generic functions
Generic Function, print-bash-completions: Exported generic functions
Generic Function, print-bash-completions-and-exit: Exported generic functions
Generic Function, print-documentation: Exported generic functions
Generic Function, print-options-usage: Exported generic functions
Generic Function, print-sub-commands-info: Exported generic functions
Generic Function, print-usage: Exported generic functions
Generic Function, print-usage-and-exit: Exported generic functions
Generic Function, print-version-and-exit: Exported generic functions
Generic Function, run: Exported generic functions
Generic Function, unknown-option-kind: Exported generic functions
Generic Function, unknown-option-name: Exported generic functions
Generic Function, validate-top-level-command: Exported generic functions
Generic Function, visible-options: Exported generic functions
Generic Function, zsh-sub-command-dispatch-items: Internal generic functions
Generic Function, zsh-sub-command-items: Internal generic functions
getopt: Exported generic functions
getopt: Exported generic functions
git-rev-parse: Exported functions
group-by: Exported functions

H
handle-missing-argument-with-restarts: Internal generic functions
handle-missing-argument-with-restarts: Internal generic functions
handle-unknown-option-with-restarts: Internal generic functions
handle-unknown-option-with-restarts: Internal generic functions
hashtable-keys: Exported functions
hashtable-values: Exported functions

I
initialize-command: Exported generic functions
initialize-command: Exported generic functions
initialize-option: Exported generic functions
initialize-option: Exported generic functions
initialize-option: Exported generic functions
initialize-option: Exported generic functions
initialize-option: Exported generic functions
initialize-option: Exported generic functions
initialize-option: Exported generic functions
initialize-option: Exported generic functions
invalid-option-item: Exported generic functions
invalid-option-item: Exported generic functions
invalid-option-reason: Exported generic functions
invalid-option-reason: Exported generic functions

J
join-list: Exported functions

L
long-option-p: Exported functions

M
Macro, with-command-tree: Exported macros
make-command: Exported functions
make-option: Exported generic functions
make-option: Exported generic functions
make-option: Exported generic functions
make-option: Exported generic functions
make-option: Exported generic functions
make-option: Exported generic functions
make-option: Exported generic functions
make-option: Exported generic functions
make-option: Exported generic functions
make-option: Exported generic functions
make-option: Exported generic functions
make-option: Exported generic functions
make-option: Exported generic functions
make-option: Exported generic functions
make-option: Exported generic functions
make-option: Exported generic functions
Method, (setf command-args-to-parse): Exported generic functions
Method, (setf command-arguments): Exported generic functions
Method, (setf command-context): Internal generic functions
Method, (setf command-options): Exported generic functions
Method, (setf command-parent): Exported generic functions
Method, (setf option-is-set-p): Exported generic functions
Method, (setf option-value): Exported generic functions
Method, apply-hooks: Exported generic functions
Method, apply-hooks: Exported generic functions
Method, circular-dependency-items: Exported generic functions
Method, command-aliases: Exported generic functions
Method, command-args-to-parse: Exported generic functions
Method, command-arguments: Exported generic functions
Method, command-authors: Exported generic functions
Method, command-context: Internal generic functions
Method, command-description: Exported generic functions
Method, command-examples: Exported generic functions
Method, command-full-name: Exported generic functions
Method, command-full-path: Exported generic functions
Method, command-handler: Exported generic functions
Method, command-is-top-level-p: Exported generic functions
Method, command-license: Exported generic functions
Method, command-lineage: Exported generic functions
Method, command-long-description: Exported generic functions
Method, command-name: Exported generic functions
Method, command-options: Exported generic functions
Method, command-parent: Exported generic functions
Method, command-post-hook: Exported generic functions
Method, command-pre-hook: Exported generic functions
Method, command-sub-commands: Exported generic functions
Method, command-tree: Exported generic functions
Method, command-usage: Exported generic functions
Method, command-usage-string: Exported generic functions
Method, command-version: Exported generic functions
Method, derive-option-value: Exported generic functions
Method, derive-option-value: Exported generic functions
Method, derive-option-value: Exported generic functions
Method, derive-option-value: Exported generic functions
Method, derive-option-value: Exported generic functions
Method, derive-option-value: Exported generic functions
Method, derive-option-value: Exported generic functions
Method, derive-option-value: Exported generic functions
Method, derive-option-value: Exported generic functions
Method, derive-option-value: Exported generic functions
Method, derive-option-value: Exported generic functions
Method, derive-option-with-restarts: Internal generic functions
Method, duplicate-command-items: Exported generic functions
Method, duplicate-option-items: Exported generic functions
Method, duplicate-option-kind: Exported generic functions
Method, duplicate-option-name: Exported generic functions
Method, ensure-unique-options: Internal generic functions
Method, ensure-unique-sub-commands: Internal generic functions
Method, finalize-command: Exported generic functions
Method, finalize-option: Exported generic functions
Method, finalize-option: Exported generic functions
Method, finalize-option: Exported generic functions
Method, find-option: Exported generic functions
Method, find-option: Exported generic functions
Method, find-sub-command: Exported generic functions
Method, getopt: Exported generic functions
Method, handle-missing-argument-with-restarts: Internal generic functions
Method, handle-unknown-option-with-restarts: Internal generic functions
Method, initialize-command: Exported generic functions
Method, initialize-option: Exported generic functions
Method, initialize-option: Exported generic functions
Method, initialize-option: Exported generic functions
Method, initialize-option: Exported generic functions
Method, initialize-option: Exported generic functions
Method, initialize-option: Exported generic functions
Method, initialize-option: Exported generic functions
Method, invalid-option-item: Exported generic functions
Method, invalid-option-reason: Exported generic functions
Method, make-option: Exported generic functions
Method, make-option: Exported generic functions
Method, make-option: Exported generic functions
Method, make-option: Exported generic functions
Method, make-option: Exported generic functions
Method, make-option: Exported generic functions
Method, make-option: Exported generic functions
Method, make-option: Exported generic functions
Method, make-option: Exported generic functions
Method, make-option: Exported generic functions
Method, make-option: Exported generic functions
Method, make-option: Exported generic functions
Method, make-option: Exported generic functions
Method, make-option: Exported generic functions
Method, make-option: Exported generic functions
Method, missing-option-argument-command: Exported generic functions
Method, missing-option-argument-item: Exported generic functions
Method, missing-required-option-value-command: Exported generic functions
Method, missing-required-option-value-item: Exported generic functions
Method, opt-is-set-p: Exported generic functions
Method, option-category: Exported generic functions
Method, option-choice-items: Exported generic functions
Method, option-counter-step: Exported generic functions
Method, option-derive-error-reason: Exported generic functions
Method, option-description: Exported generic functions
Method, option-description-details: Exported generic functions
Method, option-description-details: Exported generic functions
Method, option-description-details: Exported generic functions
Method, option-description-details: Exported generic functions
Method, option-description-details: Exported generic functions
Method, option-description-details: Exported generic functions
Method, option-description-details: Exported generic functions
Method, option-description-details: Exported generic functions
Method, option-enum-items: Exported generic functions
Method, option-env-vars: Exported generic functions
Method, option-hidden-p: Exported generic functions
Method, option-initial-value: Exported generic functions
Method, option-integer-radix: Exported generic functions
Method, option-integer-radix: Exported generic functions
Method, option-is-set-p: Exported generic functions
Method, option-key: Exported generic functions
Method, option-list-separator: Exported generic functions
Method, option-long-name: Exported generic functions
Method, option-parameter: Exported generic functions
Method, option-required-p: Exported generic functions
Method, option-short-name: Exported generic functions
Method, option-switch-off-states: Exported generic functions
Method, option-switch-on-states: Exported generic functions
Method, option-usage-details: Exported generic functions
Method, option-usage-details: Exported generic functions
Method, option-usage-details: Exported generic functions
Method, option-usage-details: Exported generic functions
Method, option-value: Exported generic functions
Method, parse-command-line: Exported generic functions
Method, parse-command-line%: Internal generic functions
Method, parse-option: Exported generic functions
Method, parse-option: Exported generic functions
Method, parse-option: Exported generic functions
Method, parse-option: Exported generic functions
Method, print-bash-completions: Exported generic functions
Method, print-bash-completions-and-exit: Exported generic functions
Method, print-documentation: Exported generic functions
Method, print-documentation: Exported generic functions
Method, print-options-usage: Exported generic functions
Method, print-sub-commands-info: Exported generic functions
Method, print-usage: Exported generic functions
Method, print-usage-and-exit: Exported generic functions
Method, print-version-and-exit: Exported generic functions
Method, run: Exported generic functions
Method, unknown-option-kind: Exported generic functions
Method, unknown-option-name: Exported generic functions
Method, validate-top-level-command: Exported generic functions
Method, visible-options: Exported generic functions
Method, zsh-sub-command-dispatch-items: Internal generic functions
Method, zsh-sub-command-items: Internal generic functions
missing-option-argument-command: Exported generic functions
missing-option-argument-command: Exported generic functions
missing-option-argument-item: Exported generic functions
missing-option-argument-item: Exported generic functions
missing-option-argument-p: Exported functions
missing-required-option-value-command: Exported generic functions
missing-required-option-value-command: Exported generic functions
missing-required-option-value-item: Exported generic functions
missing-required-option-value-item: Exported generic functions

O
opt-is-set-p: Exported generic functions
opt-is-set-p: Exported generic functions
option-category: Exported generic functions
option-category: Exported generic functions
option-choice-items: Exported generic functions
option-choice-items: Exported generic functions
option-counter-step: Exported generic functions
option-counter-step: Exported generic functions
option-derive-error-p: Exported functions
option-derive-error-reason: Exported generic functions
option-derive-error-reason: Exported generic functions
option-description: Exported generic functions
option-description: Exported generic functions
option-description-details: Exported generic functions
option-description-details: Exported generic functions
option-description-details: Exported generic functions
option-description-details: Exported generic functions
option-description-details: Exported generic functions
option-description-details: Exported generic functions
option-description-details: Exported generic functions
option-description-details: Exported generic functions
option-description-details: Exported generic functions
option-enum-items: Exported generic functions
option-enum-items: Exported generic functions
option-env-vars: Exported generic functions
option-env-vars: Exported generic functions
option-hidden-p: Exported generic functions
option-hidden-p: Exported generic functions
option-initial-value: Exported generic functions
option-initial-value: Exported generic functions
option-integer-radix: Exported generic functions
option-integer-radix: Exported generic functions
option-integer-radix: Exported generic functions
option-is-set-p: Exported generic functions
option-is-set-p: Exported generic functions
option-key: Exported generic functions
option-key: Exported generic functions
option-list-separator: Exported generic functions
option-list-separator: Exported generic functions
option-long-name: Exported generic functions
option-long-name: Exported generic functions
option-parameter: Exported generic functions
option-parameter: Exported generic functions
option-required-p: Exported generic functions
option-required-p: Exported generic functions
option-short-name: Exported generic functions
option-short-name: Exported generic functions
option-switch-off-states: Exported generic functions
option-switch-off-states: Exported generic functions
option-switch-on-states: Exported generic functions
option-switch-on-states: Exported generic functions
option-usage-details: Exported generic functions
option-usage-details: Exported generic functions
option-usage-details: Exported generic functions
option-usage-details: Exported generic functions
option-usage-details: Exported generic functions
option-value: Exported generic functions
option-value: Exported generic functions

P
parse-command-line: Exported generic functions
parse-command-line: Exported generic functions
parse-command-line%: Internal generic functions
parse-command-line%: Internal generic functions
parse-integer-or-lose: Internal functions
parse-option: Exported generic functions
parse-option: Exported generic functions
parse-option: Exported generic functions
parse-option: Exported generic functions
parse-option: Exported generic functions
print-bash-completions: Exported generic functions
print-bash-completions: Exported generic functions
print-bash-completions-and-exit: Exported generic functions
print-bash-completions-and-exit: Exported generic functions
print-documentation: Exported generic functions
print-documentation: Exported generic functions
print-documentation: Exported generic functions
print-options-usage: Exported generic functions
print-options-usage: Exported generic functions
print-sub-commands-info: Exported generic functions
print-sub-commands-info: Exported generic functions
print-usage: Exported generic functions
print-usage: Exported generic functions
print-usage-and-exit: Exported generic functions
print-usage-and-exit: Exported generic functions
print-version-and-exit: Exported generic functions
print-version-and-exit: Exported generic functions

R
run: Exported generic functions
run: Exported generic functions

S
short-option-p: Exported functions

T
treat-as-argument: Exported functions

U
unknown-option-kind: Exported generic functions
unknown-option-kind: Exported generic functions
unknown-option-name: Exported generic functions
unknown-option-name: Exported generic functions
unknown-option-p: Exported functions

V
validate-top-level-command: Exported generic functions
validate-top-level-command: Exported generic functions
visible-options: Exported generic functions
visible-options: Exported generic functions

W
walk: Exported functions
with-command-tree: Exported macros

Z
zsh-sub-command-dispatch-items: Internal generic functions
zsh-sub-command-dispatch-items: Internal generic functions
zsh-sub-command-items: Internal generic functions
zsh-sub-command-items: Internal generic functions

Jump to:   (  
A   C   D   E   F   G   H   I   J   L   M   O   P   R   S   T   U   V   W   Z  

Next: , Previous: , Up: Indexes   [Contents][Index]

A.3 Variables

Jump to:   *  
A   C   D   E   H   I   K   L   N   O   P   R   S   U   V  
Index Entry  Section

*
*default-bash-completions-flag*: Internal special variables
*default-help-flag*: Internal special variables
*default-options*: Internal special variables
*default-version-flag*: Internal special variables
*end-of-options-marker*: Exported special variables
*zsh-compfunc-with-sub-commands*: Internal special variables
*zsh-compfunc-without-sub-commands*: Internal special variables

A
aliases: Exported classes
args-to-parse: Exported classes
arguments: Exported classes
authors: Exported classes

C
category: Exported classes
command: Exported conditions
command: Exported conditions
context: Exported classes

D
description: Exported classes
description: Exported classes

E
env-vars: Exported classes
examples: Exported classes

H
handler: Exported classes
hidden: Exported classes

I
initial-value: Exported classes
is-set-p: Exported classes
item: Exported conditions
item: Exported conditions
item: Exported conditions
items: Exported conditions
items: Exported conditions
items: Exported conditions
items: Exported classes
items: Exported classes

K
key: Exported classes
kind: Exported conditions
kind: Exported conditions

L
license: Exported classes
long-description: Exported classes
long-name: Exported classes

N
name: Exported conditions
name: Exported conditions
name: Exported classes

O
off-states: Exported classes
on-states: Exported classes
options: Exported classes

P
parameter: Exported classes
parent: Exported classes
post-hook: Exported classes
pre-hook: Exported classes

R
radix: Exported classes
radix: Exported classes
reason: Exported conditions
reason: Exported conditions
required: Exported classes

S
separator: Exported classes
short-name: Exported classes
Slot, aliases: Exported classes
Slot, args-to-parse: Exported classes
Slot, arguments: Exported classes
Slot, authors: Exported classes
Slot, category: Exported classes
Slot, command: Exported conditions
Slot, command: Exported conditions
Slot, context: Exported classes
Slot, description: Exported classes
Slot, description: Exported classes
Slot, env-vars: Exported classes
Slot, examples: Exported classes
Slot, handler: Exported classes
Slot, hidden: Exported classes
Slot, initial-value: Exported classes
Slot, is-set-p: Exported classes
Slot, item: Exported conditions
Slot, item: Exported conditions
Slot, item: Exported conditions
Slot, items: Exported conditions
Slot, items: Exported conditions
Slot, items: Exported conditions
Slot, items: Exported classes
Slot, items: Exported classes
Slot, key: Exported classes
Slot, kind: Exported conditions
Slot, kind: Exported conditions
Slot, license: Exported classes
Slot, long-description: Exported classes
Slot, long-name: Exported classes
Slot, name: Exported conditions
Slot, name: Exported conditions
Slot, name: Exported classes
Slot, off-states: Exported classes
Slot, on-states: Exported classes
Slot, options: Exported classes
Slot, parameter: Exported classes
Slot, parent: Exported classes
Slot, post-hook: Exported classes
Slot, pre-hook: Exported classes
Slot, radix: Exported classes
Slot, radix: Exported classes
Slot, reason: Exported conditions
Slot, reason: Exported conditions
Slot, required: Exported classes
Slot, separator: Exported classes
Slot, short-name: Exported classes
Slot, step: Exported classes
Slot, sub-commands: Exported classes
Slot, usage: Exported classes
Slot, value: Exported classes
Slot, version: Exported classes
Special Variable, *default-bash-completions-flag*: Internal special variables
Special Variable, *default-help-flag*: Internal special variables
Special Variable, *default-options*: Internal special variables
Special Variable, *default-version-flag*: Internal special variables
Special Variable, *end-of-options-marker*: Exported special variables
Special Variable, *zsh-compfunc-with-sub-commands*: Internal special variables
Special Variable, *zsh-compfunc-without-sub-commands*: Internal special variables
step: Exported classes
sub-commands: Exported classes

U
usage: Exported classes

V
value: Exported classes
version: Exported classes

Jump to:   *  
A   C   D   E   H   I   K   L   N   O   P   R   S   U   V  

Previous: , Up: Indexes   [Contents][Index]

A.4 Data types

Jump to:   C   D   I   M   O   P   S   U  
Index Entry  Section

C
circular-dependency: Exported conditions
Class, command: Exported classes
Class, option: Exported classes
Class, option-boolean: Exported classes
Class, option-boolean-false: Exported classes
Class, option-boolean-true: Exported classes
Class, option-choice: Exported classes
Class, option-counter: Exported classes
Class, option-enum: Exported classes
Class, option-filepath: Exported classes
Class, option-integer: Exported classes
Class, option-list: Exported classes
Class, option-list-filepath: Exported classes
Class, option-list-integer: Exported classes
Class, option-string: Internal classes
Class, option-switch: Exported classes
clingon: The clingon system
clingon: The clingon package
clingon-system: The clingon-system package
clingon.command: The clingon․command package
clingon.conditions: The clingon․conditions package
clingon.options: The clingon․options package
clingon.utils: The clingon․utils package
command: Exported classes
Condition, circular-dependency: Exported conditions
Condition, duplicate-commands: Exported conditions
Condition, duplicate-options: Exported conditions
Condition, invalid-option: Exported conditions
Condition, missing-option-argument: Exported conditions
Condition, missing-required-option-value: Exported conditions
Condition, option-derive-error: Exported conditions
Condition, unknown-option: Exported conditions

D
duplicate-commands: Exported conditions
duplicate-options: Exported conditions

I
invalid-option: Exported conditions

M
missing-option-argument: Exported conditions
missing-required-option-value: Exported conditions

O
option: Exported classes
option-boolean: Exported classes
option-boolean-false: Exported classes
option-boolean-true: Exported classes
option-choice: Exported classes
option-counter: Exported classes
option-derive-error: Exported conditions
option-enum: Exported classes
option-filepath: Exported classes
option-integer: Exported classes
option-list: Exported classes
option-list-filepath: Exported classes
option-list-integer: Exported classes
option-string: Internal classes
option-switch: Exported classes

P
Package, clingon: The clingon package
Package, clingon-system: The clingon-system package
Package, clingon.command: The clingon․command package
Package, clingon.conditions: The clingon․conditions package
Package, clingon.options: The clingon․options package
Package, clingon.utils: The clingon․utils package

S
System, clingon: The clingon system

U
unknown-option: Exported conditions

Jump to:   C   D   I   M   O   P   S   U