numru-misc 0.1.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.
@@ -0,0 +1,83 @@
1
+ <?xml version="1.0" ?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5
+ <html xmlns="http://www.w3.org/1999/xhtml">
6
+ <head>
7
+ <title>lib/numru/misc/misc.rb</title>
8
+ </head>
9
+ <body>
10
+ <h1><a name="label:0" id="label:0">module NumRu::Misc</a></h1><!-- RDLabel: "module NumRu::Misc" -->
11
+ <h2><a name="label:1" id="label:1">Overview</a></h2><!-- RDLabel: "Overview" -->
12
+ <p>Miscellaneous functions and classes to facilitate programming.</p>
13
+ <h2><a name="label:2" id="label:2">Index</a></h2><!-- RDLabel: "Index" -->
14
+ <p>CLASSES</p>
15
+ <ul>
16
+ <li><a href="keywordopt.html">class KeywordOpt</a>
17
+ to support keyward arguments with default values.</li>
18
+ <li><a href="narray_ext.html">class NArray (enhancement of NArray made by M Tanaka)</a></li>
19
+ </ul>
20
+ <p>MODULES</p>
21
+ <ul>
22
+ <li><a href="md_iterators.html">module MD_Iterators</a> A Mixin for classes with
23
+ multi-dimension indexing support (such as NArray).</li>
24
+ <li><a href="emath.html">module EMath</a>
25
+ To be included instead of the Math predefined module (or NMath in NArray).
26
+ Unlike Math and NMath, EMath handles unknown classes by calling its
27
+ native instance method (assuming the same name).</li>
28
+ </ul>
29
+ <p>MODULE FUNCTIONS</p>
30
+ <ul>
31
+ <li><a href="#label:4">check_shape_consistency</a></li>
32
+ </ul>
33
+ <h2><a name="label:3" id="label:3">Module functions</a></h2><!-- RDLabel: "Module functions" -->
34
+ <dl>
35
+ <dt><a name="label:4" id="label:4"><code>check_shape_consistency(<var>cshapes</var>, *<var>args</var>)</code></a></dt><!-- RDLabel: "check_shape_consistency" -->
36
+ <dd>
37
+ <p>Check the consistency of array shapes (multi-dim such as NArray).
38
+ Exception is raised if inconsistent.</p>
39
+ <p>ARGUMENTS</p>
40
+ <ul>
41
+ <li>cshapes (String) : description of the shapes of the args.
42
+ Delimited by one-or-more spaces between arrays,
43
+ and the shape of each array is delimited by a comma. The lengths are
44
+ expressed with string names as identifiers (in that case, length
45
+ values are unquestioned) or specified as positive integers.
46
+ Use '..' or '...' for repetition of the last shape.
47
+ See EXAMPLES below.</li>
48
+ <li>args (multi-dim arrays such as NArray): arrays to be checked</li>
49
+ </ul>
50
+ <p>RETURN VALUE</p>
51
+ <ul>
52
+ <li>nil</li>
53
+ </ul>
54
+ <p>POSSIBLE EXCEPTIONS</p>
55
+ <ul>
56
+ <li>exception is raised if cshapes and args are inconsistent:
57
+ <ul>
58
+ <li>RuntimeError, if the arrays do not have shapes specified by cshapes.</li>
59
+ <li>ArgeumentError, if the number of args are inconsistent with cshapes.
60
+ This is likely a coding error of the user.</li>
61
+ </ul></li>
62
+ </ul>
63
+ <p>EXAMPLES</p>
64
+ <ul>
65
+ <li><p>to check whether three arrays u, v, and w are shaped as
66
+ u[nx], v[ny], and w[nx,ny], where nx and ny are any integer:</p>
67
+ <pre>NumRu::Misc.check_shape_consistency('nx ny nx,ny',u,v,w)</pre>
68
+ <p>Or equivalently,</p>
69
+ <pre>NumRu::Misc.check_shape_consistency('m n m,n',u,v,w)</pre>
70
+ <p>because actual strings does not matter.</p></li>
71
+ <li><p>To specify fixed lengths, use integers instead of names:</p>
72
+ <pre>NumRu::Misc.check_shape_consistency('4 n 4,n',u,v,w)</pre>
73
+ <p>In this case, u,v,w must have shapes [4], [ny], and [4,ny],
74
+ where ny is any length.</p></li>
75
+ <li><p>Use '..' or '...' to repeat the same shape:</p>
76
+ <pre>NumRu::Misc.check_shape_consistency('nx,ny ...',u,v,w)</pre>
77
+ <p>This ensures that u, v, and w are 2D arrays with the same shape.
78
+ Note: '..' and '...' are the same, so you can use whichever you like.</p></li>
79
+ </ul></dd>
80
+ </dl>
81
+
82
+ </body>
83
+ </html>
@@ -0,0 +1,104 @@
1
+ require 'rbconfig'
2
+ require 'find'
3
+ include Config
4
+
5
+ if CONFIG["MINOR"].to_i > 6 then $rb_18 = true else $rb_18 = false end
6
+ if $rb_18
7
+ require 'fileutils'
8
+ else
9
+ require 'ftools'
10
+ end
11
+
12
+ =begin
13
+ $version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
14
+ $libdir = File.join(CONFIG["libdir"], "ruby", $version)
15
+ # $archdir = File.join($libdir, CONFIG["arch"])
16
+ $site_libdir = $:.find {|x| x =~ /site_ruby$/}
17
+ if !$site_libdir
18
+ $site_libdir = File.join($libdir, "site_ruby")
19
+ elsif Regexp.compile($site_libdir) !~ Regexp.quote($version)
20
+ $site_libdir = File.join($site_libdir, $version)
21
+ end
22
+
23
+ default_destdir = $site_libdir
24
+ =end
25
+
26
+ default_destdir = CONFIG["sitelibdir"]
27
+
28
+ def install_rb(srcdir, destdir)
29
+ libdir = "lib"
30
+ libdir = File.join(srcdir, libdir) if srcdir
31
+ path = []
32
+ dir = []
33
+ Find.find(libdir) do |f|
34
+ next unless FileTest.file?(f)
35
+ next if (f = f[libdir.length+1..-1]) == nil
36
+ next if (/CVS$/ =~ File.dirname(f))
37
+ path.push f
38
+ dir |= [File.dirname(f)]
39
+ end
40
+ for f in dir
41
+ next if f == "."
42
+ next if f == "CVS"
43
+ if $rb_18
44
+ FileUtils.makedirs(File.join(destdir, f))
45
+ else
46
+ File::makedirs(File.join(destdir, f))
47
+ end
48
+ end
49
+ for f in path
50
+ next if (/\~$/ =~ f)
51
+ next if (/^\./ =~ File.basename(f))
52
+ if $rb_18
53
+ FileUtils.install(File.join("lib", f), File.join(destdir, f), {:mode => 0644, :verbose => true})
54
+ else
55
+ File::install(File.join("lib", f), File.join(destdir, f), 0644, true)
56
+ end
57
+ end
58
+ end
59
+
60
+ def ARGV.switch
61
+ return nil if self.empty?
62
+ arg = self.shift
63
+ return nil if arg == '--'
64
+ if arg =~ /^-(.)(.*)/
65
+ return arg if $1 == '-'
66
+ raise 'unknown switch "-"' if $2.index('-')
67
+ self.unshift "-#{$2}" if $2.size > 0
68
+ "-#{$1}"
69
+ else
70
+ self.unshift arg
71
+ nil
72
+ end
73
+ end
74
+
75
+ def ARGV.req_arg
76
+ self.shift || raise('missing argument')
77
+ end
78
+
79
+ destdir = default_destdir
80
+
81
+ begin
82
+ while switch = ARGV.switch
83
+ case switch
84
+ when '-d', '--destdir'
85
+ destdir = ARGV.req_arg
86
+ # when '-u', '--uninstall'
87
+ # uninstall = true
88
+ else
89
+ raise "unknown switch #{switch.dump}"
90
+ end
91
+ end
92
+ rescue
93
+ STDERR.puts $!.to_s
94
+ STDERR.puts File.basename($0) +
95
+ " -d <destdir>"
96
+ exit 1
97
+ end
98
+
99
+ #if( defined?(uninstall) && uninstall )
100
+ # uninstall_rb(nil, destdir)
101
+ #else
102
+ install_rb(nil, destdir)
103
+ #end
104
+
@@ -0,0 +1,4 @@
1
+ require 'numru/misc/misc'
2
+ require 'numru/misc/keywordopt'
3
+ require 'numru/misc/md_iterators'
4
+ require 'numru/misc/emath'
@@ -0,0 +1,75 @@
1
+ =begin
2
+ =module NumRu::Misc::EMath
3
+
4
+ To be included instead of the Math predefined module (or NMath in NArray).
5
+ Unlike Math and NMath, EMath handles unknown classes by calling its
6
+ native instance method (assuming the same name).
7
+
8
+ Therefore, if included, its function (module method) is used as:
9
+
10
+ cos( obj )
11
+
12
+ and so on. If obj is not of a supported class, EMath calls, obj.cos in
13
+ this case. (If cos is not a method of obj, then an exception is
14
+ raised.) Supported classes are Numeric (by Math) and NArray (by
15
+ NMath). EMath stands for "good Math" (for obvious reason for a
16
+ Japanese).
17
+
18
+ Note: as for atan2(a,b), a.atan2(b) will be called if a or b
19
+ is not supported. This is the case for all functions that take
20
+ two or more arguments.
21
+
22
+ =end
23
+
24
+ require "narray"
25
+
26
+ module NumRu
27
+ module Misc
28
+ module EMath
29
+
30
+ E = Math::E
31
+ PI = Math::PI
32
+
33
+ funcs = ["acos", "acosh", "asin", "asinh", "atan", "atan2", "atanh",
34
+ "cos", "cosh", "erf", "erfc", "exp", "frexp", "hypot",
35
+ "ldexp", "log", "log10", "sin", "sinh", "sqrt", "tan", "tanh"]
36
+ # FUNCS: from ruby 1.8.0, ( Math.methods - Object.methods ).sort
37
+
38
+ module_function
39
+ funcs.each{|func|
40
+ eval <<-EOS,nil,__FILE__,__LINE__+1
41
+ def #{func}(*arg)
42
+ case arg[0]
43
+ when Numeric
44
+ Math.#{func}(*arg)
45
+ when NArray
46
+ NMath.#{func}(*arg)
47
+ else
48
+ obj = arg.shift
49
+ begin
50
+ obj.#{func}(*arg)
51
+ rescue NameError
52
+ raise TypeError,"cannot handle \#{obj.class}: \#{obj.inspect}"
53
+ end
54
+ end
55
+ end
56
+ EOS
57
+ }
58
+ end
59
+ end
60
+ end
61
+
62
+ if __FILE__ == $0
63
+ include NumRu::Misc::EMath
64
+ p cos( PI )
65
+ p cos( Complex(0, 1) )
66
+ p cos( NArray[0,PI/3,PI/2] )
67
+ begin
68
+ p cos( "ggg" )
69
+ rescue
70
+ print "* error as expected >>: ",$!,"\n"
71
+ end
72
+ require 'narray_miss'
73
+ nam = NArrayMiss.to_nam( NArray[0,PI/3,PI/2] )
74
+ p cos(nam)
75
+ end
@@ -0,0 +1,498 @@
1
+ =begin
2
+ ==Index
3
+ * ((<class NumRu::Misc::KeywordOpt>))
4
+ * ((<class NumRu::Misc::KeywordOptAutoHelp < NumRu::Misc::KeywordOpt>))
5
+
6
+ = class NumRu::Misc::KeywordOpt
7
+
8
+ == Overview
9
+
10
+ A class to facilitate optional keyword arguments. More specifically,
11
+ it helps the use of a Hash to mimic the keyword argument system.
12
+ With this, you can set default values and description to each
13
+ keyword argument.
14
+
15
+ == Classes defined supplementarilly
16
+
17
+ === class NumRu::Misc::HelpMessagingException < StandardError
18
+
19
+ This is for your convenience. See the usage example below.
20
+
21
+ == Usage example
22
+
23
+ Suppose that you introduce keyword arguments "flag" and "number"
24
+ to the method "hoge" in a class/module Foo. It can be done as
25
+ follows:
26
+
27
+ require 'numru/misc' # or, specifically, require 'numru/misc/keywordopt'
28
+ include NumRu
29
+
30
+ class Foo
31
+ @@opt_hoge = Misc::KeywordOpt.new(
32
+ ['flag', false, 'whether or not ...'],
33
+ ['number', 1, 'number of ...'],
34
+ ['help', false, 'show help message']
35
+ )
36
+ def hoge(regular_arg1, regular_arg2, options=nil)
37
+ opt = @@opt_hoge.interpret(options)
38
+ if opt['help']
39
+ puts @@opt_hoge.help
40
+ puts ' Current values='+opt.inspect
41
+ raise Misc::HelpMessagingException, '** show help message and raise **'
42
+ end
43
+ # do what you want below
44
+ # (options are set in the Hash opt: opt['flag'] and opt['number'])
45
+ end
46
+ end
47
+
48
+ Here, the options are defined in the class variable @@opt_hoge
49
+ with option names, default values, and descriptions (for help
50
+ messaging). One can use the method hoge as follows:
51
+
52
+ foo = Foo.new
53
+ ...
54
+ x = ...
55
+ y = ...
56
+ ...
57
+ foo.hoge( x, y, {'flag'=>true, 'number'=>10} )
58
+
59
+ Or equivalently,
60
+
61
+ foo.hoge( x, y, 'flag'=>true, 'number'=>10 )
62
+
63
+ because '{}' can be omitted here.
64
+
65
+ Tails of options names can be shortened as long as unambiguous:
66
+
67
+ foo.hoge( x, y, 'fla'=>true, 'num'=>10 )
68
+
69
+
70
+ To show the help message, call
71
+
72
+ foo.hoge( x, y, 'help'=>true )
73
+
74
+ This will cause the following help message printed with the
75
+ exception HelpMessagingException raised.
76
+
77
+ << Description of options >>
78
+ option name => default value description:
79
+ "flag" => false whether or not ...
80
+ "number" => 1 number of ...
81
+ "help" => false show help message
82
+ Current values={"help"=>true, "number"=>1, "flag"=>false}
83
+ NumRu::Misc::HelpMessagingException: ** help messaging done **
84
+ from (irb):78:in "hoge"
85
+ from (irb):83
86
+
87
+ Do not affraid to write long descriptions. The help method
88
+ breaks lines nicely if they are long.
89
+
90
+ == Class methods
91
+
92
+ ---KeywordOpt.new( *args )
93
+
94
+ Constructor.
95
+
96
+ ARGUMENTS
97
+ * args : (case 1) arrays of two or three elements: [option name,
98
+ default value, description ], or [option name, default value]
99
+ if you do not want to write descriptions. Option names and
100
+ descriptions must be String. (case 2) another KeywordOpt.
101
+ Cases 1 and 2 can be mixed.
102
+
103
+ When case 2, a link to the other KeywordOpt is kept. Thus, change
104
+ of values in it is reflected to the current one. However,
105
+ the link is deleted if values are changed by ((<set>)).
106
+
107
+ RETURN VALUE
108
+ * a KeywordOpt object
109
+
110
+ EXAMPLE
111
+ * case 1
112
+ opt = Misc::KeywordOpt.new(
113
+ ['flag', false, 'whether or not ...'],
114
+ ['help', false, 'show help message']
115
+ )
116
+ * case 2
117
+ opt = Misc::KeywordOpt.new( optA, optB )
118
+ * case 1 & 2
119
+ opt = Misc::KeywordOpt.new(
120
+ ['flag', false, 'whether or not ...'],
121
+ optA
122
+ )
123
+
124
+ == Methods
125
+ ---interpret(hash)
126
+
127
+ Interprets a hash that specifies option values.
128
+
129
+ ARGUMENTS
130
+ * hash (Hash or nil) : a hash with string keys matching option names
131
+ (initializedwhen constructed). The matching is case sensitive and done
132
+ such that the tail of a option name can be omitted as long as
133
+ unambiguous (for example, 'num' for 'number').
134
+ If the argument is nil, the current values are returned.
135
+ If there are two options like 'max' and 'maxval', to use
136
+ a key 'max' (identical to the former paramer) is allowed, although
137
+ it matches 'maxval' as well. (Again 'ma' is regarded ambiguous.)
138
+
139
+ RETURN VALUE
140
+ * a Hash containing the option values (default values overwritten
141
+ with hash).
142
+
143
+ POSSIBLE EXCEPTION
144
+ * hash has a key that does not match any of the option names.
145
+ * hash has a key that is ambiguous
146
+
147
+ ---set(hash)
148
+
149
+ Similar to ((<interpret>)) but changes internal values.
150
+
151
+ ARGUMENTS
152
+ * hash (Hash) : see ((<interpret>)). (Here, nil is not permitted though)
153
+
154
+ RETURN VALUE
155
+ * a Hash containing the values replaced (the ones before calling this
156
+ method)
157
+
158
+ POSSIBLE EXCEPTION
159
+ * the argument is not a Hash
160
+ * others are same as in ((<interpret>))
161
+
162
+ ---help
163
+
164
+ Returns a help message
165
+
166
+ RETURN VALUE
167
+ * a String describing the option names, default values, and descriptions
168
+
169
+ ---[](key)
170
+
171
+ Returns a value associated with the key (exact matching unlike interpret)
172
+
173
+ ---keys
174
+
175
+ Retunrs the keys.
176
+
177
+ ---select_existent(hash_or_keys)
178
+
179
+ Copies hash_or_keys, exclude ones that are not included in the option
180
+ (by comparing keys), and returns it. I.e. select only the ones
181
+ exsitent.
182
+
183
+ NOTE: ambiguity is not checked, so the resultant value is not
184
+ necessarily accepted by ((<interpret>)).
185
+
186
+ ARGUMENTS
187
+ * hash_or_keys (Hash or Array)
188
+
189
+ RETURN VALUE
190
+ * a Hash or Array depending on the class of the argument hash_or_keys
191
+
192
+ = class NumRu::Misc::KeywordOptAutoHelp < NumRu::Misc::KeywordOpt
193
+
194
+ Same as ((<class NumRu::Misc::KeywordOpt>)), but the method ((<interpret>))
195
+ shows a help message and raise an exception if option 'help' is provided
196
+ as an argument and is not nil or false
197
+ ((({NumRu::Misc::HelpMessagingException < StandardError})))
198
+ or if the arguments cannot be interpreted correctly ((({ArgumentError}))).
199
+ Option 'help' is automatically defined, so you do not have to define it
200
+ yourself.
201
+
202
+ =end
203
+
204
+ module NumRu
205
+
206
+ module Misc
207
+ class HelpMessagingException < StandardError
208
+ end
209
+
210
+ class KeywordOpt
211
+ def initialize(*args)
212
+ # USAGE:
213
+ # KeywordOpt.new([key,val,description],[key,val,description],..)
214
+ # where key is a String, and description can be omitted.
215
+ @val=Hash.new
216
+ @description=Hash.new
217
+ @keys = []
218
+ args.each{ |x|
219
+ case x
220
+ when Array
221
+ unless (x[0]=='help') && @keys.include?(x[0])
222
+ #^only 'help' can overwrap in the arguments
223
+ @keys.push(x[0])
224
+ @val[x[0]] = x[1]
225
+ @description[x[0]] = ( (x.length>=3) ? x[2] : '' )
226
+ end
227
+ when KeywordOpt
228
+ x.keys.each{|k|
229
+ unless k=='help' && @keys.include?(k)
230
+ #^only 'help' can overwrap in the arguments
231
+ @keys.push(k)
232
+ @val[k] = x #.val[k]
233
+ @description[k] = x.description[k]
234
+ end
235
+ }
236
+ def @val.[](k)
237
+ val = super(k)
238
+ val.is_a?(KeywordOpt) ? val[k] : val
239
+ end
240
+ def @val.dup
241
+ out = Hash.new
242
+ each{|k,val| out[k] = (val.is_a?(KeywordOpt) ? val[k] : val)}
243
+ out
244
+ end
245
+ else
246
+ raise ArgumentError, "invalid argument: #{x.inspect}"
247
+ end
248
+ }
249
+ @keys_sort = @keys.sort
250
+ if @keys_sort.length != @keys_sort.uniq.length
251
+ raise ArgumentError, "keys are not unique"
252
+ end
253
+ end
254
+
255
+ def interpret(hash)
256
+ return @val.dup if hash.nil?
257
+ ##
258
+ len = @val.length
259
+ im = 0
260
+ out = @val.dup
261
+ hash.keys.sort.each do |key|
262
+ rkey = /^#{key}/
263
+ loop do
264
+ if rkey =~ @keys_sort[im]
265
+ if im<len-1 && rkey=~@keys_sort[im+1] &&
266
+ key != @keys_sort[im] # not identical
267
+ raise ArgumentError, "Ambiguous key specification '#{key}'."
268
+ end
269
+ out[@keys_sort[im]]=hash[key]
270
+ break
271
+ end
272
+ im += 1
273
+ if im==len
274
+ raise ArgumentError, "'#{key}' does not match any of the keys."
275
+ end
276
+ end
277
+ end
278
+ out
279
+ end
280
+
281
+ def select_existent(hash_or_keys)
282
+ hash_or_keys = hash_or_keys.dup # not to alter the original
283
+ len = @val.length
284
+ im = 0
285
+ kys = ( Array === hash_or_keys ? hash_or_keys : hash_or_keys.keys )
286
+ kys.sort.each do |key|
287
+ rkey = /^#{key}/
288
+ loop do
289
+ break if rkey =~ @keys_sort[im]
290
+ im += 1
291
+ if im==len
292
+ hash_or_keys.delete(key)
293
+ im = 0 # rewind
294
+ break
295
+ end
296
+ end
297
+ end
298
+ hash_or_keys
299
+ end
300
+
301
+ def set(hash)
302
+ raise ArgumentError, "not a hash" if !hash.is_a?(Hash)
303
+ ##
304
+ replaced = Hash.new
305
+ len = @val.length
306
+ im = 0
307
+ hash.keys.sort.each do |key|
308
+ rkey = /^#{key}/
309
+ loop do
310
+ if rkey =~ @keys_sort[im]
311
+ if im<len-1 && rkey=~@keys_sort[im+1]
312
+ raise "Ambiguous key specification '#{key}'."
313
+ end
314
+ replaced[@keys_sort[im]] = @val[@keys_sort[im]]
315
+ @val[@keys_sort[im]]=hash[key]
316
+ break
317
+ end
318
+ im += 1
319
+ raise "'#{key}' does not match any of the keys." if im==len
320
+ end
321
+ end
322
+ replaced
323
+ end
324
+
325
+ # def __line_feed(str)
326
+ # if str.length >= 68
327
+ # idx = str[0..67].rindex(/\s/)
328
+ # if idx
329
+ # str[idx, 1] = "\n\t"
330
+ # end
331
+ # end
332
+ # str
333
+ # end
334
+ def __line_feed(str, len)
335
+ if str.length >= len
336
+ idx = str[0...len].rindex(/\s/)
337
+ if idx
338
+ str = str[0...idx] + "\n\t\t\t# " + __line_feed(str[(idx+1)..-1],50)
339
+ end
340
+ end
341
+ str
342
+ end
343
+ private :__line_feed
344
+
345
+ def help
346
+ " option name\tdefault value\t# description:\n" +
347
+ @keys.collect{|k|
348
+ __line_feed(" #{k.inspect}\t#{@val[k].inspect}\t# #{@description[k]}", 66)
349
+ }.join("\n")
350
+ end
351
+
352
+ def [](k)
353
+ v = @val[k]
354
+ if v.is_a?(KeywordOpt)
355
+ v = v.val[k]
356
+ end
357
+ v
358
+ end
359
+
360
+ def keys
361
+ @keys.dup
362
+ end
363
+
364
+ ##### protected methods #####
365
+ protected
366
+ attr_reader :val, :description
367
+ end
368
+
369
+ ##################################################
370
+
371
+ class KeywordOptAutoHelp < KeywordOpt
372
+ def initialize(*args)
373
+ args.push(['help', false, 'show help message if true'])
374
+ super(*args)
375
+ end
376
+
377
+ def interpret(hash)
378
+ begin
379
+ out = super(hash)
380
+ rescue
381
+ raise $!.inspect + "\n Available parameters are:\n" + help
382
+ end
383
+ if out['help']
384
+ puts "<< Description of options >>\n" + help
385
+ puts ' Current values=' + out.inspect
386
+ raise Misc::HelpMessagingException, '** help messaging done **'
387
+ end
388
+ out
389
+ end
390
+
391
+ def set(hash)
392
+ raise ArgumentError, "not a hash" if !hash.is_a?(Hash)
393
+ if hash['help']
394
+ puts "<< Description of options >>\n" + help
395
+ raise Misc::HelpMessagingException, '** help messaging done **'
396
+ end
397
+ super
398
+ end
399
+ end
400
+
401
+ end
402
+ end
403
+
404
+ if __FILE__ == $0
405
+ include NumRu
406
+
407
+ class Foo
408
+ @@opt_hoge = Misc::KeywordOpt.new(
409
+ ['flag', false, 'whether or not ...'],
410
+ ['number', 1, 'number of ...'],
411
+ ['fff', 1, 'fff...'],
412
+ ['help', false, 'show help message']
413
+ )
414
+ def self.change_default(hash)
415
+ @@opt_hoge.set(hash)
416
+ end
417
+ def hoge(regular_arg1, regular_arg2, options=nil)
418
+ opt = @@opt_hoge.interpret(options)
419
+ if opt['help']
420
+ puts "* Description of options:\n" + @@opt_hoge.help
421
+ puts ' Current values='+opt.inspect
422
+ raise Misc::HelpMessagingException, '** show help message and raise **'
423
+ end
424
+ # do what you want below
425
+ # (options are set in the Hash opt: opt['flag'] and opt['number'])
426
+ p opt
427
+ end
428
+ end
429
+
430
+ foo = Foo.new
431
+ x = 1
432
+ y = 1
433
+ print "### 0 ###\n"
434
+ foo.hoge( x, y, {'flag'=>true, 'number'=>10} )
435
+ foo.hoge( x, y )
436
+ print "### 1 ###\n"
437
+ foo.hoge( x, y, 'fla'=>true, 'num'=>10 )
438
+ print "### 2 ###\n"
439
+ begin
440
+ foo.hoge( x, y, 'help'=>true )
441
+ rescue
442
+ puts $!
443
+ end
444
+ print "### 3 ###\n"
445
+ Foo.change_default( {'number'=>3} )
446
+ begin
447
+ foo.hoge( x, y, 'fla'=>true, 'num'=>10, 'help'=>true)
448
+ rescue
449
+ puts $!
450
+ end
451
+ print "### 4 ###\n"
452
+ begin
453
+ foo.hoge( x, y, 'dummy'=>nil)
454
+ rescue
455
+ puts $!
456
+ end
457
+ print "### 5 ###\n"
458
+ begin
459
+ foo.hoge( x, y, 'f'=>nil)
460
+ rescue
461
+ puts $!
462
+ end
463
+
464
+ print "\n###### test of KeywordOptAutoHelp ######\n"
465
+ opt = Misc::KeywordOptAutoHelp.new(
466
+ ['flag', false, 'whether or not ...'],
467
+ ['number', 1, 'number of ...']
468
+ )
469
+ print "### 11 ###\n"
470
+ begin
471
+ opt.interpret('flag'=>10,'help'=>true)
472
+ rescue
473
+ puts $!
474
+ end
475
+ print "### 12 ###\n"
476
+ begin
477
+ opt.interpret('nnn'=>10)
478
+ rescue
479
+ puts $!
480
+ end
481
+
482
+ print "### 13 ###\n"
483
+ opt2 = Misc::KeywordOptAutoHelp.new(
484
+ ['flafla', false, 'whether or not ...']
485
+ )
486
+ opt3 = Misc::KeywordOptAutoHelp.new( opt, opt2 )
487
+ p opt3.interpret('flag'=>true)
488
+ begin
489
+ opt3.interpret('help'=>true)
490
+ rescue
491
+ puts $!
492
+ end
493
+
494
+ print "### 14 ###\n"
495
+ p opt2.keys, opt.keys
496
+ p opt.select_existent({"flag"=>99, "num"=>88, 'acb'=>333})
497
+ p opt.select_existent(["flag", "num", 'acb'])
498
+ end