clop 0.0.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 (3) hide show
  1. data/README +6 -0
  2. data/lib/clop.rb +475 -0
  3. metadata +47 -0
data/README ADDED
@@ -0,0 +1,6 @@
1
+ clop package
2
+ (c) 2004-2007, Piet Hut and Jun Makino
3
+ Gem maintained by Alfred Whitehead
4
+ www.artcompsci.org
5
+
6
+ The Command Line Options gem (clop) allows developers to easily access arguments passed on the command line in a self-documenting way. Indeed, the documentation is processed to produce the desired behavior, so it can never be out of date.
@@ -0,0 +1,475 @@
1
+ # require "acs.rb" if not defined? acsrequire
2
+
3
+ class Clop_Option
4
+
5
+ attr_reader :shortname, :longname, :type, :variablename,
6
+ :description, :longdescription, :printname, :defaultvalue
7
+ attr_accessor :valuestring
8
+
9
+ def initialize(def_str)
10
+ parse_option_definition(def_str)
11
+ end
12
+
13
+ def parse_option_definition(def_str)
14
+ while s = def_str.shift
15
+ break if parse_single_lines_done?(s)
16
+ end
17
+ while s = def_str.shift
18
+ break if s =~ /^\s*$/ and def_str[0] =~ /^\s*$/
19
+ @longdescription += s + "\n"
20
+ end
21
+ end
22
+
23
+ def parse_single_lines_done?(s)
24
+ if s !~ /\s*(\w.*?)\s*\:/
25
+ raise "\n option definition line has wrong format:\n==> #{s} <==\n"
26
+ end
27
+ name = $1
28
+ content = $'
29
+ case name
30
+ when /Short\s+(N|n)ame/
31
+ @shortname = content.split[0]
32
+ when /Long\s+(N|n)ame/
33
+ @longname = content.split[0]
34
+ when /Value\s+(T|t)ype/
35
+ @type = content.sub(/^\s+/,"").sub(/\s*(#.*|$)/,"")
36
+ @valuestring = "false" if @type == "bool"
37
+ when /Default\s+(V|v)alue/
38
+ @defaultvalue = content.sub(/^\s+/,"").sub(/\s*(#.*|$)/,"")
39
+ @valuestring = @defaultvalue
40
+ when /Variable\s+(N|n)ame/
41
+ @variablename = content.split[0]
42
+ when /Print\s+(N|n)ame/
43
+ @printname = content.sub(/^\s+/,"").sub(/\s*(#.*|$)/,"")
44
+ when /Description/
45
+ @description = content.sub(/^\s+/,"").sub(/\s*(#.*|$)/,"")
46
+ when /Long\s+(D|d)escription/
47
+ @longdescription = ""
48
+ return true
49
+ else
50
+ raise "\n option definition line unrecognized:\n==> #{s} <==\n"
51
+ end
52
+ return false
53
+ end
54
+
55
+ def eval_value
56
+ case @type
57
+ when "bool"
58
+ eval(@valuestring)
59
+ when "string"
60
+ @valuestring
61
+ when "int"
62
+ @valuestring.to_i
63
+ when "float"
64
+ @valuestring.to_f
65
+ #when /^float\s*vector$/
66
+ # @valuestring.gsub(/[\[,\]]/," ").split.map{|x| x.to_f}.to_v
67
+ else
68
+ raise "\n type \"#{@type}\" is not recognized\n"
69
+ end
70
+ end
71
+
72
+ def add_tabs(s, reference_size, n)
73
+ (1..n).each{|i| s += "\t" if reference_size < 8*i}
74
+ return s
75
+ end
76
+
77
+ def to_s
78
+ if @type == nil
79
+ s = @description + "\n"
80
+ elsif @type == "bool"
81
+ if eval(@valuestring)
82
+ s = @description + "\n"
83
+ else
84
+ s = ""
85
+ end
86
+ else
87
+ s = @description
88
+ s = add_tabs(s, s.size, 4)
89
+ s += ": "
90
+ if defined? @printname
91
+ s += @printname
92
+ else
93
+ s += @variablename
94
+ end
95
+ s += " = " unless defined? @printname and @printname == ""
96
+ #s += "\n " if @type =~ /^float\s*vector$/
97
+ s += eval_value.to_s + "\n"
98
+ end
99
+ return s
100
+ end
101
+
102
+ end
103
+
104
+ class Clop
105
+
106
+ attr_writer :do_not_print_values
107
+
108
+ @@proclist=[]
109
+
110
+ def initialize(def_str, argv_array, global_variables_flag)
111
+ parse_option_definitions(def_str+@@additional_def_string)
112
+ parse_command_line_options(argv_array)
113
+ initialize_option_variables
114
+ initialize_global_variables if global_variables_flag
115
+ check_required_options
116
+ eval(mk_reader,TOPLEVEL_BINDING)
117
+ @@proclist.each{|x| x.call(self)}
118
+ @@the_only_instance = self
119
+ print_values unless defined? @do_not_print_values
120
+ end
121
+
122
+ def Clop.option
123
+ @@the_only_instance
124
+ end
125
+
126
+ def Clop.add_to_initialize_action_list(x)
127
+ @@proclist.push x
128
+ end
129
+
130
+ def parse_option_definitions(def_str)
131
+ def_str += HELP_DEFINITION_STRING
132
+ a = def_str.split("\n")
133
+ @options=[]
134
+ while a[0]
135
+ if a[0] =~ /^\s*$/
136
+ a.shift
137
+ else
138
+ @options.push(Clop_Option.new(a))
139
+ end
140
+ end
141
+ end
142
+
143
+ def parse_command_line_options(argv_array)
144
+ s1 = argv_array.clone
145
+ while s = s1.shift
146
+ if s == "-h"
147
+ parse_help(s1, false)
148
+ exit
149
+ elsif s == "--help"
150
+ parse_help(s1, true)
151
+ exit
152
+ elsif s == "---help"
153
+ print_help(true, 0)
154
+ exit
155
+ end
156
+ end
157
+ while s = argv_array.shift
158
+ if i = find_option(s)
159
+ parse_option(i, s, argv_array)
160
+ else
161
+ raise "\n option \"#{s}\" not recognized; try \"-h\" or \"--help\"\n"
162
+ end
163
+ end
164
+ end
165
+
166
+ def to_s
167
+ s = "==> " + @options[0].description + " <==\n"
168
+ for i in 1...@options.size - 2 # exclude header & help (first & last two)
169
+ s += @options[i].to_s
170
+ end
171
+ s
172
+ end
173
+
174
+ def print_values
175
+ STDERR.print to_s
176
+ end
177
+
178
+ def find_option(s)
179
+ i = nil
180
+ @options.each_index do |x|
181
+ i = x if s == @options[x].longname
182
+ if @options[x].shortname
183
+ i = x if s =~ Regexp.new(@options[x].shortname) and $` == ""
184
+ end
185
+ end
186
+ return i
187
+ end
188
+
189
+ def parse_option(i, s, argv_array)
190
+ if @options[i].type == "bool"
191
+ @options[i].valuestring = "true"
192
+ return
193
+ end
194
+ if s =~ /^-[^-]/ and (value = $') =~ /\w/
195
+ @options[i].valuestring = value
196
+ else
197
+ unless @options[i].valuestring = argv_array.shift
198
+ raise "\n option \"#{s}\" requires a value, but no value given;\n" +
199
+ " option description: #{@options[i].description}\n"
200
+ end
201
+ end
202
+ # if @options[i].type =~ /^float\s*vector$/
203
+ # while (@options[i].valuestring !~ /\]/)
204
+ # @options[i].valuestring += " " + argv_array.shift
205
+ # end
206
+ # end
207
+ end
208
+
209
+ # def initialize_variables(magic) # for connoisseurs . . .
210
+ # @options.each{|x| eval("#{magic}#{x.variablename}=x.eval_value") if
211
+ # x.variablename}
212
+ # end
213
+
214
+ def initialize_option_variables
215
+ @options.each{|x| eval("@#{x.variablename}=x.eval_value") if x.variablename}
216
+ end
217
+
218
+ def initialize_global_variables
219
+ @options.each{|x| eval("$#{x.variablename}=x.eval_value") if x.variablename}
220
+ end
221
+
222
+ def mk_reader
223
+ s = "class Clop \n attr_reader"
224
+ @options.each{|x| s += " :#{x.variablename}," if x.variablename}
225
+ s.chop!
226
+ s + "\n end"
227
+ end
228
+
229
+ def check_required_options
230
+ options_missing = 0
231
+ @options.each do |x|
232
+ if x.valuestring == "none"
233
+ options_missing += 1
234
+ STDERR.print "option "
235
+ STDERR.print "\"#{x.shortname}\" or " if x.shortname
236
+ STDERR.print "\"#{x.longname}\" required. "
237
+ STDERR.print "Description:\n#{x.longdescription}\n"
238
+ end
239
+ end
240
+ if options_missing > 0
241
+ STDERR.print "Please provide the required command line option"
242
+ STDERR.print "s" if options_missing > 1
243
+ STDERR.print ".\n"
244
+ exit(1)
245
+ end
246
+ end
247
+
248
+ def parse_help(argv_array, long)
249
+ all = true
250
+ while s = argv_array.shift
251
+ all = false
252
+ if i = find_option(s)
253
+ print_help(long, i)
254
+ else
255
+ print_help_warning(s)
256
+ end
257
+ end
258
+ print_help(long) if all
259
+ end
260
+
261
+ def print_help(long, i = nil)
262
+ if i
263
+ STDERR.print help_string(@options[i], long)
264
+ else
265
+ @options.each{|x| STDERR.print help_string(x, long)}
266
+ end
267
+ end
268
+
269
+ def print_help_warning(s)
270
+ STDERR.print "WARNING : ", s, " : ==> this option is not recognized <==\n"
271
+ end
272
+
273
+ def help_string(option, long_flag)
274
+ s = ""
275
+ if option.type or option.longname =~ /-+-help/
276
+ s += option_name_string(option)
277
+ end
278
+ if option.type or option.longname =~ /-+-help/ or not long_flag
279
+ s += "#{option.description}"
280
+ s += default_value_string(option)
281
+ s += "\n"
282
+ end
283
+ if long_flag
284
+ s += "\n#{option.longdescription}\n"
285
+ end
286
+ return s
287
+ end
288
+
289
+ def option_name_string(option)
290
+ s = ""
291
+ if option.shortname
292
+ s += "#{option.shortname} "
293
+ end
294
+ s += "#{option.longname}"
295
+ s = option.add_tabs(s, s.size, 3)
296
+ s += ": "
297
+ return s
298
+ end
299
+
300
+ def default_value_string(option)
301
+ s = ""
302
+ if option.type and option.type != "bool"
303
+ reference_size = "#{option.description}".size + 2
304
+ s = option.add_tabs(s, reference_size, 4)
305
+ s += " [default: #{option.defaultvalue}]"
306
+ end
307
+ return s
308
+ end
309
+
310
+ HELP_DEFINITION_STRING = <<-END
311
+
312
+
313
+ Short name: -h
314
+ Long name: --help
315
+ Description: Help facility
316
+ Long description:
317
+ When providing the command line option -h, followed by one or more
318
+ options, a one-line summary of each of the options will be printed.
319
+
320
+ These options can be specified in either short or long form, i.e
321
+ typing "some_command -h -x" or "some_command -h --extra" will produce
322
+ the same output, if "-x" and "--extra" invoke the same option.
323
+
324
+ When providing the command line option -h, with nothing else following,
325
+ a one-line summary of all options will be printed.
326
+
327
+ When providing the command line option --help, instead of -h, the same
328
+ actions occur, the only difference being that instead of a one-liner,
329
+ a longer description will be printed.
330
+
331
+ Anything that appears on the command line between the name of the
332
+ program and "-h" or "--help" will be ignored. For example, typing
333
+ "some_command gobbledygook -h -x" will produce the same output as
334
+ typing "some_command -h -x"
335
+
336
+
337
+ Long name: ---help
338
+ Description: Program description (the header part of --help)
339
+ Long description:
340
+ This option prints only the header part of what would be printed with
341
+ the option --help, without printing all the information about specific
342
+ option. In other words, it provides only the general information about
343
+ the program itself.
344
+
345
+
346
+ END
347
+
348
+ end
349
+
350
+ class Clop
351
+ @@additional_def_string=""
352
+ def Clop.add_defs(def_str)
353
+ @@additional_def_string+= def_str
354
+ end
355
+ end
356
+
357
+ def parse_command_line(def_str, global_variables_flag = false)
358
+ Clop.new(def_str, ARGV, global_variables_flag)
359
+ end
360
+
361
+ if __FILE__ == $0
362
+
363
+ options_definition_string = <<-END
364
+
365
+ Description: Command line option parser
366
+ Long description:
367
+ Test program for the class Clop (Command line option parser),
368
+ (c) 2004, Piet Hut and Jun Makino; see ACS at www.artcompsi.org
369
+
370
+ This program appears at the end of the file "clop.rb" that contains
371
+ the definition of the Clop class.
372
+ By running the file (typing "ruby clop.rb"), you can check whether
373
+ it still behaves correctly. Maximum help is provided by the command
374
+ "ruby clop.rb --help".
375
+
376
+
377
+ Short name: -s
378
+ Long name: --softening_length
379
+ Value type: float # double/real/...
380
+ Default value: 0.0
381
+ Variable name: eps # any comment allowed here
382
+ Description: Softening length # and here too
383
+ Long description: # and even here
384
+ This option sets the softening length used to calculate the force
385
+ between two particles. The calculation scheme comforms to standard
386
+ Plummer softening, where rs2=r**2+eps**2 is used in place of r**2.
387
+
388
+
389
+ Short name: -t
390
+ Long name: --end_time
391
+ Value type: float
392
+ Default value: 10
393
+ Variable name: t_end
394
+ Print name: t
395
+ Description: Time to stop integration
396
+ Long description:
397
+ This option gives the time to stop integration.
398
+
399
+
400
+ Short name: -n
401
+ Long name: --number_of_particles
402
+ Value type: int
403
+ Default value: none
404
+ Variable name: n_particles
405
+ Print name: N
406
+ Description: Number of particles
407
+ Long description:
408
+ Number of particles in an N-body snapshot.
409
+
410
+
411
+ Short name: -x
412
+ Long name: --extra_diagnostics
413
+ Value type: bool
414
+ Variable name: xdiag
415
+ Description: Extra diagnostics
416
+ Long description:
417
+ The following extra diagnostics will be printed:
418
+
419
+ acceleration (for all integrators)
420
+ jerk (for the Hermite integrator)
421
+
422
+
423
+ Short name: -o
424
+ Long name: --output_file_name
425
+ Value type: string
426
+ Default value: none
427
+ Variable name: output_file_name
428
+ Print name: # no name, hence name suppressed
429
+ Description: Name of the outputfile
430
+ Long description:
431
+ Name of the snapshot output file.
432
+ The snapshot contains the mass, position, and velocity values
433
+ for all particles in an N-body system.
434
+
435
+
436
+ Long name: --star_type # no short option given here
437
+ Value type: string
438
+ Default value: star: MS # parser cuts only at first ":"
439
+ Variable name: star_type
440
+ Description: Star type
441
+ Long description:
442
+ This options allows you to specify that a particle is a star, of a
443
+ certain type T, and possibly of subtypes t1, t2, ..., tk by specifying
444
+ --star_type "star: T: t1: t2: ...: tk". The ":" separators are allowed
445
+ to have blank spaces before and after them.
446
+
447
+ Examples: --star_type "star: MS"
448
+ --star_type "star : MS : ZAMS"
449
+ --star_type "star: giant: AGB"
450
+ --star_type "star:NS:pulsar:millisecond pulsar"
451
+
452
+ END
453
+
454
+ additional_definitions_string=<<-END
455
+
456
+ Short name: -a
457
+ Long name: --shared_timesteps
458
+ Value type: bool
459
+ Variable name: shared_flag
460
+ Description: All particles share the same time step
461
+ Long description:
462
+ If this flag is set to true, all particles will march in lock step,
463
+ all sharing the same time step.
464
+
465
+
466
+ END
467
+
468
+ Clop.add_defs(additional_definitions_string)
469
+ Clop.add_to_initialize_action_list(lambda{|x|
470
+ print "shared=",x.shared_flag,"\n"})
471
+ clop = parse_command_line(options_definition_string, false)
472
+
473
+ print "\nclop.rb: testing automatic generation of attribute readers:\n"
474
+ print " clop.t_end = ", clop.t_end, "\n"
475
+ end
metadata ADDED
@@ -0,0 +1,47 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: clop
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.1
7
+ date: 2007-11-06 00:00:00 -05:00
8
+ summary: A package for handling command line options
9
+ require_paths:
10
+ - lib
11
+ email: alfred dot whitehead (sign in the middle) jcu dot edu dot au
12
+ homepage:
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: clop
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Piet Hut and Jun Makino
31
+ files:
32
+ - lib/clop.rb
33
+ - README
34
+ test_files: []
35
+
36
+ rdoc_options: []
37
+
38
+ extra_rdoc_files:
39
+ - README
40
+ executables: []
41
+
42
+ extensions: []
43
+
44
+ requirements: []
45
+
46
+ dependencies: []
47
+