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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bb045208150105efa9606f2f664bec0b98339044
4
- data.tar.gz: b1a094050c0298cff7a93315b02058e7833d5a11
3
+ metadata.gz: 5f9fc1d7f33b7176bce22227eb740e2ac62471de
4
+ data.tar.gz: 618d8eec3dba4932423a28cd162f17876dbc778f
5
5
  SHA512:
6
- metadata.gz: c0352f72cadc509d1158b54203755c7476ba68b018a87d845f21ade0cde965ed42ce44e12eddea2ffdff5c0a8706812b521b3687abbb48a52548a2d4bbd51937
7
- data.tar.gz: 8480de538db701d0fd034e2e69767464bad8b1be7d3d1005ddf3e727f08d71b4125e83a4a3b6953de4def1b18fbfb6f68c334506bd0755f31bd2a99c4ed1da17
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
- module OptionUtil
26
- attr_reader :options, :opts
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 option(opt_name, names, settings = {})
29
- @opts ||= OptionParser.new
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 option_with_param(opt_name, names, settings = {})
42
- @opts ||= OptionParser.new
43
- @options ||= {}
44
- @default_settings ||= {}
45
- settings[:append] = @default_settings[:append] unless settings.has_key?(:append) || !@default_settings.has_key?(:append)
46
- settings[:type] = @default_settings[:type] unless settings.has_key?(:type) || !@default_settings.has_key?(:type)
47
- names[0] << ' PARAM' unless names.any? { |v| v.include?(' ') }
48
- names << settings[:desc] if settings.has_key?(:desc)
49
- @options[opt_name] = settings[:append] ? [] : nil
50
- @opts.on(*names, settings[:type] || String) { |param|
51
- settings[:append] ? @options[opt_name] << param : @options[opt_name] = param
52
- yield if block_given?
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
- @opts ||= OptionParser.new
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
- @opts ||= OptionParser.new
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
- @default_settings = settings
230
+ @options ||= OptionList.new
231
+ @options.default_settings = settings
75
232
  end
76
233
 
77
234
  def default_options(opts = {})
78
- opts.each { |opt| @options[opt[0]] = opt[1] }
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
- @opts ||= OptionParser.new
83
- @opts.banner = banner
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
- @opts ||= OptionParser.new
88
- @help_str ||= nil
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
- @opts ||= OptionParser.new
94
- @help_str ||= nil
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
- @opts ||= OptionParser.new
104
- default_options YAML::load_file(@defaults_file) unless @defaults_file.nil? || !File.exist?(@defaults_file)
105
- @opts.parse!(argv)
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 @set_defaults
111
- IO.write(@defaults_file, @options.to_yaml)
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
@@ -1,3 +1,3 @@
1
1
  module EverydayCliUtils
2
- VERSION = '1.4.0'
2
+ VERSION = '1.5.0'
3
3
  end
@@ -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.0
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-06 00:00:00.000000000 Z
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.0
140
+ rubygems_version: 2.2.2
141
141
  signing_key:
142
142
  specification_version: 4
143
143
  summary: A few CLI and general utils