hq-tools 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: