Thanks to visit codestin.com
Credit goes to github.com

Skip to content

subcommand parser #41

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

subcommand parser #41

wants to merge 4 commits into from

Conversation

nobu
Copy link
Member

@nobu nobu commented Oct 8, 2022

No description provided.

@nobu nobu marked this pull request as ready for review November 25, 2022 11:09
@nobu nobu changed the title [WIP] subcommand parser subcommand parser Nov 25, 2022
@nobu nobu added the enhancement New feature or request label Dec 21, 2022
@adam12
Copy link

adam12 commented Aug 30, 2024

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

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

@kwatch
Copy link

kwatch commented Oct 3, 2024

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
Copy link

kwatch commented Oct 5, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants