I'd like to get and parse command line arguments in Common Lisp, so that e.g. myscript -a 1 -b 2
will allow me to get the values, and myscript -xyz
will work too. How can I do it portably(between compilers)?
You can try unix-options
.
(ql:quickload :unix-options)
(defpackage :test
(:use :cl)
(:import-from :unix-options
:¶meters
:&free
:with-cli-options))
You probably want to :use
the package, but if you prefer to import symbols from it, don't forget about &free
and ¶meters
.
The library defines a getopt
function which is similar to the traditional getopt
utility. But it also defines with-cli-options
, which is a little more lispy.
¶meters
define parameters, which must be followed by a value;&free
For example:
(in-package :test)
(defun my-program (&rest cli-args)
(with-cli-options (cli-args)
(x y z ¶meters a b &free other)
(list x y z a b other))))
Here I define the entry point of the program. In a real program, you can simply leave the first list empty, like this:
(with-cli-options () <bindings> <body>)
... and the options will be portably fetched from the actual command line arguments of your Lisp implementation. You can also call (uiop:command-line-arguments)
to have to full command line, which seems to support more implementations and includes the name of the program as the first element.
The above function allows me to test the behavior of the parser.
Note for example that short options can be separated or joined:
(my-program "-xyz" "-a" "2" "-b" "3" "--" "something")
=> (T T T "2" "3" ("something"))
(my-program "-x" "-y" "-z" "-a" "2" "-b" "3" "--" "something")
=> (T T T "2" "3" ("something"))
Be careful about options that are declared as parameters but aren't given actual values (or maybe they are, the case is ambiguous):
(my-program "-a" "-b")
=> (NIL NIL NIL "-b" NIL NIL)
There are warnings for unknown parameters:
(ignore-errors (my-program "-w"))
; WARNING: Invalid option: w
=> (NIL NIL NIL NIL NIL NIL)
See the docs for details.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With