command line interface - How to DRYly subclass (or otherwise share code with) rubys OptionParser to e.g. share options? -


i want share options multiple scripts , prefer use 'builtin' optparse on other cli-or-optionparsing-frameworks.

i looked @ mris optparse.rb , not understand how best sublass optionparser (the initializer takes block).

optimally arrive @ code this

# exe/a_script require 'mygem'  options = {whatever: 'default'} mygem::optionparser.new |opts|   opts.on('--whatever') |w|     options[:whatever] = w   end end.parse! 

and second script consumer:

# exe/other_script require 'mygem'   options = {and_another: 'default'} mygem::optionparser.new |opts|   opts.on('--and_another') |a|     options[:and_another] = w   end end.parse! 

and define "default option" (say "-v" verbose , "-h" help" in common custom optionparser.

# lib/mygem/mygem_optionparser.rb require 'optparse' module mygem   class optionparser < optionparser     # magic     # define opts.on("-v") -> set options[:verbose],     # define opts.on_tail("-h", "print , exit") ...   end end 

both scripts should end having , handling "-h" , "-v" flags, ideally filling "options" hash, exposing mygem::optionparser#default_option_values.

where start? or there clever way of handling differently, e.g.

# exe/b_script optionparser.new |opts|   define_custom_opts(opts) end 

i wonder have not found tutorial or example on scenario, assume not such rare use-case. , yes, absolutely want stick 'optparse'.

update got confused, not looking @ correct optpase-source , not seeing yields self (which freaked me out bit :) . great answers far.

i haven't used optionparser there may better way this, i'll take stab @ anyway.

the important thing optionparser#initialize (for our purposes) yields self block given. make subclass works same, have make initialize method yield self, too:

require 'optparse' require 'ostruct'  module mygem   class optionparser < ::optionparser     attr_reader :options      def initialize(*args)       @options = openstruct.new        super *args       default_options!        yield(self, options) if block_given?     end      private     def default_options!       on '--whatever=whatever' |w|         options.whatever = w       end     end   end end 

this calls super of passed arguments except passed block (if given). calls default_options! create default options (this have done passing block super, find above cleaner).

finally, yields given block superclass did, passes second argument, options object. user can use this:

require 'my_gem/option_parser'  opts = mygem::optionparser.new |parser, options|   parser.on '--and-another=another' |a|     options.another =   end end  opts.parse! p opts.options 

this give user results following:

$ ruby script.rb --whatever=www --and-another=aaa #<openstruct whatever="www", another="aaa"> 

as alternative yield(self, options), use yield self, user need e.g. parser.options.whatever = ... inside block.

another alternative add &block argument initialize , instance_eval(&block) instead of yield. evaluate block in instance context, user access options attribute (and other instance methods, etc.) directly, e.g.:

parser = mygem::optionparser.new   on '--and-another=another' |a|     options.another =   end end  parser.parse! 

that has downside, however, user must know block evaluated in instance context. prefer explicit yield(self, options).


Comments

Popular posts from this blog

Hatching array of circles in AutoCAD using c# -

ios - UITEXTFIELD InputView Uipicker not working in swift -

Python Pig Latin Translator -