Giter Club home page Giter Club logo

slop's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

slop's Issues

--foo=bar syntax consuming following argument

Here are two samples of using on :do_thing= syntax, and having it consume the next argument if you use --do_thing=something. If you use --do_thing something then it works fine.

It's both removed from the passed in args (in parse!) mode, and ignored in terms of parsing (so if it's an option, it's not seen).

1.9.2p290 :001 > require 'slop'; args = ["--do_thing=fourtytwo", "hey dawg"]
 => ["--do_thing=fourtytwo", "hey dawg"]
1.9.2p290 :002 > opts = Slop.parse!(args) do on :do_thing=; end
 => #<Slop {:strict=>false, :help=>false, :banner=>nil, :ignore_case=>false, :autocreate=>false, :arguments=>false, :optional_arguments=>false, :multiple_switches=>true, :longest_flag=>8} ["#<Slop::Option [- | --do_thing=] () {:argument=>true, :optional_argument=>false, :tail=>false, :default=>nil, :callback=>nil, :delimiter=>\",\", :limit=>0, :match=>nil, :optional=>true, :required=>false, :as=>String, :autocreated=>false}"]>
1.9.2p290 :003 > args
 => []
1.9.2p290 :004 > opts[:do_thing]
 => "fourtytwo"


1.9.2p290 :001 > require 'slop'; args = ["--do_thing=fourtytwo", "--yes"]
 => ["--do_thing=fourtytwo", "--yes"]
1.9.2p290 :002 > opts = Slop.parse!(args) do on :do_thing=; on :yes; end
 => #<Slop {:strict=>false, :help=>false, :banner=>nil, :ignore_case=>false, :autocreate=>false, :arguments=>false, :optional_arguments=>false, :multiple_switches=>true, :longest_flag=>8} ["#<Slop::Option [- | --do_thing=] () {:argument=>true, :optional_argument=>false, :tail=>false, :default=>nil, :callback=>nil, :delimiter=>\",\", :limit=>0, :match=>nil, :optional=>true, :required=>false, :as=>String, :autocreated=>false}", "#<Slop::Option [- | --yes] () {:argument=>false, :optional_argument=>false, :tail=>false, :default=>nil, :callback=>nil, :delimiter=>\",\", :limit=>0, :match=>nil, :optional=>true, :required=>false, :as=>String, :autocreated=>false}"]>
1.9.2p290 :003 > opts.yes?
 => false
1.9.2p290 :004 > opts[:do_thing]
 => "fourtytwo"

default option values are overridden by successive options

I have the following options defined for a show-stack command:

opt.on :v, :verbose, "Include extra information."
opt.on :c, :current, "Display N frames either side of current frame (default to 5).", :optional => true, :as => Integer, :default => 5

When I invoke my command as follows:

show-stack -c -v

The 5 default for the c option is nulled out, as if i had passed in -c 0

However if i reverse the order of option passing:

show-stack -v -c

Then the default of 5 works again, and I see the expected result.

It would be nice, IMO, if show-stack -c -v and show-stack -v -c were equivalent :)

Supporting --no- prefixed for negating options

Add support to prefix --no- to an existing option, this option value will then negate the value of the option:

o = Slop.parse("--no-verbose --no-password") do
  opt(:v, :verbose, "Enable verbose mode")
  opt(:p, :password, "Disable password prompt", :default => false) # bad example
end

o[:verbose] #=> false
o[:password] #=> true

Adding a `:unless` option to a Slop::Option

This allows us to do the following:

opts = Slop.new do
  on :g, :grep, true do

  end

  on :h, :head, true, :unless => :grep do |limit|
    # this will be called unless the --grep option is used
  end

  on :t, :tail, true, :unless => :grep do |limit|
    # this will be called unless the --grep option is used
  end
end

Thoughts:

  • Should opts.head? still return true if the --head option was present, but grep was also there.
  • Should opts[:head] == 10 if --head 10. Meaning Slop would only not execute it's block, it will still collect data, or should it ignore everything, meaning opts[:head].nil? #=> true even with --head 10

shell words at option level

i wanna:

Gist a string:

gist -s "sup pig how are you"

and i also wanna:

Gist a method:

command -m "hello".chomp

Currently these are mutually exclusive as we have to specify shell words for the whole command, or not at all. It would be good if we could specify shell words on the option level.

doesn't work with 1.8.7?

I was really excited to try this out, immediately got an error on line 114 of lib/slop.rb

option = Option.new(self, *clean_options(args), options, &block)

afaik, ruby 1.8 doesn't support inlining *args into the method signature in other locations than the end. I tried the obvious modification:
option = Option.new(self, *[clean_options(args), options], &block)

but this failed with a method signature error.

Think about supporting 'bup.options' style parsing

http://apenwarr.ca/log/?m=201111#02

optspec = """
bup save [-tc] [-n name] 
--
r,remote=  hostname:/path/to/repo of remote repository
t,tree     output a tree id
c,commit   output a commit id
n,name=    name of backup set to update (if any)
d,date=    date for the commit (seconds since the epoch)
v,verbose  increase log output (can be used more than once)
q,quiet    don't show progress meter
smaller=   only back up files smaller than n bytes
bwlimit=   maximum bytes/sec to transmit to server
f,indexfile=  the name of the index file (normally BUP_DIR/bupindex)
strip      strips the path to every filename given
strip-path= path-prefix to be stripped when saving
graft=     a graft point *old_path*=*new_path* (can be used more than once)
"""
o = options.Options(optspec)
(opt, flags, extra) = o.parse(sys.argv[1:])
spec = <<-SPEC
ruby foo.rb [options]

---
r,remote=  hostname:/path/to/repo of remote repository
t,tree     output a tree id
c,commit   output a commit id
n,name=    name of backup set to update (if any)
d,date=    date for the commit (seconds since the epoch)
v,verbose  increase log output (can be used more than once)
q,quiet    don't show progress meter
smaller=   only back up files smaller than n bytes
bwlimit=   maximum bytes/sec to transmit to server
f,indexfile=  the name of the index file (normally BUP_DIR/bupindex)
strip      strips the path to every filename given
strip-path= path-prefix to be stripped when saving
graft=     a graft point *old_path*=*new_path* (can be used more than once)
SPEC

opts = Slop.spec(spec)
opts.parse

# ruby foo.rb --verbose --smaller 10 -r foo:/tmp
opts.verbose?  #=> true
opts[:smaller] #=> 10
opts[:remote]  #=> foo:/tmp

How to expect and handle non-boolean options cleanly?

I have been working with this gem, and I like it so far. One thing I'm having some trouble with is finding a clean way to expect a non-boolean value for an option. For instance:

opts = Slop.new(:strict => true) do
  banner "Usage: cmd [options]"
  on :c, :context, "Deploy to context [location]", true, :as => String
  on :a, :app, "Application Name [name]", true, :as => String
  on :s, :sinatra, "Use Sinatra?"
  on :h, :help, "Show detailed Help"
end

This works great, but if I pass to the command line cmd -cash, I will get all true values for the options, but no clean way to figure out if :app or :context were given a string or not (since the :as => String just coerces the true value to a string).

When parsing the opts, opts[:app] returns true. So, everywhere I want to work with it, I need to check two things:

if opts[:app] && opts[:app].class == String

Can you suggest any easier ways to do this? I would like to be able to roll up the Slop::InvalidOptionError for these options (since technically I require an option, but I also require a value for it, too. That would just add more complexity to every option, too).

Unable to use lists multiple times

Hi,

I'm trying to use lists several times as specified in the wiki. Here are my two trials:

# This one is like the wiki says

opts = Slop.new do
  on :friends, 'Your friends', true, :as => Array
end

opts.parse %w[ --friends lee foo bar --friends john,jack ]

p opts[:friends] #=> true
# This one is with a = sign after :friends

opts = Slop.new do
  on :friends=, 'Your friends', true, :as => Array
end

opts.parse %w[ --friends lee foo bar --friends john,jack ]

p opts[:friends] #=> ["john", "jack"]

In both cases the return value is not the expected one ["lee", "john", "jack"]

Slop object should be reusable

At the moment, Slop uses define_method for checking an options presence. This means the return value is stored and never changes, which means this does not work:

opts.parse %w()
p opts.foo? #=> false, true that

opts.parse %w( --foo )
p opts.foo? #=> false (wtf bro, this should be true!)

method_missing should not define a method and instead lazily check for an options presence on each call

Parsing negative integers

At the moment, this is impossible. Slop decides anything prefixed with a - is likely to be an option, and not an option argument. To fix this Slop should check if an argument is numeric and likely to be a negative integer rather than an existing defined option

Using default :help behaves differently to v2

Hi,

I'm not sure if this is a bug or a feature but I'm using the default :help option the following way: Slop.parse!(args, :help => true, :multiple_switches => false, &options)

In v2 when the user typed pry -h it would display help, and that's all.
In v3 when the user types pry -h it displays help AND puts them in a pry session afterwards.

So i'm guessing in v2 you broke out of option processing as soon as -h was encountered, but in v3 you do something different?

Slop cannot parse fuzzy options with arguments correctly

By "fuzzy options with arguments", in actual fact, I mean a presence of space between a flag and its option. Let me show some examples:

def slop
  Slop.new(:multiple_switches => false) do
    on :r, :argument => true
    on :I, :argument => true
  end
end

# Broken.
opts = slop
opts.parse %w( -Ilib -rgeronimo )
p opts[:I] # => "lib"
p opts[:r] # => nil

# Broken.
opts = slop
opts.parse %w( -Ilib -r geronimo )
p opts[:I] # => "lib"
p opts[:r] # => nil

# Works!
opts = slop
opts.parse %w( -I lib -r geronimo )
p opts[:I] # => "lib"
p opts[:r] # => "geronimo"

# Works!
opts = slop
opts.parse %w( -I lib -rgeronimo )
p opts[:I] # => "lib"
p opts[:r] # => "geronimo"

Question re: Slop Help

Using slop's help message, is there an easy way to indicate:

  • which parameters are optional?
  • which parameters take an argument?

Clarify documentation on compulsory arguments

This might be a bit of semantic wrangling but in the Usage section of the readme, there's the following:

on :n, :name, 'Your name', true              # compulsory argument

In my interpretation -n|--name is the argument (i.e ARGV argument) being referred to and not the argument to the option itself.

I'm honestly not sure which wording would clarify that but I spent a good amount of time looking at the tests and the code before I realized that "compulsory argument" meant that -n|--name itself required an argument and not that the option itself was required.

If anything, maybe include a small example of how to use Slop::MissingArgumentError and what it covers and doesn't?

Slop::Optionize

Feature thoughts:

require 'slop'

class User
  include Slop::Optionize

  option :n, :name=, 'Your name'
  option :a, :age=,  'Your age', :as => :int

  def birthday_year
    Time.now.year - options[:age]
  end

end

u = User.new
u.parse_options %w[--name lee --age 346]
p u.birthday_year #=> 1665

Diff: https://gist.github.com/88f890540376794559ab

negative number parsed as option and removed from input array

If i use a positive number Slop works as expected: args = ["2"]; Slop.parse!(args); args #=> ["2"]

But if i want to use a negative number as a non-option i get: args = ["-2"]; Slop.parse!(args); args #=> []

Slop appears to interpret the -2 as an option (though unrecognized) and removes it from the array.

AFAIK numbers are not valid options so this is incorrect behaviour,

thx

When autocreate is on, values are added as entries

When autocreate is turned on, values passed on to an option, get a key with value nil in the option Hash.

Here's the script I'm using.

require 'slop'
require 'pp'

opts = Slop.parse(:autocreate => true)

pp opts.to_hash

Here's it's output:

$ ruby slop.rb --name Lee -v
{:name=>"Lee", :Lee=>nil, :v=>true}

The :Lee key shouldn't be there, I think.

I'm on Slop version 3.3.2

block parameter for "execute"

Hey Lee!

I use Slop in a small project. A few days ago you introduced the "execute" method for a command context. This is great and one feature I'll want to use. So far so good ...

Now it seems that a block execution raises an error under some ruby versions. I tried it under MRI 1.8.7-p334, -p302 and 1.9.2-p180 and got the following results:

:001 > require 'rubygems'
 => true 
:002 > require 'slop'
 => true 
:003 > 
:004 >   opts = Slop.new do
:005 >       command :foo do
:006 >           on :v, :verbose
:007?>
:008 >           execute { |o| p o.verbose? }
:009?>       end
:010?>   end
 => #<Slop config_options={}>
:011 > opts.parse %w[foo --verbose] #=> true
(irb):8: warning: multiple values for a block parameter (2 for 1)
    from /Users/szimmermann/.rvm/gems/ruby-1.8.7-p334@private-jailmaster/gems/slop-1.9.1/lib/slop.rb:336
NoMethodError: undefined method `verbose?' for #<Array:0x1005557c0>
    from (irb):8
    from /Users/szimmermann/.rvm/gems/ruby-1.8.7-p334@private-jailmaster/gems/slop-1.9.1/lib/slop.rb:336:in `call'
    from /Users/szimmermann/.rvm/gems/ruby-1.8.7-p334@private-jailmaster/gems/slop-1.9.1/lib/slop.rb:336:in `execute'
    from /Users/szimmermann/.rvm/gems/ruby-1.8.7-p334@private-jailmaster/gems/slop-1.9.1/lib/slop.rb:619:in `execute_command'
    from /Users/szimmermann/.rvm/gems/ruby-1.8.7-p334@private-jailmaster/gems/slop-1.9.1/lib/slop.rb:447:in `parse_items'
    from /Users/szimmermann/.rvm/gems/ruby-1.8.7-p334@private-jailmaster/gems/slop-1.9.1/lib/slop.rb:193:in `parse'
    from (irb):11

I got this error under every 1.8.7 version, on 1.9.2 it doesn't occur and I think the problem is (as stated in the error description) on your "slop.rb" at line 336:

def execute(args=[], &block)
  if block_given?
    @execution_block = block
  elsif @execution_block.respond_to?(:call)
    @execution_block.call(self, args)
  end
end

I'm sorry, but I have no patch at this point.

But anyway: Thank you for your work on this nice helper! :-)

Stefan

Array argument processing is broken?

I am using the latest 3.3.2 gem and I am running an example from WIki about lists:

require 'rubygems'
require 'slop'
opts = Slop.new do
  on :friends, 'Your friends', true, :as => Array
end

opts.parse %w[ --friends lee,john,barney ]

p opts[:friends] #=> ["lee", "john", "barney"]

When I run this, all I get is "true" instead of the array of arguments. Had the API for array been changed, but wiki had not been updated? Or is this a real bug?

Small warning in 1.8.7

Ruby 1.8.7 throws a warning:

options.push (@arguments || extras[:argument]) ? true : (args.shift ? true : false)

Should be changed to:

options.push(@arguments || extras[:argument]) ? true : (args.shift ? true : false)

Then the warning disappears:

/Programs/Ruby/1.8.7p334/lib/ruby/site_ruby/1.8/slop.rb:1019: warning: don't put space before argument parentheses

Completion thoughts

OptParser has a horrible API, but one of the great things about it - at least in theory - is its built-in support for command completion. (I say "in theory" because it looks like you have to know to install rb_optparse.bash in your profile, and then manually define each command that might use it, and there's no documentation that would tell you that, so I'm not sure anyone's ever used it.)

I took a look at optparse.rb to see how they do it; there's a lot of code there, but it's mostly around ruby/ruby@ 644f0445e86034dde399d6db8261c82cf34b8e07 and ruby/ruby@91c0ff4. Looks like they add two secret options, --*-completion-bash=X and --*-completion-zsh=X, where X is the phrase being tab-completed, and then rb_optparse.bash sets up bash to use that option to generate the completion file.

Kinda hackish, but doable. Have you given any thought to doing that in slop eventually? I think you could/should go one further, and skip the shim. Allow me to say Slop.parse :auto_complete => true, and have slop itself install the compgen/compsys completion (if it's not present). The first time I run the script anywhere, boom - magic auto-completion.

It's a lot of work, but it'd be a killer feature ☺

Default not getting set depending on order of options.

With the following script:

slop = Slop.parse do
  on :d, :dev, 'Development-mode'
  on :s, :server, 'Start server', default: 3000
end

puts slop.to_hash.inspect

Depending on order of options, the default value for the -s option doesn't get set, ex.:

$ test -s
{:dev => nil, :server => 3000}
$ test -d -s
{:dev => true, :server => 3000}
$ test -s -d
{:dev => true, :server => 0}

This seems to be caused by the second option used as the value of the first.

Also when grouping options, the default never get set:

$ test -sd
{:dev => true, :server => 0}
$ test -ds
{:dev => true, :server => 0}

Tried with slop 2.1 and 2.4

as: :int produces odd results without argument: true

Using as: :int produces odd results when the user forgets to specify that there is an optional or mandatory argument.

do :l, :loops, as: int

opts[:l]

produces 0 when -l n or -l is provided. With optional: true, the return value is int n for -l n, and nil for -l (which is more what I would expect).

This is really more of a user bug, but I thought the behaviour was a little weird.

Support for Ruby 1.8.6?

Slop is the nicest option parser I have found, but it doesn't work on Ruby 1.8.6 because of this idiom

select(&:required)

which came in on 1.8.7

I'm loath to fork. Any chance of 1.8.6 being supported?

--long-option=val raises NoMethodError if using :multiple_switches (which is default)

From irb, explicitly disabling multiple_switches:

1.9.2p290 :001 > opts = Slop.parse!(['--asd=foo'], :multiple_switches => false) do on '--asd='; end
 => #<Slop {:strict=>false, :help=>false, :banner=>nil, :ignore_case=>false, :autocreate=>false, :arguments=>false, :optional_arguments=>false, :multiple_switches=>false, :longest_flag=>3} ["#<Slop::Option [- | --asd=] () {:argument=>true, :optional_argument=>false, :tail=>false, :default=>nil, :callback=>nil, :delimiter=>\",\", :limit=>0, :match=>nil, :optional=>true, :required=>false, :as=>String, :autocreated=>false}"]> 

From irb, default config:

1.9.2p290 :002 > opts = Slop.parse!(['--asd=foo']) do on :asd=; end
NoMethodError: undefined method `count=' for nil:NilClass
    from /Users/jtjerno/.rvm/gems/ruby-1.9.2-p290@show_me/gems/slop-3.0.0/lib/slop.rb:471:in `block in     execute_multiple_switches'
    from /Users/jtjerno/.rvm/gems/ruby-1.9.2-p290@show_me/gems/slop-3.0.0/lib/slop.rb:469:in `each'
    from /Users/jtjerno/.rvm/gems/ruby-1.9.2-p290@show_me/gems/slop-3.0.0/lib/slop.rb:469:in `execute_multiple_switches'
    from /Users/jtjerno/.rvm/gems/ruby-1.9.2-p290@show_me/gems/slop-3.0.0/lib/slop.rb:407:in `process_item'
    from /Users/jtjerno/.rvm/gems/ruby-1.9.2-p290@show_me/gems/slop-3.0.0/lib/slop.rb:369:in `block in parse_items'
    from /Users/jtjerno/.rvm/gems/ruby-1.9.2-p290@show_me/gems/slop-3.0.0/lib/slop.rb:366:in `each'
    from /Users/jtjerno/.rvm/gems/ruby-1.9.2-p290@show_me/gems/slop-3.0.0/lib/slop.rb:366:in `each_with_index'
    from /Users/jtjerno/.rvm/gems/ruby-1.9.2-p290@show_me/gems/slop-3.0.0/lib/slop.rb:366:in `parse_items'
    from /Users/jtjerno/.rvm/gems/ruby-1.9.2-p290@show_me/gems/slop-3.0.0/lib/slop.rb:195:in `parse!'
    from /Users/jtjerno/.rvm/gems/ruby-1.9.2-p290@show_me/gems/slop-3.0.0/lib/slop.rb:122:in `init_and_parse'
    from /Users/jtjerno/.rvm/gems/ruby-1.9.2-p290@show_me/gems/slop-3.0.0/lib/slop.rb:63:in `parse!'
    from (irb):5

Problem with :default => true

There's a bug in the current version of slop where setting an option like:

on :f, :foo, 'Set foo option', :default => true

and invoking Slop without any options will erroneously return:

opts.foo? => false <== This is wrong! (I think it should be automatically defaulted to true)
opts['foo'] => true

For now, I'm using the latter form for options that need :default => true

slop 2.4.0 problems

Hi,

In previous versions of slop (i only tried 2.2.0 and earlier) the code i'm about to paste worked fine - that is gist -i 1 did not raise an exception. Since i updated to 2.4.0 however I keep getting an exception, i paste the situation below:

It seems that the value of opts[:i] is always nil.

Note, it's also nil if i pass in a real Range or I leave off a paramter altogether (to rely on the default):

[4] (pry) main: 0> gist -i 1..1
NoMethodError: undefined method `>=' for nil:NilClass
from /Users/john/ruby/projects/pry/lib/pry/helpers/command_helpers.rb:254:in `absolute_index_number'
[5] (pry) main: 0> gist -i 
NoMethodError: undefined method `>=' for nil:NilClass
from /Users/john/ruby/projects/pry/lib/pry/helpers/command_helpers.rb:254:in `absolute_index_number'
[6] (pry) main: 0> 

Fetching: slop-2.4.0.gem (100%)
Successfully installed slop-2.4.0
Gems updated: slop
crow:pry john$ rake pry
(in /Users/john/ruby/projects/pry)
/Users/john/ruby/projects/pry/Rakefile:21: warning: Insecure world writable dir /Applications/MacPorts/Emacs.app/Contents in PATH, mode 040777
[1] (pry) main: 0> def hello
[1] (pry) main: 0*   puts "hi"
[1] (pry) main: 0* end  
=> nil
[2] (pry) main: 0> gist -i 1
NoMethodError: undefined method `>=' for nil:NilClass
from /Users/john/ruby/projects/pry/lib/pry/helpers/command_helpers.rb:254:in `absolute_index_number'
[3] (pry) main: 0> show-command gist

From: /Users/john/ruby/projects/pry/lib/pry/default_commands/documentation.rb @ line 58:
Number of lines: 56

command "gist", "Gist a method or expression history to github. Type `gist --help` for more info.", :requires_gem => "gist", :shellwords => false do |*args|
  require 'gist'

  target = target()

  opts = parse_options!(args) do |opt|
    opt.banner unindent <<-USAGE
      Usage: gist [OPTIONS] [METH]
      Gist method (doc or source) or input expression to github.
      Ensure the `gist` gem is properly working before use. http://github.com/defunkt/gist for instructions.
      e.g: gist -m my_method
      e.g: gist -d my_method
      e.g: gist -i 1..10
    USAGE

    opt.on :d, :doc, "Gist a method's documentation.", true
    opt.on :m, :method, "Gist a method's source.", true
    opt.on :p, :public, "Create a public gist (default: false)", :default => false
    opt.on :i, :in, "Gist entries from Pry's input expression history. Takes an index or range.", :optional => true, :as => Range, :default => -5..-1
  end

  type_map = { :ruby => "rb", :c => "c", :plain => "plain" }
  if opts.present?(:in)
    code_type = :ruby
    content = ""
    normalized_range = absolute_index_range(opts[:i], _pry_.input_array.length)
    input_items = _pry_.input_array[normalized_range] || []

    input_items.each_with_index.map do |code, index|
      corrected_index = index + normalized_range.first
      if code && code != ""
        content << code
        content << "#{comment_expression_result_for_gist(_pry_.output_array[corrected_index].pretty_inspect)}" if code !~ /;\Z/
      end
    end
  elsif opts.present?(:doc)
    meth = get_method_or_raise(opts[:d], target, {})
    content = meth.doc
    code_type = meth.source_type

    text.no_color do
      content = process_comment_markup(content, code_type)
    end
    code_type = :plain
  elsif opts.present?(:method)
    meth = get_method_or_raise(opts[:m], target, {})
    content = meth.source
    code_type = meth.source_type
  end

  link = Gist.write([:extension => ".#{type_map[code_type]}",
                     :input => content],
                    !opts[:p])

  output.puts "Gist created at #{link}"
end

to_hash returns Strings as keys, should these be Symbols?

Example

p Slop.parse { on :name, true }.to_hash

With --name lee this will return

{"name"=>"lee"}

Should keys be symbolized so this returns

{:name=>"lee"}

instead?

It's a backwards incompatible change, and Slop follows semver, so this couldn't be the default behaviour unless I released a 2.0 (even though it would be a subtle change). Until then though I could add an optional argument to to_hash

Thoughts on this?

Commands should support arguments

Currently, there is no way to implement parsing of commands that accept arguments. Let's consider a basic Slop v3 command set:

commands = Slop::Commands.new do
  on 'install'
end

Let's try to parse some input:

commands.parse %w( install geronimo )
#=> ["geronimo"]

The problem with current code is that it doesn't support arguments for install subcommand. Of course, you can save the return value of Commands#parse and use it in your program, but let's have a look at the situation when our command set have more than one command:

commands = Slop::Commands.new do
  on :install
  on :list
end

commands.parse %w( install geronimo )
#=> ["geronimo"]

commands.parse %w( list geronimo )
#=> ["geronimo"]

Both calls return the same value. Given a stroppy user of our CLI tool, it's pretty obvious that we can't tell, which of the subcommands has been executed from program's point of view: install or list?

It seems like the only way to go is to use command options:

commands = Slop::Commands.new do
  on :install do
    on :n, :name
  end

  on :list do
    on :n, :name
  end
end

commands.parse %w( install --name geronimo )
#=> ["--name", "geronimo"]
commands[:install].present? :name
#=> true

commands.parse %w( list --name geronimo )
#=> ["--name", "geronimo"]
commands[:list].present? :name
#=> true

Quite frankly, this pretty verbose and simply sucks.

Possible solutions

Add :with_argument parameter hash to Commands#on

This parameter should be specific for each command.

commands = Slop::Commands.new do
  on :install, :with_argument => true
  on :list
end

commands.parse %w( install geronimo )
#=> ["install", "geronimo"]
commands.present? :install
#=> true
commands.present? :list
#=> false
commands[:list].argument
#=> "geronimo"

Treat one of subcommand options as a default option

commands = Slop::Commands.new do
  on :install do
    as_default(on(:n, :name))
    on :v, :verbose
  end

  on :list
end

commands.parse %w( install --name geronimo )
#=> ["--name", "geronimo"]
commands.parse %w( install geronimo )
#=> ["install", "geronimo"]
commands[:list].argument
#=> "geronimo"

Commit the .yardoc file

The .yardoc file is used by services like rdoc.info/rubydoc.info and users who manually want to generate documentation. As such it is best to not gitignore it but rather commit it to the repository.

support argument next to short option

I switched from optparse to slop but now my program behaves like this :
mytool -f'hello' # doesn't match
mytool -f 'hello' # does match

Maybe a small issue in the way arguments are grabbed.

on_ event blocks are instance_eval'd rather than called

This is contrary behaviour to OptParse where the blocks are called -- i think it's important that they're called rather than instance_eval'd as, esp in my case, i need to access utility functions defined in the enclosing scope inside the block. For example:

  on :h, :help, 'Show this message.', :tail => true do
    output.puts help
  end        

Iin the above the output method is not available.

Options without dashes

It's possible to create commands without dashes? For example: boo init something

Awesome gem BTW :-)

Wrong event fired

Note below that the help event is triggered and not the replay event. Yet when passed any other value than 1 to replay (such as --replay 2) the correct behavior is observed.

require 'slop'
require 'shellwords'

args = "--replay 1".shellsplit

opts = Slop.parse(args) do
  banner "Usage: hist [-rSTART..END]"
  on :r, :replay, 'The line (or range of lines) to replay.', true, :as => Range do |r|
    options[:r].argument_value = r.to_i if r.is_a?(String)
  end
  on :h, :help, 'Show this message.', :tail => true do
    puts help
  end        
end

# output is the standard `help` information ?!

EDIT: weird behaviour also occurs when passing --replay 0. I get the following error for --replay 0:

/home/john/.rvm/gems/ruby-1.9.2-head/gems/slop-1.5.0/lib/slop.rb:354:in `check_optional_argument!': '0' expects an   argument, none given (Slop::MissingArgumentError)

Regressions in 3.2.0 (vs 2.4.4)

As you know, pry has been using slop for ages. Unfortunately the new version of slop breaks in a lot of ways.

Some of these I can fix at our end:

• convert true, to :argument => true
• convert :optional => true to :optional_argument => true.

Some of these I can't:

• Argument arrays can no longer contain nil values.
We were using this facility so we could pass a regex capture groups through slop.
• Ranges can no-longer have negative argument values.
We used this in a lot of places in the same way ruby allows array[-1]
:as => :count doesn't work anymore.
I tried the obvious fix to return @count but it looks like the counting itself is also broken

I'll try to send pull-requests for these over the weekend. Another alternative we're strongly considering would just be to bundle Slop 2.4.4 inside the Pry namespace; but that will become a worse-and-worse solution as the future goes on.

two separator's don't add an extra return

Why doesn’t the following give me an extra return?

separator ''
separator '-create options'

Only if I add a 'on' then it will, like this

separator ''
on
separator '-create options'

2.4.0 command not working

I am trying the example

require 'slop'

opts = Slop.new do
  command :clean do
    on :v, :verbose, do
      puts 'Enabled verbose mode for clean'
    end
  end

  # non-command specific options
  on :v, :version do
    puts 'version 1'
  end
end

puts opts.to_hash

and I see nothing being outputted

~$ ruby slop.rb 
{:version=>nil}
~$ ruby slop.rb -v
{:version=>nil}
~$ ruby slop.rb clean -v
{:version=>nil}
~s$ ruby slop.rb clean -v
{:version=>nil}

I am using ruby 1.9.2 on Ubuntu 10.04

Command ideas

Following up ticket #38 , here is what I would like to see with command.

  1. They should work similar to git? so

git help clone => show clone options and help
git help or --help => show generic help and available commands

Maybe it could be define as:

command :one, 'description' do
    on :help  => print current  options help , combined with global options if any?
end

on :help => show list of commands?
on :v , 'Verbose'

or using the Slop.new(:help => true) , it does automatically what is describe above?

  1. I would like to be able to nest command like
command :config do

 command :one do
   on :specific_to_one
 end

 command :two do
   on :specific_to_two
 end

 on : common_opt_for_two_and_one
end

on :global_opt

Nested commands

Is slop capable of doing nested command? So take for example a cli tool:

Usage: test.rb
*required

--user
  --get 
      --id*
  --create
      --first-name*
      --middle-name
      --last-name*
--group
  --get
     --id*
  --delete
     --id*

./test.rb --user --get --id=1 (would be a valid command)

however

./test.rb --user --delete (would not)

basically allowing each opt to have child opts which are printed in the help and handled by the parser.

I would be happy to create a fork and do the work myself, if you could maybe point me in a general direction as to how this might be implemented using slop.

Thanks:)

Slop "opts" object uses method_missing for "option?" methods

Using method_missing to receive "option?" messages causes problems when someone defines an "option?" method on Object -- the overridden method gets called instead of Slop's.

For example, pry has an #in? option: https://github.com/pry/pry/blob/master/lib/pry/default_commands/shell.rb#L91

Meanwhile, my library adds #in? to Object, which breaks pry thusly:

[7] pry(main)> [].each_cons :barf
TypeError: can't convert Symbol into Integer
from (pry):2:in `each_cons'
[8] pry(main)> cat --ex
ArgumentError: wrong number of arguments (0 for 1)
from /home/epi/.rvm/gems/ruby-1.9.3-rc1/gems/epitools-0.5.2/lib/epitools/basetypes.rb:817:in `in?'
[9] pry(main)>

Solutions:

  • define_method the methods
  • Inherit from BasicObject instead of Object

Slop doesn't parse correctly with multiple_switches

Hi,

Using the multiple_switches feature, Slop doesn't work as expected. For example, with the following code where args is ["-mLv", "-C", "Ripper"] :

    opts = Slop.parse! args, :multiple_switches => true do
      on :v, :verbose, "Show value of variables and constants and locations of methods"
      on :L, :less, "Only show methods set by the receiver"
      on :a, :more, "Show all of the methods, including those defined in Object"
      on :f, :filter, "Regular expression to filter methods and variables",
        :optional => false, :default => ""
      on :C, :context, "Changes self", :optional => false do |arg|
        p arg
        ctxt.target = Pry.binding_for(target.eval(context))
      end

      on :l, :locals, "Show local variables"
      on :g, :globals, "Show global variables"
      on :i, 'instance-variables', "Show instance variables"
      on :k, 'class-variables', "Show class variables"

      on :c, :constants, "Show constants"

      on :m, :methods, "Show methods"
      on :M, 'instance-methods', "Show instance methods"

      on :h, :help, 'Print this help message', :tail => true
    end

args still contains the flags passed to Slop and the block passed to the context flag doesn't get called.

internal error when providing bad options

Not sure if you consider this a bug, but the error i get when providing bad options ls -mj (where 'j' is not a defined option) results in a pretty low-level error:

[3] (pry) main: 0> ls -mj
NoMethodError: undefined method `count' for nil:NilClass
from /Users/john/.rvm/gems/ruby-1.9.3-p194/gems/slop-3.3.1/lib/slop.rb:495:in `block in execute_multiple_switches'
[4] (pry) main: 0> cat --ex
Exception: NoMethodError: undefined method `count' for nil:NilClass
--
From: /Users/john/.rvm/gems/ruby-1.9.3-p194/gems/slop-3.3.1/lib/slop.rb @ line 495 @ level: 0 of backtrace (of 58).

    490:   # Returns nothing.
    491:   def execute_multiple_switches(option, argument, index)
    492:     execute_option(option, nil, index)
    493:     argument.split('').each do |key|
    494:       opt = fetch_option(key)
 => 495:       opt.count += 1
    496:       execute_option(opt, nil, index, key)
    497:     end
    498:   end
    499: 
    500:   # Extract an option from a flag.
[5] (pry) main: 0> wtf??
Exception: NoMethodError: undefined method `count' for nil:NilClass
--
 0: /Users/john/.rvm/gems/ruby-1.9.3-p194/gems/slop-3.3.1/lib/slop.rb:495:in `block in execute_multiple_switches'
 1: /Users/john/.rvm/gems/ruby-1.9.3-p194/gems/slop-3.3.1/lib/slop.rb:493:in `each'
 2: /Users/john/.rvm/gems/ruby-1.9.3-p194/gems/slop-3.3.1/lib/slop.rb:493:in `execute_multiple_switches'
 3: /Users/john/.rvm/gems/ruby-1.9.3-p194/gems/slop-3.3.1/lib/slop.rb:442:in `process_item'
 4: /Users/john/.rvm/gems/ruby-1.9.3-p194/gems/slop-3.3.1/lib/slop.rb:387:in `block in parse_items'
 5: /Users/john/.rvm/gems/ruby-1.9.3-p194/gems/slop-3.3.1/lib/slop.rb:384:in `each'
 6: /Users/john/.rvm/gems/ruby-1.9.3-p194/gems/slop-3.3.1/lib/slop.rb:384:in `each_with_index'
 7: /Users/john/.rvm/gems/ruby-1.9.3-p194/gems/slop-3.3.1/lib/slop.rb:384:in `parse_items'
 8: /Users/john/.rvm/gems/ruby-1.9.3-p194/gems/slop-3.3.1/lib/slop.rb:202:in `parse!'
 9: /Users/john/ruby/projects/pry/lib/pry/command.rb:467:in `call'
10: /Users/john/ruby/projects/pry/lib/pry/command.rb:394:in `call_with_hooks'
11: /Users/john/ruby/projects/pry/lib/pry/command.rb:372:in `call_safely'
12: /Users/john/ruby/projects/pry/lib/pry/command.rb:319:in `process_line'
13: /Users/john/ruby/projects/pry/lib/pry/command_set.rb:343:in `process_line'
14: /Users/john/ruby/projects/pry/lib/pry/pry_instance.rb:423:in `process_command'
15: /Users/john/ruby/projects/pry/lib/pry/pry_instance.rb:407:in `retrieve_line'
16: /Users/john/ruby/projects/pry/lib/pry/pry_instance.rb:304:in `block in r'
17: /Users/john/ruby/projects/pry/lib/pry/pry_instance.rb:301:in `loop'
18: /Users/john/ruby/projects/pry/lib/pry/pry_instance.rb:301:in `r'
19: /Users/john/ruby/projects/pry/lib/pry/pry_instance.rb:271:in `re'
[6] (pry) main: 0> 

Printing help from an InvalidOptionError rescue

Maybe I'm approaching this the wrong way, please advise:

begin
    opts = Slop.parse(:strict => true) do
      on :d, :destdir=, 'destination directory'
   end
rescue Slop::InvalidOptionError => x
    puts x.to_s
    # how to do the equivalent of opts.help in here?
end

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.