From: Akinori MUSHA Date: 2002-03-04T05:55:41+09:00 Subject: [ruby-dev:16193] Re: getopts() broken At Mon, 4 Mar 2002 05:12:42 +0900, I wrote: >  なお、上記の仕様は sh(1) の getopts を知っていると間違えそう > なので、ちょっといじってみます。  以下のようにいじりました。 - single_opts_exp, single_colon, single_colon_exp はあまり存在 意義がないので廃止。--c と -- に続けて一文字オプションを指定 する(不正な)ケースは arg のループで弾くようにした。 - 第一引数内に : を許すようにした。("ab:cde:f" 等) - --long-option=value 形式の = を入れた指定に対応。 - 空の初期値を 0 にしておいて後で nil にする意味が分からないので やめた。 - インデントを直した。 すっきりしたので、問題なさそうならあとで 1.7 に入れます。 -- / /__ __ Akinori.org / MUSHA.org / ) ) ) ) / FreeBSD.org / Ruby-lang.org Akinori MUSHA aka / (_ / ( (__( @ iDaemons.org / and.or.jp "Somewhere out of a memory.. of lighted streets on quiet nights.." Index: lib/getopts.rb =================================================================== RCS file: /src/ruby/lib/getopts.rb,v retrieving revision 1.5 diff -u -r1.5 getopts.rb --- lib/getopts.rb 2001/05/06 15:04:52 1.5 +++ lib/getopts.rb 2002/03/03 20:43:49 @@ -16,11 +16,6 @@ def getopts( single_opts, *options ) - single_opts_exp = (single_opts && !single_opts.empty?) ? - /[#{single_opts}]/ : nil - single_colon_exp = nil - single_colon = nil - opt = arg = val = nil boolopts = {} valopts = {} argv = ARGV @@ -30,34 +25,25 @@ # set default # if single_opts then - single_opts.each_byte do |byte| - boolopts[ byte.chr ] = false + single_opts.scan(/.:?/) do |opt| + if opt.size == 1 then + boolopts[ opt ] = false + else + valopts[ opt[0, 1] ] = 0 + end + end end -end unless options.empty? then - single_colon = '' - - options.each do |opt| - m = /\A([^:]+):(.*)\z/.match( opt ) - if m then - valopts[ m[1] ] = m[2].empty? ? 0 : m[2] + options.each do |arg| + opt, val = arg.split(':', 2) + if val then + valopts[ opt ] = val.empty? ? nil : val else boolopts[ opt ] = false -end - end - valopts.each do |opt, dflt| - if opt.size == 1 then - single_colon << opt -end - end - - if single_colon.empty? then - single_colon = single_colon_exp = nil - else - single_colon_exp = /[#{single_colon}]/ + end end end - + # # scan # @@ -70,10 +56,11 @@ break when /\A--(.*)/ - opt = $1 - if valopts.key? opt then # imclean --src +trash - return nil if argv.empty? - valopts[ opt ] = argv.shift + opt, val = $1.split('=', 2) + if opt.size == 1 then + return nil + elsif valopts.key? opt then # imclean --src +trash + valopts[ opt ] = val || argv.shift or return nil elsif boolopts.key? opt then # ruby --verbose boolopts[ opt ] = true else @@ -85,41 +72,39 @@ arg = $1 0.upto( arg.size - 1 ) do |idx| opt = arg[idx, 1] - if single_opts and single_opts_exp === opt then + if boolopts.key? opt then boolopts[ opt ] = true # ruby -h c += 1 - - elsif single_colon and single_colon_exp === opt then + elsif valopts.key? opt then val = arg[ (idx+1)..-1 ] if val.empty? then # ruby -e 'p $:' - return nil if argv.empty? - valopts[ opt ] = argv.shift + valopts[ opt ] = argv.shift or return nil else # cc -ohello ... valopts[ opt ] = val - end + end c += 1 break - else + else return nil - end - end + end + end else # ruby test.rb newargv.push arg - end + end arg = argv.shift - end - + end + # # set # boolopts.each do |opt, val| eval "$OPT_#{opt} = val" - end + end valopts.each do |opt, val| - eval "$OPT_#{opt} = #{val == 0 ? 'nil' : 'val'}" + eval "$OPT_#{opt} = val" end argv.replace newargv