[ANN] parseargs-0.1.0

A

Ara.T.Howard

URLS

http://raa.ruby-lang.org/search.rhtml?search=parseargs
http://codeforpeople.com/lib/ruby/parseargs

ABOUT

parseargs is a library that faciltates the parsing of arguments and keywords
from method paramters, setting of default values, validation, contraints via
class based or duck based typing, and coercion/convincing to type/ducktype
when possible.


HISTORY

0.1.0

several critical bug fixes and made a few mods the enable more compact
argument specifications (it's gone positive!)

0.0.0

initial version


AUTHOR

ara [dot] t [dot] howard [at] noaa [dot] gov

SAMPLES

<========< sample/a.rb >========>

~ > cat sample/a.rb

require 'parseargs'
include ParseArgs

#
# simple use will declare which required and optional arguments a method can
# accept. default values may be specifed if a hash is given as the argument
# specification. an exception is thrown if required arguments are not given at
# method invocation.
#

def method(*a)
pa = parseargs(a) {
required_argument :a
optional_argument :b => 2
}

p pa
end

method 4 #=> {:a=>4, :b=>2}


~ > ruby sample/a.rb

{:a=>4, :b=>2}



<========< sample/b.rb >========>

~ > cat sample/b.rb

require 'parseargs'
include ParseArgs

#
# keywords can be declared in exactly the same way, and can be given at
# invocation as either strings or symbols. default values may also be named for
# both arguments and keywords. note that a required keyword with a default
# specified is really an optional keyword ;-)
#

def method(*a)
pa = parseargs(a) {
required_argument :a
required_keyword :b, :default => 2
optional_keyword :c
}

p pa
end

method 4, 'b' => 2 #=> {:a=>4, :b=>2, :c=>nil}


~ > ruby sample/b.rb

{:a=>4, :b=>2, :c=>nil}



<========< sample/c.rb >========>

~ > cat sample/c.rb

require 'parseargs'
include ParseArgs

#
# several abbreviations exist to make the declaration more compact.
#
def method(*a)
pa = parseargs(a) {
r_arg :a
r_kw :b
o_kw :c
}

if pa.c
puts "#{ pa.c }"
else
puts "#{ pa.a }#{ pa.b }"
end
end

method 4, :b => 2 #=> 42
method 4, :b => 2, 'c' => 42 #=> 42

#
# groups of definitions can be specified, here x, y, and z all share a default
# value of 1
#
def method(*a)
pa = parseargs(a){ arg 'a'; kws %w( x y z ) => 1 }

puts "#{ pa.a + pa.x }#{ pa.y + pa.z }"
end

method 3 #=> 42


~ > ruby sample/c.rb

42
42
42



<========< sample/d.rb >========>

~ > cat sample/d.rb

require 'parseargs'
include ParseArgs

#
# many keywords or arguments can be specified at once using a list or something
# enumerable - this example specifies 26 possible keywords
#

def method(*a)
pa = parseargs(a) {
r_arg 'arg'
o_kws 'a' .. 'z'
}

puts "#{ pa.arg }#{ pa.a ? pa.a : pa.z }"
end

method 4, 'a' => 2 #=> 42
method 4, 'z' => 2 #=> 42


~ > ruby sample/d.rb

42
42



<========< sample/e.rb >========>

~ > cat sample/e.rb

require 'parseargs'
include ParseArgs

#
# a single, or list of types may be given and the argument of invocation must be
# one of those types as reports by '==='
#

def method(*a)
pa = parseargs(a) {
req_arg 'number', 'types' => [Float, Fixnum]
}

p pa.number
end

method 42 #=> 42
method 42.0 #=> 42.0
method '42.0' #=> ./lib/parseargs.rb:112:in `value=': value given not of type(Float,Fixnum) in 'number=' (TypeError)


~ > ruby sample/e.rb

42
42.0
./lib/parseargs.rb:112:in `value=': value given not of type(Float,Fixnum) in 'number=' (TypeError)
from ./lib/parseargs.rb:344:in `parse'
from ./lib/parseargs.rb:339:in `each'
from ./lib/parseargs.rb:339:in `parse'
from ./lib/parseargs.rb:447:in `parseargs'
from ./lib/parseargs.rb:430:in `parseargs'
from sample/e.rb:10:in `method'
from sample/e.rb:19



<========< sample/f.rb >========>

~ > cat sample/f.rb

require 'parseargs'
include ParseArgs

#
# failure of an argument to match a given type will cause coercion to be applied
# if specified. the coerce argument may be either a method name or a proc that
# receives the obj to be coerced. in either case the return value is used as
# the new argument.
#

def method(*a)
pa = parseargs(a) {
arg :a, :types => Fixnum, :coerce => 'to_i'
kw :b, :types => Fixnum, :coerce => lambda{|obj| obj.to_i}
}

p pa
end

method 4, :b => 2 #=> {:a=>4, :b=>2}
method '4', :b => '2' #=> {:a=>4, :b=>2}


~ > ruby sample/f.rb

{:a=>4, :b=>2}
{:a=>4, :b=>2}



<========< sample/g.rb >========>

~ > cat sample/g.rb

require 'parseargs'
include ParseArgs

#
# ducktyping is supported as a method name, or list of method names - all of
# which an argument must respond_to? in order for an exception not to be thrown.
# this is a very simple ducktype signature.
#

def method(*a)
pa = parseargs(a) {
r_arg 'string', 'ducktype' => [:upcase, :downcase]
}

puts pa.string.upcase.downcase
end

method '42' #=> 42
method :fubar #=> ./lib/parseargs.rb:127:in `value=': value given not of ducktype(upcase,downcase) in 'string=' (TypeError)


~ > ruby sample/g.rb

42
./lib/parseargs.rb:127:in `value=': value given not of ducktype(upcase,downcase) in 'string=' (TypeError)
from ./lib/parseargs.rb:344:in `parse'
from ./lib/parseargs.rb:339:in `each'
from ./lib/parseargs.rb:339:in `parse'
from ./lib/parseargs.rb:447:in `parseargs'
from ./lib/parseargs.rb:430:in `parseargs'
from sample/g.rb:11:in `method'
from sample/g.rb:19



<========< sample/h.rb >========>

~ > cat sample/h.rb

require 'parseargs'
include ParseArgs

#
# a kind of ducktype 'coercion' - somthing i'm calling 'convincing' - may be
# applied in order to convince an object that it really can play a certain role.
# an argument may be 'convinced' via a module, which will be used to extend the
# object on the fly, or a block which is passed the object and expected to
# modify it's singleton class in such a way as to allow the object to become a
# valid argument
#

module M
def quack
2
end
end

def method(*a)
pa = parseargs(a) {
ra 'a', 'ducktype' => :quack,
'convince' => lambda{|obj| class << obj; def quack; 4; end; end}

ra 'b', 'ducktype' => :quack,
'convince' => M
}

puts "#{ pa.a.quack }#{ pa.b.quack }"
end

method 'any ol', 'objects' #=> 42


~ > ruby sample/h.rb

42



<========< sample/i.rb >========>

~ > cat sample/i.rb

require 'parseargs'

#
# of course all this would be kind of silly for the simple cases shown - but it
# can become very powerful as a form of meta-programming aid or when many
# kewords are to be supported
#

class Command
include ParseArgs

KEYWORDS = %w(
verbose
quiet
log
help
info
force
recursive
stdin
stdout
stderr
)

PARSER =
ParseArgs::parser::new {
KEYWORDS.each{|kw| optional_keyword kw}
}

def initialize cmd
@cmd = cmd
end

def execute(*argv)
opts = PARSER.parse argv
p @cmd => opts.select{|k,v| not v.nil?}
end

def background(*argv)
opts = PARSER.parse argv
p @cmd => opts.select{|k,v| not v.nil?}
end

end


foo = Command::new 'foo.exe'
foo.execute 'verbose' => true, 'stdin' => 'input.txt' #=> {"foo.exe"=>[["stdin", "input.txt"], ["verbose", true]]}

bar = Command::new 'bar.exe'
bar.execute 'verbose' => false, 'stdout' => 'output.txt' #=> {"bar.exe"=>[["stdout", "output.txt"], ["verbose", false]]}


~ > ruby sample/i.rb

{"foo.exe"=>[["stdin", "input.txt"], ["verbose", true]]}
{"bar.exe"=>[["stdout", "output.txt"], ["verbose", false]]}



CAVEATS

this library is __experimental__!

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| My religion is very simple. My religion is kindness.
| --Tenzin Gyatso
===============================================================================
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top