bitclust-core 0.5.4 → 0.5.5

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.
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
+