bitclust-core 0.6.0 → 0.7.0

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 (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