bitclust-core 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +7 -0
  2. data/ChangeLog +7 -0
  3. data/Gemfile +1 -0
  4. data/bitclust.gemspec +1 -0
  5. data/data/bitclust/template.offline/class +1 -1
  6. data/lib/bitclust/crossrubyutils.rb +2 -2
  7. data/lib/bitclust/methodentry.rb +1 -2
  8. data/lib/bitclust/progress_bar.rb +7 -0
  9. data/lib/bitclust/rdcompiler.rb +1 -1
  10. data/lib/bitclust/runner.rb +46 -32
  11. data/lib/bitclust/searcher.rb +14 -13
  12. data/lib/bitclust/silent_progress_bar.rb +17 -0
  13. data/lib/bitclust/subcommand.rb +27 -0
  14. data/lib/bitclust/subcommands/ancestors_command.rb +145 -0
  15. data/lib/bitclust/subcommands/chm_command.rb +268 -0
  16. data/lib/bitclust/subcommands/classes_command.rb +73 -0
  17. data/lib/bitclust/subcommands/extract_command.rb +55 -0
  18. data/lib/bitclust/subcommands/htmlfile_command.rb +105 -0
  19. data/lib/bitclust/subcommands/init_command.rb +29 -30
  20. data/lib/bitclust/subcommands/list_command.rb +39 -41
  21. data/lib/bitclust/subcommands/lookup_command.rb +71 -73
  22. data/lib/bitclust/subcommands/methods_command.rb +159 -0
  23. data/lib/bitclust/subcommands/preproc_command.rb +35 -0
  24. data/lib/bitclust/subcommands/property_command.rb +47 -48
  25. data/lib/bitclust/subcommands/query_command.rb +12 -18
  26. data/lib/bitclust/subcommands/server_command.rb +180 -182
  27. data/lib/bitclust/subcommands/setup_command.rb +85 -89
  28. data/lib/bitclust/subcommands/statichtml_command.rb +276 -0
  29. data/lib/bitclust/subcommands/update_command.rb +39 -41
  30. data/lib/bitclust/version.rb +1 -1
  31. data/test/test_bitclust.rb +1 -1
  32. data/test/test_rdcompiler.rb +1 -1
  33. data/test/test_runner.rb +7 -14
  34. metadata +120 -114
@@ -0,0 +1,268 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'bitclust'
4
+ require 'bitclust/subcommand'
5
+
6
+ require 'fileutils'
7
+ # TODO Remove this line when we drop 1.8 support
8
+ require 'kconv'
9
+ require 'bitclust/progress_bar'
10
+
11
+ module BitClust
12
+ module Subcommands
13
+ class ChmCommand < Subcommand
14
+
15
+ HHP_SKEL = <<EOS
16
+ [OPTIONS]
17
+ Compatibility=1.1 or later
18
+ Compiled file=refm.chm
19
+ Contents file=refm.hhc
20
+ Default Window=titlewindow
21
+ Default topic=doc/index.html
22
+ Display compile progress=No
23
+ Error log file=refm.log
24
+ Full-text search=Yes
25
+ Index file=refm.hhk
26
+ Language=0x411 日本語 (日本)
27
+ Title=Rubyリファレンスマニュアル
28
+
29
+ [WINDOWS]
30
+ titlewindow="Rubyリファレンスマニュアル","refm.hhc","refm.hhk","doc/index.html","doc/index.html",,,,,0x21420,,0x387e,,,,,,,,0
31
+
32
+ [FILES]
33
+ <%= @html_files.join("\n") %>
34
+ EOS
35
+
36
+ HHC_SKEL = <<EOS
37
+ <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
38
+ <HTML>
39
+ <HEAD>
40
+ </HEAD>
41
+ <BODY>
42
+ <UL><% [:library].each do |k| %>
43
+ <%= @sitemap[k].to_html %>
44
+ <% end %></UL>
45
+ </BODY>
46
+ </HTML>
47
+ EOS
48
+
49
+ HHK_SKEL = <<EOS
50
+ <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
51
+ <HTML>
52
+ <HEAD>
53
+ </HEAD>
54
+ <BODY>
55
+ <UL><% @index_contents.sort.each do |content| %>
56
+ <%= content.to_html %>
57
+ <% end %></UL>
58
+ </BODY>
59
+ </HTML>
60
+ EOS
61
+
62
+ class Sitemap
63
+ def initialize(name, local = nil)
64
+ @name = name
65
+ @contents = Content.new(name, local)
66
+ end
67
+
68
+ def method_missing(name, *args, &block)
69
+ @contents.send(name, *args, &block)
70
+ end
71
+
72
+ class Content
73
+ include Enumerable
74
+ include ERB::Util
75
+
76
+ def initialize(name, local = nil)
77
+ @name = name
78
+ @local = local
79
+ @contents = []
80
+ end
81
+ attr_reader :name, :local, :contents
82
+
83
+ def [](index)
84
+ @contents[index]
85
+ end
86
+
87
+ def <<(content)
88
+ @contents << content
89
+ end
90
+
91
+ def <=>(other)
92
+ @name <=> other.name
93
+ end
94
+
95
+ def each
96
+ @contents.each do |content|
97
+ yield content
98
+ end
99
+ end
100
+
101
+ def to_html
102
+ str = "<LI> <OBJECT type=\"text/sitemap\">\n"
103
+ str << " <param name=\"Name\" value=\"<%=h @name%>\">\n"
104
+ if @local
105
+ str << " <param name=\"Local\" value=\"<%=@local%>\">\n"
106
+ end
107
+ str << " </OBJECT>\n"
108
+ unless contents.empty?
109
+ str << "<UL>\n"
110
+ @contents.each do |content|
111
+ str << content.to_html
112
+ end
113
+ str << "</UL>\n"
114
+ end
115
+ ERB.new(str).result(binding)
116
+ end
117
+ end
118
+ end
119
+
120
+ class URLMapperEx < URLMapper
121
+ def library_url(name)
122
+ if name == '/'
123
+ "/library/index.html"
124
+ else
125
+ "/library/#{encodename_fs(name)}.html"
126
+ end
127
+ end
128
+
129
+ def class_url(name)
130
+ "/class/#{encodename_fs(name)}.html"
131
+ end
132
+
133
+ def method_url(spec)
134
+ cname, tmark, mname = *split_method_spec(spec)
135
+ "/method/#{encodename_fs(cname)}/#{typemark2char(tmark)}/#{encodename_fs(mname)}.html"
136
+ end
137
+
138
+ def document_url(name)
139
+ "/doc/#{encodename_fs(name)}.html"
140
+ end
141
+ end
142
+
143
+ def initialize
144
+ super
145
+ @sitemap = {
146
+ :library => Sitemap.new('ライブラリ', 'library/index.html'),
147
+ }
148
+ @sitemap[:library] << Sitemap::Content.new('標準ライブラリ', 'library/_builtin.html')
149
+ @sitemap[:library] << Sitemap::Content.new('添付ライブラリ')
150
+ @stdlibs = {}
151
+ @index_contents = []
152
+ @parser.banner = "Usage: #{File.basename($0, '.*')} chm [options]"
153
+ @parser.on('-o', '--outputdir=PATH', 'Output directory') do |path|
154
+ begin
155
+ @outputdir = Pathname.new(path).realpath
156
+ rescue Errno::ENOENT
157
+ FileUtils.mkdir_p(path, :verbose => true)
158
+ retry
159
+ end
160
+ end
161
+ end
162
+
163
+ def exec(argv, options)
164
+ create_manager_config
165
+ prefix = options[:prefix]
166
+ db = MethodDatabase.new(prefix.to_s)
167
+ manager = ScreenManager.new(@manager_config)
168
+ @html_files = []
169
+ db.transaction do
170
+ methods = {}
171
+ db.methods.each do |entry|
172
+ method_name = entry.klass.name + entry.typemark + entry.name
173
+ (methods[method_name] ||= []) << entry
174
+ end
175
+
176
+ entries = db.docs + db.libraries.sort + db.classes.sort + methods.values.sort
177
+ pb = ProgressBar.new('entry', entries.size)
178
+ entries.each do |c|
179
+ filename = create_html_file(c, manager, @outputdir, db)
180
+ @html_files << filename
181
+ e = c.is_a?(Array) ? c.sort.first : c
182
+ case e.type_id
183
+ when :library
184
+ content = Sitemap::Content.new(e.name.to_s, filename)
185
+ if e.name.to_s != '_builtin'
186
+ @sitemap[:library][1] << content
187
+ @stdlibs[e.name.to_s] = content
188
+ end
189
+ @index_contents << Sitemap::Content.new(e.name.to_s, filename)
190
+ when :class
191
+ content = Sitemap::Content.new(e.name.to_s, filename)
192
+ if e.library.name.to_s == '_builtin'
193
+ @sitemap[:library][0] << content
194
+ else
195
+ @stdlibs[e.library.name.to_s] << content
196
+ end
197
+ @index_contents << Sitemap::Content.new("#{e.name} (#{e.library.name})", filename)
198
+ when :method
199
+ e.names.each do |e_name|
200
+ name = e.typename == :special_variable ? "$#{e_name}" : e_name
201
+ @index_contents <<
202
+ Sitemap::Content.new("#{name} (#{e.library.name} - #{e.klass.name})", filename)
203
+ @index_contents <<
204
+ Sitemap::Content.new("#{e.klass.name}#{e.typemark}#{name} (#{e.library.name})", filename)
205
+ end
206
+ end
207
+ pb.title.replace(e.name)
208
+ pb.inc
209
+ end
210
+ pb.finish
211
+ end
212
+ @html_files.sort!
213
+ create_file(@outputdir + 'refm.hhp', HHP_SKEL, true)
214
+ create_file(@outputdir + 'refm.hhc', HHC_SKEL, true)
215
+ create_file(@outputdir + 'refm.hhk', HHK_SKEL, true)
216
+ create_file(@outputdir + 'library/index.html', manager.library_index_screen(db.libraries.sort, {:database => db}).body)
217
+ create_file(@outputdir + 'class/index.html', manager.class_index_screen(db.classes.sort, {:database => db}).body)
218
+ FileUtils.cp(@manager_config[:themedir] + @manager_config[:css_url],
219
+ @outputdir.to_s, {:verbose => true, :preserve => true})
220
+ end
221
+
222
+ private
223
+
224
+ def create_manager_config
225
+ @manager_config = {
226
+ :baseurl => 'http://example.com/',
227
+ :suffix => '.html',
228
+ :templatedir => srcdir_root + 'data'+ 'bitclust' + 'template',
229
+ :themedir => srcdir_root + 'theme' + 'default',
230
+ :css_url => 'style.css',
231
+ :cgi_url => '',
232
+ :tochm_mode => true
233
+ }
234
+ @manager_config[:urlmapper] = URLMapperEx.new(@manager_config)
235
+ end
236
+
237
+ def create_html_file(entry, manager, outputdir, db)
238
+ html = manager.entry_screen(entry, {:database => db}).body
239
+ e = entry.is_a?(Array) ? entry.sort.first : entry
240
+ path = case e.type_id
241
+ when :library, :class, :doc
242
+ outputdir + e.type_id.to_s + (NameUtils.encodename_fs(e.name) + '.html')
243
+ when :method
244
+ outputdir + e.type_id.to_s + NameUtils.encodename_fs(e.klass.name) +
245
+ e.typechar + (NameUtils.encodename_fs(e.name) + '.html')
246
+ else
247
+ raise
248
+ end
249
+ FileUtils.mkdir_p(path.dirname) unless path.dirname.directory?
250
+ path.open('w') do |f|
251
+ f.write(html)
252
+ end
253
+ path.relative_path_from(outputdir).to_s
254
+ end
255
+
256
+ def create_file(path, skel, sjis_flag = false)
257
+ $stderr.print("creating #{path} ...")
258
+ str = ERB.new(skel).result(binding)
259
+ # TODO Use String#encode when we drop 1.8 support
260
+ str = str.tosjis if sjis_flag
261
+ path.open('w') do |f|
262
+ f.write(str)
263
+ end
264
+ $stderr.puts(" done.")
265
+ end
266
+ end
267
+ end
268
+ end
@@ -0,0 +1,73 @@
1
+ require 'pathname'
2
+ require 'optparse'
3
+
4
+ require 'bitclust/crossrubyutils'
5
+
6
+ module BitClust
7
+ module Subcommands
8
+ class ClassesCommand < Subcommand
9
+ include CrossRubyUtils
10
+
11
+ def initialize
12
+ super
13
+ @rejects = []
14
+ @verbose = false
15
+ @parser.banner = "Usage: #{File.basename($0, '.*')} [-r<lib>] <lib>"
16
+ @parser.on('-r', '--reject=LIB', 'Reject library LIB') {|lib|
17
+ @rejects.concat lib.split(',')
18
+ }
19
+ @parser.on('-v', '--verbose', 'Show all ruby version.') {
20
+ @verbose = true
21
+ }
22
+ end
23
+
24
+ def parse(argv)
25
+ super
26
+ option_error('wrong number of arguments') unless argv.size == 1
27
+ end
28
+
29
+ def exec(argv, options)
30
+ lib = argv[0]
31
+ print_crossruby_table {|ruby| defined_classes(ruby, lib, @rejects) }
32
+ end
33
+
34
+ def defined_classes(ruby, lib, rejects)
35
+ script = <<-SCRIPT
36
+ def class_extent
37
+ result = []
38
+ ObjectSpace.each_object(Module) do |c|
39
+ result.push c
40
+ end
41
+ result
42
+ end
43
+
44
+ %w(#{rejects.join(" ")}).each do |lib|
45
+ begin
46
+ require lib
47
+ rescue LoadError
48
+ end
49
+ end
50
+ if "#{lib}" == "_builtin"
51
+ class_extent().each do |c|
52
+ puts c
53
+ end
54
+ else
55
+ before = class_extent()
56
+ begin
57
+ require "#{lib}"
58
+ rescue LoadError
59
+ $stderr.puts "\#{RUBY_VERSION} (\#{RUBY_RELEASE_DATE}): library not exist: #{lib}"
60
+ exit
61
+ end
62
+ after = class_extent()
63
+ (after - before).each do |c|
64
+ puts c
65
+ end
66
+ end
67
+ SCRIPT
68
+ output = `#{ruby} -e '#{script}'`
69
+ output.split
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,55 @@
1
+ require 'pathname'
2
+ require 'optparse'
3
+
4
+ require 'bitclust'
5
+ require 'bitclust/subcommand'
6
+
7
+ module BitClust
8
+ module Subcommands
9
+ class ExtractCommand < Subcommand
10
+
11
+ def initialize
12
+ super
13
+ @parser.banner = "Usage: #{File.basename($0, '.*')} <file>..."
14
+ @parser.on('-c', '--check-only', 'Check syntax and output status.') {
15
+ @check_only = true
16
+ }
17
+ end
18
+
19
+ def exec(argv, options)
20
+ success = true
21
+ argv.each do |path|
22
+ begin
23
+ lib = RRDParser.parse_stdlib_file(path)
24
+ if @check_only
25
+ $stderr.puts "#{path}: OK"
26
+ else
27
+ show_library lib
28
+ end
29
+ rescue WriterError => err
30
+ raise if $DEBUG
31
+ $stderr.puts "#{File.basename($0, '.*')}: FAIL: #{err.message}"
32
+ success = false
33
+ end
34
+ end
35
+ exit success
36
+ end
37
+
38
+ def show_library(lib)
39
+ puts "= Library #{lib.name}"
40
+ lib.classes.each do |c|
41
+ puts "#{c.type} #{c.name}"
42
+ c.each do |m|
43
+ puts "\t* #{m.klass.name}#{m.typemark}#{m.names.join(',')}"
44
+ end
45
+ end
46
+ unless lib.methods.empty?
47
+ puts "Additional Methods:"
48
+ lib.methods.each do |m|
49
+ puts "\t* #{m.klass.name}#{m.typemark}#{m.names.join(',')}"
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,105 @@
1
+ # Copyright (c) 2006-2007 Minero Aoki
2
+ #
3
+ # This program is free software.
4
+ # You can distribute/modify this program under the Ruby License.
5
+ #
6
+
7
+ require 'bitclust'
8
+ require 'bitclust/subcommand'
9
+
10
+ module BitClust
11
+ module Subcommands
12
+ class HtmlfileCommand < Subcommand
13
+ def initialize
14
+ super
15
+ @target = nil
16
+ @templatedir = srcdir_root + "data/bitclust/template.offline"
17
+ @baseurl = "file://" + srcdir_root.to_s
18
+ @version = "2.0.0"
19
+ @parser.banner = "Usage: #{File.basename($0, '.*')} htmlfile [options] rdfile"
20
+ @parser.on('--target=NAME', 'Compile NAME to HTML.') {|name|
21
+ @target = name
22
+ }
23
+ @parser.on('--force', '-f', 'Force to use rd_file template.') {|name|
24
+ @rd_file = true
25
+ }
26
+ @parser.on('--ruby_version=VER', '--ruby=VER', 'Set Ruby version') {|version|
27
+ @version = version
28
+ }
29
+ @parser.on('--baseurl=URL', 'Base URL of generated HTML') {|url|
30
+ @baseurl = url
31
+ }
32
+ @parser.on('--templatedir=PATH', 'Template directory') {|path|
33
+ @templatedir = path
34
+ }
35
+ end
36
+
37
+ def exec(argv, options)
38
+ db = MethodDatabase.dummy({'version' => @version})
39
+ if options[:prefix]
40
+ db = MethodDatabase.new(options[:prefix])
41
+ end
42
+ @capi = options[:capi]
43
+ target_file = argv[0]
44
+ options = { 'version' => @version }
45
+ manager = ScreenManager.new(:templatedir => @templatedir,
46
+ :base_url => @baseurl,
47
+ :cgi_url => @baseurl,
48
+ :default_encoding => 'utf-8')
49
+
50
+ unless @rd_file
51
+ begin
52
+ if @capi
53
+ lib = FunctionReferenceParser.parse_file(target_file, options)
54
+ unless @target
55
+ raise NotImplementedError, "generating a C API html without --target=NAME is not implemented yet."
56
+ end
57
+ else
58
+ lib = RRDParser.parse_stdlib_file(target_file, options)
59
+ end
60
+ entry = @target ? lookup(lib, @target) : lib
61
+ puts manager.entry_screen(entry, { :database => db }).body
62
+ return
63
+ rescue ParseError => ex
64
+ $stderr.puts ex.message
65
+ $stderr.puts ex.backtrace[0], ex.backtrace[1..-1].map{|s| "\tfrom " + s}
66
+ end
67
+ end
68
+
69
+ begin
70
+ entry = DocEntry.new(db, target_file)
71
+ source = Preprocessor.read(target_file, options)
72
+ entry.source = source
73
+ puts manager.doc_screen(entry, { :database => db }).body
74
+ rescue WriterError => ex
75
+ $stderr.puts ex.message
76
+ exit 1
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ def lookup(lib, key)
83
+ case
84
+ when @capi && NameUtils.functionname?(key)
85
+ lib.find {|func| func.name == key}
86
+ when NameUtils.method_spec?(key)
87
+ spec = MethodSpec.parse(key)
88
+ if spec.constant?
89
+ begin
90
+ lib.fetch_class(key)
91
+ rescue UserError
92
+ lib.fetch_methods(spec)
93
+ end
94
+ else
95
+ lib.fetch_methods(spec)
96
+ end
97
+ when NameUtils.classname?(key)
98
+ lib.fetch_class(key)
99
+ else
100
+ raise InvalidKey, "wrong search key: #{key.inspect}"
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end