langhelp 0.9.8
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.
- data/Changes +2530 -0
- data/bin/mklanghelp +50 -0
- data/data/langhelp/config.sample +889 -0
- data/files +39 -0
- data/graphviz-dot.jpg +0 -0
- data/langhelp.en.html +409 -0
- data/langhelp.en.rd +390 -0
- data/langhelp.ja.html +524 -0
- data/langhelp.ja.rd +487 -0
- data/lib/el4r/emacsruby/autoload/50langhelp.rb +2 -0
- data/lib/el4r/emacsruby/langhelp.rb +864 -0
- data/lib/el4r/emacsruby/test-langhelp.rb +300 -0
- data/lib/langhelp/langhelp-base.rb +649 -0
- data/lib/langhelp/langhelp-sub.rb +1023 -0
- data/lib/langhelp/lh_lua.rb +25 -0
- data/lib/langhelp/lh_perl.rb +112 -0
- data/lib/langhelp/lh_php.rb +34 -0
- data/lib/langhelp/lh_python.rb +31 -0
- data/lib/langhelp/lh_ruby.rb +400 -0
- data/lib/langhelp/mklanghelp.rb +140 -0
- data/lib/langhelp/parse-info.rb +145 -0
- data/ri.jpg +0 -0
- data/setup.rb +1551 -0
- data/test/a_classes.lst +2 -0
- data/test/a_methods.lst +2 -0
- data/test/b_classes.lst +2 -0
- data/test/b_methods.lst +2 -0
- data/test/c_methods.lst +4 -0
- data/test/common.rb +15 -0
- data/test/d_methods.lst +4 -0
- data/test/langhelp.e +566 -0
- data/test/ruby.e +3 -0
- data/test/tagify01-before.html +11 -0
- data/test/tagify02-before.html +11 -0
- data/test/test-base.rb +538 -0
- data/test/test-command.rb +92 -0
- data/test/test-parse-info.rb +175 -0
- data/test/test-ruby.rb +242 -0
- data/test/testdoc.rd +6 -0
- metadata +84 -0
@@ -0,0 +1,1023 @@
|
|
1
|
+
# This script is auto-generated. DON'T EDIT!!!
|
2
|
+
#!/usr/bin/env ruby
|
3
|
+
|
4
|
+
=begin
|
5
|
+
== Candidates
|
6
|
+
# (view-srcfile "tgen/test-tgen.rb" "assert_permission")
|
7
|
+
=end
|
8
|
+
|
9
|
+
#### print
|
10
|
+
class Object
|
11
|
+
# puts MSG = self.inspect
|
12
|
+
# for debug.
|
13
|
+
def pr(msg=nil)
|
14
|
+
if msg then
|
15
|
+
print "#{msg} = "
|
16
|
+
end
|
17
|
+
|
18
|
+
display
|
19
|
+
print "\n"
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
# pr when $VERBOSE
|
24
|
+
def vpr(msg=nil)
|
25
|
+
if $VERBOSE then
|
26
|
+
self.pr msg
|
27
|
+
else
|
28
|
+
self
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# eval and print
|
33
|
+
def ev(str)
|
34
|
+
puts "#{str} = #{eval str}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
#### array
|
39
|
+
class Array
|
40
|
+
# Make random value array. length==n
|
41
|
+
def Array.rand(n, r=0)
|
42
|
+
(1 .. n).collect{super(r)}
|
43
|
+
end
|
44
|
+
|
45
|
+
# join ' '
|
46
|
+
def js
|
47
|
+
join ' '
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
#### vrequire
|
54
|
+
# verbose require
|
55
|
+
def vrequire(f)
|
56
|
+
puts "loading " + f + "..."
|
57
|
+
require f
|
58
|
+
puts "loading " + f + "...done"
|
59
|
+
end
|
60
|
+
|
61
|
+
#### vsystem
|
62
|
+
# verbose system
|
63
|
+
def vsystem(cmd)
|
64
|
+
puts cmd
|
65
|
+
system cmd
|
66
|
+
end
|
67
|
+
|
68
|
+
#### time
|
69
|
+
class Time
|
70
|
+
# Simple benchmark function.
|
71
|
+
# Time.time(start_msg) { ... }
|
72
|
+
def Time.time(smsg="", emsg="%s seconds")
|
73
|
+
s=Time.now
|
74
|
+
print smsg
|
75
|
+
puts if smsg != ""
|
76
|
+
yield
|
77
|
+
sec=Time.now - s
|
78
|
+
printf emsg, sec
|
79
|
+
puts ""
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
#### nonzero
|
84
|
+
class Numeric
|
85
|
+
# 1 : self >=0 / -1 : self < 0
|
86
|
+
def sign
|
87
|
+
if self >= 0 then 1 else -1 end
|
88
|
+
end
|
89
|
+
|
90
|
+
# If self is negative, returns 0
|
91
|
+
def nonzero
|
92
|
+
[self, 0].max
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
class Vector
|
98
|
+
# If self is negative, returns 0
|
99
|
+
def nonzero
|
100
|
+
map{|x| x.nonzero}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
class Matrix
|
105
|
+
# If self is negative, returns 0
|
106
|
+
def nonzero
|
107
|
+
map{|x| x.nonzero}
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
#### sigma
|
112
|
+
module Math
|
113
|
+
# Math.sigma(b, e) { expr }
|
114
|
+
def sigma(b,e)
|
115
|
+
if b > e then
|
116
|
+
0
|
117
|
+
else
|
118
|
+
s=0
|
119
|
+
b.upto(e) do |i|
|
120
|
+
s += yield(i) || 0
|
121
|
+
end
|
122
|
+
s
|
123
|
+
end
|
124
|
+
end
|
125
|
+
alias sum sigma
|
126
|
+
module_function :sigma
|
127
|
+
end
|
128
|
+
|
129
|
+
#### nonempty
|
130
|
+
class Object
|
131
|
+
# Is self non-nil and not-empty.
|
132
|
+
def nonempty?
|
133
|
+
if self and !self.empty?
|
134
|
+
self
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
#### tempfile
|
141
|
+
require 'pathname'
|
142
|
+
require 'tempfile'
|
143
|
+
require 'tmpdir'
|
144
|
+
class << Tempfile
|
145
|
+
# Create a temporary file whose contents is CONTENT.
|
146
|
+
# Returns the file's path.
|
147
|
+
def path(content, dir=Dir.tmpdir)
|
148
|
+
x = Tempfile.open("content", dir)
|
149
|
+
x.write content
|
150
|
+
x.close
|
151
|
+
x.open
|
152
|
+
x.path
|
153
|
+
end
|
154
|
+
|
155
|
+
# Similar to Tempfile.path. But returns Pathname object.
|
156
|
+
def pathname(content, dir=Dir.tmpdir)
|
157
|
+
Pathname.new(path(content, dir=Dir.tmpdir))
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
#### untar
|
162
|
+
module Untar
|
163
|
+
# Returns a command to uncompress an archive FILE.
|
164
|
+
def untar_command(file)
|
165
|
+
f = file
|
166
|
+
case f
|
167
|
+
when /\.tar\.gz$/, /\.tgz$/
|
168
|
+
"(tar xzvf #{f} || tar xvf #{f})"
|
169
|
+
when /\.tar\.bz2$/
|
170
|
+
"(tar xjvf #{f} || tar xvf #{f})"
|
171
|
+
when /\.tar$/, /\.gz$/
|
172
|
+
"tar xf #{f}"
|
173
|
+
when /\.zip$/
|
174
|
+
"unzip #{f}"
|
175
|
+
when /\.lzh$/
|
176
|
+
"lha x #{f}"
|
177
|
+
when /\.afz$/
|
178
|
+
"afio -ivZ #{f}"
|
179
|
+
when /\.rar$/i
|
180
|
+
"unrar %s"
|
181
|
+
when /\.sit$/i
|
182
|
+
"ln -s %s tmp.sit; unstuff tmp.sit"
|
183
|
+
else
|
184
|
+
nil
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
#### getopts
|
190
|
+
def _getopts_sub(argv, single_opts, *long_opts)
|
191
|
+
require 'optparse'
|
192
|
+
opt = OptionParser.new
|
193
|
+
|
194
|
+
(single_opts || "").split(//).each do |single_opt|
|
195
|
+
opt.on("-#{single_opt}"){ eval "$OPT_#{single_opt}=true" }
|
196
|
+
end
|
197
|
+
|
198
|
+
long_opts.each do |long_opt|
|
199
|
+
have_arg_p = (long_opt[-1,1] == ':')
|
200
|
+
long_opt.chomp!(':')
|
201
|
+
block = lambda{|x| eval "$OPT_#{long_opt}=x"}
|
202
|
+
if have_arg_p
|
203
|
+
if long_opt.length == 1 # -x arg
|
204
|
+
opt.on("-#{long_opt} [ARG]",&block)
|
205
|
+
else # --long arg
|
206
|
+
opt.on("--#{long_opt}=[ARG]",&block)
|
207
|
+
end
|
208
|
+
else # --long
|
209
|
+
opt.on("--#{long_opt}"){ eval "$OPT_#{long_opt}=true"}
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
opt.parse! argv
|
214
|
+
end
|
215
|
+
|
216
|
+
# getopts compatibility layer using optparse.rb
|
217
|
+
def getopts(single_opts, *long_opts)
|
218
|
+
_getopts_sub ARGV, single_opts, *long_opts
|
219
|
+
end
|
220
|
+
|
221
|
+
#### run config
|
222
|
+
# run config
|
223
|
+
# c = RunConfig.new("test")
|
224
|
+
# c.run_user_config
|
225
|
+
# c.run_local_config
|
226
|
+
#
|
227
|
+
class RunConfig
|
228
|
+
|
229
|
+
def initialize(name)
|
230
|
+
@name = name
|
231
|
+
end
|
232
|
+
|
233
|
+
def run_user_config
|
234
|
+
run_config [File.expand_path("~/.#{@name}rc")] if ENV.key?("HOME")
|
235
|
+
end
|
236
|
+
|
237
|
+
def run_local_config
|
238
|
+
rcs = []
|
239
|
+
rcs.push ".#{@name}rc"
|
240
|
+
rcs.push "#{@name}.rc"
|
241
|
+
rcs.push "_#{@name}rc"
|
242
|
+
rcs.push "$#{@name}rc"
|
243
|
+
rcs.push "#{@name}rc"
|
244
|
+
run_config rcs
|
245
|
+
end
|
246
|
+
|
247
|
+
private
|
248
|
+
def run_config(rcs)
|
249
|
+
catch(:EXIT) do
|
250
|
+
for rc in rcs
|
251
|
+
begin
|
252
|
+
load rc
|
253
|
+
throw :EXIT
|
254
|
+
rescue LoadError, Errno::ENOENT
|
255
|
+
rescue
|
256
|
+
print "load error: #{rc}\n"
|
257
|
+
print $!.class, ": ", $!, "\n"
|
258
|
+
for err in $@[0, $@.size - 2]
|
259
|
+
print "\t", err, "\n"
|
260
|
+
end
|
261
|
+
throw :EXIT
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
#### set_attr
|
269
|
+
class Object
|
270
|
+
# Defines a singleton attribute. for testing purpose.
|
271
|
+
def set_attr(ivar_name, init_value)
|
272
|
+
eval("class << self; attr_accessor :#{ivar_name} end")
|
273
|
+
self.instance_variable_set("@#{ivar_name}", init_value)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
#### quote
|
278
|
+
class String
|
279
|
+
def quote(q="'")
|
280
|
+
%Q[#{q}#{self}#{q}]
|
281
|
+
end
|
282
|
+
|
283
|
+
# This function is different from dump.
|
284
|
+
def dquote
|
285
|
+
quote('"')
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
|
290
|
+
#### assert-file
|
291
|
+
# Example1:
|
292
|
+
# es = AssertFile.new("testdata/shorten-test.e")
|
293
|
+
# el = AssertFile.new("testdata/shorten-test.el")
|
294
|
+
# system "shorten.rb -l #{el} -e #{es} testdata/shorten-test-input.e"
|
295
|
+
# assert_file(es)
|
296
|
+
# assert_file(el)
|
297
|
+
#
|
298
|
+
# Example2:
|
299
|
+
# assert_file(:expected=>expected, :actual=>actual, :no_remove=>true)
|
300
|
+
#
|
301
|
+
# Example3:
|
302
|
+
# AssertFile.transaction(expected) {|asf|
|
303
|
+
# system "foo input > #{asf}"
|
304
|
+
# }
|
305
|
+
class AssertFile
|
306
|
+
require 'fileutils'
|
307
|
+
@@basedir = nil
|
308
|
+
def self.basedir=(basedir)
|
309
|
+
@@basedir = basedir
|
310
|
+
end
|
311
|
+
|
312
|
+
def self.transaction(*args, &block)
|
313
|
+
if block_given?
|
314
|
+
testcase = eval("self", block)
|
315
|
+
assert_files = args.map{|x| new(x) }
|
316
|
+
|
317
|
+
if @@basedir
|
318
|
+
Dir.chdir(@@basedir) { yield assert_files }
|
319
|
+
else
|
320
|
+
yield(assert_files)
|
321
|
+
end
|
322
|
+
assert_files.each{|asf| testcase.assert_file(asf)}
|
323
|
+
else
|
324
|
+
raise ArgumentError, "must have block"
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
|
329
|
+
|
330
|
+
|
331
|
+
# new("expected_filename")
|
332
|
+
# new(:expeced=>"expected_filename", :actual=>"actual_filename")
|
333
|
+
# new(:expeced=>"expected_filename", :actual=>"actual_filename", :diff=>"diff")
|
334
|
+
|
335
|
+
def initialize(arg)
|
336
|
+
require 'test/unit'
|
337
|
+
|
338
|
+
case arg
|
339
|
+
when String # expected
|
340
|
+
@expected = arg
|
341
|
+
@actual = arg+".actual"
|
342
|
+
@diff = arg+".diff"
|
343
|
+
when Hash
|
344
|
+
@basedir = arg[:basedir]
|
345
|
+
@expected = arg[:expected]
|
346
|
+
@no_remove = arg[:no_remove]
|
347
|
+
|
348
|
+
@actual = arg[:actual] || (@expected+".actual")
|
349
|
+
@diff = arg[:diff] || (@expected+".diff")
|
350
|
+
else
|
351
|
+
raise TypeError, "AssertFile.new: must be String or Hash."
|
352
|
+
end
|
353
|
+
@basedir ||= @@basedir
|
354
|
+
FileUtils.mkdir_p @basedir if @basedir
|
355
|
+
@expected = pathconv(@expected)
|
356
|
+
@actual = pathconv(@actual)
|
357
|
+
@diff = pathconv(@diff)
|
358
|
+
end
|
359
|
+
attr_accessor :expected, :actual, :diff, :no_remove
|
360
|
+
|
361
|
+
def pathconv(path)
|
362
|
+
if @basedir
|
363
|
+
File.expand_path(path, @basedir)
|
364
|
+
else
|
365
|
+
path
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
|
370
|
+
def unlink_diff
|
371
|
+
File.unlink(diff) if File.exist?(diff)
|
372
|
+
end
|
373
|
+
|
374
|
+
def make_diff
|
375
|
+
system "diff -u #{expected} #{actual} | tee #{diff}"
|
376
|
+
end
|
377
|
+
|
378
|
+
def to_s
|
379
|
+
actual
|
380
|
+
end
|
381
|
+
alias :to_str :to_s
|
382
|
+
end
|
383
|
+
|
384
|
+
module Test
|
385
|
+
module Unit
|
386
|
+
|
387
|
+
# Use at Test::Unit::Assertions::AssertionMessage#convert
|
388
|
+
class System
|
389
|
+
def initialize(cmd)
|
390
|
+
@cmd = cmd
|
391
|
+
end
|
392
|
+
|
393
|
+
def inspect
|
394
|
+
`#{@cmd}`.to_s
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
module Assertions
|
399
|
+
def assert_file(assert_file, message=nil)
|
400
|
+
AssertFile === assert_file or assert_file = AssertFile.new(assert_file)
|
401
|
+
$>.sync = true
|
402
|
+
assert_file.unlink_diff
|
403
|
+
diff = System.new("diff -u #{assert_file.expected} #{assert_file.actual} | tee #{assert_file.diff}")
|
404
|
+
full_message = build_message(message, <<EOM, diff)
|
405
|
+
#{assert_file.expected} and #{assert_file.actual} differ!
|
406
|
+
# #{assert_file.expected} size=#{File.size(assert_file.expected)}
|
407
|
+
# #{assert_file.actual} size=#{File.size(assert_file.actual)}
|
408
|
+
# expected (view-fline #{assert_file.expected.dump})
|
409
|
+
# actual (view-fline #{assert_file.actual.dump})
|
410
|
+
# ediff (ediff #{assert_file.expected.dump} #{assert_file.actual.dump})
|
411
|
+
?
|
412
|
+
EOM
|
413
|
+
assert_block(full_message) {
|
414
|
+
File.read(assert_file.expected) == File.read(assert_file.actual)
|
415
|
+
}
|
416
|
+
File.unlink assert_file.actual unless assert_file.no_remove
|
417
|
+
end
|
418
|
+
end
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
#### AssertFile depend: assert-file
|
423
|
+
#### w3m
|
424
|
+
module W3MUtils
|
425
|
+
module_function
|
426
|
+
|
427
|
+
def remove_local_cgi_url(url)
|
428
|
+
case url
|
429
|
+
when nil
|
430
|
+
nil
|
431
|
+
when %r!^file:///cgi-bin/fline.cgi\?(.+):\d+$!
|
432
|
+
"file://#{$1}"
|
433
|
+
else
|
434
|
+
url
|
435
|
+
end
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
#### W3MUtils depend: w3m
|
440
|
+
#### iftest
|
441
|
+
# Test mode.
|
442
|
+
# Returns a temporary value when unit-testing.
|
443
|
+
module IfTest
|
444
|
+
# Set true when unit-testing.
|
445
|
+
attr_accessor :test_mode
|
446
|
+
alias :test_mode? :test_mode
|
447
|
+
|
448
|
+
|
449
|
+
# Returns a temporary value when unit-testing.
|
450
|
+
def if_test(test_value, non_test_value=nil, &block)
|
451
|
+
if self.test_mode?
|
452
|
+
test_value
|
453
|
+
else
|
454
|
+
if block
|
455
|
+
block.call
|
456
|
+
else
|
457
|
+
non_test_value
|
458
|
+
end
|
459
|
+
end
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
#### IfTest depend: iftest
|
464
|
+
|
465
|
+
#### tempdir
|
466
|
+
require 'tmpdir'
|
467
|
+
# Makes a temporary directory and executes a block and cleans the directory.
|
468
|
+
def with_temp_dir(dir=Dir.tmpdir+"/tmp_#{$$}")
|
469
|
+
require 'fileutils'
|
470
|
+
begin
|
471
|
+
dir = Pathname.new(dir).expand_path
|
472
|
+
dir.mkdir
|
473
|
+
Dir.chdir(dir) { yield(dir) }
|
474
|
+
ensure
|
475
|
+
FileUtils.rm_rf(dir)
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
#### textarea
|
480
|
+
class String
|
481
|
+
|
482
|
+
def textarea_default_cols
|
483
|
+
begin
|
484
|
+
require 'curses'
|
485
|
+
Curses.init_screen
|
486
|
+
Curses.stdscr.maxx-3
|
487
|
+
ensure
|
488
|
+
Curses.close_screen
|
489
|
+
end
|
490
|
+
end
|
491
|
+
private :textarea_default_cols
|
492
|
+
|
493
|
+
# Makes a string textarea-ize.
|
494
|
+
# COLS is adjusted to terminal by default.
|
495
|
+
# String is HTML escaped when ESCAPE is true.
|
496
|
+
def textarea_ize(cols=nil, rows=nil, escape=true)
|
497
|
+
cols ||= textarea_default_cols
|
498
|
+
rows = self.split(/\r?\n/).inject(0){|result, item| result + (item.length/cols+1)}+1 unless rows
|
499
|
+
content = if escape
|
500
|
+
require 'fastesc'
|
501
|
+
self.html_escape
|
502
|
+
else
|
503
|
+
self
|
504
|
+
end
|
505
|
+
"<textarea rows=#{rows} cols=#{cols}>#{content}</textarea>"
|
506
|
+
end
|
507
|
+
|
508
|
+
# Same as textarea_ize. But the string is not escaped.
|
509
|
+
# It is expected that the string is HTML.
|
510
|
+
def textarea_ize_noconv(cols=nil, rows=nil)
|
511
|
+
textarea_ize(cols, rows, false)
|
512
|
+
end
|
513
|
+
|
514
|
+
end
|
515
|
+
|
516
|
+
#### redirect
|
517
|
+
class << IO
|
518
|
+
# Redirect stdout to STDOUT and executes the block.
|
519
|
+
def redirect(stdout)
|
520
|
+
begin
|
521
|
+
stdout_sv = STDOUT.dup
|
522
|
+
STDOUT.reopen(stdout)
|
523
|
+
yield
|
524
|
+
ensure
|
525
|
+
STDOUT.flush
|
526
|
+
STDOUT.reopen(stdout_sv)
|
527
|
+
end
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
#### system_to_string depend:redirect
|
532
|
+
# Similar to `` [backquotes]. If multiple arguments are given, the
|
533
|
+
# second and subsequent arguments are passed as parameters to command
|
534
|
+
# with no shell expansion.
|
535
|
+
require 'tmpdir'
|
536
|
+
require 'fileutils'
|
537
|
+
@@__system_to_string_count__ = 0
|
538
|
+
def system_to_string(*args)
|
539
|
+
begin
|
540
|
+
tmpf = File.join(Dir.tmpdir, "#{$$}-#{@@__system_to_string_count__}")
|
541
|
+
@@__system_to_string_count__ += 1
|
542
|
+
ret = nil
|
543
|
+
open(tmpf,"w") do |f|
|
544
|
+
IO.redirect(f) {
|
545
|
+
system *args
|
546
|
+
}
|
547
|
+
end
|
548
|
+
File.read(tmpf)
|
549
|
+
ensure
|
550
|
+
FileUtils.rm_f tmpf
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
#### EmacsLisp depend: system_to_string
|
555
|
+
module EmacsLisp
|
556
|
+
# Executes an EmacsLisp string by gnudoit.
|
557
|
+
def elisp(lisp)
|
558
|
+
system_to_string("gnudoit", lisp).chomp
|
559
|
+
end
|
560
|
+
|
561
|
+
# Converts a Ruby string to EmacsLisp string.
|
562
|
+
# [imported from el4r]
|
563
|
+
def dump_string(string)
|
564
|
+
dumped = string.dup
|
565
|
+
# \ -> \\
|
566
|
+
dumped.gsub! %r"\\" do '\\\\' end
|
567
|
+
# " -> \"
|
568
|
+
dumped.gsub! %r'"' do '\\"' end
|
569
|
+
# (zero byte) -> \0
|
570
|
+
dumped.gsub! %r'\0' do "\\\0" end
|
571
|
+
%Q'"#{dumped}"'
|
572
|
+
end
|
573
|
+
|
574
|
+
end
|
575
|
+
|
576
|
+
#### flib
|
577
|
+
class Object
|
578
|
+
# Same as File.read. But FILENAME is expanded.
|
579
|
+
def readf(filename)
|
580
|
+
File.read( File.expand_path(filename.to_s) )
|
581
|
+
end
|
582
|
+
|
583
|
+
# Write an object's string form. FILENAME is expanded.
|
584
|
+
def writef(filename)
|
585
|
+
open(File.expand_path(filename.to_s), "w"){|f| f.write(self.to_s)}
|
586
|
+
end
|
587
|
+
end
|
588
|
+
|
589
|
+
#### notify_exit
|
590
|
+
def notify_exit
|
591
|
+
# Notify when the program is exited.
|
592
|
+
at_exit do
|
593
|
+
bell_message "#$0 exited."
|
594
|
+
end
|
595
|
+
end
|
596
|
+
|
597
|
+
#### region
|
598
|
+
class String
|
599
|
+
# Scans a regexp once. Then cut matched part from string. Returns the matched part.
|
600
|
+
def kill_region!(regexp)
|
601
|
+
ret = ""
|
602
|
+
sub!(regexp) {
|
603
|
+
ret = $&
|
604
|
+
""
|
605
|
+
}
|
606
|
+
ret
|
607
|
+
end
|
608
|
+
end
|
609
|
+
|
610
|
+
#### ext
|
611
|
+
class String
|
612
|
+
# Returns a string which is replaced the filename's extension with NEWEXT.
|
613
|
+
def ext(newext=nil)
|
614
|
+
if newext
|
615
|
+
newext[0,1] != '.' and newext="."+newext
|
616
|
+
sub(/\.[^\.]+?$/, newext)
|
617
|
+
else
|
618
|
+
File.extname(self)
|
619
|
+
end
|
620
|
+
end
|
621
|
+
|
622
|
+
# Returns a string which is stripped the filename's extension.
|
623
|
+
def noext
|
624
|
+
sub(/\.[^\.]+$/,'')
|
625
|
+
end
|
626
|
+
end
|
627
|
+
|
628
|
+
#### StructWithType
|
629
|
+
class StructWithType < Struct
|
630
|
+
|
631
|
+
# TODO: document
|
632
|
+
def self.new(*args)
|
633
|
+
|
634
|
+
keys = []
|
635
|
+
types = []
|
636
|
+
args.each_with_index do |x,i|
|
637
|
+
if i%2 == 0
|
638
|
+
keys << x
|
639
|
+
else
|
640
|
+
types << x
|
641
|
+
end
|
642
|
+
end
|
643
|
+
|
644
|
+
unless keys.length > 0 &&
|
645
|
+
types.length > 0 &&
|
646
|
+
keys.length == types.length
|
647
|
+
raise ArgumentError, "#{self}: args.length must be even"
|
648
|
+
end
|
649
|
+
|
650
|
+
|
651
|
+
klass = super(*keys)
|
652
|
+
|
653
|
+
klass.instance_eval do
|
654
|
+
@@__type_dic__ = {}
|
655
|
+
@@__keys__ = keys
|
656
|
+
keys.each_with_index{|k,i| @@__type_dic__[k] = types[i]}
|
657
|
+
end
|
658
|
+
|
659
|
+
klass
|
660
|
+
end
|
661
|
+
|
662
|
+
def initialize(*args)
|
663
|
+
args.each_with_index do |x, i|
|
664
|
+
args[i] = __convert__(@@__keys__[i], x)
|
665
|
+
end
|
666
|
+
|
667
|
+
class << self
|
668
|
+
@@__keys__.each do |k|
|
669
|
+
define_method("#{k}="){|v| self[k]=v}
|
670
|
+
end
|
671
|
+
end
|
672
|
+
|
673
|
+
super *args
|
674
|
+
end
|
675
|
+
|
676
|
+
def __convert__(k,v)
|
677
|
+
__send__(@@__type_dic__[k.to_sym],v)
|
678
|
+
end
|
679
|
+
private :__convert__
|
680
|
+
|
681
|
+
def []=(k,v)
|
682
|
+
v = __convert__(k,v)
|
683
|
+
super(k,v)
|
684
|
+
end
|
685
|
+
|
686
|
+
|
687
|
+
end
|
688
|
+
|
689
|
+
#### ep
|
690
|
+
class String
|
691
|
+
# Expand tilde
|
692
|
+
def ep
|
693
|
+
case self
|
694
|
+
when /^~/
|
695
|
+
File.expand_path(self)
|
696
|
+
else
|
697
|
+
self
|
698
|
+
end
|
699
|
+
end
|
700
|
+
end
|
701
|
+
|
702
|
+
|
703
|
+
#### change_home
|
704
|
+
class File
|
705
|
+
def self.change_home(dir)
|
706
|
+
oldhome = ENV['HOME']
|
707
|
+
begin
|
708
|
+
ENV['HOME'] = dir
|
709
|
+
yield(dir)
|
710
|
+
ensure
|
711
|
+
ENV['HOME'] = oldhome
|
712
|
+
end
|
713
|
+
end
|
714
|
+
end
|
715
|
+
|
716
|
+
#### mapf
|
717
|
+
module Enumerable
|
718
|
+
#
|
719
|
+
# "map function"
|
720
|
+
# enum.mapf(:x)
|
721
|
+
# is short for
|
722
|
+
# enum.map { |elt| elt.x }
|
723
|
+
#
|
724
|
+
def mapf(message)
|
725
|
+
self.map { |elt| elt.send(message) }
|
726
|
+
end
|
727
|
+
end
|
728
|
+
|
729
|
+
#### build_hash
|
730
|
+
module Enumerable
|
731
|
+
#
|
732
|
+
# Like <tt>#map</tt>/<tt>#collect</tt>, but it generates a Hash. The block
|
733
|
+
# is expected to return two values: the key and the value for the new hash.
|
734
|
+
# numbers = (1..3)
|
735
|
+
# squares = numbers.build_hash { |n| [n, n*n] } # 1=>1, 2=>4, 3=>9
|
736
|
+
# sq_roots = numbers.build_hash { |n| [n*n, n] } # 1=>1, 4=>2, 9=>3
|
737
|
+
#
|
738
|
+
def build_hash
|
739
|
+
result = {}
|
740
|
+
self.each do |elt|
|
741
|
+
key, value = yield elt
|
742
|
+
result[key] = value
|
743
|
+
end
|
744
|
+
result
|
745
|
+
end
|
746
|
+
|
747
|
+
end
|
748
|
+
|
749
|
+
#### map_with_index
|
750
|
+
module Enumerable
|
751
|
+
#
|
752
|
+
# Same as Enumerable#map, but the index is yielded as well. See
|
753
|
+
# Enumerable#each_with_index.
|
754
|
+
# puts files.map_with_index { |fn, idx| "#{idx}. #{fn}" }
|
755
|
+
# print "Please select a file (0-#{files.size}): "
|
756
|
+
#
|
757
|
+
def map_with_index
|
758
|
+
result = []
|
759
|
+
self.each_with_index do |elt, idx|
|
760
|
+
result << yield(elt, idx)
|
761
|
+
end
|
762
|
+
result
|
763
|
+
end
|
764
|
+
end
|
765
|
+
|
766
|
+
|
767
|
+
|
768
|
+
#### bug!
|
769
|
+
class ScriptBug < Exception; end
|
770
|
+
|
771
|
+
# Raises ScriptBug exception.
|
772
|
+
def bug!( message = 'must not happen' )
|
773
|
+
raise ScriptBug, "\n[SCRIPT BUG] " + message
|
774
|
+
end
|
775
|
+
|
776
|
+
#### must
|
777
|
+
class Object
|
778
|
+
|
779
|
+
# Assert: type === obj
|
780
|
+
# ex. obj.must Fixnum, Float
|
781
|
+
def must( *args )
|
782
|
+
args.each {|c| return self if c === self }
|
783
|
+
raise TypeError, "wrong arg type '#{self.class}' for required #{args.join('/')}"
|
784
|
+
end
|
785
|
+
|
786
|
+
# Assert: obj.respond_to? meth
|
787
|
+
# ex. obj.must_have :read, :readlines
|
788
|
+
# ex. obj.needed :read, :readlines
|
789
|
+
def must_have( *args )
|
790
|
+
args.each do |m|
|
791
|
+
self.respond_to? m or
|
792
|
+
raise ArgumentError, "receiver #{inspect} does not have '#{m}'"
|
793
|
+
end
|
794
|
+
self
|
795
|
+
end
|
796
|
+
|
797
|
+
alias needed must_have
|
798
|
+
|
799
|
+
# Assert: self == obj
|
800
|
+
def must_be( obj )
|
801
|
+
self == obj or
|
802
|
+
raise ArgumentError, "expected #{obj.inspect} but is #{inspect}"
|
803
|
+
self
|
804
|
+
end
|
805
|
+
|
806
|
+
# Assert: self != nil
|
807
|
+
def must_exist
|
808
|
+
nil? and raise ArgumentError, 'receiver is wrongly nil'
|
809
|
+
end
|
810
|
+
|
811
|
+
end
|
812
|
+
|
813
|
+
|
814
|
+
|
815
|
+
#### Contents
|
816
|
+
class GenericContents
|
817
|
+
require 'forwardable'
|
818
|
+
extend Forwardable
|
819
|
+
methods = String.instance_methods(false) - %w[to_s to_str]
|
820
|
+
def_delegators(:@to_s, *methods)
|
821
|
+
attr :to_s
|
822
|
+
alias :to_str :to_s
|
823
|
+
end
|
824
|
+
|
825
|
+
# str = FileContents.new(filename)
|
826
|
+
class FileContents < GenericContents
|
827
|
+
def initialize(filename)
|
828
|
+
@to_s = File.read(filename)
|
829
|
+
end
|
830
|
+
end
|
831
|
+
|
832
|
+
# str = URIContents.new(uri)
|
833
|
+
class URIContents < GenericContents
|
834
|
+
def initialize(uri)
|
835
|
+
require 'open-uri'
|
836
|
+
@to_s = URI(uri).read
|
837
|
+
end
|
838
|
+
end
|
839
|
+
|
840
|
+
|
841
|
+
#### show_usage
|
842
|
+
# Prints the script's first comment block.
|
843
|
+
def show_usage(msg=nil)
|
844
|
+
name = caller[-1].sub(/:\d+$/, '')
|
845
|
+
$stderr.puts "\nError: #{msg}" if msg
|
846
|
+
$stderr.puts
|
847
|
+
File.open(name) do |f|
|
848
|
+
while line = f.readline and line.sub!(/^# ?/, '')
|
849
|
+
$stderr.puts line
|
850
|
+
end
|
851
|
+
end
|
852
|
+
exit 1
|
853
|
+
end
|
854
|
+
|
855
|
+
#### UnTable
|
856
|
+
# Strip table-related tags in HTML
|
857
|
+
class UnTable
|
858
|
+
# Strip table-related tags in SRC
|
859
|
+
def untable!(src)
|
860
|
+
src.gsub!(%r!</?(table)\b[^>]*>!i,'')
|
861
|
+
# src.gsub!(%r!<t[hd]\b[^>]*>!i,' ')
|
862
|
+
src.gsub!(%r!<t[hd]\b[^>]*>!i,'')
|
863
|
+
src.gsub!(%r!<tr[^>]*>!i,'<br>')
|
864
|
+
src.gsub!(%r!</tr>!i, '')
|
865
|
+
src
|
866
|
+
end
|
867
|
+
|
868
|
+
def untable(src)
|
869
|
+
untable!(src.dup)
|
870
|
+
end
|
871
|
+
end
|
872
|
+
|
873
|
+
|
874
|
+
#### system_safe
|
875
|
+
# mswin32 ruby's `system' workaround.
|
876
|
+
def system_safe(*x)
|
877
|
+
begin
|
878
|
+
system *x
|
879
|
+
rescue
|
880
|
+
end
|
881
|
+
end
|
882
|
+
|
883
|
+
|
884
|
+
#### unproc
|
885
|
+
class Object
|
886
|
+
def unproc(*x)
|
887
|
+
self
|
888
|
+
end
|
889
|
+
end
|
890
|
+
|
891
|
+
class Proc
|
892
|
+
def unproc(*x)
|
893
|
+
call *x
|
894
|
+
end
|
895
|
+
end
|
896
|
+
|
897
|
+
#### ConfigScript depend: set_attr, build_hash, unproc
|
898
|
+
require 'forwardable'
|
899
|
+
class ConfigScript
|
900
|
+
extend Forwardable
|
901
|
+
include Enumerable
|
902
|
+
def initialize(arg)
|
903
|
+
unless Hash === arg
|
904
|
+
eval(readf(arg.to_s))
|
905
|
+
arg = instance_variables.map{|iv|
|
906
|
+
[iv[1..-1], instance_variable_get(iv)]
|
907
|
+
}.build_hash{|kv| kv}
|
908
|
+
end
|
909
|
+
|
910
|
+
s_class = class << self; self end
|
911
|
+
arg.each do |k,v|
|
912
|
+
if Symbol === k
|
913
|
+
arg.delete k
|
914
|
+
k = k.to_s
|
915
|
+
arg[k]=v
|
916
|
+
end
|
917
|
+
|
918
|
+
s_class.class_eval do
|
919
|
+
define_method(k) {arg[k].unproc}
|
920
|
+
define_method("#{k}=") {|v| arg[k]=v}
|
921
|
+
end
|
922
|
+
end
|
923
|
+
@hash = arg
|
924
|
+
end
|
925
|
+
|
926
|
+
alias :[] :__send__
|
927
|
+
def_delegators :@hash, :keys, :each
|
928
|
+
|
929
|
+
def []=(k,v)
|
930
|
+
@hash[k.to_s]=v
|
931
|
+
end
|
932
|
+
|
933
|
+
def method_missing(name, *args, &block)
|
934
|
+
nil
|
935
|
+
end
|
936
|
+
end
|
937
|
+
|
938
|
+
|
939
|
+
#### dump
|
940
|
+
class Numeric
|
941
|
+
def dump() self end
|
942
|
+
end
|
943
|
+
|
944
|
+
#### __funcall
|
945
|
+
class Object
|
946
|
+
# Call a method even if it is private.
|
947
|
+
def __funcall(meth, *args, &block)
|
948
|
+
m = method(meth)
|
949
|
+
instance_eval { m.call(*args, &block) }
|
950
|
+
end
|
951
|
+
end
|
952
|
+
|
953
|
+
|
954
|
+
#### scriptdir
|
955
|
+
class Dir
|
956
|
+
def Dir.scriptdir
|
957
|
+
File.dirname(File.expand_path(caller(1)[0].scan(/^(.+?):\d+:/).to_s))
|
958
|
+
end
|
959
|
+
end
|
960
|
+
|
961
|
+
#### URLConv
|
962
|
+
module URLConv
|
963
|
+
def relative2absolute(html, baseurl)
|
964
|
+
# relativelink to absolute link
|
965
|
+
html.gsub!(/(href|src)=['"]?\s*(.*?)\s*?['"]?(>|\s)/mi) do |x|
|
966
|
+
begin
|
967
|
+
uri = URI.parse($2)
|
968
|
+
|
969
|
+
absolute_url = if uri.scheme.nil?
|
970
|
+
URI.join(baseurl, $2)
|
971
|
+
else
|
972
|
+
$2
|
973
|
+
end
|
974
|
+
|
975
|
+
"#{$1}=\"#{absolute_url}\"#{$3}"
|
976
|
+
rescue URI::InvalidURIError
|
977
|
+
next
|
978
|
+
end
|
979
|
+
end
|
980
|
+
end
|
981
|
+
end
|
982
|
+
|
983
|
+
#### END OF LIBRARY
|
984
|
+
# To add a new code (mylib-rb-add)
|
985
|
+
|
986
|
+
#### test
|
987
|
+
if __FILE__==$0
|
988
|
+
|
989
|
+
class MylibCommand
|
990
|
+
def initialize
|
991
|
+
@lines = File.readlines($0)
|
992
|
+
end
|
993
|
+
|
994
|
+
def run
|
995
|
+
meth = "do_#{ARGV[0]}"
|
996
|
+
if respond_to?(meth)
|
997
|
+
__send__ meth
|
998
|
+
else
|
999
|
+
do_list
|
1000
|
+
end
|
1001
|
+
end
|
1002
|
+
|
1003
|
+
def do_list
|
1004
|
+
@lines.select{|line|
|
1005
|
+
line =~ /^ *(class|module|def|attr|attr_reader|attr_writer|attr_accessor) |^#### /
|
1006
|
+
}.display
|
1007
|
+
end
|
1008
|
+
|
1009
|
+
def do_pieces
|
1010
|
+
@lines.inject([]){|result, line|
|
1011
|
+
if line =~ /^#### (.+?)/
|
1012
|
+
result + ["#{$1}\n"]
|
1013
|
+
else
|
1014
|
+
result
|
1015
|
+
end
|
1016
|
+
}.display
|
1017
|
+
end
|
1018
|
+
alias :do_piece :do_pieces
|
1019
|
+
end
|
1020
|
+
|
1021
|
+
MylibCommand.new.run
|
1022
|
+
end
|
1023
|
+
|