From: Josh Cheek Date: 2011-09-26T06:07:27+09:00 Subject: Re: Looking for better/familiar approach to command line opts --f46d04339cced15d8104adca6dad Content-Type: text/plain; charset=ISO-8859-1 On Sun, Sep 25, 2011 at 4:03 PM, Josh Cheek wrote: > On Sun, Sep 25, 2011 at 3:48 PM, Perl J. wrote: > >> So I guess the warning to the reader upfront is... I'm a bit of a Perl >> hack who should have moved to Ruby a decade ago and just couldn't let go >> of Perl. Perl still does stuff that I use extensively that I can't >> (take the time to) figure out how to do in Ruby, so... that's why I'm >> here. >> >> I've got a small framework I wrote in Perl I've been using for years >> that is lightweight and yet powerful. A lot of it centers around the >> use of AUTOLOAD, which some Perlers say is bad -- I say it's extremely >> powerful if used properly, and actually, AUTOLOAD forms a lot of the >> backbone for my framework. And honestly, it's helped me do some things >> in Perl that I see in Ruby. So there's some irony here in that I wrote >> a framework to give me some of the power I see in Ruby in Perl. :-) >> >> With all that as a backdrop, here's how I can process command line >> arguments in Perl (*everything* I do in Perl is OO!!) and I want the >> same thing in Ruby. OptParser in Ruby is WAY more than I'm looking for >> -- not as easy as what I'm used to (or maybe I don't understand >> OptParser, which is likely). >> >> In Perl, I can do this: >> >> options = MyFramework::Options->new( >> sourcePath => 's:' >> destPath => 'd:' >> verbose => 'v' >> ); >> >> What ends up happening behind the scenes is a class instance is created >> dynamically that essentially gives me the ability to say: >> >> ## I actually have a puts() I created in Perl as well, >> ## borrowed from Ruby! >> puts( >> "Source path.......: " . $options->sourcePath, >> "Destination path..: " . $options->destPath, >> "Verbose is........: " . ($options->verbose ? 'ON' : 'OFF'), >> ); >> >> So I have a getter for sourcePath, a getter for destPath and a getter >> for verbose, automagically created for that instance loaded with the >> values from the command line. If I said: >> >> whatever = MyFramework::Options->new( >> foo => 'f:', >> bar => 'b:', >> ); >> >> Then I would have an instance of 'whatever' with foo and bar as getters, >> etc. with the values of 'f' and 'b' from the command line loaded >> appropriately. >> >> Now how to do this in Ruby? Like I said, the OptParser seems WAY too >> complicated for what I want and am trying to do. It seems like you >> still are coding some kind of OptParser class for the specific options >> you want -- I don't want to create classes that mirror the command line >> options. I want to tell the class instance at the time I create it >> (kind of like OpenStruct) what it looks like and it just creates the >> right instance. I want to be able to do this in Ruby, assuming I would >> "define" this dynamically on the fly using maybe a hash as initial >> input... I like the flexibility of hashes: >> >> options = Options.new({ >> :sPath => 's:', >> :dPath => 'd:', >> :verbose => 'v', >> }) >> >> puts "Source path.......: #{options.sPath}" >> puts "Destination path..: #{options.dPath}" >> puts "Verbose is........: #{options.verbose ? 'ON' : 'OFF'}" >> >> What this is saying is "map the value of 's' from the command line into >> @sPath, map the value of 'd' from the command line into @dPath, and map >> whether 'v' exists, true or false, into @verbose." Now how much more >> simple can you get??!! >> >> Again, the warning of "trying to do Ruby stuff in a Perl way" comes to >> me, but what I do in Perl is so stinking simple, it's unbelievable, and >> this is one reason I haven't switched over to Ruby yet. But now I'm >> trying. >> >> Things I've tried: A lot of different combinations of... >> -- missing_method() >> -- define_method() >> (I don't understand why a lot of d_m() examples use self.class.send()!!) >> -- Struct() >> -- OpenStruct() >> >> So far, requiring "optparse" and doing ARGV.getopts() does some of what >> I want. This is as close as I've gotten and it's not working: >> >> require "optparse" >> >> class Options >> attr_reader :cmdline, :options_list >> def initialize( options ) >> @cmdline = ARGV.join( ' ' ) >> @options_list = options.values.join >> params = ARGV.getopts( @options_list ) >> options.each do |key,value| >> ## Why do I need to send( :define_method, ... ) here? >> ## Why can't I just say self.define_method? >> ## This seems like it would create proper closure >> ## on params[] elements?! >> self.class.send( :define_method, key ) { params[value] } >> end >> end >> end >> >> options = Options.new({ >> :sPath => 's:', >> :dPath => 'd:', >> :verbose => 'v', >> }) >> >> If someone can tell me how to do this using OptParser, so be it. But >> from an encapsulation standpoint, I'd like to be able to call it as I do >> above. If the innards of the Options class use OptParser, fine. >> >> -pj >> >> -- >> Posted via http://www.ruby-forum.com/. >> >> > Ruby has a builtin -s flag, which will parse args > > I don't know Perl so I can't say if it will meet your needs, but does this > program do what you want? > > ----- > > #!/usr/bin/env ruby -s > options = { > :source_path => 's' > :dest_path => 'd' > :verbose => 'v' > } > p options > > Sorry, that should be like this: --- #!/usr/bin/env ruby -s options = { :source_path => $s, :dest_path => $d, :verbose => $v, } p options --- And you could invoke it like this $ ./script.rb -s=path/to/input.txt -d=path/to/output.txt -v {:source_path=>"path/to/input.txt", :dest_path=>"path/to/output.txt", :verbose=>true} --f46d04339cced15d8104adca6dad--