9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
# File 'lib/hq/tools/getopt.rb', line 9
def self.process argv, easy_specs
argv = argv.flatten
specs = {}
ret = {}
easy_specs.each do |easy_spec|
if easy_spec[:options]
options = easy_spec[:options].clone
options << easy_spec[:default] if easy_spec[:default]
options.each do |option|
spec = {}
spec[:long_name] = to_long option
spec[:type] = option == easy_spec[:default] ? :switch_default : :switch
spec[:key] = easy_spec[:name]
spec[:arg_value] = option
specs[spec[:long_name]] = spec
end
ret[easy_spec[:name]] = easy_spec[:default]
else
easy_spec[:long_name] = to_long easy_spec[:name]
spec = {}
spec[:long_name] = to_long easy_spec[:name]
spec[:type] = case
when easy_spec[:boolean] then :boolean
when easy_spec[:required] then :required
else :optional
end
spec[:key] = easy_spec[:name]
spec[:arg_value] = easy_spec[:default]
spec[:verify] = easy_spec[:regex]
spec[:convert] = easy_spec[:convert]
spec[:multi] = easy_spec[:multi]
specs[spec[:long_name]] = spec
if easy_spec[:multi]
ret[easy_spec[:name]] = []
elsif easy_spec[:boolean]
ret[easy_spec[:name]] = false
elsif easy_spec[:required]
else
ret[easy_spec[:name]] = easy_spec[:default]
end
end
end
old_argv = []
ARGV.each { |arg| old_argv << arg }
new_argv = []
argv.each { |arg| new_argv << arg }
begin
require "getoptlong"
getopt_args = []
specs.each do |long_name, spec|
getopt_flags = case spec[:type]
when :required then GetoptLong::REQUIRED_ARGUMENT
when :optional then GetoptLong::REQUIRED_ARGUMENT
when :boolean then GetoptLong::NO_ARGUMENT
when :switch then GetoptLong::NO_ARGUMENT
when :switch_default then GetoptLong::NO_ARGUMENT
else raise "Invalid getopt argument type: #{spec[:type]}"
end
getopt_args << [ spec[:long_name], getopt_flags ]
end
ARGV.clear
new_argv.each { |arg| ARGV << arg }
GetoptLong.new(*getopt_args).each do |opt, arg|
spec = specs[opt]
case spec[:type]
when :required, :optional
ret[spec[:key]] << arg if spec[:multi]
ret[spec[:key]] = arg unless spec[:multi]
when :switch, :switch_default
ret[spec[:key]] = spec[:arg_value]
when :boolean
ret[spec[:key]] = true
else
raise "Error"
end
end
specs.values.each do |spec|
next unless spec[:type] == :required
next if ! spec[:multi] && ret.include?(spec[:key])
next if spec[:multi] && ! ret[spec[:key]].empty?
msg = "#{$0}: option '#{spec[:long_name]}' is required"
$stderr.puts msg
raise GetoptError.new msg
end
easy_specs.each do |easy_spec|
next unless easy_spec[:regex]
if easy_spec[:multi]
ret[easy_spec[:name]].each do |value|
next if value =~ /^#{easy_spec[:regex]}$/
msg = "#{$0}: option '#{easy_spec[:long_name]}' is invalid: #{value}"
$stderr.puts msg
raise GetoptError.new msg
end
else
next if ret[easy_spec[:name]] == easy_spec[:default]
next if ret[easy_spec[:name]] =~ /^#{easy_spec[:regex]}$/
msg = "#{$0}: option '#{easy_spec[:long_name]}' is invalid: #{ret[easy_spec[:name]]}"
$stderr.puts msg
raise GetoptError.new msg
end
end
specs.values.each do |spec|
next unless ret[spec[:key]].is_a? String
case spec[:convert]
when nil
when Symbol
ret[spec[:key]] = ret[spec[:key]].send spec[:convert]
when Method
ret[spec[:key]] = spec[:convert].call ret[spec[:key]]
else
raise "Don't know what to do with #{spec[:convert].class}"
end
end
rest = []
ARGV.each { |arg| rest << arg }
return ret, rest
rescue GetoptLong::MissingArgument
raise GetoptError
ensure
ARGV.clear
old_argv.each { |arg| ARGV << arg }
end
end
|