hq-tools 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/hq/tools/getopt.rb +158 -0
  2. metadata +4 -3
@@ -0,0 +1,158 @@
1
+ module HQ
2
+ module Tools
3
+ module Getopt
4
+
5
+ def self.to_long name
6
+ return "--#{name.to_s.gsub "_", "-"}"
7
+ end
8
+
9
+ def self.process argv, easy_specs
10
+
11
+ argv = argv.flatten
12
+
13
+ # convert easy_specs into specs
14
+ specs = {}
15
+ ret = {}
16
+ easy_specs.each do |easy_spec|
17
+ if easy_spec[:options]
18
+ options = easy_spec[:options].clone
19
+ options << easy_spec[:default] if easy_spec[:default]
20
+ options.each do |option|
21
+ spec = {}
22
+ spec[:long_name] = to_long option
23
+ spec[:type] = option == easy_spec[:default] ? :switch_default : :switch
24
+ spec[:key] = easy_spec[:name]
25
+ spec[:arg_value] = option
26
+ specs[spec[:long_name]] = spec
27
+ end
28
+ ret[easy_spec[:name]] = easy_spec[:default]
29
+ else
30
+ easy_spec[:long_name] = to_long easy_spec[:name]
31
+ spec = {}
32
+ spec[:long_name] = to_long easy_spec[:name]
33
+ spec[:type] = case
34
+ when easy_spec[:boolean] then :boolean
35
+ when easy_spec[:required] then :required
36
+ else :optional
37
+ end
38
+ spec[:key] = easy_spec[:name]
39
+ spec[:arg_value] = easy_spec[:default]
40
+ spec[:verify] = easy_spec[:regex]
41
+ spec[:convert] = easy_spec[:convert]
42
+ spec[:multi] = easy_spec[:multi]
43
+ specs[spec[:long_name]] = spec
44
+ if easy_spec[:multi]
45
+ ret[easy_spec[:name]] = []
46
+ elsif easy_spec[:boolean]
47
+ ret[easy_spec[:name]] = false
48
+ elsif easy_spec[:required]
49
+ # do nothing
50
+ else
51
+ ret[easy_spec[:name]] = easy_spec[:default]
52
+ end
53
+ end
54
+ end
55
+
56
+ # save main argv value because we clobber it
57
+ old_argv = []
58
+ ARGV.each { |arg| old_argv << arg }
59
+ new_argv = []
60
+ argv.each { |arg| new_argv << arg }
61
+ begin
62
+
63
+ require "getoptlong"
64
+ getopt_args = []
65
+ specs.each do |long_name, spec|
66
+ getopt_flags = case spec[:type]
67
+ when :required then GetoptLong::REQUIRED_ARGUMENT
68
+ when :optional then GetoptLong::REQUIRED_ARGUMENT
69
+ when :boolean then GetoptLong::NO_ARGUMENT
70
+ when :switch then GetoptLong::NO_ARGUMENT
71
+ when :switch_default then GetoptLong::NO_ARGUMENT
72
+ else raise "Invalid getopt argument type: #{spec[:type]}"
73
+ end
74
+ getopt_args << [ spec[:long_name], getopt_flags ]
75
+ #ret[spec[:key]] = spec[:arg_value] if [ :optional, :switch_default ].include? spec[:type]
76
+ #ret[spec[:key]] = [] if spec[:multi]
77
+ #ret[spec[:key]] = false if spec[:type] == :boolean
78
+ end
79
+ ARGV.clear
80
+ new_argv.each { |arg| ARGV << arg }
81
+ GetoptLong.new(*getopt_args).each do |opt, arg|
82
+ spec = specs[opt]
83
+ case spec[:type]
84
+ when :required, :optional
85
+ ret[spec[:key]] << arg if spec[:multi]
86
+ ret[spec[:key]] = arg unless spec[:multi]
87
+ when :switch, :switch_default
88
+ ret[spec[:key]] = spec[:arg_value]
89
+ when :boolean
90
+ ret[spec[:key]] = true
91
+ else
92
+ raise "Error"
93
+ end
94
+ end
95
+
96
+ # check for missing required arguments
97
+ specs.values.each do |spec|
98
+ next unless spec[:type] == :required
99
+ next if ! spec[:multi] && ret.include?(spec[:key])
100
+ next if spec[:multi] && ! ret[spec[:key]].empty?
101
+ msg = "#{$0}: option '#{spec[:long_name]}' is required"
102
+ $stderr.puts msg
103
+ raise GetoptError.new msg
104
+ end
105
+
106
+ # check for mismatched regex arguments
107
+ easy_specs.each do |easy_spec|
108
+ next unless easy_spec[:regex]
109
+ if easy_spec[:multi]
110
+ ret[easy_spec[:name]].each do |value|
111
+ next if value =~ /^#{easy_spec[:regex]}$/
112
+ msg = "#{$0}: option '#{easy_spec[:long_name]}' is invalid: #{value}"
113
+ $stderr.puts msg
114
+ raise GetoptError.new msg
115
+ end
116
+ else
117
+ next if ret[easy_spec[:name]] == easy_spec[:default]
118
+ next if ret[easy_spec[:name]] =~ /^#{easy_spec[:regex]}$/
119
+ msg = "#{$0}: option '#{easy_spec[:long_name]}' is invalid: #{ret[easy_spec[:name]]}"
120
+ $stderr.puts msg
121
+ raise GetoptError.new msg
122
+ end
123
+ end
124
+
125
+ # perform conversions
126
+ specs.values.each do |spec|
127
+ next unless ret[spec[:key]].is_a? String
128
+ case spec[:convert]
129
+ when nil
130
+ # do nothing
131
+ when Symbol
132
+ ret[spec[:key]] = ret[spec[:key]].send spec[:convert]
133
+ when Method
134
+ ret[spec[:key]] = spec[:convert].call ret[spec[:key]]
135
+ else
136
+ raise "Don't know what to do with #{spec[:convert].class}"
137
+ end
138
+ end
139
+
140
+ rest = []
141
+ ARGV.each { |arg| rest << arg }
142
+ return ret, rest
143
+
144
+ rescue GetoptLong::MissingArgument
145
+ raise GetoptError
146
+
147
+ ensure
148
+ ARGV.clear
149
+ old_argv.each { |arg| ARGV << arg }
150
+ end
151
+ end
152
+
153
+ class HQ::Tools::GetoptError < StandardError
154
+ end
155
+
156
+ end
157
+ end
158
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hq-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -97,13 +97,14 @@ email:
97
97
  executables: []
98
98
  extensions: []
99
99
  extra_rdoc_files: []
100
- files: []
100
+ files:
101
+ - lib/hq/tools/getopt.rb
101
102
  homepage: https://github.com/jamespharaoh/hq-tools
102
103
  licenses: []
103
104
  post_install_message:
104
105
  rdoc_options: []
105
106
  require_paths:
106
- - ruby
107
+ - lib
107
108
  required_ruby_version: !ruby/object:Gem::Requirement
108
109
  none: false
109
110
  requirements: