bitclust-core 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (127) hide show
  1. data/ChangeLog +2907 -0
  2. data/Gemfile +7 -0
  3. data/README +21 -0
  4. data/Rakefile +20 -0
  5. data/bin/bitclust +14 -0
  6. data/bin/refe +36 -0
  7. data/bitclust-dev.gemspec +33 -0
  8. data/bitclust.gemspec +30 -0
  9. data/config.in +23 -0
  10. data/config.ru +48 -0
  11. data/config.ru.sample +31 -0
  12. data/data/bitclust/catalog/ja_JP.EUC-JP +78 -0
  13. data/data/bitclust/catalog/ja_JP.UTF-8 +78 -0
  14. data/data/bitclust/template.lillia/class +98 -0
  15. data/data/bitclust/template.lillia/class-index +28 -0
  16. data/data/bitclust/template.lillia/doc +48 -0
  17. data/data/bitclust/template.lillia/layout +19 -0
  18. data/data/bitclust/template.lillia/library +129 -0
  19. data/data/bitclust/template.lillia/library-index +32 -0
  20. data/data/bitclust/template.lillia/method +20 -0
  21. data/data/bitclust/template.lillia/rd_file +6 -0
  22. data/data/bitclust/template.offline/class +67 -0
  23. data/data/bitclust/template.offline/class-index +28 -0
  24. data/data/bitclust/template.offline/doc +13 -0
  25. data/data/bitclust/template.offline/function +22 -0
  26. data/data/bitclust/template.offline/function-index +24 -0
  27. data/data/bitclust/template.offline/layout +18 -0
  28. data/data/bitclust/template.offline/library +87 -0
  29. data/data/bitclust/template.offline/library-index +32 -0
  30. data/data/bitclust/template.offline/method +21 -0
  31. data/data/bitclust/template.offline/rd_file +6 -0
  32. data/data/bitclust/template/class +133 -0
  33. data/data/bitclust/template/class-index +30 -0
  34. data/data/bitclust/template/doc +14 -0
  35. data/data/bitclust/template/function +21 -0
  36. data/data/bitclust/template/function-index +25 -0
  37. data/data/bitclust/template/layout +19 -0
  38. data/data/bitclust/template/library +89 -0
  39. data/data/bitclust/template/library-index +35 -0
  40. data/data/bitclust/template/method +24 -0
  41. data/data/bitclust/template/opensearchdescription +10 -0
  42. data/data/bitclust/template/search +57 -0
  43. data/lib/bitclust.rb +9 -0
  44. data/lib/bitclust/app.rb +129 -0
  45. data/lib/bitclust/classentry.rb +425 -0
  46. data/lib/bitclust/compat.rb +39 -0
  47. data/lib/bitclust/completion.rb +531 -0
  48. data/lib/bitclust/crossrubyutils.rb +91 -0
  49. data/lib/bitclust/database.rb +181 -0
  50. data/lib/bitclust/docentry.rb +83 -0
  51. data/lib/bitclust/entry.rb +223 -0
  52. data/lib/bitclust/exception.rb +38 -0
  53. data/lib/bitclust/functiondatabase.rb +115 -0
  54. data/lib/bitclust/functionentry.rb +81 -0
  55. data/lib/bitclust/functionreferenceparser.rb +76 -0
  56. data/lib/bitclust/htmlutils.rb +80 -0
  57. data/lib/bitclust/interface.rb +87 -0
  58. data/lib/bitclust/libraryentry.rb +211 -0
  59. data/lib/bitclust/lineinput.rb +165 -0
  60. data/lib/bitclust/messagecatalog.rb +95 -0
  61. data/lib/bitclust/methoddatabase.rb +401 -0
  62. data/lib/bitclust/methodentry.rb +202 -0
  63. data/lib/bitclust/methodid.rb +209 -0
  64. data/lib/bitclust/methodsignature.rb +82 -0
  65. data/lib/bitclust/nameutils.rb +236 -0
  66. data/lib/bitclust/parseutils.rb +60 -0
  67. data/lib/bitclust/preprocessor.rb +273 -0
  68. data/lib/bitclust/rdcompiler.rb +507 -0
  69. data/lib/bitclust/refsdatabase.rb +66 -0
  70. data/lib/bitclust/requesthandler.rb +330 -0
  71. data/lib/bitclust/ridatabase.rb +349 -0
  72. data/lib/bitclust/rrdparser.rb +522 -0
  73. data/lib/bitclust/runner.rb +143 -0
  74. data/lib/bitclust/screen.rb +554 -0
  75. data/lib/bitclust/searcher.rb +518 -0
  76. data/lib/bitclust/server.rb +59 -0
  77. data/lib/bitclust/simplesearcher.rb +84 -0
  78. data/lib/bitclust/subcommand.rb +746 -0
  79. data/lib/bitclust/textutils.rb +51 -0
  80. data/lib/bitclust/version.rb +3 -0
  81. data/packer.rb +224 -0
  82. data/refe2.gemspec +29 -0
  83. data/server.exe +0 -0
  84. data/server.exy +159 -0
  85. data/server.rb +10 -0
  86. data/setup.rb +1596 -0
  87. data/standalone.rb +193 -0
  88. data/test/run_test.rb +15 -0
  89. data/test/test_bitclust.rb +81 -0
  90. data/test/test_entry.rb +39 -0
  91. data/test/test_functiondatabase.rb +55 -0
  92. data/test/test_libraryentry.rb +31 -0
  93. data/test/test_methoddatabase.rb +81 -0
  94. data/test/test_methodsignature.rb +14 -0
  95. data/test/test_nameutils.rb +324 -0
  96. data/test/test_preprocessor.rb +84 -0
  97. data/test/test_rdcompiler.rb +534 -0
  98. data/test/test_refsdatabase.rb +76 -0
  99. data/test/test_rrdparser.rb +26 -0
  100. data/test/test_runner.rb +102 -0
  101. data/test/test_simplesearcher.rb +48 -0
  102. data/theme/default/images/external.png +0 -0
  103. data/theme/default/rurema.png +0 -0
  104. data/theme/default/style.css +288 -0
  105. data/theme/default/test.css +254 -0
  106. data/theme/lillia/rurema.png +0 -0
  107. data/theme/lillia/style.css +331 -0
  108. data/theme/lillia/test.css +254 -0
  109. data/tools/bc-ancestors.rb +153 -0
  110. data/tools/bc-checkparams.rb +246 -0
  111. data/tools/bc-classes.rb +80 -0
  112. data/tools/bc-convert.rb +165 -0
  113. data/tools/bc-list.rb +63 -0
  114. data/tools/bc-methods.rb +171 -0
  115. data/tools/bc-preproc.rb +42 -0
  116. data/tools/bc-rdoc.rb +343 -0
  117. data/tools/bc-tochm.rb +301 -0
  118. data/tools/bc-tohtml.rb +125 -0
  119. data/tools/bc-tohtmlpackage.rb +241 -0
  120. data/tools/check-signature.rb +19 -0
  121. data/tools/forall-ruby.rb +20 -0
  122. data/tools/gencatalog.rb +69 -0
  123. data/tools/statrefm.rb +98 -0
  124. data/tools/stattodo.rb +150 -0
  125. data/tools/update-database.rb +146 -0
  126. data/view.cgi +6 -0
  127. metadata +222 -0
@@ -0,0 +1,518 @@
1
+ #
2
+ # bitclust/searcher.rb
3
+ #
4
+ # Copyright (C) 2006-2007 Minero Aoki
5
+ #
6
+ # This program is free software.
7
+ # You can distribute/modify this program under the Ruby License.
8
+ #
9
+
10
+ require 'bitclust/methoddatabase'
11
+ require 'bitclust/functiondatabase'
12
+ require 'bitclust/nameutils'
13
+ require 'bitclust/methodid'
14
+ require 'bitclust/exception'
15
+ require 'uri'
16
+ require 'rbconfig'
17
+ require 'optparse'
18
+ require 'nkf'
19
+
20
+ module BitClust
21
+
22
+ class Searcher
23
+
24
+ include NameUtils
25
+
26
+ def initialize
27
+ cmd = File.basename($0, '.*')
28
+ @dblocation = nil
29
+ @name = (/\Abitclust/ =~ cmd ? 'bitclust search' : 'refe')
30
+ @describe_all = false
31
+ @linep = false
32
+ @encoding = nil
33
+ @target_type = nil
34
+ @listen_url = nil
35
+ @foreground = false
36
+ @parser = OptionParser.new {|opt|
37
+ opt.banner = "Usage: #{@name} <pattern>"
38
+ unless cmd == 'bitclust'
39
+ opt.on('-d', '--database=URL', "Database location (default: #{dblocation_name()})") {|loc|
40
+ url = (/:/ =~ loc) ? loc : "file://#{File.expand_path(loc)}"
41
+ @dblocation = URI.parse(url)
42
+ }
43
+ opt.on('--server=URL', 'Spawns BitClust database server and listen URL. Requires --database option with local path.') {|url|
44
+ require 'bitclust/server' # require here for speed
45
+ @listen_url = url
46
+ }
47
+ opt.on('--foreground', 'Do not become daemon (for debug)') {
48
+ @foreground = true
49
+ }
50
+ end
51
+ opt.on('-a', '--all', 'Prints descriptions for all matched entries.') {
52
+ @describe_all = true
53
+ }
54
+ opt.on('-l', '--line', 'Prints one entry in one line.') {
55
+ @linep = true
56
+ }
57
+ opt.on('-e', '--encoding=ENCODING', 'Select encoding.') {|enc|
58
+ @encoding = enc
59
+ }
60
+ opt.on('--class', 'Search class or module.') {
61
+ @target_type = :class
62
+ }
63
+ opt.on('--version', 'Prints version and quit.') {
64
+ if cmd == 'bitclust'
65
+ puts "BitClust -- Next generation reference manual interface"
66
+ exit 1
67
+ else
68
+ puts "ReFe version 2"
69
+ exit 1
70
+ end
71
+ }
72
+ opt.on('--help', 'Prints this message and quit.') {
73
+ puts opt.help
74
+ exit 0
75
+ }
76
+ }
77
+ end
78
+
79
+ attr_reader :parser
80
+
81
+ def parse(argv)
82
+ @parser.parse! argv
83
+ if @listen_url # server mode
84
+ server_mode_check argv
85
+ else
86
+ refe_mode_check argv
87
+ end
88
+ end
89
+
90
+ def exec(db, argv)
91
+ if @listen_url
92
+ spawn_server db
93
+ else
94
+ search_pattern db, argv
95
+ end
96
+ end
97
+
98
+ private
99
+
100
+ def server_mode_check(argv)
101
+ if @dblocation
102
+ unless @dblocation.scheme == 'file'
103
+ $stderr.puts "Give local path to --database option on server mode"
104
+ exit 1
105
+ end
106
+ else
107
+ unless dbpath()
108
+ $stderr.puts "no local database given; use --database option with local database path"
109
+ exit 1
110
+ end
111
+ end
112
+ unless argv.empty?
113
+ $stderr.puts "too many arguments"
114
+ exit 1
115
+ end
116
+ end
117
+
118
+ def refe_mode_check(argv)
119
+ case @target_type
120
+ when :class
121
+ unless argv.size == 1
122
+ $stderr.puts "--class option requires only 1 argument"
123
+ exit 1
124
+ end
125
+ else
126
+ if argv.size > 3
127
+ $stderr.puts "too many arguments (#{argv.size} for 2)"
128
+ exit 1
129
+ end
130
+ end
131
+ # FIXME
132
+ #compiler = RDCompiler::Text.new
133
+ compiler = Plain.new
134
+ @view = TerminalView.new(compiler,
135
+ {:describe_all => @describe_all,
136
+ :line => @linep,
137
+ :encoding => @encoding})
138
+ end
139
+
140
+ def spawn_server(db)
141
+ Server.new(new_local_database(db)).listen @listen_url, @foreground
142
+ end
143
+
144
+ def new_local_database(db)
145
+ return db if db
146
+ path = @dblocation ? @dblocation.path : dbpath()
147
+ MethodDatabase.new(path)
148
+ end
149
+
150
+ def new_database
151
+ db = MethodDatabase.connect(@dblocation || dblocation())
152
+ @view.database = db if @view
153
+ db
154
+ end
155
+
156
+ def dblocation_name
157
+ find_dblocation() or 'NONE'
158
+ end
159
+
160
+ def dblocation
161
+ find_dblocation() or
162
+ raise InvalidDatabase, "database not exist or invalid database"
163
+ end
164
+
165
+ def find_dblocation
166
+ %w( REFE2_SERVER BITCLUST_SERVER ).each do |key|
167
+ return URI.parse(ENV[key]) if ENV[key]
168
+ end
169
+ if path = dbpath()
170
+ URI.parse("file://#{path}")
171
+ else
172
+ nil
173
+ end
174
+ end
175
+
176
+ def dbpath
177
+ env_dbpath() || default_dbpath()
178
+ end
179
+
180
+ def env_dbpath
181
+ [ 'REFE2_DATADIR', 'BITCLUST_DATADIR' ].each do |key|
182
+ if ENV.key?(key)
183
+ unless MethodDatabase.datadir?(ENV[key])
184
+ raise InvalidDatabase, "environment variable #{key} given but #{ENV[key]} is not a valid BitClust database"
185
+ end
186
+ return ENV[key]
187
+ end
188
+ end
189
+ nil
190
+ end
191
+
192
+ def default_dbpath
193
+ datadir = ::RbConfig::CONFIG['datadir']
194
+ [ "#{datadir}/refe2", "#{datadir}/bitclust" ].each do |path|
195
+ return path if MethodDatabase.datadir?(path)
196
+ end
197
+ nil
198
+ end
199
+
200
+ def search_pattern(db, argv)
201
+ db ||= new_database()
202
+ @view.database ||= db if @view
203
+ case @target_type || db
204
+ when :class
205
+ find_class db, argv[0]
206
+ when FunctionDatabase
207
+ case argv.size
208
+ when 0
209
+ show_all_functions db
210
+ when 1
211
+ find_function db, argv[0]
212
+ else
213
+ raise "must not happen: #{argv.size}"
214
+ end
215
+ else
216
+ case argv.size
217
+ when 0
218
+ show_all_classes db
219
+ when 1
220
+ find_class_or_method db, argv[0]
221
+ when 2
222
+ c, m = *argv
223
+ find_method db, c, nil, m
224
+ when 3
225
+ c, t, m = *argv
226
+ check_method_type t
227
+ find_method db, c, t, m
228
+ else
229
+ raise "must not happen: #{argv.size}"
230
+ end
231
+ end
232
+ end
233
+
234
+ def show_all_classes(db)
235
+ @view.show_class db.classes
236
+ end
237
+
238
+ def show_all_functions(db)
239
+ @view.show_function db.functions
240
+ end
241
+
242
+ def find_class(db, c)
243
+ @view.show_class db.search_classes(c)
244
+ end
245
+
246
+ def find_method(db, c, t, m)
247
+ @view.show_method db.search_methods(MethodNamePattern.new(c, t, m))
248
+ end
249
+
250
+ def find_function(db, f)
251
+ @view.show_function db.search_functions(f)
252
+ end
253
+
254
+ def check_method_type(t)
255
+ if t == '$'
256
+ raise InvalidKey, "'$' cannot be used as method type"
257
+ end
258
+ unless typemark?(t)
259
+ raise InvalidKey, "unknown method type: #{t.inspect}"
260
+ end
261
+ end
262
+
263
+ def find_class_or_method(db, pattern)
264
+ case pattern
265
+ when /\A\$/ # Special variable.
266
+ find_method db, 'Kernel', '$', pattern.sub(/\A\$/, '')
267
+ when /[\#,]\.|\.[\#,]|[\#\.\,]/ # method spec
268
+ find_method db, *parse_method_spec_pattern(pattern)
269
+ when /::/ # Class name or constant name.
270
+ find_constant db, pattern
271
+ when /\A[A-Z]/ # Method name or class name, but class name is better.
272
+ begin
273
+ find_class db, pattern
274
+ rescue ClassNotFound
275
+ find_method db, nil, nil, pattern
276
+ end
277
+ else # No hint. Method name or class name.
278
+ begin
279
+ find_method db, nil, nil, pattern
280
+ rescue MethodNotFound
281
+ find_class db, pattern
282
+ end
283
+ end
284
+ end
285
+
286
+ def find_constant(db, pattern)
287
+ # class lookup is faster
288
+ find_class db, pattern
289
+ rescue ClassNotFound
290
+ cnames = pattern.split(/::/)
291
+ name = cnames.pop
292
+ find_method db, cnames.join('::'), '::', name
293
+ end
294
+
295
+ def parse_method_spec_pattern(pat)
296
+ _m, _t, _c = pat.reverse.split(/([\#,]\.|\.[\#,]|[\#\.\,])/, 2)
297
+ c = _c.reverse
298
+ t = _t.tr(',', '#').sub(/\#\./, '.#')
299
+ m = _m.reverse
300
+ return c, t, m
301
+ end
302
+
303
+ end
304
+
305
+
306
+ class Plain
307
+ def compile(src)
308
+ src
309
+ end
310
+ end
311
+
312
+
313
+ class TerminalView
314
+
315
+ def initialize(compiler, opts)
316
+ @compiler = compiler
317
+ @describe_all = opts[:describe_all]
318
+ @line = opts[:line]
319
+ @encoding = opts[:encoding]
320
+ @database = nil
321
+ end
322
+
323
+ attr_accessor :database
324
+
325
+ def show_class(cs)
326
+ if cs.size == 1
327
+ if @line
328
+ print_names [cs.first.label]
329
+ else
330
+ describe_class cs.first
331
+ end
332
+ else
333
+ if @describe_all
334
+ cs.sort.each do |c|
335
+ describe_class c
336
+ end
337
+ else
338
+ print_names cs.map {|c| c.labels }.flatten
339
+ end
340
+ end
341
+ end
342
+
343
+ def show_method(result)
344
+ if result.determined?
345
+ if @line
346
+ print_names result.names
347
+ else
348
+ describe_method result.record
349
+ end
350
+ else
351
+ if @describe_all
352
+ result.each_record do |rec|
353
+ describe_method rec
354
+ end
355
+ else
356
+ print_names result.names
357
+ end
358
+ end
359
+ end
360
+
361
+ def show_function(fs)
362
+ if fs.size == 1
363
+ if @line
364
+ print_names [fs.first.label]
365
+ else
366
+ describe_function fs.first
367
+ end
368
+ else
369
+ if @describe_all
370
+ fs.sort.each do |f|
371
+ describe_function f
372
+ end
373
+ else
374
+ print_names fs.map {|f| f.label }
375
+ end
376
+ end
377
+ end
378
+
379
+ private
380
+
381
+ def print_names(names)
382
+ if @line
383
+ names.sort.each do |n|
384
+ puts n
385
+ end
386
+ else
387
+ print_packed_names names.sort
388
+ end
389
+ end
390
+
391
+ def print_packed_names(names)
392
+ max = terminal_column()
393
+ buf = ''
394
+ names.each do |name|
395
+ if buf.size + name.size + 1 > max
396
+ if buf.empty?
397
+ puts name
398
+ next
399
+ end
400
+ puts buf
401
+ buf = ''
402
+ end
403
+ buf << name << ' '
404
+ end
405
+ puts buf unless buf.empty?
406
+ end
407
+
408
+ def terminal_column
409
+ (ENV['COLUMNS'] || 70).to_i
410
+ end
411
+
412
+ def describe_class(c)
413
+ if c.alias?
414
+ describe_class(c.aliasof)
415
+ return
416
+ end
417
+
418
+ unless c.library.name == '_builtin'
419
+ puts "require '#{c.library.name}'"
420
+ puts
421
+ end
422
+ puts "#{c.type} #{c.name}#{c.superclass ? " < #{c.superclass.name}" : ''}"
423
+ unless c.included.empty?
424
+ puts
425
+ c.included.each do |mod|
426
+ puts "include #{mod.name}"
427
+ end
428
+ end
429
+ unless c.aliases.empty?
430
+ puts
431
+ c.aliases.each do |al|
432
+ puts "alias #{al.name}"
433
+ end
434
+ end
435
+ unless c.source.strip.empty?
436
+ puts
437
+ puts @compiler.compile(c.source.strip)
438
+ end
439
+ end
440
+
441
+ def describe_method(rec)
442
+ unless rec.entry.library.name == '_builtin'
443
+ puts "require '#{rec.entry.library.name}'"
444
+ end
445
+ # FIXME: replace method signature by method spec
446
+ if rec.method_of_alias_class?
447
+ rec.specs.each do |spec|
448
+ puts "#{rec.origin.klass}#{rec.origin.type}#{spec.method} (#{spec.klass} is an alias of #{rec.origin.klass})"
449
+ end
450
+ elsif rec.inherited_method?
451
+ rec.specs.each do |spec|
452
+ puts "#{spec.klass}\t< #{rec.origin.klass}#{rec.origin.type}#{spec.method}"
453
+ end
454
+ else
455
+ rec.names.each do |name|
456
+ puts name
457
+ end
458
+ end
459
+
460
+ puts @compiler.compile(rec.entry.source.strip)
461
+ puts
462
+ end
463
+
464
+ def describe_function(f)
465
+ puts "#{f.type_label} #{f.name}"
466
+ puts f.header
467
+ puts @compiler.compile(f.source.strip)
468
+ puts
469
+ end
470
+
471
+ def puts(*args)
472
+ super(*args.collect {|arg| convert(arg)})
473
+ end
474
+
475
+ def convert(string)
476
+ return string if @database.nil?
477
+ _output_encoding = output_encoding
478
+ return string if _output_encoding.nil?
479
+ input_nkf_option = encoding_to_nkf_option(@database.encoding)
480
+ output_nkf_option = encoding_to_nkf_option(_output_encoding)
481
+ if input_nkf_option and output_nkf_option
482
+ NKF.nkf("-#{input_nkf_option.upcase}#{output_nkf_option}", string)
483
+ else
484
+ string
485
+ end
486
+ end
487
+
488
+ def output_encoding
489
+ return @encoding if @encoding
490
+
491
+ locale = ENV["LC_ALL"] || ENV["LC_MESSAGE"] || ENV["LANG"]
492
+ case locale
493
+ when /\.([a-z\d\-]+)\z/i
494
+ $1
495
+ else
496
+ nil
497
+ end
498
+ end
499
+
500
+ def encoding_to_nkf_option(encoding)
501
+ return nil if encoding.nil?
502
+ case encoding
503
+ when /\A(?:euc[-_]?jp|ujis)\z/i
504
+ "e"
505
+ when /\Autf[-_]?8\z/i
506
+ "w"
507
+ when /\As(?:hift[-_]?)?jis\z/i
508
+ "s"
509
+ when /\Aiso-2022-jp\z/i
510
+ "j"
511
+ else
512
+ nil
513
+ end
514
+ end
515
+
516
+ end
517
+
518
+ end