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
@@ -8,39 +8,38 @@ require 'yaml'
8
8
  require 'bitclust'
9
9
  require 'bitclust/subcommand'
10
10
 
11
- module BitClust::Subcommands
12
- class InitCommand < BitClust::Subcommand
13
- def initialize
14
- @parser = OptionParser.new {|opt|
15
- opt.banner = "Usage: #{File.basename($0, '.*')} init [KEY=VALUE ...]"
16
- opt.on('--help', 'Prints this message and quit.') {
17
- puts opt.help
18
- exit 0
19
- }
20
- }
21
- end
11
+ module BitClust
12
+ module Subcommands
13
+ class InitCommand < Subcommand
14
+ def initialize
15
+ super
16
+ @parser.banner = "Usage: #{File.basename($0, '.*')} init [KEY=VALUE ...]"
17
+ end
22
18
 
23
- STANDARD_PROPERTIES = %w( encoding version )
19
+ STANDARD_PROPERTIES = %w( encoding version )
24
20
 
25
- def exec(db, argv)
26
- db.init
27
- db.transaction {
28
- argv.each do |kv|
29
- k, v = kv.split('=', 2)
30
- db.propset k, v
31
- end
32
- }
33
- fail = false
34
- STANDARD_PROPERTIES.each do |key|
35
- unless db.propget(key)
36
- $stderr.puts "#{File.basename($0, '.*')}: warning: standard property `#{key}' not given"
37
- fail = true
21
+ def exec(argv, options)
22
+ prefix = options[:prefix]
23
+ db = MethodDatabase.new(prefix)
24
+ db.init
25
+ db.transaction {
26
+ argv.each do |kv|
27
+ k, v = kv.split('=', 2)
28
+ db.propset k, v
29
+ end
30
+ }
31
+ fail = false
32
+ STANDARD_PROPERTIES.each do |key|
33
+ unless db.propget(key)
34
+ $stderr.puts "#{File.basename($0, '.*')}: warning: standard property `#{key}' not given"
35
+ fail = true
36
+ end
38
37
  end
39
- end
40
- if fail
41
- $stderr.puts "---- Current Properties ----"
42
- db.properties.each do |key, value|
43
- $stderr.puts "#{key}=#{value}"
38
+ if fail
39
+ $stderr.puts "---- Current Properties ----"
40
+ db.properties.each do |key, value|
41
+ $stderr.puts "#{key}=#{value}"
42
+ end
44
43
  end
45
44
  end
46
45
  end
@@ -8,60 +8,58 @@ require 'yaml'
8
8
  require 'bitclust'
9
9
  require 'bitclust/subcommand'
10
10
 
11
- module BitClust::Subcommands
12
- class ListCommand < BitClust::Subcommand
13
- def initialize
14
- @mode = nil
15
- @parser = OptionParser.new {|opt|
16
- opt.banner = "Usage: #{File.basename($0, '.*')} list (--library|--class|--method|--function)"
17
- opt.on('--library', 'List libraries.') {
11
+ module BitClust
12
+ module Subcommands
13
+ class ListCommand < Subcommand
14
+ def initialize
15
+ super
16
+ @mode = nil
17
+ @parser.banner = "Usage: #{File.basename($0, '.*')} list (--library|--class|--method|--function)"
18
+ @parser.on('--library', 'List libraries.') {
18
19
  @mode = :library
19
20
  }
20
- opt.on('--class', 'List classes.') {
21
+ @parser.on('--class', 'List classes.') {
21
22
  @mode = :class
22
23
  }
23
- opt.on('--method', 'List methods.') {
24
+ @parser.on('--method', 'List methods.') {
24
25
  @mode = :method
25
26
  }
26
- opt.on('--function', 'List functions.') {
27
+ @parser.on('--function', 'List functions (C API).') {
27
28
  @mode = :function
28
29
  }
29
- opt.on('--help', 'Prints this message and quit.') {
30
- puts opt.help
31
- exit 0
32
- }
33
- }
34
- end
35
-
36
- def parse(argv)
37
- super
38
- unless @mode
39
- error 'one of (--library|--class|--method|--function) is required'
40
30
  end
41
- end
42
31
 
43
- def exec(db, argv)
44
- case @mode
45
- when :library
46
- db.libraries.map {|lib| lib.name }.sort.each do |name|
47
- puts name
48
- end
49
- when :class
50
- db.classes.map {|c| c.name }.sort.each do |name|
51
- puts name
32
+ def parse(argv)
33
+ super
34
+ unless @mode
35
+ error 'one of (--library|--class|--method|--function) is required'
52
36
  end
53
- when :method
54
- db.classes.sort_by {|c| c.name }.each do |c|
55
- c.entries.sort_by {|m| m.id }.each do |m|
56
- puts m.label
37
+ end
38
+
39
+ def exec(argv, options)
40
+ super
41
+ case @mode
42
+ when :library
43
+ @db.libraries.map {|lib| lib.name }.sort.each do |name|
44
+ puts name
57
45
  end
46
+ when :class
47
+ @db.classes.map {|c| c.name }.sort.each do |name|
48
+ puts name
49
+ end
50
+ when :method
51
+ @db.classes.sort_by {|c| c.name }.each do |c|
52
+ c.entries.sort_by {|m| m.id }.each do |m|
53
+ puts m.label
54
+ end
55
+ end
56
+ when :function
57
+ @db.functions.sort_by {|f| f.name }.each do |f|
58
+ puts f.name
59
+ end
60
+ else
61
+ raise "must not happen: @mode=#{@mode.inspect}"
58
62
  end
59
- when :function
60
- db.functions.sort_by {|f| f.name }.each do |f|
61
- puts f.name
62
- end
63
- else
64
- raise "must not happen: @mode=#{@mode.inspect}"
65
63
  end
66
64
  end
67
65
  end
@@ -8,82 +8,79 @@ require 'yaml'
8
8
  require 'bitclust'
9
9
  require 'bitclust/subcommand'
10
10
 
11
- module BitClust::Subcommands
12
- class LookupCommand < BitClust::Subcommand
13
- def initialize
14
- @format = :text
15
- @type = nil
16
- @key = nil
17
- @parser = OptionParser.new {|opt|
18
- opt.banner = "Usage: #{File.basename($0, '.*')} lookup (--library|--class|--method|--function) [--html] <key>"
19
- opt.on('--library=NAME', 'Lookup library.') {|name|
11
+ module BitClust
12
+ module Subcommands
13
+ class LookupCommand < Subcommand
14
+ def initialize
15
+ super
16
+ @format = :text
17
+ @type = nil
18
+ @key = nil
19
+ @parser.banner = "Usage: #{File.basename($0, '.*')} lookup (--library|--class|--method|--function) [--html] <key>"
20
+ @parser.on('--library=NAME', 'Lookup library.') {|name|
20
21
  @type = :library
21
22
  @key = name
22
23
  }
23
- opt.on('--class=NAME', 'Lookup class.') {|name|
24
+ @parser.on('--class=NAME', 'Lookup class.') {|name|
24
25
  @type = :class
25
26
  @key = name
26
27
  }
27
- opt.on('--method=NAME', 'Lookup method.') {|name|
28
+ @parser.on('--method=NAME', 'Lookup method.') {|name|
28
29
  @type = :method
29
30
  @key = name
30
31
  }
31
- opt.on('--function=NAME', 'Lookup function.') {|name|
32
+ @parser.on('--function=NAME', 'Lookup function. (C API)') {|name|
32
33
  @type = :function
33
34
  @key = name
34
35
  }
35
- opt.on('--html', 'Show result in HTML.') {
36
+ @parser.on('--html', 'Show result in HTML.') {
36
37
  @format = :html
37
38
  }
38
- opt.on('--help', 'Prints this message and quit.') {
39
- puts opt.help
40
- exit 0
41
- }
42
- }
43
- end
44
-
45
- def parse(argv)
46
- super
47
- unless @type
48
- error "one of --library/--class/--method/--function is required"
49
39
  end
50
- unless argv.empty?
51
- error "too many arguments"
40
+
41
+ def parse(argv)
42
+ super
43
+ unless @type
44
+ error "one of --library/--class/--method/--function is required"
45
+ end
46
+ unless argv.empty?
47
+ error "too many arguments"
48
+ end
52
49
  end
53
- end
54
50
 
55
- def exec(db, argv)
56
- entry = fetch_entry(db, @type, @key)
57
- puts fill_template(get_template(@type, @format), entry)
58
- end
51
+ def exec(argv, options)
52
+ super
53
+ entry = fetch_entry(@db, @type, @key)
54
+ puts fill_template(get_template(@type, @format), entry)
55
+ end
59
56
 
60
- def fetch_entry(db, type, key)
61
- case type
62
- when :library
63
- db.fetch_library(key)
64
- when :class
65
- db.fetch_class(key)
66
- when :method
67
- db.fetch_method(BitClust::MethodSpec.parse(key))
68
- when :function
69
- db.fetch_function(key)
70
- else
71
- raise "must not happen: #{type.inspect}"
57
+ def fetch_entry(db, type, key)
58
+ case type
59
+ when :library
60
+ db.fetch_library(key)
61
+ when :class
62
+ db.fetch_class(key)
63
+ when :method
64
+ db.fetch_method(MethodSpec.parse(key))
65
+ when :function
66
+ db.fetch_function(key)
67
+ else
68
+ raise "must not happen: #{type.inspect}"
69
+ end
72
70
  end
73
- end
74
71
 
75
- def fill_template(template, entry)
76
- ERB.new(template).result(binding())
77
- end
72
+ def fill_template(template, entry)
73
+ ERB.new(template).result(binding())
74
+ end
78
75
 
79
- def get_template(type, format)
80
- template = TEMPLATE[type][format]
81
- BitClust::TextUtils.unindent_block(template.lines).join('')
82
- end
76
+ def get_template(type, format)
77
+ template = TEMPLATE[type][format]
78
+ TextUtils.unindent_block(template.lines).join('')
79
+ end
83
80
 
84
- TEMPLATE = {
85
- :library => {
86
- :text => <<-End,
81
+ TEMPLATE = {
82
+ :library => {
83
+ :text => <<-End,
87
84
  type: library
88
85
  name: <%= entry.name %>
89
86
  classes: <%= entry.classes.map {|c| c.name }.sort.join(', ') %>
@@ -91,7 +88,7 @@ module BitClust::Subcommands
91
88
 
92
89
  <%= entry.source %>
93
90
  End
94
- :html => <<-End
91
+ :html => <<-End
95
92
  <dl>
96
93
  <dt>type</dt><dd>library</dd>
97
94
  <dt>name</dt><dd><%= entry.name %></dd>
@@ -100,9 +97,9 @@ module BitClust::Subcommands
100
97
  </dl>
101
98
  <%= compile_rd(entry.source) %>
102
99
  End
103
- },
104
- :class => {
105
- :text => <<-End,
100
+ },
101
+ :class => {
102
+ :text => <<-End,
106
103
  type: class
107
104
  name: <%= entry.name %>
108
105
  library: <%= entry.library.name %>
@@ -113,7 +110,7 @@ module BitClust::Subcommands
113
110
 
114
111
  <%= entry.source %>
115
112
  End
116
- :html => <<-End
113
+ :html => <<-End
117
114
  <dl>
118
115
  <dt>type</dt><dd>class</dd>
119
116
  <dt>name</dt><dd><%= entry.name %></dd>
@@ -123,9 +120,9 @@ module BitClust::Subcommands
123
120
  </dl>
124
121
  <%= compile_rd(entry.source) %>
125
122
  End
126
- },
127
- :method => {
128
- :text => <<-End,
123
+ },
124
+ :method => {
125
+ :text => <<-End,
129
126
  type: <%= entry.type %>
130
127
  name: <%= entry.name %>
131
128
  names: <%= entry.names.sort.join(', ') %>
@@ -135,7 +132,7 @@ module BitClust::Subcommands
135
132
 
136
133
  <%= entry.source %>
137
134
  End
138
- :html => <<-End
135
+ :html => <<-End
139
136
  <dl>
140
137
  <dt>type</dt><dd><%= entry.type %></dd>
141
138
  <dt>name</dt><dd><%= entry.name %></dd>
@@ -146,16 +143,16 @@ module BitClust::Subcommands
146
143
  </dl>
147
144
  <%= compile_rd(entry.source) %>
148
145
  End
149
- },
150
- :function => {
151
- :text => <<-End,
146
+ },
147
+ :function => {
148
+ :text => <<-End,
152
149
  kind: <%= entry.kind %>
153
150
  header: <%= entry.header %>
154
151
  filename: <%= entry.filename %>
155
152
 
156
153
  <%= entry.source %>
157
154
  End
158
- :html => <<-End
155
+ :html => <<-End
159
156
  <dl>
160
157
  <dt>kind</dt><dd><%= entry.kind %></dd>
161
158
  <dt>header</dt><dd><%= entry.header %></dd>
@@ -163,14 +160,15 @@ module BitClust::Subcommands
163
160
  </dl>
164
161
  <%= compile_rd(entry.source) %>
165
162
  End
163
+ }
166
164
  }
167
- }
168
165
 
169
- def compile_rd(src)
170
- umap = BitClust::URLMapper.new(:base_url => 'http://example.com',
171
- :cgi_url => 'http://example.com/view')
172
- compiler = BitClust::RDCompiler.new(umap, 2)
173
- compiler.compile(src)
166
+ def compile_rd(src)
167
+ umap = URLMapper.new(:base_url => 'http://example.com',
168
+ :cgi_url => 'http://example.com/view')
169
+ compiler = RDCompiler.new(umap, 2)
170
+ compiler.compile(src)
171
+ end
174
172
  end
175
173
  end
176
174
  end
@@ -0,0 +1,159 @@
1
+ require 'pathname'
2
+ require 'optparse'
3
+
4
+ require 'bitclust'
5
+ require 'bitclust/crossrubyutils'
6
+ require 'bitclust/subcommand'
7
+
8
+ module BitClust
9
+ module Subcommands
10
+ class MethodsCommand < Subcommand
11
+ include CrossRubyUtils
12
+
13
+ def initialize
14
+ super
15
+ @requires = []
16
+ @verbose = false
17
+ @version = RUBY_VERSION
18
+ @mode = :list
19
+ @target = nil
20
+ @parser.banner = "Usage: #{File.basename($0, '.*')} [-r<lib>] <classname>"
21
+ @parser.on('-r LIB', 'Requires library LIB') {|lib|
22
+ @requires.push lib
23
+ }
24
+ @parser.on('-v', '--verbose', "Prints each ruby's version") {
25
+ @verbose = true
26
+ }
27
+ @parser.on('--diff=RDFILE', 'RD file name') {|path|
28
+ @mode = :diff
29
+ @target = path
30
+ }
31
+ @parser.on('-c', '') {
32
+ @content = true
33
+ require 'bitclust/ridatabase'
34
+ }
35
+ @parser.on('--ruby=[VER]', "The version of Ruby interpreter"){|version|
36
+ @version = version
37
+ }
38
+ @parser.on('--ri-database', 'The path of ri database'){|path|
39
+ @ri_path = path
40
+ }
41
+ end
42
+
43
+ def parse(argv)
44
+ super
45
+ option_error("wrong number of arguments") unless argv.size == 1
46
+ end
47
+
48
+ def exec(argv, options)
49
+ classname = argv[0]
50
+ case @mode
51
+ when :list
52
+ print_crossruby_table {|ruby| defined_methods(ruby, classname) }
53
+ when :diff
54
+ unless ruby = get_ruby(@version)
55
+ raise "Not found Ruby interpreter of the given version"
56
+ end
57
+ keys = defined_methods(ruby, classname)
58
+ lib = RRDParser.parse_stdlib_file(@target, { 'version' => @version })
59
+ c = lib.fetch_class(classname)
60
+ list0 = lib.classes.find_all{|c0| /\A#{classname}\b/o =~ c0.name }
61
+ list0 = c.entries + list0
62
+ list = list0.map {|ent| ent.labels.map {|n| expand_mf(n) } }.flatten
63
+ if @content
64
+ ri = @ri_path ? RiDatabase.open(@ri_path, nil) : RiDatabase.open_system_db
65
+ ri.current_class = c.name
66
+ mthds = ( ri.singleton_methods + ri.instance_methods )
67
+ fmt = Formatter.new
68
+ (keys - list).sort.each do |name|
69
+ mthd = mthds.find{|m| name == m.fullname }
70
+ if mthd
71
+ puts fmt.method_info(mthd.entry)
72
+ else
73
+ name = name.sub(/\A\w+#/, '')
74
+ puts "--- #{name}\n\#@todo\n\n"
75
+ end
76
+ end
77
+ else
78
+ (keys - list).sort.each do |name|
79
+ puts "-#{name}"
80
+ end
81
+ (list - keys).sort.each do |name|
82
+ puts "+#{name}"
83
+ end
84
+ end
85
+ else
86
+ raise "must not happen: #{mode.inspect}"
87
+ end
88
+ end
89
+
90
+ def expand_mf(n)
91
+ if /\.\#/ =~ n
92
+ [n.sub(/\.\#/, '.'), n.sub(/\.\#/, '#')]
93
+ else
94
+ n
95
+ end
96
+ end
97
+
98
+ def crossrubyutils_sort_entries(ents)
99
+ ents.sort_by {|m| m_order(m) }
100
+ end
101
+
102
+ ORDER = { '.' => 1, '#' => 2, '::' => 3 }
103
+
104
+ def m_order(m)
105
+ m, t, c = *m.reverse.split(/(\#|\.|::)/, 2)
106
+ [ORDER[t] || 0, m.reverse]
107
+ end
108
+
109
+ def defined_methods(ruby, classname)
110
+ req = @requires.map {|lib| "-r#{lib}" }.join(' ')
111
+ avoid_tracer = ""
112
+ avoid_tracer = "Tracer.off" if @requires.include?("tracer")
113
+ case classname
114
+ when 'Object'
115
+ script = <<-SCRIPT
116
+ c = #{classname}
117
+ c.singleton_methods(false).each do |m|
118
+ puts "#{classname}.\#{m}"
119
+ end
120
+ c.instance_methods(true).each do |m|
121
+ puts "#{classname}\\#\#{m}"
122
+ end
123
+ SCRIPT
124
+ when 'Kernel'
125
+ script = <<-SCRIPT
126
+ c = #{classname}
127
+ c.singleton_methods(true).each do |m|
128
+ puts "#{classname}.\#{m}"
129
+ end
130
+ ( c.private_instance_methods(false) && c.methods(false) ).each do |m|
131
+ puts "#{classname}\\#\#{m}"
132
+ end
133
+ Object::constants.delete_if{|c| cl = Object.const_get(c).class; cl == Class or cl == Module }.each do |m|
134
+ puts "#{classname}::\#{m}"
135
+ end
136
+ global_variables.each do |m|
137
+ puts "#{classname}\#{m}"
138
+ end
139
+ SCRIPT
140
+ else
141
+ script = <<-SCRIPT
142
+ #{avoid_tracer}
143
+ c = #{classname}
144
+ c.singleton_methods(false).each do |m|
145
+ puts "#{classname}.\#{m}"
146
+ end
147
+ c.instance_methods(false).each do |m|
148
+ puts "#{classname}\\#\#{m}"
149
+ end
150
+ c.ancestors.map {|mod| mod.constants }.inject {|r,n| r-n }.each do |m|
151
+ puts "#{classname}::\#{m}"
152
+ end
153
+ SCRIPT
154
+ end
155
+ `#{ruby} #{req} -e '#{script}'`.split
156
+ end
157
+ end
158
+ end
159
+ end