bitclust-core 1.7.0 → 1.8.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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/data/bitclust/template/class-index +0 -1
  3. data/data/bitclust/template.epub/class +5 -5
  4. data/data/bitclust/template.epub/class-index +0 -1
  5. data/data/bitclust/template.epub/contents +7 -4
  6. data/data/bitclust/template.epub/layout +4 -4
  7. data/data/bitclust/template.offline/class-index +0 -1
  8. data/lib/bitclust/generators/epub.rb +69 -5
  9. data/lib/bitclust/irb.rb +14 -8
  10. data/lib/bitclust/markdown_bridge.rb +11 -6
  11. data/lib/bitclust/markdown_tree.rb +118 -11
  12. data/lib/bitclust/methoddatabase.rb +17 -4
  13. data/lib/bitclust/nameutils.rb +13 -0
  14. data/lib/bitclust/preprocessor.rb +0 -36
  15. data/lib/bitclust/remote.rb +405 -0
  16. data/lib/bitclust/runner.rb +5 -10
  17. data/lib/bitclust/screen.rb +2 -1
  18. data/lib/bitclust/searcher.rb +43 -24
  19. data/lib/bitclust/subcommands/chm_command.rb +1 -1
  20. data/lib/bitclust/subcommands/epub_command.rb +2 -2
  21. data/lib/bitclust/subcommands/extract_command.rb +7 -0
  22. data/lib/bitclust/subcommands/htmlfile_command.rb +7 -0
  23. data/lib/bitclust/subcommands/methods_command.rb +5 -28
  24. data/lib/bitclust/subcommands/query_command.rb +1 -0
  25. data/lib/bitclust/subcommands/server_command.rb +21 -10
  26. data/lib/bitclust/subcommands/setup_command.rb +28 -10
  27. data/lib/bitclust/syntax_highlighter.rb +65 -4
  28. data/lib/bitclust/user_dirs.rb +62 -0
  29. data/lib/bitclust/version.rb +1 -1
  30. data/test/test_chm_command.rb +22 -0
  31. data/test/test_epub_command.rb +60 -0
  32. data/test/test_epub_generator.rb +330 -0
  33. data/test/test_extract_command.rb +45 -0
  34. data/test/test_irb_plugin.rb +100 -6
  35. data/test/test_markdown_bridge.rb +35 -0
  36. data/test/test_markdown_tree.rb +144 -0
  37. data/test/test_mdparser.rb +39 -0
  38. data/test/test_methods_command.rb +32 -0
  39. data/test/test_opensearchdescription_screen.rb +39 -0
  40. data/test/test_query_command.rb +30 -0
  41. data/test/test_remote.rb +374 -0
  42. data/test/test_runner.rb +61 -1
  43. data/test/test_searcher.rb +63 -0
  44. data/test/test_server_command.rb +41 -0
  45. data/test/test_setup_command.rb +143 -0
  46. data/test/test_syntax_highlighter.rb +124 -0
  47. data/test/test_user_dirs.rb +62 -0
  48. metadata +37 -2
  49. data/lib/bitclust/ridatabase.rb +0 -359
@@ -1,359 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'rdoc/ri/ri_reader'
3
- require 'rdoc/ri/ri_cache'
4
- require 'rdoc/ri/ri_paths'
5
-
6
- class ApplicationError < StandardError; end
7
- class RiClassNotFound < ApplicationError; end
8
-
9
- # Handle RDoc(ri) database for tools/bc-rdoc.rb and
10
- # `bitclust methods --diff`.
11
- class RiDatabase
12
- def RiDatabase.open_system_db
13
- new(RI::Paths.path(true, false, false, false), RUBY_VERSION)
14
- end
15
-
16
- def RiDatabase.open(dir, version)
17
- new(RI::Paths.path(false, false, false, false, dir), version)
18
- end
19
-
20
- def initialize(ripath, version)
21
- @ripath = ripath
22
- @reader = RI::RiReader.new(RI::RiCache.new(@ripath))
23
- @version = version
24
- end
25
-
26
- attr_reader :version
27
-
28
- def get_method(m)
29
- @reader.get_method(m)
30
- end
31
-
32
- def current_class=(name)
33
- @klass = lookup_class(name)
34
- @singleton_methods = wrap_entries(@reader.singleton_methods(@klass))
35
- @instance_methods = wrap_entries(@reader.instance_methods(@klass))
36
- rescue RiClassNotFound
37
- @klass = nil
38
- @singleton_methods = []
39
- @instance_methods = []
40
- end
41
-
42
- attr_reader :class
43
- attr_reader :singleton_methods
44
- attr_reader :instance_methods
45
-
46
- def lookup_class(name)
47
- ns = @reader.top_level_namespace.first
48
- name.split('::').each do |const|
49
- ns = ns.contained_class_named(const) or
50
- raise RiClassNotFound, "no such class in RDoc database: #{name}"
51
- end
52
- ns
53
- end
54
-
55
- private
56
-
57
- def wrap_entries(ents)
58
- ents.map {|m|
59
- [RiMethodEntry.new(m.name, m)] +
60
- m.aliases.map {|a| RiMethodEntry.new(a.name, m) }
61
- }.flatten.uniq
62
- end
63
- end
64
-
65
- class Ent
66
- def initialize(name, ent)
67
- @name = name
68
- @entry = ent
69
- end
70
-
71
- attr_reader :name
72
- attr_reader :entry
73
-
74
- def ==(other)
75
- return false if self.class != other.class
76
- @name == other.name
77
- end
78
-
79
- alias eql? ==
80
-
81
- def hash
82
- @name.hash
83
- end
84
-
85
- def <=>(other)
86
- @name <=> other.name
87
- end
88
- end
89
-
90
- class BCMethodEntry < Ent
91
- def bitclust?
92
- true
93
- end
94
-
95
- def inspect
96
- "\#<BitClust #{@name} #{@entry.inspect}>"
97
- end
98
-
99
- def fullname
100
- "#{@entry.klass.name}#{@entry.typemark}#{@name}"
101
- end
102
-
103
- def id
104
- if @entry.defined?
105
- fullname()
106
- else
107
- "#{fullname()}.#{@entry.library.name}"
108
- end
109
- end
110
- end
111
-
112
- class RiMethodEntry < Ent
113
- def bitclust?
114
- false
115
- end
116
-
117
- def inspect
118
- "\#<RDoc #{@name} #{@entry.fullname}>"
119
- end
120
-
121
- def singleton_method?
122
- @entry.singleton_method?
123
- end
124
-
125
- def fullname
126
- c, t = @entry.fullname.split(/([\.\#])/, 2)
127
- "#{c}#{t}#{@name}"
128
- end
129
- end
130
-
131
-
132
- module RI
133
-
134
- class RiReader # reopen
135
- def singleton_methods(c)
136
- c.singleton_methods.map {|ent| get_method(ent) }
137
- end
138
-
139
- def instance_methods(c)
140
- c.instance_methods.map {|ent| get_method(ent) }
141
- end
142
- end
143
-
144
- class ClassEntry # reopen
145
- def singleton_methods
146
- @class_methods
147
- end
148
-
149
- attr_reader :instance_methods
150
-
151
- def method_entries
152
- @class_methods.sort_by {|m| m.name } +
153
- @instance_methods.sort_by {|m| m.name }
154
- end
155
- end
156
-
157
- class MethodEntry # reopen
158
- def fullname
159
- "#{@in_class.full_name}#{@is_class_method ? '.' : '#'}#{@name}"
160
- end
161
-
162
- def singleton_method?
163
- @is_class_method
164
- end
165
- end
166
-
167
- class MethodDescription # reopen
168
- def fullname
169
- name = full_name()
170
- unless /\#/ =~ name
171
- components = name.split('::')
172
- m = components.pop || raise
173
- components.join('::') + '.' + m
174
- else
175
- name
176
- end
177
- end
178
-
179
- def singleton_method?
180
- @is_class_method ||= false
181
- @is_class_method
182
- end
183
- end
184
-
185
- end
186
-
187
-
188
- module HTMLUtils
189
-
190
- ESC = {
191
- '&' => '&amp;',
192
- '<' => '&lt;',
193
- '>' => '&gt;',
194
- '"' => '&quot;'
195
- }
196
-
197
- def escape(str)
198
- t = ESC
199
- str.gsub(/[&"<>]/) {|s| t[s] }
200
- end
201
- module_function :escape
202
-
203
- UNESC = ESC.invert
204
- UNESC['&nbsp;'] = ' '
205
-
206
- def unescape(str)
207
- t = UNESC
208
- str.gsub(/&\w+;/) {|s| t[s] || s }
209
- end
210
- module_function :unescape
211
-
212
- end
213
-
214
-
215
- class Formatter
216
-
217
- include HTMLUtils
218
-
219
- def method_info(m)
220
- @f = StringIO.new
221
- describe_method m
222
- @f.string
223
- end
224
-
225
- private
226
-
227
- def line(s = nil)
228
- if s
229
- @f.puts s
230
- else
231
- @f.puts
232
- end
233
- end
234
-
235
- def describe_method(m)
236
- if m.params[0,1] == '('
237
- line "--- #{m.full_name}#{trim_space(m.params)}"
238
- else
239
- m.params.lines.each do |sig|
240
- line "--- #{trim_sig(sig)}#%todo\n"
241
- end
242
- end
243
- unless m.aliases.empty?
244
- m.aliases.each do |a|
245
- line "alias #{a.name}"
246
- end
247
- end
248
- #line "\#@TODO rewrite me"
249
- line
250
- @f.puts format_elements(m.comment)
251
- line
252
- end
253
-
254
- def trim_space(s)
255
- s.sub(/\(\s+/, '(').sub(/\s+\)/, ')').sub(/\(\)/, '')
256
- end
257
-
258
- def trim_sig(s)
259
- s = trim_space(s)
260
- s.sub!(/\A[a-z]\w+\./, '')
261
- s.sub!(/=>/, '->')
262
- # steep:ignore:start
263
- s.sub!(/(->.*)\bstr(ing)?\b/){ $1 + 'String' }
264
- s.sub!(/(->.*)\bint(eger)?\b/){ $1 + 'Integer' }
265
- s.sub!(/(->.*)\b(an_)?obj\b/){ $1 + 'object' }
266
- s.sub!(/(->.*)\b(a_)?hash\b/){ $1 + 'Hash' }
267
- s.sub!(/(->.*)\b(an_)?array\b/){ $1 + 'Array' }
268
- # steep:ignore:end
269
- s.sub!(/ or /, ' | ')
270
- s
271
- end
272
-
273
- def format_elements(elems)
274
- return "" unless elems
275
- return "" if elems.empty?
276
- elems.map {|elem| format_element(elem) }.join("\n\n")
277
- end
278
-
279
- def format_element(e)
280
- # steep:ignore:start
281
- case e
282
- when SM::Flow::P, SM::Flow::LI
283
- paragraph(e)
284
- when SM::Flow::LIST
285
- list(e)
286
- when SM::Flow::VERB
287
- verbatim(e)
288
- when SM::Flow::H
289
- headline(e)
290
- when SM::Flow::RULE
291
- ;
292
- else
293
- raise "unkwnown markup: #{e.class}"
294
- end
295
- # steep:ignore:end
296
- end
297
-
298
- def headline(e)
299
- h = '==' + ('=' * e.level)
300
- text = unescape(e.text)
301
- "#{h} #{text}"
302
- end
303
-
304
- def paragraph(e)
305
- wrap(unescape(remove_inline(e.body)))
306
- end
307
-
308
- def verbatim(e)
309
- unescape(e.body.rstrip) #.gsub(/^/, ' ')
310
- end
311
-
312
- def list(e)
313
- # steep:ignore:start
314
- case e.type
315
- when SM::ListBase::BULLET
316
- e.contents.map {|item| "* #{format_element(e)}" }.join("\n")
317
- when SM::ListBase::NUMBER,
318
- SM::ListBase::LOWERALPHA,
319
- SM::ListBase::UPPERALPHA
320
- num = case e.type
321
- when SM::ListBase::NUMBER then '1'
322
- when SM::ListBase::LOWERALPHA then 'a'
323
- when SM::ListBase::UPPERALPHA then 'A'
324
- end
325
- e.contents.map {|item|
326
- str = "#{num}. #{format_element(e)}"
327
- num = num.succ
328
- str
329
- }.join("\n")
330
- when SM::ListBase::LABELED
331
- e.contents.map {|item| "#{item.label} #{format_element(e)}" }.join("\n")
332
- when SM::ListBase::NOTE
333
- e.contents.map {|item| "#{item.label}\t#{format_element(e)}" }.join("\n")
334
- else
335
- raise "unknown list type: #{e.type.inspect}"
336
- end
337
- # steep:ignore:end
338
- end
339
-
340
- def remove_inline(str)
341
- str.gsub(/<\/?\w+>/, '')
342
- end
343
-
344
- def wrap(str)
345
- width = 60
346
- buf = ''
347
- line = ''
348
- str.split.each do |chunk|
349
- line << chunk << ' '
350
- if line.size > width
351
- buf << line.strip << "\n"
352
- line = ''
353
- end
354
- end
355
- buf << line
356
- buf.strip
357
- end
358
-
359
- end