=begin = class NumRu::Misc::KeywordOpt == Overview A class to facilitate optional keyword arguments. More specifically, it helps the use of a Hash to mimic the keyword argument system. == Usage example Suppose that you introduce keyword arguments "flag" and "number" to the method "hoge" in a class/module Foo. It can be done as follows: require 'numru/misc/keywordopt' include NumRu class Foo @@opt_hoge = KeywordOpt.new( ['flag', false, 'whether or not ...'], ['number', 1, 'number of ...'], ['help', false, 'show help message'] ) def hoge(regular_arg1, regular_arg2, options=nil) opt = @@opt_hoge.interpret(options) if opt['help'] puts @@opt_hoge.help puts ' Current values='+opt.inspect raise HelpMessagingException, '** show help message and raise **' end # do what you want below # (options are set in the Hash opt: opt['flag'] and opt['number']) end end Here, the options are defined in the class variable @@opt_hoge with option names, defualt values, and descriptions (for help messaging). One can use the method hoge as follows: foo = Foo.new ... x = ... y = ... ... foo.hoge( x, y, {'flag'=>true, 'number'=>10} ) Or equivalently, foo.hoge( x, y, 'flag'=>true, 'number'=>10 ) because '{}' can be omitted here. If you want to show the help message, use foo.hoge( x, y, 'help'=>true ) Tails of options names can be shortened as long as unambiguous: foo.hoge( x, y, 'fla'=>true, 'num'=>10 ) This will cause an exception raised with the following help message such as: \** Description of options ** option name => default value (description), ..: { "flag" => false (whether or not ...), "number" => 1 (number of ...), "help" => false (show help message)} Current values={"help"=>true, "number"=>1, "flag"=>false} NumRu::Misc::HelpMessagingException: ** show help message and raise ** from (irb):78:in `hoge' from (irb):83 == Class methods ---KeywordOpt.new( *args ) Constructor. ARGUMENTS * args : arrays of two or three elements: [option name, defualt value, description ], or [option name, defualt value] if you don't want to write descriptions. Option names and descriptions must be String. RETURN VALUE * a KeywordOpt object == Methods ---interpret(hash) Interprets a hash that specifies option values. ARGUMENTS * hash (Hash) : a hash with string keys matching option names (initialized when constructed). The matching is case sensitive and done such that the tail of a option name can be omitted as long as unambiguous (for example, 'num' for 'number'). RETURN VALUE * a Hash containing the option values (default values overwritten with hash). POSSIBLE EXCEPTION * hash has a key that does not match any of the option names. * hash has a key that is ambigous ---help Returns a help message RETURN VALUE * a String describing the option names, defualt values, and descriptions =end module NumRu class HelpMessagingException < StandardError end class KeywordOpt def initialize(*args) # USAGE: # KeywordOpt.new([key,val,description],[key,val,description],..) # where key is a String, and description can be omitted. @val=Hash.new @description=Hash.new @keys = [] args.each{ |x| @keys.push(x[0]) @val[x[0]]=x[1] @description[x[0]]= ( (x.length>=3) ? x[2] : '' ) } @keys_sort = @keys.sort end def interpret(hash) return @val if !hash ## len = @val.length im = 0 out = @val.dup hash.keys.sort.each do |key| rkey = /^#{key}/ loop do if rkey =~ @keys_sort[im] if im default value (description), ..:\n{" + @keys.collect{|k| " #{k.inspect} => #{@val[k].inspect} (#{@description[k]})"}.join(",\n") + '}' end end module DCL_Ext module_function #< def sgset sgstx udset udstx etc. > # USAGE EAXPLE: usset('lxinv'=>true, 'xfac'=>10, 'cxttl'=>'longitude') %w!gl sl sg sw uc ud ue ug ul um us uu uz!.each do |pkg| %w!set stx!.each do |set| eval <<-EOS def #{pkg}#{set}( hash ) hash.each{|k,v| DCL.#{pkg}p#{set}(k,v) } end EOS end end # < contour/tone level handling > @@opt_levels = KeywordOpt.new( ['levels',nil, 'levels'], ['mjmn', nil, 'whether major or minor ex.[false,true,false,...]'], ['cmin', nil, 'minimum level'], ['cmax', nil, 'maximum level'], ['cint', nil, 'interval'], ['nlev', 10, 'number of levels'], ['help', nil, 'show help message'] ) def ud_set_levels(z,options=nil) # < interpret options > opt = @@opt_levels.interpret(options) if opt['help'] puts @@opt_levels.help puts ' Current values='+opt.inspect return end if levels=opt['levels'] icycle = DCL.udiget('icycle') indxmj = DCL.udiget('indxmj') indxmn = DCL.udiget('indxmn') idash = DCL.udiget('idash') ldash = DCL.udlget('ldash') label = DCL.udlget('label') isolid = DCL.udiget('isolid') rsizel = DCL.udrget('rsizel') nlev=levels.length if (mjmn=opt['mjmn']) if mjmn.length != levels.length raise ArgumentError,"lengths of levels and mjmn do not agree" end else if levels.include?(0) idx = levels.index(0) ioffset = icycle*idx - idx else ioffset = 1 end mjmn = (0...nlev).collect{|x| ((x+ioffset)%icycle)==0} end indices = mjmn.collect{|x| (x ? indxmj : indxmn)} DCL.udiclv (0...nlev).each{ |i| lev = levels[i] clev = DCL.udlabl(lev) ityp = ( ldash && lev<0 ) ? idash : isolid ht = ( mjmn[i] && label ) ? rsizel : 0.0 DCL.udsclv(lev,indices[i],ityp,clev,ht) } elsif opt['cmin'] || opt['cmax'] || opt['cint'] || opt['nlev'] cmin=opt['cmin'] cmax=opt['cmax'] cint=opt['cint'] nlev=opt['nlev'] dx = ( cint || -nlev ) if cmin || cmax # if one or two of [cmin,cmax] is/are defined: cmin = z.min if !cmin cmax = z.max if !cmax DCL.udgcla(cmin,cmax,dx) else DCL.udgclb(z,dx) end else levels = nil end end end end ################################################# if $0 == __FILE__ require "narray" require "numru/dcl" include NumRu include Math nx = 19 ny = 19 xmin = 0 xmax = 360 ymin = -90 ymax = 90 drad = PI/180 dz = 0.05 p = NArray.sfloat(nx, ny) #-- data --- for j in 0..ny-1 for i in 0..nx-1 alon = (xmin + (xmax-xmin)*i/(nx-1)) * drad alat = (ymin + (ymax-ymin)*j/(ny-1)) * drad slat = sin(alat) p[i,j] = cos(alon) * (1-slat**2) * sin(2*PI*slat) + dz end end #-- graph --- iws = (ARGV[0] || (puts ' WORKSTATION ID (I) ? ;'; DCL::sgpwsn; gets)).to_i DCL::gropn iws DCL::sldiv('y',2,1) DCL::grfrm DCL::grswnd(xmin, xmax, ymin, ymax) DCL::grsvpt(0.2, 0.8, 0.2, 0.8) DCL::grstrn(1) DCL::grstrf DCL::usdaxs DCL_Ext.udset('icycle'=>3,'idash'=>4) DCL_Ext.ud_set_levels(p, 'nlev'=>8, 'help'=>true) DCL_Ext.ud_set_levels(p,{'nlev'=>8, 'cmin'=>-0.2}) DCL::udcntr(p) DCL::grfrm DCL::grswnd(xmin, xmax, ymin, ymax) DCL::grsvpt(0.2, 0.8, 0.2, 0.8) DCL::grstrn(1) DCL::grstrf DCL::usdaxs DCL_Ext.ud_set_levels(p,{'lev'=>[-0.3,-0.1,0,0.1,0.3]}) DCL::udcntr(p) DCL::grcls end