optparse icon indicating copy to clipboard operation
optparse copied to clipboard

subcommand parser

Open nobu opened this issue 3 years ago • 3 comments

nobu avatar Oct 08 '22 10:10 nobu

I was just looking to suggest something like this, after using the Crystal OptionParser library. :+1:

What do you think about the ability to make .on support a bare-word subcommand, which doesn't necessitate a sub-parser or another method?

Here's the example from the Crystal website:

verbose = false
salute = false
welcome = false
name = "World"
parser = OptionParser.new do |parser|
  parser.banner = "Usage: example [subcommand] [arguments]"
  parser.on("salute", "Salute a name") do
    salute = true
    parser.banner = "Usage: example salute [arguments]"
    parser.on("-t NAME", "--to=NAME", "Specify the name to salute") { |_name| name = _name }
  end
  parser.on("welcome", "Print a greeting message") do # This UX is very symmetric with the rest
    welcome = true
    parser.banner = "Usage: example welcome" # Re-uses original parser in scope - which might affect visitor pattern of Ruby's optparse?
  end
  parser.on("-v", "--verbose", "Enabled verbose output") { verbose = true }
  parser.on("-h", "--help", "Show this help") do
    puts parser
    exit
  end
end

parser.parse

if salute
  STDERR.puts "Saluting #{name}" if verbose
  puts "Hello #{name}"
elsif welcome
  STDERR.puts "Welcoming #{name}" if verbose
  puts "Welcome!"
else
  puts parser
  exit(1)
end

adam12 avatar Aug 30 '24 15:08 adam12

I think that it is NOT a good idea to support subcommand functionality in OptionParser. Subcommand functionality is not a feature of command option parser library such as OptionParser, but is a feature of command-line application framework. If you need subcommand functionality, use (or create) a command-line application framework (ex: Benry-CmdApp framework).

I strongly recommend for OptionParser to focus on its role as command option parsing.

kwatch avatar Oct 03 '24 23:10 kwatch

I released cliapp gem which is a small framework for CLI application similar to Git or Docker. I created it in order to insist that subcommand functionality should be covered by framework, not by option parser library. Because the cliapp gem is so small, it is a good example of how to design a CLI application framework which has subcommand functionality.

Example code of cliapp (filename: sample):

#!/usr/bin/env ruby
require 'cliapp'

## create an application object
app = CLIApp.new("Sample", "Sample Application", version: "1.0.0")
app.global_options({
  :help    => ["-h", "--help"      , "print help message"],
  :version => [      "--version"   , "print version number"],
  :list    => ["-l", "--list"      , "list action names"],
})

## 'hello' action
app.action("hello", "greeting message", {
  :lang => ["-l", "--lang=<en|fr|it>", "language", ["en", "it", "fr"]],
}) do |name="world", lang: "en"|
  case lang
  when "en"  ; puts "Hello, #{name}!"
  when "fr"  ; puts "Bonjour, #{name}!"
  when "it"  ; puts "Chao, #{name}!"
  else  raise "** internal error: lang=#{lang.inspect}"
  end
end

## main
begin
  app.run(*ARGV)
  exit 0
rescue OptionParser::ParseError, CLIApp::ActionError => exc
  $stderr.puts "[ERROR] #{exc.message}"
  exit 1
end

Example output:

$ chmod ./sample
$ ./sample hello                      # subcommand example
Hello, world!
$ ./sample hello --lang=fr            # subcommand option example
Bonjour, world!
$ ./sample hello Alice --lang=fr      # subcommand argument example
Bonjour, Alice!

Again, I strongly recommend for OptionParser to focus on its role as command option parsing.

kwatch avatar Oct 05 '24 04:10 kwatch