command_mapper 0.1.1 → 0.2.1

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.
@@ -5,6 +5,11 @@ require 'command_mapper/option'
5
5
  require 'shellwords'
6
6
 
7
7
  module CommandMapper
8
+ #
9
+ # Base class for all mapped commands.
10
+ #
11
+ # @api public
12
+ #
8
13
  class Command
9
14
 
10
15
  include Types
@@ -24,16 +29,6 @@ module CommandMapper
24
29
  # @return [Hash{String => String}]
25
30
  attr_reader :command_env
26
31
 
27
- # The option values to execute the command with.
28
- #
29
- # @return [Hash{String => Object}]
30
- attr_reader :command_options
31
-
32
- # The argument values to execute the command with.
33
- #
34
- # @return [Hash{String => Object}]
35
- attr_reader :command_arguments
36
-
37
32
  # The subcommand's options and arguments.
38
33
  #
39
34
  # @return [Command, nil]
@@ -51,7 +46,7 @@ module CommandMapper
51
46
  # @param [String, nil] command_path
52
47
  # Overrides the command with a custom path to the command.
53
48
  #
54
- # @param [Hash{String => String}] env
49
+ # @param [Hash{String => String}] command_env
55
50
  # Custom environment variables to pass to the command.
56
51
  #
57
52
  # @param [Hash{Symbol => Object}] kwargs
@@ -94,12 +89,16 @@ module CommandMapper
94
89
  # Initializes and runs the command.
95
90
  #
96
91
  # @param [Hash{Symbol => Object}] params
97
- # The option values.
92
+ # The option and argument values.
98
93
  #
99
- # @yield [self]
94
+ # @param [Hash{Symbol => Object}] kwargs
95
+ # Additional keywords arguments. These will be used to populate
96
+ # {#options} and {#arguments}, along with `params`.
97
+ #
98
+ # @yield [command]
100
99
  # The newly initialized command.
101
100
  #
102
- # @yieldparam [Command] self
101
+ # @yieldparam [Command] command
103
102
  #
104
103
  # @return [Boolean, nil]
105
104
  #
@@ -109,15 +108,49 @@ module CommandMapper
109
108
  end
110
109
 
111
110
  #
112
- # Runs the command in a shell and captures all stdout output.
111
+ # Initializes and spawns the command as a separate process, returning the
112
+ # PID of the process.
113
113
  #
114
114
  # @param [Hash{Symbol => Object}] params
115
- # The option values.
115
+ # The option and argument values.
116
116
  #
117
- # @yield [self]
117
+ # @param [Hash{Symbol => Object}] kwargs
118
+ # Additional keywords arguments. These will be used to populate
119
+ # {#options} and {#arguments}, along with `params`.
120
+ #
121
+ # @yield [command]
118
122
  # The newly initialized command.
119
123
  #
120
- # @yieldparam [Command] self
124
+ # @yieldparam [Command] command
125
+ #
126
+ # @return [Integer]
127
+ # The PID of the new command process.
128
+ #
129
+ # @raise [Errno::ENOENT]
130
+ # The command could not be found.
131
+ #
132
+ # @since 0.2.0
133
+ #
134
+ def self.spawn(params={},**kwargs,&block)
135
+ command = new(params,**kwargs,&block)
136
+ command.spawn_command
137
+ end
138
+
139
+ #
140
+ # Initializes and runs the command in a shell and captures all stdout
141
+ # output.
142
+ #
143
+ # @param [Hash{Symbol => Object}] params
144
+ # The option and argument values.
145
+ #
146
+ # @param [Hash{Symbol => Object}] kwargs
147
+ # Additional keywords arguments. These will be used to populate
148
+ # {#options} and {#arguments}, along with `params`.
149
+ #
150
+ # @yield [command]
151
+ # The newly initialized command.
152
+ #
153
+ # @yieldparam [Command] command
121
154
  #
122
155
  # @return [String]
123
156
  # The stdout output of the command.
@@ -128,15 +161,22 @@ module CommandMapper
128
161
  end
129
162
 
130
163
  #
131
- # Executes the command and returns an IO object to it.
164
+ # Initializes and executes the command and returns an IO object to it.
132
165
  #
133
166
  # @param [Hash{Symbol => Object}] params
134
- # The option values.
167
+ # The option and argument values.
135
168
  #
136
- # @yield [self]
169
+ # @param [String] mode
170
+ # The IO "mode" to open the IO pipe in.
171
+ #
172
+ # @param [Hash{Symbol => Object}] kwargs
173
+ # Additional keywords arguments. These will be used to populate
174
+ # {#options} and {#arguments}, along with `params`.
175
+ #
176
+ # @yield [command]
137
177
  # The newly initialized command.
138
178
  #
139
- # @yieldparam [Command] self
179
+ # @yieldparam [Command] command
140
180
  #
141
181
  # @return [IO]
142
182
  #
@@ -146,18 +186,18 @@ module CommandMapper
146
186
  end
147
187
 
148
188
  #
149
- # Initializes and runs the command through sudo.
189
+ # Initializes and runs the command through `sudo`.
150
190
  #
151
191
  # @param [Hash{Symbol => Object}] params
152
- # The option values.
192
+ # The option and argument values.
153
193
  #
154
194
  # @param [Hash{Symbol => Object}] kwargs
155
195
  # Additional keyword arguments for {#initialize}.
156
196
  #
157
- # @yield [self]
197
+ # @yield [command]
158
198
  # The newly initialized command.
159
199
  #
160
- # @yieldparam [Command] self
200
+ # @yieldparam [Command] command
161
201
  #
162
202
  # @return [Boolean, nil]
163
203
  #
@@ -181,7 +221,11 @@ module CommandMapper
181
221
  # @api semipublic
182
222
  #
183
223
  def self.command_name
184
- @command_name || raise(NotImplementedError,"#{self} did not call command(...)")
224
+ @command_name || if superclass < Command
225
+ superclass.command_name
226
+ else
227
+ raise(NotImplementedError,"#{self} did not call command(...)")
228
+ end
185
229
  end
186
230
 
187
231
  #
@@ -221,6 +265,23 @@ module CommandMapper
221
265
  end
222
266
  end
223
267
 
268
+ #
269
+ # Determines if an option with the given name has been defined.
270
+ #
271
+ # @param [Symbol] name
272
+ # The given name.
273
+ #
274
+ # @return [Boolean]
275
+ # Specifies whether an option with the given name has been defined.
276
+ #
277
+ # @api semipublic
278
+ #
279
+ # @since 0.2.0
280
+ #
281
+ def self.has_option?(name)
282
+ options.has_key?(name)
283
+ end
284
+
224
285
  #
225
286
  # Defines an option for the command.
226
287
  #
@@ -230,10 +291,6 @@ module CommandMapper
230
291
  # @param [Symbol, nil] name
231
292
  # The option's name.
232
293
  #
233
- # @param [Boolean] equals
234
- # Specifies whether the option's flag and value should be separated with a
235
- # `=` character.
236
- #
237
294
  # @param [Hash, nil] value
238
295
  # The option's value.
239
296
  #
@@ -246,6 +303,14 @@ module CommandMapper
246
303
  # @param [Boolean] repeats
247
304
  # Specifies whether the option can be given multiple times.
248
305
  #
306
+ # @param [Boolean] equals
307
+ # Specifies whether the option's flag and value should be separated with a
308
+ # `=` character.
309
+ #
310
+ # @param [Boolean] value_in_flag
311
+ # Specifies that the value should be appended to the option's flag
312
+ # (ex: `-Fvalue`).
313
+ #
249
314
  # @api public
250
315
  #
251
316
  # @example Defining an option:
@@ -260,6 +325,9 @@ module CommandMapper
260
325
  # @example Defining an option who's value is optional:
261
326
  # option '--file', value: {required: false}
262
327
  #
328
+ # @example Defining an `-Fvalue` option:
329
+ # option '--foo', value: true, value_in_flag: true
330
+ #
263
331
  # @example Defining an `--opt=value` option:
264
332
  # option '--foo', equals: true, value: true
265
333
  #
@@ -270,25 +338,35 @@ module CommandMapper
270
338
  # option '--list', value: List.new
271
339
  #
272
340
  # @raise [ArgumentError]
273
- # The option flag conflicts with a pre-existing internal method.
274
- #
275
- def self.option(flag, name: nil, equals: nil, value: nil, repeats: false, &block)
341
+ # The option flag conflicts with a pre-existing internal method, or
342
+ # another argument or subcommand.
343
+ #
344
+ def self.option(flag, name: nil, value: nil, repeats: false,
345
+ # formatting options
346
+ equals: nil,
347
+ value_in_flag: nil,
348
+ &block)
276
349
  option = Option.new(flag, name: name,
277
- equals: equals,
278
350
  value: value,
279
351
  repeats: repeats,
352
+ # formatting options
353
+ equals: equals,
354
+ value_in_flag: value_in_flag,
280
355
  &block)
281
356
 
282
- self.options[option.name] = option
283
-
284
357
  if is_internal_method?(option.name)
285
358
  if name
286
359
  raise(ArgumentError,"option #{flag.inspect} with name #{name.inspect} cannot override the internal method with same name: ##{option.name}")
287
360
  else
288
361
  raise(ArgumentError,"option #{flag.inspect} maps to method name ##{option.name} and cannot override the internal method with same name: ##{option.name}")
289
362
  end
363
+ elsif has_argument?(option.name)
364
+ raise(ArgumentError,"option #{flag.inspect} with name #{option.name.inspect} conflicts with another argument with the same name")
365
+ elsif has_subcommand?(option.name)
366
+ raise(ArgumentError,"option #{flag.inspect} with name #{option.name.inspect} conflicts with another subcommand with the same name")
290
367
  end
291
368
 
369
+ self.options[option.name] = option
292
370
  attr_accessor option.name
293
371
  end
294
372
 
@@ -296,6 +374,7 @@ module CommandMapper
296
374
  # All defined options.
297
375
  #
298
376
  # @return [Hash{Symbol => Argument}]
377
+ # The mapping of argument names and {Argument} objects.
299
378
  #
300
379
  # @api semipublic
301
380
  #
@@ -307,6 +386,23 @@ module CommandMapper
307
386
  end
308
387
  end
309
388
 
389
+ #
390
+ # Determines if an argument with the given name has been defined.
391
+ #
392
+ # @param [Symbol] name
393
+ # The given name.
394
+ #
395
+ # @return [Boolean]
396
+ # Specifies whether an argument with the given name has been defined.
397
+ #
398
+ # @api semipublic
399
+ #
400
+ # @since 0.2.0
401
+ #
402
+ def self.has_argument?(name)
403
+ arguments.has_key?(name)
404
+ end
405
+
310
406
  #
311
407
  # Defines an option for the command.
312
408
  #
@@ -333,7 +429,8 @@ module CommandMapper
333
429
  # argument :file, required: false
334
430
  #
335
431
  # @raise [ArgumentError]
336
- # The argument name conflicts with a pre-existing internal method.
432
+ # The argument name conflicts with a pre-existing internal method, or
433
+ # another option or subcommand.
337
434
  #
338
435
  def self.argument(name, required: true, type: Str.new, repeats: false)
339
436
  name = name.to_sym
@@ -341,19 +438,23 @@ module CommandMapper
341
438
  type: type,
342
439
  repeats: repeats)
343
440
 
344
- self.arguments[argument.name] = argument
345
-
346
441
  if is_internal_method?(argument.name)
347
442
  raise(ArgumentError,"argument #{name.inspect} cannot override internal method with same name: ##{argument.name}")
443
+ elsif has_option?(argument.name)
444
+ raise(ArgumentError,"argument #{name.inspect} conflicts with another option with the same name")
445
+ elsif has_subcommand?(argument.name)
446
+ raise(ArgumentError,"argument #{name.inspect} conflicts with another subcommand with the same name")
348
447
  end
349
448
 
449
+ self.arguments[argument.name] = argument
350
450
  attr_accessor name
351
451
  end
352
452
 
353
453
  #
354
454
  # All defined subcommands.
355
455
  #
356
- # @return [Hash{Symbol => Command}]
456
+ # @return [Hash{Symbol => Command.class}]
457
+ # The mapping of subcommand names and subcommand classes.
357
458
  #
358
459
  # @api semipublic
359
460
  #
@@ -365,6 +466,23 @@ module CommandMapper
365
466
  end
366
467
  end
367
468
 
469
+ #
470
+ # Determines if a subcommand with the given name has been defined.
471
+ #
472
+ # @param [Symbol] name
473
+ # The given name.
474
+ #
475
+ # @return [Boolean]
476
+ # Specifies whether a subcommand with the given name has been defined.
477
+ #
478
+ # @api semipublic
479
+ #
480
+ # @since 0.2.0
481
+ #
482
+ def self.has_subcommand?(name)
483
+ subcommands.has_key?(name)
484
+ end
485
+
368
486
  #
369
487
  # Defines a subcommand.
370
488
  #
@@ -392,25 +510,30 @@ module CommandMapper
392
510
  # end
393
511
  #
394
512
  # @raise [ArgumentError]
395
- # The subcommand name conflicts with a pre-existing internal method.
513
+ # The subcommand name conflicts with a pre-existing internal method, or
514
+ # another option or argument.
396
515
  #
397
516
  def self.subcommand(name,&block)
398
- name = name.to_s
517
+ name = name.to_s
518
+ method_name = name.tr('-','_')
519
+ class_name = name.split(/[_-]+/).map(&:capitalize).join
520
+ subcommand_name = method_name.to_sym
521
+
522
+ if is_internal_method?(method_name)
523
+ raise(ArgumentError,"subcommand #{name.inspect} maps to method name ##{method_name} and cannot override the internal method with same name: ##{method_name}")
524
+ elsif has_option?(subcommand_name)
525
+ raise(ArgumentError,"subcommand #{name.inspect} conflicts with another option with the same name")
526
+ elsif has_argument?(subcommand_name)
527
+ raise(ArgumentError,"subcommand #{name.inspect} conflicts with another argument with the same name")
528
+ end
399
529
 
400
530
  subcommand_class = Class.new(Command)
401
531
  subcommand_class.command(name)
402
532
  subcommand_class.class_eval(&block)
403
533
 
404
- method_name = name.tr('-','_')
405
- class_name = name.split(/[_-]+/).map(&:capitalize).join
406
-
407
- self.subcommands[method_name.to_sym] = subcommand_class
534
+ self.subcommands[subcommand_name] = subcommand_class
408
535
  const_set(class_name,subcommand_class)
409
536
 
410
- if is_internal_method?(method_name)
411
- raise(ArgumentError,"subcommand #{name.inspect} maps to method name ##{method_name} and cannot override the internal method with same name: ##{method_name}")
412
- end
413
-
414
537
  define_method(method_name) do |&block|
415
538
  if block then @command_subcommand = subcommand_class.new(&block)
416
539
  else @command_subcommand
@@ -428,8 +551,10 @@ module CommandMapper
428
551
  # Gets the value of an option or an argument.
429
552
  #
430
553
  # @param [Symbol] name
554
+ # The name of the option, argument, or subcommand.
431
555
  #
432
556
  # @return [Object]
557
+ # The value of the option, argument, or subcommand.
433
558
  #
434
559
  # @raise [ArgumentError]
435
560
  # The given name was not match any option or argument.
@@ -448,10 +573,13 @@ module CommandMapper
448
573
  # Sets an option or an argument with the given name.
449
574
  #
450
575
  # @param [Symbol] name
576
+ # The name of the option, argument, or subcommand.
451
577
  #
452
578
  # @param [Object] value
579
+ # The new value for the option, argument, or subcommand.
453
580
  #
454
581
  # @return [Object]
582
+ # The new value for the option, argument, or subcommand.
455
583
  #
456
584
  # @raise [ArgumentError]
457
585
  # The given name was not match any option or argument.
@@ -468,6 +596,7 @@ module CommandMapper
468
596
  # Returns an Array of command-line arguments for the command.
469
597
  #
470
598
  # @return [Array<String>]
599
+ # The formatted command-line arguments.
471
600
  #
472
601
  # @raise [ArgumentReqired]
473
602
  # A required argument was not set.
@@ -490,8 +619,10 @@ module CommandMapper
490
619
  self.class.arguments.each do |name,argument|
491
620
  value = self[name]
492
621
 
493
- if value.nil? && argument.required?
494
- raise(ArgumentRequired,"argument #{name} is required")
622
+ if value.nil?
623
+ if argument.required?
624
+ raise(ArgumentRequired,"argument #{name} is required")
625
+ end
495
626
  else
496
627
  argument.argv(additional_args,value)
497
628
  end
@@ -529,12 +660,30 @@ module CommandMapper
529
660
  end
530
661
 
531
662
  #
532
- # Initializes and runs the command.
663
+ # Runs the command.
533
664
  #
534
665
  # @return [Boolean, nil]
666
+ # Indicates whether the command exited successfully or not.
667
+ # `nil` indicates the command could not be found.
535
668
  #
536
669
  def run_command
537
- system(@command_env,*command_argv)
670
+ Kernel.system(@command_env,*command_argv)
671
+ end
672
+
673
+ #
674
+ # Spawns the command as a separate process, returning the PID of the
675
+ # process.
676
+ #
677
+ # @return [Integer]
678
+ # The PID of the new command process.
679
+ #
680
+ # @raise [Errno::ENOENT]
681
+ # The command could not be found.
682
+ #
683
+ # @since 0.2.0
684
+ #
685
+ def spawn_command
686
+ Process.spawn(@command_env,*command_argv)
538
687
  end
539
688
 
540
689
  #
@@ -551,6 +700,7 @@ module CommandMapper
551
700
  # Executes the command and returns an IO object to it.
552
701
  #
553
702
  # @return [IO]
703
+ # The IO object for the command's `STDIN`.
554
704
  #
555
705
  def popen_command(mode=nil)
556
706
  if mode then IO.popen(@command_env,command_argv,mode)
@@ -559,12 +709,14 @@ module CommandMapper
559
709
  end
560
710
 
561
711
  #
562
- # Initializes and runs the command through sudo.
712
+ # Runs the command through `sudo`.
563
713
  #
564
714
  # @param [Hash{Symbol => Object}] sudo_params
565
715
  # Additional keyword arguments for {Sudo#initialize}.
566
716
  #
567
717
  # @return [Boolean, nil]
718
+ # Indicates whether the command exited successfully or not.
719
+ # `nil` indicates the command could not be found.
568
720
  #
569
721
  def sudo_command(**sudo_kwargs,&block)
570
722
  sudo_params = sudo_kwargs.merge(command: command_argv)
@@ -595,6 +747,7 @@ module CommandMapper
595
747
  # The method name.
596
748
  #
597
749
  # @return [Boolean]
750
+ # Indicates that the method name is also an intenral method name.
598
751
  #
599
752
  def self.is_internal_method?(name)
600
753
  Command.instance_methods(false).include?(name.to_sym)
@@ -7,12 +7,18 @@ module CommandMapper
7
7
  #
8
8
  class Option
9
9
 
10
+ # The option's flag (ex: `-o` or `--output`).
11
+ #
10
12
  # @return [String]
11
13
  attr_reader :flag
12
14
 
15
+ # The option's name.
16
+ #
13
17
  # @return [Symbol]
14
18
  attr_reader :name
15
19
 
20
+ # Describes the option's value.
21
+ #
16
22
  # @return [OptionValue, nil]
17
23
  attr_reader :value
18
24
 
@@ -25,10 +31,6 @@ module CommandMapper
25
31
  # @param [Symbol, nil] name
26
32
  # The option's name.
27
33
  #
28
- # @param [Boolean] equals
29
- # Specifies whether the option's flag and value should be separated with a
30
- # `=` character.
31
- #
32
34
  # @param [Hash, nil] value
33
35
  # The option's value.
34
36
  #
@@ -41,15 +43,31 @@ module CommandMapper
41
43
  # @param [Boolean] repeats
42
44
  # Specifies whether the option can be given multiple times.
43
45
  #
44
- def initialize(flag, name: nil, equals: nil, value: nil, repeats: false)
46
+ # @param [Boolean] equals
47
+ # Specifies whether the option's flag and value should be separated with a
48
+ # `=` character.
49
+ #
50
+ # @param [Boolean] value_in_flag
51
+ # Specifies that the value should be appended to the option's flag
52
+ # (ex: `-Fvalue`).
53
+ #
54
+ # @api private
55
+ #
56
+ def initialize(flag, name: nil, value: nil, repeats: false,
57
+ # formatting options
58
+ equals: nil,
59
+ value_in_flag: nil)
45
60
  @flag = flag
46
61
  @name = name || self.class.infer_name_from_flag(flag)
47
- @equals = equals
48
62
  @value = case value
49
63
  when Hash then OptionValue.new(**value)
50
64
  when true then OptionValue.new
51
65
  end
52
66
  @repeats = repeats
67
+
68
+ # formatting options
69
+ @equals = equals
70
+ @value_in_flag = value_in_flag
53
71
  end
54
72
 
55
73
  #
@@ -65,6 +83,8 @@ module CommandMapper
65
83
  # Could not infer the name from the given option flag or was not given a
66
84
  # valid option flag.
67
85
  #
86
+ # @api private
87
+ #
68
88
  def self.infer_name_from_flag(flag)
69
89
  if flag.start_with?('--')
70
90
  name = flag[2..-1]
@@ -90,6 +110,15 @@ module CommandMapper
90
110
  !@value.nil?
91
111
  end
92
112
 
113
+ #
114
+ # Determines whether the option can be given multiple times.
115
+ #
116
+ # @return [Boolean]
117
+ #
118
+ def repeats?
119
+ @repeats
120
+ end
121
+
93
122
  #
94
123
  # Indicates whether the option flag and value should be separated with a
95
124
  # `=` character.
@@ -101,12 +130,14 @@ module CommandMapper
101
130
  end
102
131
 
103
132
  #
104
- # Determines whether the option can be given multiple times.
133
+ # Indicates whether the value will be appended to the option's flag.
105
134
  #
106
135
  # @return [Boolean]
107
136
  #
108
- def repeats?
109
- @repeats
137
+ # @since 0.2.0
138
+ #
139
+ def value_in_flag?
140
+ @value_in_flag
110
141
  end
111
142
 
112
143
  #
@@ -119,6 +150,8 @@ module CommandMapper
119
150
  # Returns true if the value is valid, or `false` and a validation error
120
151
  # message if the value is not compatible.
121
152
  #
153
+ # @api semipublic
154
+ #
122
155
  def validate(value)
123
156
  if accepts_value?
124
157
  if repeats?
@@ -146,6 +179,8 @@ module CommandMapper
146
179
  # @raise [ArgumentError]
147
180
  # The given value was incompatible with the option.
148
181
  #
182
+ # @api semipublic
183
+ #
149
184
  def argv(argv=[],value)
150
185
  valid, message = validate(value)
151
186
 
@@ -269,13 +304,15 @@ module CommandMapper
269
304
  else
270
305
  string = @value.format(value)
271
306
 
272
- if string.start_with?('-')
273
- raise(ValidationError,"option #{@name} formatted value (#{string.inspect}) cannot start with a '-'")
274
- end
275
-
276
307
  if equals?
277
308
  argv << "#{@flag}=#{string}"
309
+ elsif value_in_flag?
310
+ argv << "#{@flag}#{string}"
278
311
  else
312
+ if string.start_with?('-')
313
+ raise(ValidationError,"option #{@name} formatted value (#{string.inspect}) cannot start with a '-'")
314
+ end
315
+
279
316
  argv << @flag << string
280
317
  end
281
318
  end
@@ -6,6 +6,26 @@ module CommandMapper
6
6
  #
7
7
  class OptionValue < Arg
8
8
 
9
+ #
10
+ # Validates whether a given value is compatible with the option {#type}.
11
+ #
12
+ # @param [Object] value
13
+ # The given value to validate.
14
+ #
15
+ # @return [true, (false, String)]
16
+ # Returns true if the value is valid, or `false` and a validation error
17
+ # message if the value is not compatible.
18
+ #
19
+ # @api semipublic
20
+ #
21
+ def validate(value)
22
+ if !required? && value == true
23
+ return true
24
+ else
25
+ super(value)
26
+ end
27
+ end
28
+
9
29
  #
10
30
  # Formats a value using the options {#type}.
11
31
  #
@@ -15,6 +35,8 @@ module CommandMapper
15
35
  # @return [String]
16
36
  # The formatted value.
17
37
  #
38
+ # @api semipublic
39
+ #
18
40
  def format(value)
19
41
  @type.format(value)
20
42
  end
@@ -2,9 +2,17 @@ require 'command_mapper/types/map'
2
2
 
3
3
  module CommandMapper
4
4
  module Types
5
+ #
6
+ # Represents a mapping of Ruby values to their String equivalents.
7
+ #
5
8
  class Enum < Map
6
9
 
10
+ # The values of the enum.
11
+ #
7
12
  # @return [Array<Object>]
13
+ #
14
+ # @api semipublic
15
+ #
8
16
  attr_reader :values
9
17
 
10
18
  #