davetron5000 / optparse-plus

Start your command line scripts off right in Ruby
http://davetron5000.github.com/optparse-plus
Apache License 2.0
521 stars 54 forks source link

Methadone option parsing not working as expected #72

Closed gerricchaplin closed 10 years ago

gerricchaplin commented 10 years ago

Hello David,

This may not be the best place to ask this question but it may be a bug. I am not quite sure yet but I would appreciate the help.

I have installed the following methadone gem and I can't seem to get my script to work. The script only acts as it should if I include an additional command line option that is not actually used in/by the script.

# ruby -v
ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-linux]

# gem list methadone
methadone (1.3.1)

I used the following script which has been stripped down even further to be sure I have not missed anything. It comes from the rdocs at http://davetron5000.github.io/methadone/rdoc/classes/Methadone/Main.html

#!/usr/bin/env ruby

require 'methadone'

class App
  include Methadone::Main
  include Methadone::CLILogging

  main do |needed|
    puts options[:needed]
  end

  # Proxy to an OptionParser instance's on method
  on("--needed NEEDED")

  arg :needed

  go!
end

Is there a chance I missed something fundamental? If so please tell me to RTFM again.

# ./test.rb --needed iamneeded notneeded
iamneeded
# ./test.rb --needed iamneeded
parse error: 'needed' is required
davetron5000 commented 10 years ago

This:

arg :needed

tells methadone that your app requires an argument, beyond its options. In this parlance, option is somethingn starting with a dash and argument is whatever else is on the command line, so:

> ./test.rb --foo bar blah

--foo is an option that itself takes an argument (bar) and then blah is an argument to the command itself.

When I write it out, it's actually fairly confusing :)

That is a long way of saying you can remove arg :needed.

If you want to see it more clearly, change it to arg :something_else and then do ./test.rb -h

Let me know if that doesn't make sense.

gerricchaplin commented 10 years ago

Hi David,

Thanks for the reply. I get it now. I had it in my mind that specifying an arg was there to enforce the requirement of the option. I see now that they are separate. Is there any way to enforce the requirement of an option rather than an argument or should I do that in code?

Thanks again for your help with clearing that up. It is much appreciated.

davetron5000 commented 10 years ago

If you do

on("--needed VAL")

then the user must supply an argument to --needed

if you do

on("--needed [VAL]") # note brackets

then the argument to --needed is optional.

The error message when the user omits a required arg to a flag might not be very good, though, but it should abort before main is called.

gerricchaplin commented 10 years ago

Thanks for the info.

Just to be a little more specific. I would like to enforce the requirement for "--needed" to be called in the first place. I know the help displays all of the options. I guess the solution is to specify that they are required in their description. Then programatically check that they are specified. Without that I can give one option but miss a second or third (if they exist) and main is still called, or I can give no options and main is still called at least in the script above.

davetron5000 commented 10 years ago

Yeah, if you want the user to always specify a particular flag or option, you'll have to check that manually. The reason is that it's somewhat unusual. More typically, if an option is absolute required, you'd make it an argument to the command line app itself, so instead of

my_app --needed=foo

You'd do

my_app foo

and

my_app

would generate a failure (which methadone supports via the arg method that created the confusion in the first place :)

davetron5000 commented 10 years ago

That said, if you have several required options, the command-line invocation is much more readable if you use flags like you are suggesting—you just need to do a bit more work on your own to check that they are all specified.

gerricchaplin commented 10 years ago

I don't mind a bit more work. You already saved me some in the first place. ;)

Thanks again for the help!