Glitzersachen
On glitter things found at the road sideRomulan now supports CLIs without sub-commands
Background
Command line interfaces essentially can be classified in three types as follows.
Simple command line interfaces
For these, one calls a program or script and then passes options and possible positional arguments. For example:
$ ls -lt /etc
Interfaces with subcommands
Here, the first positional argument is a command verb (a so-called subcommand) that decides what actually needs to be done.
$ git --config-env=/some/config log --oneline some-file
Typically, before the verb go global options (applicable to all subcommands) and after the verb subcommand specific options and positional arguments.
This type of command line interface has been made popular by version control systems like cvs, svn or git.
The command verb is the program name
These largely work like interfaces with subcommands, but here the command verb upon which the program dispatches is the name with which the program was called (argv[0]).
Typically the program has a name (for example my-apps), but is linked in bin under multiple different names (say foo or bar).
Calling the program via those names invokes different functionality which might do totally different things:
$ foo -n 113 some-file $ bar some-file another-file
From their usage this type of interfaces is indistinguishable from multiple separate programs, but internally it is always the same program that is invoked. Such interfaces are useful if those different functions share a large runtime.
One popular example for such an interface is busybox.
This type of interfaces might also come handy when dumping images from lisp systems: Instead of having to dump multiple (large) images for a collection of small utilities one might just dump one image and link that under different names.
Romulan
As described in Releasing Romulan 1.0.0 (first release), Romulan so far provided only the possibility to define interfaces with subcommands ("git style").
With release 1.1.1 Romulan also allows to define simple command line interfaces as described above.
For example:
(commandline-interface romulan-test (words &key user verbose) "shouts back anything you write" (:usage "[options ...] [arguments ...]" :varargs t :options (:user (:description "user to greet" :short-name #\u :env-vars ("USER")) :verbose (:type :counter :description "every -v bumps up the verbosity by 1" :short-name #\v :long-name "verbose"))) (if (< 1 verbose) (format t "DEBUG: verbosity => ~S~%" verbose)) (if (< 0 verbose) (format t "Hello, ~A!~%" user)) (format t "~{~A~^ ~}!!!~%" (mapcar #'string-upcase words)))
This works in principle as described for subcommands in Releasing Romulan 1.0.0 (first release): For execution of the body, the command line arguments are extracted automatically from the command line and bound to the lisp parameters.
Comments
Due to legal pitfalls in Europe there is no comment section in this blog at the moment (sorry), but you can discuss this article or comment on its content ⮕ here on Mastodon.