Command Line Subcommands in Crystal
Here’s the translation of the Go code to Crystal, 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 how tools like git have subcommands like git commit and git push, each with their own options.
require "option_parser"
# We declare a subcommand using a separate OptionParser
# and proceed to define new flags specific for this subcommand.
foo_cmd = OptionParser.new do |parser|
parser.banner = "Usage: foo [options]"
foo_enable = false
foo_name = ""
parser.on("-e", "--enable", "Enable") { foo_enable = true }
parser.on("-n NAME", "--name=NAME", "Name") { |name| foo_name = name }
parser.on("-h", "--help", "Show this help") do
puts parser
exit
end
parser.unknown_args do |args|
puts "subcommand 'foo'"
puts " enable: #{foo_enable}"
puts " name: #{foo_name}"
puts " tail: #{args}"
end
end
# For a different subcommand we can define different
# supported flags.
bar_cmd = OptionParser.new do |parser|
parser.banner = "Usage: bar [options]"
bar_level = 0
parser.on("-l LEVEL", "--level=LEVEL", "Level") { |level| bar_level = level.to_i }
parser.on("-h", "--help", "Show this help") do
puts parser
exit
end
parser.unknown_args do |args|
puts "subcommand 'bar'"
puts " level: #{bar_level}"
puts " tail: #{args}"
end
end
# The subcommand is expected as the first argument
# to the program.
if ARGV.empty?
puts "expected 'foo' or 'bar' subcommands"
exit(1)
end
# Check which subcommand is invoked.
case ARGV[0]
# For every subcommand, we parse its own flags and
# have access to trailing positional arguments.
when "foo"
foo_cmd.parse(ARGV[1..-1])
when "bar"
bar_cmd.parse(ARGV[1..-1])
else
puts "expected 'foo' or 'bar' subcommands"
exit(1)
endTo run the program, save it as command_line_subcommands.cr and use the Crystal compiler:
$ crystal build command_line_subcommands.crFirst invoke the foo subcommand:
$ ./command_line_subcommands foo --enable --name=joe a1 a2
subcommand 'foo'
enable: true
name: joe
tail: ["a1", "a2"]Now try bar:
$ ./command_line_subcommands bar --level 8 a1
subcommand 'bar'
level: 8
tail: ["a1"]But bar won’t accept foo’s flags:
$ ./command_line_subcommands bar --enable a1
Error: Unknown option '--enable'This example demonstrates how to create a command-line application with subcommands in Crystal. It uses the OptionParser class to define and parse command-line options for each subcommand. The structure is similar to the original, but it uses Crystal’s idiomatic ways of handling command-line arguments and subcommands.
Next, we’ll look at environment variables, another common way to parameterize programs.