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