bitclust-core 0.5.4 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog CHANGED
@@ -1,3 +1,45 @@
1
+ 2012-10-09 Ippei Obayashi <ohai@kmc.gr.jp>
2
+
3
+ * lib/bitclust/subcommands/server_command.rb
4
+ (BitClust::Subcommands::ServerCommand#initialize): fix set_srcdir call
5
+ (BitClust::Subcommands::ServerCommand#srcdir_root): fix default srcdir
6
+
7
+ 2012-09-24 okkez <okkez000@gmail.com>
8
+
9
+ * lib/bitclust/subcommand.rb: split subcommands.
10
+
11
+ * lib/bitclust/subcommands/update_command.rb: split update
12
+ subcommand.
13
+
14
+ * lib/bitclust/subcommands/setup_command.rb: split setup
15
+ subcommand.
16
+
17
+ * lib/bitclust/subcommands/server_command.rb: split server
18
+ subcommand.
19
+
20
+ * lib/bitclust/subcommands/query_command.rb: split query
21
+ subcommand.
22
+
23
+ * lib/bitclust/subcommands/property_command.rb: split property
24
+ subcommand.
25
+
26
+ * lib/bitclust/subcommands/lookup_command.rb: split lookup
27
+ subcommand.
28
+
29
+ * lib/bitclust/subcommands/list_command.rb: split list subcommand.
30
+
31
+ * lib/bitclust/subcommands/init_command.rb: split init subcommand.
32
+
33
+ 2012-09-16 Sho Hashimoto <sho-h@netlab.jp>
34
+
35
+ * lib/bitclust/subcommand.rb (BitClust::SetupCommand#checkout):
36
+ check svn installed Windows, too. (see #7026)
37
+
38
+ 2012-09-15 Sho Hashimoto <sho-h@netlab.jp>
39
+
40
+ * lib/bitclust/subcommand.rb (BitClust::ServerCommand#exec): start
41
+ browser mingw, cygwin and bccwin. (same as r5167)
42
+
1
43
  2012-09-02 okkez <okkez000@gmail.com>
2
44
 
3
45
  * lib/bitclust/subcommand.rb (BitClust::SetupCommand#prepare): do
@@ -13,44 +13,34 @@
13
13
 
14
14
  <%
15
15
  headline_push
16
- err_classes = @entry.error_classes
17
- modules = @entry.all_classes.select{|c| c.module? }.sort
18
- objects = @entry.all_classes.select{|c| c.object? }.sort
19
- classes = (@entry.all_classes - @entry.all_error_classes - modules - objects).sort
20
-
21
- class_tree = classes.group_by{|c| c.superclass }
22
- class_root = class_tree.keys.select{|c| !c || !classes.include?(c)}
23
- class_root.map!{|c| class_tree[c] }.flatten!
24
- err_class_tree = err_classes.group_by{|c| c.superclass }
25
- err_class_root = err_class_tree.keys.select{|c| !c || !err_classes.include?(c)}
26
- err_class_root.map!{|c| err_class_tree[c] }.flatten!
16
+ all_classes = @entry.all_classes
17
+ err_classes = @entry.all_error_classes.sort
18
+ modules = @entry.all_modules
19
+ objects = @entry.all_objects
20
+ classes = all_classes - err_classes - modules - objects
27
21
  %>
28
22
 
29
23
 
30
24
  <%= headline(_("Abstract")) %>
31
25
  <%= compile_rd(@entry.source) %>
32
- <% draw_tree = proc do |list, tree, indent = 0| %>
33
- <tr>
34
- <% list.each do |c| %>
35
- <td class="signature" style="text-indent: <%= indent * 1.0%>em;"><span style="display:none"><%= "&nbsp;" * indent %></span>
36
- <%= class_link(c.name, c.name) %></td>
37
- <td class="description"><%= compile_rd(c.synopsis_source) %></td>
38
- </tr>
39
- <%
40
- tree && tree[c] && draw_tree.call(tree[c], tree, indent + 1)
41
- end
42
- end
43
- %>
44
26
  <%
45
- [[class_root, class_tree , _('Classes')],
46
- [modules, nil , _('Modules')],
47
- [objects, nil , _('Objects')],
48
- [err_class_root, err_class_tree, _('Exception Classes')]].each do |cs, tree, msg|
27
+ [[classes, _('Classes')],
28
+ [modules, _('Modules')],
29
+ [objects, _('Objects')],
30
+ [err_classes, _('Exception Classes')]].each do |cs, msg|
49
31
  unless cs.empty?
50
32
  %>
51
33
  <%= headline(msg) %>
52
34
  <table class="entries libraries">
53
- <% draw_tree.call(cs, tree) %>
35
+ <% draw_tree(cs) do |c, indent| %>
36
+ <tr>
37
+ <td class="signature" style="text-indent: <%= indent * 1.0%>em;">
38
+ <span style="display:none"><%= "&nbsp;" * indent %></span>
39
+ <%= class_link(c.name, c.name) %>
40
+ </td>
41
+ <td class="description"><%= compile_rd(c.synopsis_source) %></td>
42
+ </tr>
43
+ <% end %>
54
44
  </table>
55
45
  <%
56
46
  end
@@ -11,46 +11,34 @@
11
11
 
12
12
  <%
13
13
  headline_push
14
- required_classes = (@entry.sublibraries & @entry.requires).map{|lib| lib.classes }.flatten
15
- all_classes = (@entry.classes + required_classes).uniq.sort
16
- err_classes = all_classes.select {|c| c.error_class? }.sort
17
- modules = all_classes.select{|c| c.module? }.sort
18
- objects = all_classes.select{|c| c.object? }.sort
19
- classes = (all_classes - err_classes - modules - objects).sort
20
-
21
- class_tree = classes.group_by{|c| c.superclass }
22
- class_root = class_tree.keys.select{|c| !c || !classes.include?(c)}
23
- class_root.map!{|c| class_tree[c] }.flatten!
24
- err_class_tree = err_classes.group_by{|c| c.superclass }
25
- err_class_root = err_class_tree.keys.select{|c| !c || !err_classes.include?(c)}
26
- err_class_root.map!{|c| err_class_tree[c] }.flatten!
14
+ all_classes = @entry.all_classes
15
+ err_classes = @entry.all_error_classes.sort
16
+ modules = @entry.all_modules
17
+ objects = @entry.all_objects
18
+ classes = all_classes - err_classes - modules - objects
27
19
  %>
28
20
 
29
21
 
30
22
  <%= headline(_("Abstract")) %>
31
23
  <%= compile_rd(@entry.source) %>
32
- <% draw_tree = proc do |list, tree, indent = 0| %>
33
- <tr>
34
- <% list.each do |c| %>
35
- <td class="signature" style="text-indent: <%= indent * 1.0%>em;"><span style="display:none"><%= "&nbsp;" * indent %></span>
36
- <%= class_link(c.name, c.name) %></td>
37
- <td class="description"><%= compile_rd(c.synopsis_source) %></td>
38
- </tr>
39
- <%
40
- tree && tree[c] && draw_tree.call(tree[c], tree, indent + 1)
41
- end
42
- end
43
- %>
44
24
  <%
45
- [[class_root, class_tree , _('Classes')],
46
- [modules, nil , _('Modules')],
47
- [objects, nil , _('Objects')],
48
- [err_class_root, err_class_tree, _('Exception Classes')]].each do |cs, tree, msg|
25
+ [[classes, _('Classes')],
26
+ [modules, _('Modules')],
27
+ [objects, _('Objects')],
28
+ [err_classes, _('Exception Classes')]].each do |cs, msg|
49
29
  unless cs.empty?
50
30
  %>
51
31
  <%= headline(msg) %>
52
32
  <table class="entries libraries">
53
- <% draw_tree.call(cs, tree) %>
33
+ <% draw_tree(cs) do |c, indent| %>
34
+ <tr>
35
+ <td class="signature" style="text-indent: <%= indent * 1.0%>em;">
36
+ <span style="display:none"><%= "&nbsp;" * indent %></span>
37
+ <%= class_link(c.name, c.name) %>
38
+ </td>
39
+ <td class="description"><%= compile_rd(c.synopsis_source) %></td>
40
+ </tr>
41
+ <% end %>
54
42
  </table>
55
43
  <%
56
44
  end
@@ -13,46 +13,34 @@
13
13
 
14
14
  <%
15
15
  headline_push
16
- required_classes = (@entry.sublibraries & @entry.requires).map{|lib| lib.classes }.flatten
17
- all_classes = (@entry.classes + required_classes).uniq.sort
18
- err_classes = all_classes.select {|c| c.error_class? }.sort
19
- modules = all_classes.select{|c| c.module? }.sort
20
- objects = all_classes.select{|c| c.object? }.sort
21
- classes = (all_classes - err_classes - modules - objects).sort
22
-
23
- class_tree = classes.group_by{|c| c.superclass }
24
- class_root = class_tree.keys.select{|c| !c || !classes.include?(c)}
25
- class_root.map!{|c| class_tree[c] }.flatten!
26
- err_class_tree = err_classes.group_by{|c| c.superclass }
27
- err_class_root = err_class_tree.keys.select{|c| !c || !err_classes.include?(c)}
28
- err_class_root.map!{|c| err_class_tree[c] }.flatten!
16
+ all_classes = @entry.all_classes
17
+ err_classes = @entry.all_error_classes.sort
18
+ modules = @entry.all_modules
19
+ objects = @entry.all_objects
20
+ classes = all_classes - err_classes - modules - objects
29
21
  %>
30
22
 
31
23
 
32
24
  <%= headline(_("Abstract")) %>
33
25
  <%= compile_rd(@entry.source) %>
34
- <% draw_tree = proc do |list, tree, indent = 0| %>
35
- <tr>
36
- <% list.each do |c| %>
37
- <td class="signature" style="text-indent: <%= indent * 1.0%>em;"><span style="display:none"><%= "&nbsp;" * indent %></span>
38
- <%= class_link(c.name, c.name) %></td>
39
- <td class="description"><%= compile_rd(c.synopsis_source) %></td>
40
- </tr>
41
- <%
42
- tree && tree[c] && draw_tree.call(tree[c], tree, indent + 1)
43
- end
44
- end
45
- %>
46
26
  <%
47
- [[class_root, class_tree , _('Classes')],
48
- [modules, nil , _('Modules')],
49
- [objects, nil , _('Objects')],
50
- [err_class_root, err_class_tree, _('Exception Classes')]].each do |cs, tree, msg|
27
+ [[classes, _('Classes')],
28
+ [modules, _('Modules')],
29
+ [objects, _('Objects')],
30
+ [err_classes, _('Exception Classes')]].each do |cs, msg|
51
31
  unless cs.empty?
52
32
  %>
53
33
  <%= headline(msg) %>
54
34
  <table class="entries libraries">
55
- <% draw_tree.call(cs, tree) %>
35
+ <% draw_tree(cs) do |c, indent| %>
36
+ <tr>
37
+ <td class="signature" style="text-indent: <%= indent * 1.0%>em;">
38
+ <span style="display:none"><%= "&nbsp;" * indent %></span>
39
+ <%= class_link(c.name, c.name) %>
40
+ </td>
41
+ <td class="description"><%= compile_rd(c.synopsis_source) %></td>
42
+ </tr>
43
+ <% end %>
56
44
  </table>
57
45
  <%
58
46
  end
@@ -43,7 +43,7 @@ module BitClust
43
43
  @in_transaction = false
44
44
  @properties_dirty = false
45
45
  end
46
-
46
+
47
47
  def dummy?
48
48
  not @prefix
49
49
  end
@@ -114,6 +114,14 @@ module BitClust
114
114
  @all_error_classes ||= all_classes.select{|c| c.error_class? }
115
115
  end
116
116
 
117
+ def all_modules
118
+ @all_modules ||= all_classes.select{|c| c.module? }.sort
119
+ end
120
+
121
+ def all_objects
122
+ @all_objects ||= all_classes.select{|c| c.object? }.sort
123
+ end
124
+
117
125
  def require(lib)
118
126
  requires().push lib
119
127
  end
@@ -18,8 +18,8 @@ module BitClust
18
18
  LIBNAME_RE = %r<[\w\-]+(/[\w\-]+)*>
19
19
  CONST_RE = /[A-Z]\w*/
20
20
  CONST_PATH_RE = /#{CONST_RE}(?:::#{CONST_RE})*/
21
- CLASS_NAME_RE = /(?:#{CONST_RE}|fatal)/
22
- CLASS_PATH_RE = /(?:#{CONST_PATH_RE}|fatal)/
21
+ CLASS_NAME_RE = /(?:#{CONST_RE}|fatal|ARGF.class)/
22
+ CLASS_PATH_RE = /(?:#{CONST_PATH_RE}|fatal|ARGF.class)/
23
23
  METHOD_NAME_RE = /\w+[?!=]?|===|==|=~|<=>|<=|>=|!=|!|!@|!~|\[\]=|\[\]|\*\*|>>|<<|\+@|\-@|[~+\-*\/%&|^<>`]/
24
24
  TYPEMARK_RE = /(?:\.|\#|\.\#|::|\$)/
25
25
  METHOD_SPEC_RE = /#{CLASS_PATH_RE}#{TYPEMARK_RE}#{METHOD_NAME_RE}/
@@ -50,6 +50,7 @@ module BitClust
50
50
  end
51
51
 
52
52
  def method_spec?(str)
53
+ return false if str == "ARGF.class"
53
54
  (/\A#{METHOD_SPEC_RE}\z/o =~ str) ? true : false
54
55
  end
55
56
 
@@ -120,7 +121,8 @@ module BitClust
120
121
 
121
122
  # private module function
122
123
  def split_method_id(id)
123
- return *id.split(%r<[/\.]>, 4)
124
+ c, rest = id.split("/")
125
+ return *[c, *rest.split(%r<[/\.]>, 3)]
124
126
  end
125
127
 
126
128
  NAME_TO_MARK = {
@@ -193,21 +193,21 @@ module BitClust
193
193
 
194
194
  def read_includes(f, reopen = false)
195
195
  f.while_match(/\Ainclude\s/) do |line|
196
- tty_warn "#{line.location}: dynamic include is not implemented yet" if reopen
196
+ tty_warn "#{line.location}: dynamic include is not implemented yet" if reopen
197
197
  @context.include line.split[1] unless reopen # FIXME
198
198
  end
199
199
  end
200
200
 
201
201
  def read_extends(f, reopen = false)
202
202
  f.while_match(/\Aextend\s/) do |line|
203
- tty_warn "#{line.location}: dynamic extend is not implemented yet" if reopen
203
+ tty_warn "#{line.location}: dynamic extend is not implemented yet" if reopen
204
204
  @context.extend line.split[1] unless reopen # FIXME
205
205
  end
206
206
  end
207
207
 
208
- def tty_warn(msg)
209
- $stderr.puts msg if $stderr.tty?
210
- end
208
+ def tty_warn(msg)
209
+ $stderr.puts msg if $stderr.tty?
210
+ end
211
211
 
212
212
  def read_level2_blocks(f)
213
213
  read_entries f
@@ -5,15 +5,20 @@ unless Object.const_defined?(:Encoding)
5
5
  $KCODE = 'UTF-8'
6
6
  end
7
7
 
8
- def srcdir_root
8
+ def libdir
9
9
  Pathname.new(__FILE__).realpath.dirname.parent.cleanpath
10
10
  end
11
11
 
12
- $LOAD_PATH.unshift((srcdir_root() + 'lib').to_s)
12
+ $LOAD_PATH.unshift(libdir.to_s)
13
13
 
14
14
  require 'bitclust'
15
15
  require 'bitclust/subcommand'
16
16
 
17
+ subcommands_dir = libdir + "bitclust/subcommands"
18
+ Dir.glob(File.join(subcommands_dir.to_s, "*.rb")) do |entry|
19
+ require "bitclust/subcommands/#{File.basename(entry, ".rb")}"
20
+ end
21
+
17
22
  module BitClust
18
23
  class Runner
19
24
  def initialize
@@ -66,15 +71,15 @@ Global Options:
66
71
  exit 0
67
72
  }
68
73
  @subcommands = {
69
- 'init' => BitClust::InitCommand.new,
70
- 'list' => BitClust::ListCommand.new,
71
- 'lookup' => BitClust::LookupCommand.new,
74
+ 'init' => BitClust::Subcommands::InitCommand.new,
75
+ 'list' => BitClust::Subcommands::ListCommand.new,
76
+ 'lookup' => BitClust::Subcommands::LookupCommand.new,
72
77
  'search' => BitClust::Searcher.new,
73
- 'query' => BitClust::QueryCommand.new,
74
- 'update' => BitClust::UpdateCommand.new,
75
- 'property' => BitClust::PropertyCommand.new,
76
- 'setup' => BitClust::SetupCommand.new,
77
- 'server' => BitClust::ServerCommand.new,
78
+ 'query' => BitClust::Subcommands::QueryCommand.new,
79
+ 'update' => BitClust::Subcommands::UpdateCommand.new,
80
+ 'property' => BitClust::Subcommands::PropertyCommand.new,
81
+ 'setup' => BitClust::Subcommands::SetupCommand.new,
82
+ 'server' => BitClust::Subcommands::ServerCommand.new,
78
83
  }
79
84
  end
80
85
 
@@ -458,6 +458,29 @@ module BitClust
458
458
  def body
459
459
  run_template('library')
460
460
  end
461
+
462
+ def draw_tree(cs, &block)
463
+ return if cs.empty?
464
+ if cs.first.class?
465
+ tree = cs.group_by{|c| c.superclass }
466
+ tree.each {|key, list| list.sort_by!{|c| c ? c.name : "" } }
467
+ roots = tree.keys.select{|c| !c || !cs.include?(c) }
468
+ roots.map!{|c| tree[c] }.flatten!
469
+ else
470
+ tree = {}
471
+ roots = cs
472
+ end
473
+ draw_treed_entries(roots, tree, &block)
474
+ end
475
+
476
+ private
477
+
478
+ def draw_treed_entries(entries, tree, indent = 0, &block)
479
+ entries.each do |c|
480
+ yield c, indent
481
+ draw_treed_entries(tree[c], tree, indent + 1, &block) if tree[c]
482
+ end
483
+ end
461
484
  end
462
485
 
463
486
  class ClassIndexScreen < IndexScreen
@@ -24,733 +24,10 @@ module BitClust
24
24
  exit 1
25
25
  end
26
26
  end
27
+ end
27
28
 
28
-
29
- class InitCommand < Subcommand
30
-
31
- def initialize
32
- @parser = OptionParser.new {|opt|
33
- opt.banner = "Usage: #{File.basename($0, '.*')} init [KEY=VALUE ...]"
34
- opt.on('--help', 'Prints this message and quit.') {
35
- puts opt.help
36
- exit 0
37
- }
38
- }
39
- end
40
-
41
- STANDARD_PROPERTIES = %w( encoding version )
42
-
43
- def exec(db, argv)
44
- db.init
45
- db.transaction {
46
- argv.each do |kv|
47
- k, v = kv.split('=', 2)
48
- db.propset k, v
49
- end
50
- }
51
- fail = false
52
- STANDARD_PROPERTIES.each do |key|
53
- unless db.propget(key)
54
- $stderr.puts "#{File.basename($0, '.*')}: warning: standard property `#{key}' not given"
55
- fail = true
56
- end
57
- end
58
- if fail
59
- $stderr.puts "---- Current Properties ----"
60
- db.properties.each do |key, value|
61
- $stderr.puts "#{key}=#{value}"
62
- end
63
- end
64
- end
65
-
66
- end
67
-
68
-
69
- class UpdateCommand < Subcommand
70
-
71
- def initialize
72
- @root = nil
73
- @library = nil
74
- @parser = OptionParser.new {|opt|
75
- opt.banner = "Usage: #{File.basename($0, '.*')} update [<file>...]"
76
- opt.on('--stdlibtree=ROOT', 'Process stdlib source directory tree.') {|path|
77
- @root = path
78
- }
79
- opt.on('--library-name=NAME', 'Use NAME for library name in file mode.') {|name|
80
- @library = name
81
- }
82
- opt.on('--help', 'Prints this message and quit.') {
83
- puts opt.help
84
- exit 0
85
- }
86
- }
87
- end
88
-
89
- def parse(argv)
90
- super
91
- if not @root and argv.empty?
92
- error "no input file given"
93
- end
94
- end
95
-
96
- def exec(db, argv)
97
- db.transaction {
98
- if @root
99
- db.update_by_stdlibtree @root
100
- end
101
- argv.each do |path|
102
- db.update_by_file path, @library || guess_library_name(path)
103
- end
104
- }
105
- end
106
-
107
- private
108
-
109
- def guess_library_name(path)
110
- if %r<(\A|/)src/> =~ path
111
- path.sub(%r<.*(\A|/)src/>, '').sub(/\.rd\z/, '')
112
- else
113
- path
114
- end
115
- end
116
-
117
- def get_c_filename(path)
118
- File.basename(path, '.rd')
119
- end
120
-
121
- end
122
-
123
-
124
- class ListCommand < Subcommand
125
-
126
- def initialize
127
- @mode = nil
128
- @parser = OptionParser.new {|opt|
129
- opt.banner = "Usage: #{File.basename($0, '.*')} list (--library|--class|--method|--function)"
130
- opt.on('--library', 'List libraries.') {
131
- @mode = :library
132
- }
133
- opt.on('--class', 'List classes.') {
134
- @mode = :class
135
- }
136
- opt.on('--method', 'List methods.') {
137
- @mode = :method
138
- }
139
- opt.on('--function', 'List functions.') {
140
- @mode = :function
141
- }
142
- opt.on('--help', 'Prints this message and quit.') {
143
- puts opt.help
144
- exit 0
145
- }
146
- }
147
- end
148
-
149
- def parse(argv)
150
- super
151
- unless @mode
152
- error 'one of (--library|--class|--method|--function) is required'
153
- end
154
- end
155
-
156
- def exec(db, argv)
157
- case @mode
158
- when :library
159
- db.libraries.map {|lib| lib.name }.sort.each do |name|
160
- puts name
161
- end
162
- when :class
163
- db.classes.map {|c| c.name }.sort.each do |name|
164
- puts name
165
- end
166
- when :method
167
- db.classes.sort_by {|c| c.name }.each do |c|
168
- c.entries.sort_by {|m| m.id }.each do |m|
169
- puts m.label
170
- end
171
- end
172
- when :function
173
- db.functions.sort_by {|f| f.name }.each do |f|
174
- puts f.name
175
- end
176
- else
177
- raise "must not happen: @mode=#{@mode.inspect}"
178
- end
179
- end
180
-
181
- end
182
-
183
-
184
- class LookupCommand < Subcommand
185
-
186
- def initialize
187
- @format = :text
188
- @type = nil
189
- @key = nil
190
- @parser = OptionParser.new {|opt|
191
- opt.banner = "Usage: #{File.basename($0, '.*')} lookup (--library|--class|--method|--function) [--html] <key>"
192
- opt.on('--library=NAME', 'Lookup library.') {|name|
193
- @type = :library
194
- @key = name
195
- }
196
- opt.on('--class=NAME', 'Lookup class.') {|name|
197
- @type = :class
198
- @key = name
199
- }
200
- opt.on('--method=NAME', 'Lookup method.') {|name|
201
- @type = :method
202
- @key = name
203
- }
204
- opt.on('--function=NAME', 'Lookup function.') {|name|
205
- @type = :function
206
- @key = name
207
- }
208
- opt.on('--html', 'Show result in HTML.') {
209
- @format = :html
210
- }
211
- opt.on('--help', 'Prints this message and quit.') {
212
- puts opt.help
213
- exit 0
214
- }
215
- }
216
- end
217
-
218
- def parse(argv)
219
- super
220
- unless @type
221
- error "one of --library/--class/--method/--function is required"
222
- end
223
- unless argv.empty?
224
- error "too many arguments"
225
- end
226
- end
227
-
228
- def exec(db, argv)
229
- entry = fetch_entry(db, @type, @key)
230
- puts fill_template(get_template(@type, @format), entry)
231
- end
232
-
233
- def fetch_entry(db, type, key)
234
- case type
235
- when :library
236
- db.fetch_library(key)
237
- when :class
238
- db.fetch_class(key)
239
- when :method
240
- db.fetch_method(BitClust::MethodSpec.parse(key))
241
- when :function
242
- db.fetch_function(key)
243
- else
244
- raise "must not happen: #{type.inspect}"
245
- end
246
- end
247
-
248
- def fill_template(template, entry)
249
- ERB.new(template).result(binding())
250
- end
251
-
252
- def get_template(type, format)
253
- template = TEMPLATE[type][format]
254
- BitClust::TextUtils.unindent_block(template.lines).join('')
255
- end
256
-
257
- TEMPLATE = {
258
- :library => {
259
- :text => <<-End,
260
- type: library
261
- name: <%= entry.name %>
262
- classes: <%= entry.classes.map {|c| c.name }.sort.join(', ') %>
263
- methods: <%= entry.methods.map {|m| m.name }.sort.join(', ') %>
264
-
265
- <%= entry.source %>
266
- End
267
- :html => <<-End
268
- <dl>
269
- <dt>type</dt><dd>library</dd>
270
- <dt>name</dt><dd><%= entry.name %></dd>
271
- <dt>classes</dt><dd><%= entry.classes.map {|c| c.name }.sort.join(', ') %></dd>
272
- <dt>methods</dt><dd><%= entry.methods.map {|m| m.name }.sort.join(', ') %></dd>
273
- </dl>
274
- <%= compile_rd(entry.source) %>
275
- End
276
- },
277
- :class => {
278
- :text => <<-End,
279
- type: class
280
- name: <%= entry.name %>
281
- library: <%= entry.library.name %>
282
- singleton_methods: <%= entry.singleton_methods.map {|m| m.name }.sort.join(', ') %>
283
- instance_methods: <%= entry.instance_methods.map {|m| m.name }.sort.join(', ') %>
284
- constants: <%= entry.constants.map {|m| m.name }.sort.join(', ') %>
285
- special_variables: <%= entry.special_variables.map {|m| '$' + m.name }.sort.join(', ') %>
286
-
287
- <%= entry.source %>
288
- End
289
- :html => <<-End
290
- <dl>
291
- <dt>type</dt><dd>class</dd>
292
- <dt>name</dt><dd><%= entry.name %></dd>
293
- <dt>library</dt><dd><%= entry.library.name %></dd>
294
- <dt>singleton_methods</dt><dd><%= entry.singleton_methods.map {|m| m.name }.sort.join(', ') %></dd>
295
- <dt>instance_methods</dt><dd><%= entry.instance_methods.map {|m| m.name }.sort.join(', ') %></dd>
296
- </dl>
297
- <%= compile_rd(entry.source) %>
298
- End
299
- },
300
- :method => {
301
- :text => <<-End,
302
- type: <%= entry.type %>
303
- name: <%= entry.name %>
304
- names: <%= entry.names.sort.join(', ') %>
305
- visibility: <%= entry.visibility %>
306
- kind: <%= entry.kind %>
307
- library: <%= entry.library.name %>
308
-
309
- <%= entry.source %>
310
- End
311
- :html => <<-End
312
- <dl>
313
- <dt>type</dt><dd><%= entry.type %></dd>
314
- <dt>name</dt><dd><%= entry.name %></dd>
315
- <dt>names</dt><dd><%= entry.names.sort.join(', ') %></dd>
316
- <dt>visibility</dt><dd><%= entry.visibility %></dd>
317
- <dt>kind</dt><dd><%= entry.kind %></dd>
318
- <dt>library</dt><dd><%= entry.library.name %></dd>
319
- </dl>
320
- <%= compile_rd(entry.source) %>
321
- End
322
- },
323
- :function => {
324
- :text => <<-End,
325
- kind: <%= entry.kind %>
326
- header: <%= entry.header %>
327
- filename: <%= entry.filename %>
328
-
329
- <%= entry.source %>
330
- End
331
- :html => <<-End
332
- <dl>
333
- <dt>kind</dt><dd><%= entry.kind %></dd>
334
- <dt>header</dt><dd><%= entry.header %></dd>
335
- <dt>filename</dt><dd><%= entry.filename %></dd>
336
- </dl>
337
- <%= compile_rd(entry.source) %>
338
- End
339
- }
340
- }
341
-
342
- def compile_rd(src)
343
- umap = BitClust::URLMapper.new(:base_url => 'http://example.com',
344
- :cgi_url => 'http://example.com/view')
345
- compiler = BitClust::RDCompiler.new(umap, 2)
346
- compiler.compile(src)
347
- end
348
-
349
- end
350
-
351
-
352
- class QueryCommand < Subcommand
353
-
354
- def initialize
355
- @parser = OptionParser.new {|opt|
356
- opt.banner = "Usage: #{File.basename($0, '.*')} query <ruby-script>"
357
- opt.on('--help', 'Prints this message and quit.') {
358
- puts opt.help
359
- exit 0
360
- }
361
- }
362
- end
363
-
364
- def parse(argv)
365
- end
366
-
367
- def exec(db, argv)
368
- argv.each do |query|
369
- #pp eval(query) # FIXME: causes ArgumentError
370
- p eval(query)
371
- end
372
- end
373
- end
374
-
375
-
376
- class PropertyCommand < Subcommand
377
-
378
- def initialize
379
- @mode = nil
380
- @parser = OptionParser.new {|opt|
381
- opt.banner = "Usage: #{File.basename($0, '.*')} property [options]"
382
- opt.on('--list', 'List all properties.') {
383
- @mode = :list
384
- }
385
- opt.on('--get', 'Get property value.') {
386
- @mode = :get
387
- }
388
- opt.on('--set', 'Set property value.') {
389
- @mode = :set
390
- }
391
- opt.on('--help', 'Prints this message and quit.') {
392
- puts opt.help
393
- exit 0
394
- }
395
- }
396
- end
397
-
398
- def parse(argv)
399
- super
400
- unless @mode
401
- error "one of (--list|--get|--set) is required"
402
- end
403
- case @mode
404
- when :list
405
- unless argv.empty?
406
- error "--list requires no argument"
407
- end
408
- when :get
409
- ;
410
- when :set
411
- unless argv.size == 2
412
- error "--set requires just 2 arguments"
413
- end
414
- else
415
- raise "must not happen: #{@mode}"
416
- end
417
- end
418
-
419
- def exec(db, argv)
420
- case @mode
421
- when :list
422
- db.properties.each do |key, val|
423
- puts "#{key}=#{val}"
424
- end
425
- when :get
426
- argv.each do |key|
427
- puts db.propget(key)
428
- end
429
- when :set
430
- key, val = *argv
431
- db.transaction {
432
- db.propset key, val
433
- }
434
- else
435
- raise "must not happen: #{@mode}"
436
- end
437
- end
438
-
439
- end
440
-
441
- class SetupCommand < Subcommand
442
-
443
- REPOSITORY_PATH = "http://jp.rubyist.net/svn/rurema/doctree/trunk"
444
-
445
- def initialize
446
- @prepare = nil
447
- @cleanup = nil
448
- @versions = ["1.8.7", "1.9.3"]
449
- @parser = OptionParser.new {|opt|
450
- opt.banner = "Usage: #{File.basename($0, '.*')} setup [options]"
451
- opt.on('--prepare', 'Prepare config file and checkout repository. Do not create database.') {
452
- @prepare = true
453
- }
454
- opt.on('--cleanup', 'Cleanup datebase before create database.') {
455
- @cleanup = true
456
- }
457
- opt.on('--versions=V1,V2,...', "Specify versions. [#{@versions.join(',')}]") {|versions|
458
- @versions = versions.split(",")
459
- }
460
- opt.on('--help', 'Prints this message and quit.') {
461
- puts opt.help
462
- exit 0
463
- }
464
- }
465
- end
466
-
467
- def exec(db, argv)
468
- prepare
469
- return if @prepare
470
- @config[:versions].each do |version|
471
- puts "Generating database for Ruby#{version}..."
472
- prefix = "#{@config[:database_prefix]}-#{version}"
473
- FileUtils.rm_rf(prefix) if @cleanup
474
- init_argv = ["version=#{version}", "encoding=#{@config[:encoding]}"]
475
- db = BitClust::MethodDatabase.new(prefix)
476
- InitCommand.new.exec(db, init_argv)
477
- update_method_database(prefix, ["--stdlibtree=#{@config[:stdlibtree]}"])
478
- argv = Pathname(@config[:capi_src]).children.select(&:file?).map{|v| v.realpath.to_s }
479
- update_function_database(prefix, argv)
480
- end
481
- end
482
-
483
- private
484
-
485
- def prepare
486
- home_directory = Pathname(ENV["HOME"])
487
- config_dir = home_directory + ".bitclust"
488
- config_dir.mkpath
489
- config_path = config_dir + "config"
490
- rubydoc_dir = config_dir + "rubydoc"
491
- @config = {
492
- :database_prefix => (config_dir + "db").to_s,
493
- :encoding => "utf-8",
494
- :versions => @versions,
495
- :default_version => @versions.max,
496
- :stdlibtree => (rubydoc_dir + "refm/api/src").to_s,
497
- :capi_src => (rubydoc_dir + "refm/capi/src/").to_s,
498
- :baseurl => "http://localhost:10080",
499
- :port => "10080",
500
- :pid_file => "/tmp/bitclust.pid",
501
- }
502
- if config_path.exist?
503
- @config = YAML.load_file(config_path)
504
- unless @config[:versions].sort == @versions.sort
505
- print("overwrite config file? > [y/N]")
506
- if /\Ay\z/i =~ $stdin.gets.chomp
507
- @config[:versions] = @versions
508
- @config[:default_version] = @versions.max
509
- generate_config(config_path, @config)
510
- end
511
- end
512
- else
513
- generate_config(config_path, @config)
514
- end
515
- checkout(rubydoc_dir)
516
- end
517
-
518
- def generate_config(path, config)
519
- path.open("w+", 0644) do |file|
520
- file.puts config.to_yaml
521
- end
522
- end
523
-
524
- def checkout(rubydoc_dir)
525
- # FIXME Is this working on Windows?
526
- unless system("which svn > /dev/null")
527
- warn "svn command is not found. Please install Subversion."
528
- exit 1
529
- end
530
- system("svn", "co", REPOSITORY_PATH, rubydoc_dir.to_s)
531
- end
532
-
533
- def update_method_database(prefix, argv)
534
- db = BitClust::MethodDatabase.new(prefix)
535
- cmd = UpdateCommand.new
536
- cmd.parse(argv)
537
- cmd.exec(db, argv)
538
- end
539
-
540
- def update_function_database(prefix, argv)
541
- db = BitClust::FunctionDatabase.new(prefix)
542
- cmd = UpdateCommand.new
543
- cmd.parse(argv)
544
- cmd.exec(db, argv)
545
- end
546
-
547
- end
548
-
549
- class ServerCommand < Subcommand
550
-
551
- def initialize
552
- require 'webrick'
553
- require 'uri'
554
-
555
- @params = {
556
- :BindAddress => "0.0.0.0",
557
- :Port => 10080
558
- }
559
- @baseurl = nil
560
- @dbpath = nil
561
- @srcdir = @datadir = @themedir = @theme = @templatedir = nil
562
- @encoding = 'utf-8' # encoding of view
563
- if Object.const_defined?(:Encoding)
564
- Encoding.default_external = @encoding
565
- end
566
-
567
- @debugp = false
568
- @autop = false
569
- @browser = nil
570
- @pid_file = nil
571
- @capi = false
572
-
573
- @parser = OptionParser.new
574
- @parser.banner = "#{$0} [--bind-address=ADDR] [--port=NUM] --baseurl=URL --database=PATH [--srcdir=PATH] [--datadir=PATH] [--themedir=PATH] [--debug] [--auto] [--browser=BROWSER] [--pid-file=PATH] [--capi]"
575
- @parser.on('--bind-address=ADDR', 'Bind address') {|addr|
576
- @params[:BindAddress] = addr
577
- }
578
- @parser.on('--port=NUM', 'Listening port number') {|num|
579
- @params[:Port] = num.to_i
580
- }
581
- @parser.on('--baseurl=URL', 'The base URL to host.') {|url|
582
- @baseurl = url
583
- }
584
- @parser.on('--database=PATH', 'MethodDatabase root directory.') {|path|
585
- @dbpath = path
586
- }
587
- @parser.on('--srcdir=PATH', 'BitClust source directory.') {|path|
588
- @set_srcdir.call path
589
- }
590
- @parser.on('--datadir=PATH', 'BitClust data directory.') {|path|
591
- @datadir = path
592
- }
593
- @parser.on('--templatedir=PATH', 'Template directory.') {|path|
594
- @templatedir = path
595
- }
596
- @parser.on('--themedir=PATH', 'BitClust theme directory.') {|path|
597
- @themedir = path
598
- }
599
- @parser.on('--theme=THEME', 'BitClust theme.') {|th|
600
- @theme = th
601
- }
602
- @parser.on('--[no-]debug', 'Debug mode.') {|flag|
603
- @debugp = flag
604
- }
605
- @parser.on('--[no-]auto', 'Auto mode.') {|flag|
606
- @autop = flag
607
- }
608
- @parser.on('--browser=BROWSER', 'Open with the browser.') {|path|
609
- @browser = path
610
- }
611
- @parser.on('--pid-file=PATH', 'Write pid of the daemon to the specified file.') {|path|
612
- @pid_file = path
613
- }
614
- @parser.on('--help', 'Prints this message and quit.') {
615
- puts @parser.help
616
- exit 0
617
- }
618
- @parser.on('--capi', 'see also FunctionDatabase.') {|path|
619
- @capi = true
620
- }
621
- end
622
-
623
- def parse(argv)
624
- super
625
- load_config_file
626
- set_srcdir(srcdir_root) unless @srcdir
627
-
628
- unless @baseurl
629
- $stderr.puts "missing base URL. Use --baseurl or check ~/.bitclust/config"
630
- exit 1
631
- end
632
- unless @dbpath || @autop
633
- $stderr.puts "missing database path. Use --database"
634
- exit 1
635
- end
636
- unless @datadir
637
- $stderr.puts "missing datadir. Use --datadir"
638
- exit 1
639
- end
640
- unless @themedir
641
- $stderr.puts "missing themedir. Use --themedir"
642
- exit 1
643
- end
644
- if @pid_file
645
- if File.exist?(@pid_file)
646
- $stderr.puts "There is still #{@pid_file}. Is another process running?"
647
- exit 1
648
- end
649
- @pid_file = File.expand_path(@pid_file)
650
- end
651
- end
652
-
653
- def exec(db, argv)
654
- require 'bitclust/app'
655
- if @debugp
656
- @params[:Logger] = WEBrick::Log.new($stderr, WEBrick::Log::DEBUG)
657
- @params[:AccessLog] = [
658
- [ $stderr, WEBrick::AccessLog::COMMON_LOG_FORMAT ],
659
- [ $stderr, WEBrick::AccessLog::REFERER_LOG_FORMAT ],
660
- [ $stderr, WEBrick::AccessLog::AGENT_LOG_FORMAT ],
661
- ]
662
- else
663
- @params[:Logger] = WEBrick::Log.new($stderr, WEBrick::Log::INFO)
664
- @params[:AccessLog] = []
665
- end
666
- basepath = URI.parse(@baseurl).path
667
- server = WEBrick::HTTPServer.new(@params)
668
-
669
- if @autop
670
- app = BitClust::App.new(
671
- :dbpath => Dir.glob("#{@database_prefix}-*"),
672
- :baseurl => @baseurl,
673
- :datadir => @datadir,
674
- :templatedir => @templatedir,
675
- :theme => @theme,
676
- :encoding => @encoding,
677
- :capi => @capi
678
- )
679
- app.interfaces.each do |version, interface|
680
- server.mount(File.join(basepath, version), interface)
681
- end
682
- server.mount(File.join(basepath, '/'), app)
683
- else
684
- viewpath = File.join(basepath, 'view')
685
- app = BitClust::App.new(
686
- :viewpath => viewpath,
687
- :dbpath => @dbpath,
688
- :baseurl => @baseurl,
689
- :datadir => @datadir,
690
- :templatedir => @templatedir,
691
- :theme => @theme,
692
- :encoding => @encoding,
693
- :capi => @capi
694
- )
695
- app.interfaces.each do |viewpath, interface|
696
- server.mount viewpath, interface
697
- end
698
- # Redirect from '/' to "#{viewpath}/"
699
- server.mount('/', app)
700
- end
701
-
702
- server.mount File.join(basepath, 'theme/'), WEBrick::HTTPServlet::FileHandler, @themedir
703
-
704
- if @debugp
705
- trap(:INT) { server.shutdown }
706
- else
707
- WEBrick::Daemon.start do
708
- trap(:TERM) {
709
- server.shutdown
710
- begin
711
- File.unlink @pid_file if @pid_file
712
- rescue Errno::ENOENT
713
- end
714
- }
715
- File.open(@pid_file, 'w') {|f| f.write Process.pid } if @pid_file
716
- end
717
- end
718
- exit if $".include?("exerb/mkexy.rb")
719
- if @autop && !@browser
720
- case RUBY_PLATFORM
721
- when /mswin/
722
- @browser = "start"
723
- end
724
- end
725
- system("#{browser} http://localhost:#{params[:Port]}/") if @browser
726
- server.start
727
- end
728
-
729
- private
730
-
731
- def srcdir_root
732
- Pathname.new(__FILE__).realpath.dirname.parent.parent.cleanpath
733
- end
734
-
735
- def set_srcdir(dir)
736
- @srcdir ||= dir
737
- @datadir ||= "#{@srcdir}/data/bitclust"
738
- @themedir ||= "#{@srcdir}/theme"
739
- end
740
-
741
- def load_config_file
742
- home_directory = Pathname(ENV['HOME'])
743
- config_path = home_directory + ".bitclust/config"
744
- if config_path.exist?
745
- config = YAML.load_file(config_path)
746
- @baseurl ||= config[:baseurl]
747
- @dbpath ||= "#{config[:database_prefix]}-#{config[:default_version]}"
748
- @port ||= config[:port]
749
- @pid_file ||= config[:pid_file]
750
- @database_prefix ||= config[:database_prefix]
751
- end
752
- end
753
-
29
+ module BitClust
30
+ module Subcommands
754
31
  end
755
-
756
32
  end
33
+