Command Line Subcommands in Lisp
Here’s the translation of the Go code to Lisp, formatted in Markdown suitable for Hugo:
Our first example demonstrates how to create command-line subcommands with their own set of flags. This is similar to how tools like git
have different subcommands (e.g., git commit
, git push
) with their own specific options.
(defun main ()
;; We declare subcommands using make-command-table and define
;; new flags specific for each subcommand.
(let ((foo-cmd (make-command-table :name "foo"
:options '(("enable" :type boolean :initial-value nil)
("name" :type string :initial-value ""))))
(bar-cmd (make-command-table :name "bar"
:options '(("level" :type integer :initial-value 0)))))
;; The subcommand is expected as the first argument to the program.
(when (< (length (uiop:command-line-arguments)) 1)
(format t "expected 'foo' or 'bar' subcommands~%")
(uiop:quit 1))
;; Check which subcommand is invoked.
(let ((subcommand (first (uiop:command-line-arguments))))
(cond
((string= subcommand "foo")
(multiple-value-bind (options free-args)
(command-line-arguments:process-command-line-options foo-cmd (rest (uiop:command-line-arguments)))
(format t "subcommand 'foo'~%")
(format t " enable: ~a~%" (getf options :enable))
(format t " name: ~a~%" (getf options :name))
(format t " tail: ~a~%" free-args)))
((string= subcommand "bar")
(multiple-value-bind (options free-args)
(command-line-arguments:process-command-line-options bar-cmd (rest (uiop:command-line-arguments)))
(format t "subcommand 'bar'~%")
(format t " level: ~a~%" (getf options :level))
(format t " tail: ~a~%" free-args)))
(t
(format t "expected 'foo' or 'bar' subcommands~%")
(uiop:quit 1))))))
To run the program, you would typically save this code in a file (e.g., command-line-subcommands.lisp
) and use your Lisp implementation to compile and run it. Here are some example invocations:
First, invoke the foo subcommand:
$ sbcl --script command-line-subcommands.lisp foo --enable --name=joe a1 a2
subcommand 'foo'
enable: T
name: joe
tail: (a1 a2)
Now try bar:
$ sbcl --script command-line-subcommands.lisp bar --level 8 a1
subcommand 'bar'
level: 8
tail: (a1)
But bar won’t accept foo’s flags:
$ sbcl --script command-line-subcommands.lisp bar --enable a1
expected 'foo' or 'bar' subcommands
This Lisp implementation uses a hypothetical make-command-table
function and the command-line-arguments
library to parse command-line options. The exact implementation might vary depending on the specific Lisp dialect and libraries you’re using.
In Lisp, we don’t have a direct equivalent of Go’s flag
package, so we’ve simulated similar functionality using a custom approach. The cond
statement is used instead of a switch
to handle different subcommands.
Next, we’ll look at environment variables, another common way to parameterize programs.