1# OptionParser internal utility
2
3class << OptionParser
4  def show_version(*pkgs)
5    progname = ARGV.options.program_name
6    result = false
7    show = proc do |klass, cname, version|
8      str = "#{progname}"
9      unless klass == ::Object and cname == :VERSION
10        version = version.join(".") if Array === version
11        str << ": #{klass}" unless klass == Object
12        str << " version #{version}"
13      end
14      [:Release, :RELEASE].find do |rel|
15        if klass.const_defined?(rel)
16          str << " (#{klass.const_get(rel)})"
17        end
18      end
19      puts str
20      result = true
21    end
22    if pkgs.size == 1 and pkgs[0] == "all"
23      self.search_const(::Object, /\AV(?:ERSION|ersion)\z/) do |klass, cname, version|
24        unless cname[1] == ?e and klass.const_defined?(:Version)
25          show.call(klass, cname.intern, version)
26        end
27      end
28    else
29      pkgs.each do |pkg|
30        begin
31          pkg = pkg.split(/::|\//).inject(::Object) {|m, c| m.const_get(c)}
32          v = case
33              when pkg.const_defined?(:Version)
34                pkg.const_get(n = :Version)
35              when pkg.const_defined?(:VERSION)
36                pkg.const_get(n = :VERSION)
37              else
38                n = nil
39                "unknown"
40              end
41          show.call(pkg, n, v)
42        rescue NameError
43        end
44      end
45    end
46    result
47  end
48
49  def each_const(path, base = ::Object)
50    path.split(/::|\//).inject(base) do |klass, name|
51      raise NameError, path unless Module === klass
52      klass.constants.grep(/#{name}/i) do |c|
53        klass.const_defined?(c) or next
54        c = klass.const_get(c)
55      end
56    end
57  end
58
59  def search_const(klass, name)
60    klasses = [klass]
61    while klass = klasses.shift
62      klass.constants.each do |cname|
63        klass.const_defined?(cname) or next
64        const = klass.const_get(cname)
65        yield klass, cname, const if name === cname
66        klasses << const if Module === const and const != ::Object
67      end
68    end
69  end
70end
71