clasp-ruby 0.23.0.1 → 0.23.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +63 -52
  3. data/examples/cr-example.rb +16 -16
  4. data/examples/flag_and_option_specifications.md +25 -25
  5. data/examples/flag_and_option_specifications.rb +15 -15
  6. data/examples/show_usage_and_version.md +5 -5
  7. data/examples/show_usage_and_version.rb +10 -11
  8. data/examples/simple_command_line_no_specifications.rb +1 -1
  9. data/lib/clasp/arguments.rb +543 -543
  10. data/lib/clasp/clasp.rb +15 -11
  11. data/lib/clasp/cli.rb +145 -139
  12. data/lib/clasp/doc_.rb +3 -3
  13. data/lib/clasp/old_module.rb +9 -9
  14. data/lib/clasp/specifications.rb +346 -339
  15. data/lib/clasp/util/exceptions.rb +22 -23
  16. data/lib/clasp/util/value_parser.rb +101 -103
  17. data/lib/clasp/version.rb +20 -20
  18. data/lib/clasp-ruby.rb +9 -7
  19. data/lib/clasp.rb +9 -7
  20. data/test/scratch/test_list_command_line.rb +6 -6
  21. data/test/scratch/test_specifications.rb +14 -14
  22. data/test/scratch/test_usage.rb +6 -6
  23. data/test/scratch/test_usage_from_DATA.rb +1 -1
  24. data/test/scratch/test_usage_with_duplicate_specifications.rb +6 -6
  25. data/test/unit/tc_ARGV_rewrite.rb +36 -38
  26. data/test/unit/tc_arguments_1.rb +694 -694
  27. data/test/unit/tc_arguments_2.rb +52 -53
  28. data/test/unit/tc_arguments_3.rb +77 -77
  29. data/test/unit/tc_arguments_inspect.rb +55 -56
  30. data/test/unit/tc_cli.rb +4 -4
  31. data/test/unit/tc_default_value.rb +91 -91
  32. data/test/unit/tc_defaults_1.rb +38 -38
  33. data/test/unit/tc_examples_Arguments.rb +130 -132
  34. data/test/unit/tc_extras.rb +24 -26
  35. data/test/unit/tc_option_required.rb +38 -39
  36. data/test/unit/tc_option_value_aliases.rb +45 -45
  37. data/test/unit/tc_specifications.rb +7 -8
  38. data/test/unit/tc_typed_options.rb +204 -204
  39. data/test/unit/tc_usage.rb +112 -55
  40. data/test/unit/tc_with_action.rb +23 -24
  41. data/test/unit/ts_all.rb +1 -1
  42. metadata +12 -10
data/lib/clasp/clasp.rb CHANGED
@@ -1,16 +1,17 @@
1
1
 
2
2
  # ######################################################################## #
3
- # File: clasp/clasp.rb
3
+ # File: clasp/clasp.rb
4
4
  #
5
- # Purpose: Common 'require file' for CLASP.Ruby library
5
+ # Purpose: Common 'require file' for CLASP.Ruby library
6
6
  #
7
- # Created: 14th February 2014
8
- # Updated: 11th April 2019
7
+ # Created: 14th February 2014
8
+ # Updated: 6th March 2025
9
9
  #
10
- # Home: http://github.com/synesissoftware/CLASP.Ruby
10
+ # Home: http://github.com/synesissoftware/CLASP.Ruby
11
11
  #
12
- # Author: Matthew Wilson
12
+ # Author: Matthew Wilson
13
13
  #
14
+ # Copyright (c) 2019-2025, Matthew Wilson and Synesis Information Systems
14
15
  # Copyright (c) 2014-2019, Matthew Wilson and Synesis Software
15
16
  # All rights reserved.
16
17
  #
@@ -50,15 +51,18 @@ require 'clasp/specifications'
50
51
  require 'clasp/cli'
51
52
  require 'clasp/version'
52
53
 
54
+ =begin
55
+ =end
56
+
53
57
  module CLASP
54
58
 
55
- # TBC (but is a shorthand for calling +Arguments.new()+
56
- def self.parse(argv = ARGV, specifications = nil, options = {})
59
+ # TBC (but is a shorthand for calling +Arguments.new()+
60
+ def self.parse(argv = ARGV, specifications = nil, options = {})
57
61
 
58
- return Arguments.new(argv, specifications, options)
59
- end
62
+ return Arguments.new(argv, specifications, options)
63
+ end
60
64
  end # module CLASP
61
65
 
62
- # ############################## end of file ############################# #
63
66
 
67
+ # ############################## end of file ############################# #
64
68
 
data/lib/clasp/cli.rb CHANGED
@@ -1,16 +1,17 @@
1
1
 
2
2
  # ######################################################################## #
3
- # File: clasp/cli.rb
3
+ # File: clasp/cli.rb
4
4
  #
5
- # Purpose: Command-line interface
5
+ # Purpose: Command-line interface
6
6
  #
7
- # Created: 27th July 2015
8
- # Updated: 19th April 2019
7
+ # Created: 27th July 2015
8
+ # Updated: 6th March 2025
9
9
  #
10
- # Home: http://github.com/synesissoftware/CLASP.Ruby
10
+ # Home: http://github.com/synesissoftware/CLASP.Ruby
11
11
  #
12
- # Author: Matthew Wilson
12
+ # Author: Matthew Wilson
13
13
  #
14
+ # Copyright (c) 2019-2025, Matthew Wilson and Synesis Information Systems
14
15
  # Copyright (c) 2015-2019, Matthew Wilson and Synesis Software
15
16
  # All rights reserved.
16
17
  #
@@ -53,6 +54,7 @@
53
54
 
54
55
  module CLASP
55
56
 
57
+
56
58
  # ######################################################################## #
57
59
  # helpers
58
60
 
@@ -64,47 +66,48 @@ module CLASP
64
66
  # @!visibility private
65
67
  module CLI_helpers_ # :nodoc: all
66
68
 
67
- # @!visibility private
68
- module Constants # :nodoc: all
69
+ # @!visibility private
70
+ module Constants # :nodoc: all
69
71
 
70
- # @!visibility private
71
- VALID_ALIAS_TYPES = [ FlagSpecification, OptionSpecification, AliasSpecification ]
72
- # @!visibility private
73
- VALID_ALIAS_TYPES_STRING = VALID_ALIAS_TYPES[0...-1].join(', ') + ', or ' + VALID_ALIAS_TYPES[-1].to_s
74
- end # module Constants
72
+ # @!visibility private
73
+ VALID_ALIAS_TYPES = [ FlagSpecification, OptionSpecification, AliasSpecification ]
74
+ # @!visibility private
75
+ VALID_ALIAS_TYPES_STRING = VALID_ALIAS_TYPES[0...-1].join(', ') + ', or ' + VALID_ALIAS_TYPES[-1].to_s
76
+ end # module Constants
75
77
 
76
- # @!visibility private
77
- def self.generate_version_string_ options # :nodoc:
78
+ # @!visibility private
79
+ def self.generate_version_string_ options # :nodoc:
78
80
 
79
- program_name = options[:program_name] || File.basename($0)
81
+ program_name = options[:program_name] || File.basename($0)
80
82
 
81
- version_prefix = options[:version_prefix]
83
+ version_prefix = options[:version_prefix]
82
84
 
83
- if options[:version]
85
+ if options[:version]
84
86
 
85
- case options[:version]
86
- when ::Array
87
- version = options[:version].join('.')
88
- else
89
- version = options[:version]
90
- end
91
- else
87
+ case options[:version]
88
+ when ::Array
89
+ version = options[:version].join('.')
90
+ else
91
+ version = options[:version]
92
+ end
93
+ else
92
94
 
93
- version_major = options[:version_major] or raise ArgumentError, "options must specify :version or :version_major [ + :version_minor [ + :version_revision [ + :version_build ]]]"
94
- version_minor = options[:version_minor]
95
- version_rev = options[:version_revision]
96
- version_build = options[:version_build]
95
+ version_major = options[:version_major] or raise ArgumentError, "options must specify :version or :version_major [ + :version_minor [ + :version_revision [ + :version_build ]]]"
96
+ version_minor = options[:version_minor]
97
+ version_rev = options[:version_revision]
98
+ version_build = options[:version_build]
97
99
 
98
- version = version_major.to_s
99
- version += ".#{version_minor}" if version_minor
100
- version += ".#{version_rev}" if version_rev
101
- version += ".#{version_build}" if version_build
102
- end
100
+ version = version_major.to_s
101
+ version += ".#{version_minor}" if version_minor
102
+ version += ".#{version_rev}" if version_rev
103
+ version += ".#{version_build}" if version_build
104
+ end
103
105
 
104
- "#{program_name} #{version_prefix}#{version}"
105
- end
106
+ "#{program_name} #{version_prefix}#{version}"
107
+ end
106
108
  end # module CLI_helpers_
107
109
 
110
+
108
111
  # ######################################################################## #
109
112
  # methods
110
113
 
@@ -132,141 +135,142 @@ end # module CLI_helpers_
132
135
  # - +:default_indicator+ (String) a string placed after the matching value in the listing of an option's range of values. Defaults to "(default)". If +nil+ default is used. If empty string no indication given
133
136
  def self.show_usage specifications, options={}
134
137
 
135
- options ||= {}
138
+ options ||= {}
136
139
 
137
- raise ArgumentError, "specifications may not be nil" if specifications.nil?
138
- raise TypeError, "specifications must be an array or must respond to each, reject and select" unless ::Array === specifications || (specifications.respond_to?(:each) && specifications.respond_to?(:reject) && specifications.respond_to?(:select))
140
+ raise ArgumentError, "specifications may not be nil" if specifications.nil?
141
+ raise TypeError, "specifications must be an array or must respond to each, reject and select" unless ::Array === specifications || (specifications.respond_to?(:each) && specifications.respond_to?(:reject) && specifications.respond_to?(:select))
139
142
 
140
- constants = CLI_helpers_::Constants
141
- specifications.each { |s| raise ::TypeError, "each element in specifications array must be one of the types #{constants::VALID_ALIAS_TYPES_STRING}" unless constants::VALID_ALIAS_TYPES.any? { |c| c === s } }
143
+ constants = CLI_helpers_::Constants
142
144
 
143
- alias_dups = {}
144
- specifications.each { |s| s.aliases.each { |aa| warn "WARNING: alias '#{aa}' is already used for specification '#{s}'" if alias_dups.has_key? aa; alias_dups[aa] = s; } }
145
+ specifications.each { |s| raise ::TypeError, "each element in specifications array must be one of the types #{constants::VALID_ALIAS_TYPES_STRING}" unless constants::VALID_ALIAS_TYPES.any? { |c| c === s } }
145
146
 
146
- suppress_blanks = options[:suppress_blank_lines_between_options] || ENV['SUPPRESS_BLANK_LINES_BETWEEN_OPTIONS']
147
+ alias_dups = {}
148
+ specifications.each { |s| s.aliases.each { |aa| warn "WARNING: alias '#{aa}' is already used for specification '#{s}'" if alias_dups.has_key? aa; alias_dups[aa] = s; } }
147
149
 
148
- stream = options[:stream] || $stdout
149
- program_name = options[:program_name] || File.basename($0)
150
+ suppress_blanks = options[:suppress_blank_lines_between_options] || ENV['SUPPRESS_BLANK_LINES_BETWEEN_OPTIONS']
150
151
 
151
- info_lines = options[:info_lines]
152
- case info_lines
153
- when ::Array
152
+ stream = options[:stream] || $stdout
153
+ program_name = options[:program_name] || File.basename($0)
154
154
 
155
- ;
156
- when ::NilClass
155
+ info_lines = options[:info_lines]
156
+ case info_lines
157
+ when ::Array
157
158
 
158
- info_lines = []
159
- else
159
+ ;
160
+ when ::NilClass
160
161
 
161
- info_lines = [ info_lines ] unless [ :each, :empty? ].all? { |m| info_lines.respond_to? m }
162
- end
163
- info_lines = info_lines.map do |line|
162
+ info_lines = []
163
+ else
164
164
 
165
- case line
166
- when :version
165
+ info_lines = [ info_lines ] unless [ :each, :empty? ].all? { |m| info_lines.respond_to? m }
166
+ end
167
+ info_lines = info_lines.map do |line|
167
168
 
168
- CLI_helpers_.generate_version_string_ options
169
- else
169
+ case line
170
+ when :version
170
171
 
171
- line
172
- end
173
- end
172
+ CLI_helpers_.generate_version_string_ options
173
+ else
174
174
 
175
- values = options[:values] || ''
176
- values = " #{values}" if !values.empty? && ' ' != values[0]
175
+ line
176
+ end
177
+ end
177
178
 
178
- flags_and_options = options[:flags_and_options] || ' [ ... flags and options ... ]'
179
- flags_and_options = " #{flags_and_options}" if !flags_and_options.empty? && ' ' != flags_and_options[0]
179
+ values = options[:values] || ''
180
+ values = " #{values}" if !values.empty? && ' ' != values[0]
180
181
 
181
- default_indicator = options[:default_indicator] || '(default)'
182
- default_indicator = nil if default_indicator.empty?
182
+ flags_and_options = options[:flags_and_options] || ' [ ... flags and options ... ]'
183
+ flags_and_options = " #{flags_and_options}" if !flags_and_options.empty? && ' ' != flags_and_options[0]
183
184
 
184
- # sift the specifications to sort out which are value-option
185
- # specifications (VOAs)
185
+ default_indicator = options[:default_indicator] || '(default)'
186
+ default_indicator = nil if default_indicator.empty?
186
187
 
187
- voas = {}
188
+ # sift the specifications to sort out which are value-option
189
+ # specifications (VOAs)
188
190
 
189
- specifications.select { |s| s.name =~ /^-+[a-zA-Z0-3_-]+[=:].+/ }.each do |s|
191
+ voas = {}
190
192
 
191
- s.name =~ /^(-+[a-zA-Z0-3_-]+)[=:](.+)$/
193
+ specifications.select { |s| s.name =~ /^-+[a-zA-Z0-3_-]+[=:].+/ }.each do |s|
192
194
 
193
- voas[$1] = [] unless voas.has_key? $1
194
- voas[$1] << [ s, $2 ]
195
- end
195
+ s.name =~ /^(-+[a-zA-Z0-3_-]+)[=:](.+)$/
196
196
 
197
- fas = {}
197
+ voas[$1] = [] unless voas.has_key? $1
198
+ voas[$1] << [ s, $2 ]
199
+ end
198
200
 
199
- specifications.select { |s| AliasSpecification === s }.each do |s|
201
+ fas = {}
200
202
 
201
- fas[s.name] = [] unless fas.has_key? $1
202
- fas[s.name] << s
203
- end
203
+ specifications.select { |s| AliasSpecification === s }.each do |s|
204
204
 
205
- specifications = specifications.reject { |s| s.name =~ /^-+[a-zA-Z0-3_-]+[=:].+/ }
205
+ fas[s.name] = [] unless fas.has_key? $1
206
+ fas[s.name] << s
207
+ end
206
208
 
207
- info_lines.each { |info_line| stream.puts info_line } unless info_lines.empty?
209
+ specifications = specifications.reject { |s| s.name =~ /^-+[a-zA-Z0-3_-]+[=:].+/ }
208
210
 
209
- stream.puts "USAGE: #{program_name}#{flags_and_options}#{values}"
210
- stream.puts
211
+ info_lines.each { |info_line| stream.puts info_line } unless info_lines.empty?
211
212
 
212
- unless specifications.empty?
213
+ stream.puts "USAGE: #{program_name}#{flags_and_options}#{values}"
214
+ stream.puts
213
215
 
214
- stream.puts "flags/options:"
215
- stream.puts
216
- specifications.each do |s|
216
+ unless specifications.empty?
217
217
 
218
- case s
219
- when AliasSpecification
218
+ stream.puts "flags/options:"
219
+ stream.puts
220
+ specifications.each do |s|
220
221
 
221
- next
222
- when FlagSpecification
222
+ case s
223
+ when AliasSpecification
223
224
 
224
- if fas.has_key? s.name
225
+ next
226
+ when FlagSpecification
225
227
 
226
- fas[s.name].each do |fa|
228
+ if fas.has_key? s.name
227
229
 
228
- fa.aliases.each { |al| stream.puts "\t#{al}" }
229
- end
230
- end
231
- s.aliases.each { |al| stream.puts "\t#{al}" }
232
- stream.puts "\t#{s.name}"
233
- stream.puts "\t\t#{s.help}"
234
- when OptionSpecification
230
+ fas[s.name].each do |fa|
235
231
 
236
- if voas.has_key? s.name
232
+ fa.aliases.each { |al| stream.puts "\t#{al}" }
233
+ end
234
+ end
235
+ s.aliases.each { |al| stream.puts "\t#{al}" }
236
+ stream.puts "\t#{s.name}"
237
+ stream.puts "\t\t#{s.help}"
238
+ when OptionSpecification
237
239
 
238
- voas[s.name].each do |ar|
240
+ if voas.has_key? s.name
239
241
 
240
- ar[0].aliases.each { |al| stream.puts "\t#{al} #{ar[0].name}" }
241
- end
242
- end
243
- s.aliases.each { |al| stream.puts "\t#{al} <value>" }
244
- stream.puts "\t#{s.name}=<value>"
245
- stream.puts "\t\t#{s.help}"
246
- unless s.values_range.empty?
242
+ voas[s.name].each do |ar|
247
243
 
248
- d = s.default_value
244
+ ar[0].aliases.each { |al| stream.puts "\t#{al} #{ar[0].name}" }
245
+ end
246
+ end
247
+ s.aliases.each { |al| stream.puts "\t#{al} <value>" }
248
+ stream.puts "\t#{s.name}=<value>"
249
+ stream.puts "\t\t#{s.help}"
250
+ unless s.values_range.empty?
249
251
 
250
- stream.puts "\t\twhere <value> one of:"
251
- s.values_range.each do |v|
252
+ d = s.default_value
252
253
 
253
- if default_indicator && v == d
254
+ stream.puts "\t\twhere <value> one of:"
255
+ s.values_range.each do |v|
254
256
 
255
- stream.puts "\t\t\t#{v}\t#{default_indicator}"
256
- else
257
+ if default_indicator && v == d
257
258
 
258
- stream.puts "\t\t\t#{v}"
259
- end
260
- end
261
- end
262
- end
263
- stream.puts unless suppress_blanks
264
- end
265
- end
259
+ stream.puts "\t\t\t#{v}\t#{default_indicator}"
260
+ else
266
261
 
267
- exit_code = options[:exit_code] || options[:exit]
262
+ stream.puts "\t\t\t#{v}"
263
+ end
264
+ end
265
+ end
266
+ end
267
+ stream.puts unless suppress_blanks
268
+ end
269
+ end
268
270
 
269
- exit exit_code if exit_code
271
+ exit_code = options[:exit_code] || options[:exit]
272
+
273
+ exit exit_code if exit_code
270
274
  end
271
275
 
272
276
  # Displays version for the program according to the given specifications and options
@@ -289,30 +293,32 @@ end
289
293
  # - +:version_prefix+ optional string to prefix the version number(s).
290
294
  def self.show_version specifications, options = {}
291
295
 
292
- options ||= {}
296
+ options ||= {}
297
+
298
+ raise ArgumentError, "specifications may not be nil" if specifications.nil?
299
+ raise TypeError, "specifications must be an array or must respond to each, reject and select" unless ::Array === specifications || (specifications.respond_to?(:each) && specifications.respond_to?(:reject) && specifications.respond_to?(:select))
293
300
 
294
- raise ArgumentError, "specifications may not be nil" if specifications.nil?
295
- raise TypeError, "specifications must be an array or must respond to each, reject and select" unless ::Array === specifications || (specifications.respond_to?(:each) && specifications.respond_to?(:reject) && specifications.respond_to?(:select))
301
+ constants = CLI_helpers_::Constants
296
302
 
297
- constants = CLI_helpers_::Constants
298
- specifications.each { |s| raise ::TypeError, "each element in specifications array must be one of the types #{constants::VALID_ALIAS_TYPES_STRING}" unless constants::VALID_ALIAS_TYPES.any? { |c| c === s } }
303
+ specifications.each { |s| raise ::TypeError, "each element in specifications array must be one of the types #{constants::VALID_ALIAS_TYPES_STRING}" unless constants::VALID_ALIAS_TYPES.any? { |c| c === s } }
299
304
 
300
- stream = options[:stream] || $stdout
305
+ stream = options[:stream] || $stdout
301
306
 
302
- version_string = CLI_helpers_.generate_version_string_ options
307
+ version_string = CLI_helpers_.generate_version_string_ options
303
308
 
304
- stream.puts version_string
309
+ stream.puts version_string
305
310
 
306
- exit_code = options[:exit_code] || options[:exit]
311
+ exit_code = options[:exit_code] || options[:exit]
307
312
 
308
- exit exit_code if exit_code
313
+ exit exit_code if exit_code
309
314
  end
310
315
 
316
+
311
317
  # ######################################################################## #
312
318
  # module
313
319
 
314
320
  end # module CLASP
315
321
 
316
- # ############################## end of file ############################# #
317
322
 
323
+ # ############################## end of file ############################# #
318
324
 
data/lib/clasp/doc_.rb CHANGED
@@ -5,13 +5,13 @@
5
5
  # Purpose: Documentation of the CLASP.Ruby modules
6
6
  #
7
7
  # Created: 11th June 2016
8
- # Updated: 19th April 2019
8
+ # Updated: 20th January 2024
9
9
  #
10
10
  # Home: http://github.com/synesissoftware/xqsr3
11
11
  #
12
12
  # Author: Matthew Wilson
13
13
  #
14
- # Copyright (c) 2016-2019, Matthew Wilson and Synesis Software
14
+ # Copyright (c) 2016-2024, Matthew Wilson and Synesis Software
15
15
  # All rights reserved.
16
16
  #
17
17
  # Redistribution and use in source and binary forms, with or without
@@ -163,6 +163,6 @@ module CLASP
163
163
 
164
164
  end # module CLASP
165
165
 
166
- # ############################## end of file ############################# #
167
166
 
167
+ # ############################## end of file ############################# #
168
168
 
@@ -1,18 +1,18 @@
1
1
 
2
2
  # ######################################################################## #
3
- # File: clasp/old_module.rb
3
+ # File: clasp/old_module.rb
4
4
  #
5
- # Purpose: Introduces old module Clasp (which clashes with an existing
6
- # gem)
5
+ # Purpose: Introduces old module Clasp (which clashes with an existing gem)
7
6
  #
8
- # Created: 10th June 2016
9
- # Updated: 10th June 2016
7
+ # Created: 10th June 2016
8
+ # Updated: 6th March 2025
10
9
  #
11
- # Home: http://github.com/synesissoftware/CLASP.Ruby
10
+ # Home: http://github.com/synesissoftware/CLASP.Ruby
12
11
  #
13
- # Author: Matthew Wilson
12
+ # Author: Matthew Wilson
14
13
  #
15
- # Copyright (c) 2016, Matthew Wilson and Synesis Software
14
+ # Copyright (c) 2019-2025, Matthew Wilson and Synesis Information Systems
15
+ # Copyright (c) 2016-2019, Matthew Wilson and Synesis Software
16
16
  # All rights reserved.
17
17
  #
18
18
  # Redistribution and use in source and binary forms, with or without
@@ -50,6 +50,6 @@ require 'clasp'
50
50
  # Backwards-compatible alias for the CLASP library's CLASP module
51
51
  Clasp = CLASP
52
52
 
53
- # ############################## end of file ############################# #
54
53
 
54
+ # ############################## end of file ############################# #
55
55