leejarvis / slop Goto Github PK
View Code? Open in Web Editor NEWSimple Lightweight Option Parsing - ✨ new contributors welcome ✨
License: MIT License
Simple Lightweight Option Parsing - ✨ new contributors welcome ✨
License: MIT License
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"
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 :)
Just listing this here :)
it would be great if --range 0..-1
could be made to work :P
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
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:
opts.head?
still return true if the --head
option was present, but grep was also there.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
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.
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.
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
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).
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"]
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
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
See the output here:
https://gist.github.com/2517009
Any ideas?
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?
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"
Using slop's help message, is there an easy way to indicate:
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?
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
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 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
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
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?
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
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 ☺
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
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.
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?
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
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
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
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?
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.
: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"
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"
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.
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.
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.
It's possible to create commands without dashes? For example: boo init something
Awesome gem BTW :-)
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)
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.
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'
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
Adding a separator after banner doesn't seem to show.
Any chance you can fix this?
Thanks
Following up ticket #38 , here is what I would like to see with command.
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?
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
opt.on :i, :in, "Gist entries from Pry's input expression history. Takes an index or range.", :optional => true, :as => Range, :default => -5..-1 do |range|
If i invoke it with gist -i 1
it would be useful if range
could be yielded as 1..1
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:)
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 methodsHi,
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.
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>
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
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.