everyday-cli-utils 1.4.0 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +4 -0
- data/lib/everyday-cli-utils/option.rb +225 -45
- data/lib/everyday-cli-utils/version.rb +1 -1
- data/spec/everyday-cli-utils/option_spec.rb +22 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f9fc1d7f33b7176bce22227eb740e2ac62471de
|
4
|
+
data.tar.gz: 618d8eec3dba4932423a28cd162f17876dbc778f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 62e8a9e6fecc2acaf672c576792209e4b81a843a908cb970f6325495b5d0f67f822787bf8d2ba846dd765e3a959861cc9af0a8ed3bafbdfe67f6971450908d6a
|
7
|
+
data.tar.gz: 00230d29037dda5978fd74d37e04720a4e71d60f2867e26dd3f15f337eb0362da0e6f9ebf07973332463b7cdec964f422991606d8cfe9ae746a11eb33007e926
|
data/README.md
CHANGED
@@ -338,6 +338,10 @@ As of version 0.7.0, there is now built-in handling for setting and retrieving d
|
|
338
338
|
|
339
339
|
As of version 1.0.0, there is now support for the help display in `OptionParser`. You can now provide a `desc:` hash option to the option creating methods (even pre-made ones like `defaults_option` and `help_option`). You can set the banner with the `EverydayCliUtils::OptionUtil.banner` method, which takes the banner string as its parameter. You can get the help string with `EverydayCliUtils::OptionUtil.help` or `EverydayCliUtils::OptionUtil.to_s`, or you can handle it with `EverydayCliUtils::OptionUtil.help_option`, which takes an array of the names and an optional `desc:` hash option. When the user specifies one of those options, the utility will automatically print out the help and exit (unless you specify the hash option `exit_on_print: false`).
|
340
340
|
|
341
|
+
As of version 1.4.0, there is support for overriding the built-in help display. You can now use the `help_str=` method to set the help string override. See my `mvr` gem for an example.
|
342
|
+
|
343
|
+
As of version 1.5.0, there is support for having global defaults. It is basically the same as the regular defaults option, but it uses the method `global_default_options` instead of just `default_options`. If the global defaults file exists, it will be loaded first, with the local defaults being loaded on top of it as if they were passed as flags, and then the flags are loaded on top of that in the same manner.
|
344
|
+
|
341
345
|
## Contributing
|
342
346
|
|
343
347
|
1. Fork it ( http://github.com/henderea/everyday-cli-utils/fork )
|
@@ -22,93 +22,273 @@ module EverydayCliUtils
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
|
26
|
-
|
25
|
+
class OptionType
|
26
|
+
def initialize(default_value_block, value_determine_block, name_mod_block = nil, value_transform_block = nil)
|
27
|
+
@default_value_block = default_value_block
|
28
|
+
@value_determine_block = value_determine_block
|
29
|
+
@name_mod_block = name_mod_block
|
30
|
+
@value_transform_block = value_transform_block
|
31
|
+
end
|
27
32
|
|
28
|
-
def
|
29
|
-
@
|
30
|
-
@options ||= {}
|
31
|
-
@default_settings ||= {}
|
32
|
-
settings[:toggle] = @default_settings[:toggle] unless settings.has_key?(:toggle) || !@default_settings.has_key?(:toggle)
|
33
|
-
names << settings[:desc] if settings.has_key?(:desc)
|
34
|
-
@options[opt_name] = false
|
35
|
-
@opts.on(*names) {
|
36
|
-
@options[opt_name] = !settings[:toggle] || !@options[opt_name]
|
37
|
-
yield if block_given?
|
38
|
-
}
|
33
|
+
def default_value(settings = {})
|
34
|
+
@default_value_block.call(settings)
|
39
35
|
end
|
40
36
|
|
41
|
-
def
|
42
|
-
@
|
43
|
-
@
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
37
|
+
def updated_value(current_value, new_value, settings = {})
|
38
|
+
new_value = @value_transform_block.call(new_value, settings) unless @value_transform_block.nil?
|
39
|
+
@value_determine_block.call(current_value, new_value, settings)
|
40
|
+
end
|
41
|
+
|
42
|
+
def mod_names(names, settings = {})
|
43
|
+
@name_mod_block.call(names, settings)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class OptionTypes
|
48
|
+
def self.def_type(type, default_value_block, value_determine_block, name_mod_block = nil, value_transform_block = nil)
|
49
|
+
@types ||= {}
|
50
|
+
@types[type] = OptionType.new(default_value_block, value_determine_block, name_mod_block, value_transform_block)
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.default_value(type, settings = {})
|
54
|
+
@types ||= {}
|
55
|
+
@types.has_key?(type) ? @types[type].default_value(settings) : nil
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.updated_value(type, current_value, new_value, settings = {})
|
59
|
+
@types ||= {}
|
60
|
+
@types.has_key?(type) ? @types[type].updated_value(current_value, new_value, settings) : current_value
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.mod_names(type, names, settings = {})
|
64
|
+
@types ||= {}
|
65
|
+
@types.has_key?(type) ? @types[type].mod_names(names, settings) : names
|
66
|
+
end
|
67
|
+
|
68
|
+
def_type(:option,
|
69
|
+
->(_) {
|
70
|
+
false
|
71
|
+
},
|
72
|
+
->(current_value, new_value, settings) {
|
73
|
+
new_value ? (!settings[:toggle] || !current_value) : current_value
|
74
|
+
},
|
75
|
+
->(names, settings) {
|
76
|
+
settings.has_key?(:desc) ? (names + [settings[:desc]]) : names
|
77
|
+
},
|
78
|
+
->(new_value, _) {
|
79
|
+
!(!new_value)
|
80
|
+
})
|
81
|
+
def_type(:option_with_param,
|
82
|
+
->(settings) {
|
83
|
+
settings[:append] ? [] : nil
|
84
|
+
},
|
85
|
+
->(current_value, new_value, settings) {
|
86
|
+
settings[:append] ? (current_value + new_value) : new_value
|
87
|
+
},
|
88
|
+
->(names, settings) {
|
89
|
+
names[0] << ' PARAM' unless names.any? { |v| v.include?(' ') }
|
90
|
+
names = settings.has_key?(:desc) ? (names + [settings[:desc]]) : names
|
91
|
+
settings.has_key?(:type) ? (names + [settings[:type]]) : names
|
92
|
+
},
|
93
|
+
->(new_value, settings) {
|
94
|
+
new_value.is_a?(Array) ? (settings[:append] ? new_value : new_value[0]) : (settings[:append] ? [new_value] : new_value)
|
95
|
+
})
|
96
|
+
end
|
97
|
+
|
98
|
+
class OptionDef
|
99
|
+
attr_reader :value
|
100
|
+
|
101
|
+
def initialize(type, settings = {}, &block)
|
102
|
+
@type = type
|
103
|
+
@settings = settings
|
104
|
+
@block = block
|
105
|
+
@value = OptionTypes.default_value(type, settings)
|
106
|
+
@values = {}
|
107
|
+
end
|
108
|
+
|
109
|
+
def set(value)
|
110
|
+
@value = value
|
111
|
+
@values = {}
|
112
|
+
end
|
113
|
+
|
114
|
+
def update(value, layer)
|
115
|
+
@values[layer] = OptionTypes.default_value(@type, @settings) unless @values.has_key?(layer)
|
116
|
+
@values[layer] = OptionTypes.updated_value(@type, @values[layer], value, @settings)
|
117
|
+
end
|
118
|
+
|
119
|
+
def run
|
120
|
+
@block.call unless @block.nil? || !@block
|
121
|
+
end
|
122
|
+
|
123
|
+
def composite(*layers)
|
124
|
+
value = @value
|
125
|
+
layers.each { |layer| value = OptionTypes.updated_value(@type, value, @values[layer], @settings) if @values.has_key?(layer) }
|
126
|
+
value
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.register(opts, options, type, opt_name, names, settings = {}, default_settings = {}, &block)
|
130
|
+
settings = settings.clone
|
131
|
+
default_settings.each { |v| settings[v[0]] = v[1] unless settings.has_key?(v[0]) }
|
132
|
+
opt = OptionDef.new(type, settings, &block)
|
133
|
+
options[opt_name] = opt
|
134
|
+
names = OptionTypes.mod_names(type, names, settings)
|
135
|
+
opts.on(*names) { |*args|
|
136
|
+
opt.update(args, :arg)
|
137
|
+
opt.run
|
53
138
|
}
|
54
139
|
end
|
140
|
+
end
|
141
|
+
|
142
|
+
class OptionList
|
143
|
+
attr_reader :opts
|
144
|
+
attr_accessor :default_settings, :help_str
|
145
|
+
|
146
|
+
def initialize
|
147
|
+
@options = {}
|
148
|
+
@default_settings = {}
|
149
|
+
@opts = OptionParser.new
|
150
|
+
@help_str = nil
|
151
|
+
end
|
152
|
+
|
153
|
+
def []=(opt_name, opt)
|
154
|
+
@options[opt_name] = opt
|
155
|
+
end
|
156
|
+
|
157
|
+
def set(opt_name, value)
|
158
|
+
@options[opt_name].set(value) if @options.has_key?(opt_name)
|
159
|
+
end
|
160
|
+
|
161
|
+
def update(opt_name, value, layer)
|
162
|
+
@options[opt_name].update(value, layer) if @options.has_key?(opt_name)
|
163
|
+
end
|
164
|
+
|
165
|
+
def register(type, opt_name, names, settings = {}, &block)
|
166
|
+
OptionDef.register(@opts, @options, type, opt_name, names, settings, @default_settings, &block)
|
167
|
+
end
|
168
|
+
|
169
|
+
def composite(*layers)
|
170
|
+
hash = {}
|
171
|
+
@options.each { |v| hash[v[0]] = v[1].composite(*layers) }
|
172
|
+
hash
|
173
|
+
end
|
174
|
+
|
175
|
+
def help
|
176
|
+
@help_str.nil? ? @opts.help : @help_str
|
177
|
+
end
|
178
|
+
|
179
|
+
def to_s
|
180
|
+
@help_str.nil? ? @opts.to_s : @help_str
|
181
|
+
end
|
182
|
+
|
183
|
+
def banner=(banner)
|
184
|
+
@opts.banner = banner
|
185
|
+
end
|
186
|
+
|
187
|
+
def parse!(argv = ARGV)
|
188
|
+
@opts.parse!(argv)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
module OptionUtil
|
193
|
+
def option(opt_name, names, settings = {}, &block)
|
194
|
+
@options ||= OptionList.new
|
195
|
+
@options.register(:option, opt_name, names, settings, &block)
|
196
|
+
end
|
197
|
+
|
198
|
+
def option_with_param(opt_name, names, settings = {}, &block)
|
199
|
+
@options ||= OptionList.new
|
200
|
+
@options.register(:option_with_param, opt_name, names, settings, &block)
|
201
|
+
end
|
55
202
|
|
56
203
|
def defaults_option(file_path, names, settings = {})
|
57
|
-
@
|
204
|
+
@options ||= OptionList.new
|
58
205
|
@set_defaults = false
|
59
206
|
@defaults_file = File.expand_path(file_path)
|
60
207
|
@exit_on_save = !settings.has_key?(:exit_on_save) || settings[:exit_on_save]
|
61
208
|
names << settings[:desc] if settings.has_key?(:desc)
|
62
|
-
@opts.on(*names) { @set_defaults = true }
|
209
|
+
@options.opts.on(*names) { @set_defaults = true }
|
210
|
+
end
|
211
|
+
|
212
|
+
def global_defaults_option(file_path, names, settings = {})
|
213
|
+
@options ||= OptionList.new
|
214
|
+
@set_global_defaults = false
|
215
|
+
@global_defaults_file = File.expand_path(file_path)
|
216
|
+
@exit_on_global_save = !settings.has_key?(:exit_on_save) || settings[:exit_on_save]
|
217
|
+
names << settings[:desc] if settings.has_key?(:desc)
|
218
|
+
@options.opts.on(*names) { @set_global_defaults = true }
|
63
219
|
end
|
64
220
|
|
65
221
|
def help_option(names, settings = {})
|
66
|
-
@
|
222
|
+
@options ||= OptionList.new
|
67
223
|
@display_help = false
|
68
224
|
@exit_on_print = !settings.has_key?(:exit_on_print) || settings[:exit_on_print]
|
69
225
|
names << settings[:desc] if settings.has_key?(:desc)
|
70
|
-
@opts.on(*names) { @display_help = true }
|
226
|
+
@options.opts.on(*names) { @display_help = true }
|
71
227
|
end
|
72
228
|
|
73
229
|
def default_settings(settings = {})
|
74
|
-
@
|
230
|
+
@options ||= OptionList.new
|
231
|
+
@options.default_settings = settings
|
75
232
|
end
|
76
233
|
|
77
234
|
def default_options(opts = {})
|
78
|
-
|
235
|
+
@options ||= OptionList.new
|
236
|
+
opts.each { |opt| @options.set(opt[0], opt[1]) }
|
237
|
+
end
|
238
|
+
|
239
|
+
def apply_options(layer, opts = {})
|
240
|
+
@options ||= OptionList.new
|
241
|
+
opts.each { |opt| @options.update(opt[0], opt[1], layer) }
|
79
242
|
end
|
80
243
|
|
81
244
|
def banner(banner)
|
82
|
-
@
|
83
|
-
@
|
245
|
+
@options ||= OptionList.new
|
246
|
+
@options.banner = banner
|
247
|
+
end
|
248
|
+
|
249
|
+
def opts
|
250
|
+
@options.opts
|
251
|
+
end
|
252
|
+
|
253
|
+
def options
|
254
|
+
@options.composite(:global, :local, :arg)
|
255
|
+
end
|
256
|
+
|
257
|
+
def option_list
|
258
|
+
@options
|
84
259
|
end
|
85
260
|
|
86
261
|
def help
|
87
|
-
@
|
88
|
-
@
|
89
|
-
@help_str.nil? ? @opts.help : @help_str
|
262
|
+
@options ||= OptionList.new
|
263
|
+
@options.help
|
90
264
|
end
|
91
265
|
|
92
266
|
def to_s
|
93
|
-
@
|
94
|
-
@
|
95
|
-
@help_str.nil? ? @opts.to_s : @help_str
|
267
|
+
@options ||= OptionList.new
|
268
|
+
@options.to_s
|
96
269
|
end
|
97
270
|
|
98
271
|
def help_str=(str)
|
99
|
-
@help_str = str
|
272
|
+
@options.help_str = str
|
100
273
|
end
|
101
274
|
|
102
275
|
def parse!(argv = ARGV)
|
103
|
-
@
|
104
|
-
|
105
|
-
@
|
276
|
+
@options ||= OptionList.new
|
277
|
+
apply_options :global, YAML::load_file(@global_defaults_file) unless @global_defaults_file.nil? || !File.exist?(@global_defaults_file)
|
278
|
+
apply_options :local, YAML::load_file(@defaults_file) unless @defaults_file.nil? || !File.exist?(@defaults_file)
|
279
|
+
@options.parse!(argv)
|
106
280
|
if @display_help
|
107
281
|
puts help
|
108
282
|
exit 0 if @exit_on_print
|
109
283
|
end
|
110
|
-
if @
|
111
|
-
IO.write(@
|
284
|
+
if @set_global_defaults
|
285
|
+
IO.write(@global_defaults_file, @options.composite(:global, :arg).to_yaml)
|
286
|
+
if @exit_on_global_save
|
287
|
+
puts 'Global defaults set'
|
288
|
+
exit 0
|
289
|
+
end
|
290
|
+
elsif @set_defaults
|
291
|
+
IO.write(@defaults_file, @options.composite(:local, :arg).to_yaml)
|
112
292
|
if @exit_on_save
|
113
293
|
puts 'Defaults set'
|
114
294
|
exit 0
|
@@ -183,4 +183,26 @@ describe EverydayCliUtils::OptionUtil do
|
|
183
183
|
'
|
184
184
|
opt.to_s.should eq expected
|
185
185
|
end
|
186
|
+
|
187
|
+
it 'supports layers' do
|
188
|
+
expected1 = { opt1: true }
|
189
|
+
expected2 = { opt1: false }
|
190
|
+
clean = { opt1: false }
|
191
|
+
opt = Option1.new
|
192
|
+
opt.default_settings toggle: true
|
193
|
+
opt.option :opt1, %w(-1 --opt-1)
|
194
|
+
opt.options.should eq clean
|
195
|
+
opt.default_options opt1: false
|
196
|
+
opt.apply_options :global, opt1: true
|
197
|
+
opt.options.should eq expected1
|
198
|
+
opt.apply_options :local, opt1: false
|
199
|
+
opt.options.should eq expected1
|
200
|
+
opt.apply_options :arg, opt1: true
|
201
|
+
opt.options.should eq expected2
|
202
|
+
opt.option_list.composite(:global, :arg).should eq expected2
|
203
|
+
opt.option_list.composite(:global).should eq expected1
|
204
|
+
opt.option_list.composite(:local, :arg).should eq expected1
|
205
|
+
opt.option_list.composite(:arg).should eq expected1
|
206
|
+
opt.option_list.composite(:global, :local, :arg).should eq expected2
|
207
|
+
end
|
186
208
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: everyday-cli-utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Henderson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-02-
|
11
|
+
date: 2014-02-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -137,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
137
137
|
version: '0'
|
138
138
|
requirements: []
|
139
139
|
rubyforge_project:
|
140
|
-
rubygems_version: 2.2.
|
140
|
+
rubygems_version: 2.2.2
|
141
141
|
signing_key:
|
142
142
|
specification_version: 4
|
143
143
|
summary: A few CLI and general utils
|