Command Line Subcommands in Racket
Here’s the translation of the Go code to Racket, with explanations in Markdown format suitable for Hugo:
Our first program demonstrates how to create command-line subcommands with their own set of flags. This is similar to tools like git
where different subcommands (git commit
, git push
) have their own flags.
#lang racket
(require racket/cmdline)
(define (main)
(define args (current-command-line-arguments))
; We declare subcommands and their flags using command-line-parser
(define-values (foo-cmd foo-args)
(command-line-parser
#:program "foo"
#:args args
#:once-each
[("-e" "--enable") "Enable option" (enable #t)]
[("-n" "--name") name "Set name" (name #f)]))
(define-values (bar-cmd bar-args)
(command-line-parser
#:program "bar"
#:args args
#:once-each
[("-l" "--level") level "Set level" (level 0)]))
; The subcommand is expected as the first argument to the program
(when (< (vector-length args) 1)
(displayln "expected 'foo' or 'bar' subcommands")
(exit 1))
; Check which subcommand is invoked
(case (vector-ref args 0)
[("foo")
(foo-cmd)
(printf "subcommand 'foo'~n")
(printf " enable: ~a~n" enable)
(printf " name: ~a~n" name)
(printf " tail: ~a~n" foo-args)]
[("bar")
(bar-cmd)
(printf "subcommand 'bar'~n")
(printf " level: ~a~n" level)
(printf " tail: ~a~n" bar-args)]
[else
(displayln "expected 'foo' or 'bar' subcommands")
(exit 1)]))
(main)
To run the program, save it as command-line-subcommands.rkt
and use racket
.
First, invoke the foo subcommand:
$ racket command-line-subcommands.rkt foo --enable --name=joe a1 a2
subcommand 'foo'
enable: #t
name: joe
tail: (a1 a2)
Now try bar:
$ racket command-line-subcommands.rkt bar --level 8 a1
subcommand 'bar'
level: 8
tail: (a1)
But bar won’t accept foo’s flags:
$ racket command-line-subcommands.rkt bar --enable a1
bar: unknown switch: --enable
In Racket, we use the command-line-parser
function from the racket/cmdline
module to define subcommands and their flags. This approach provides similar functionality to the flag
package in the original example.
The structure of the program remains similar, with separate definitions for each subcommand and their respective flags. The main difference is in the syntax and the way we handle command-line arguments in Racket.
Next, we’ll look at environment variables, another common way to parameterize programs.