bitclust-core 1.2.1 → 1.2.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/data/bitclust/catalog/ja_JP.UTF-8 +4 -0
  3. data/data/bitclust/template.lillia/layout +1 -1
  4. data/data/bitclust/template.offline/class +127 -34
  5. data/data/bitclust/template.offline/class-index +33 -6
  6. data/data/bitclust/template.offline/doc +41 -8
  7. data/data/bitclust/template.offline/function +42 -9
  8. data/data/bitclust/template.offline/function-index +33 -7
  9. data/data/bitclust/template.offline/layout +21 -14
  10. data/data/bitclust/template.offline/library +48 -12
  11. data/data/bitclust/template.offline/library-index +33 -6
  12. data/data/bitclust/template.offline/method +56 -11
  13. data/lib/bitclust/classentry.rb +13 -2
  14. data/lib/bitclust/compat.rb +8 -0
  15. data/lib/bitclust/completion.rb +1 -0
  16. data/lib/bitclust/docentry.rb +4 -2
  17. data/lib/bitclust/entry.rb +3 -0
  18. data/lib/bitclust/functionentry.rb +8 -7
  19. data/lib/bitclust/functionreferenceparser.rb +2 -0
  20. data/lib/bitclust/libraryentry.rb +4 -1
  21. data/lib/bitclust/lineinput.rb +6 -2
  22. data/lib/bitclust/methoddatabase.rb +3 -0
  23. data/lib/bitclust/methodentry.rb +10 -8
  24. data/lib/bitclust/methodid.rb +1 -0
  25. data/lib/bitclust/nameutils.rb +15 -11
  26. data/lib/bitclust/preprocessor.rb +26 -21
  27. data/lib/bitclust/rdcompiler.rb +29 -19
  28. data/lib/bitclust/requesthandler.rb +3 -3
  29. data/lib/bitclust/ridatabase.rb +2 -1
  30. data/lib/bitclust/rrdparser.rb +19 -20
  31. data/lib/bitclust/screen.rb +39 -4
  32. data/lib/bitclust/silent_progress_bar.rb +8 -4
  33. data/lib/bitclust/simplesearcher.rb +1 -1
  34. data/lib/bitclust/subcommand.rb +9 -0
  35. data/lib/bitclust/subcommands/chm_command.rb +3 -3
  36. data/lib/bitclust/subcommands/methods_command.rb +1 -1
  37. data/lib/bitclust/subcommands/server_command.rb +6 -1
  38. data/lib/bitclust/subcommands/setup_command.rb +2 -2
  39. data/lib/bitclust/subcommands/statichtml_command.rb +44 -21
  40. data/lib/bitclust/syntax_highlighter.rb +5 -3
  41. data/lib/bitclust/version.rb +1 -1
  42. data/test/test_bitclust.rb +1 -1
  43. data/test/test_entry.rb +14 -1
  44. data/test/test_functionreferenceparser.rb +4 -4
  45. data/test/test_preprocessor.rb +21 -0
  46. data/test/test_rdcompiler.rb +240 -0
  47. data/test/test_rrdparser.rb +16 -0
  48. data/test/test_syntax_highlighter.rb +22 -4
  49. data/theme/default/rurema.png +0 -0
  50. data/theme/default/rurema.svg +31 -0
  51. data/theme/default/script.js +34 -0
  52. data/theme/default/style.css +112 -8
  53. metadata +32 -19
@@ -9,6 +9,7 @@
9
9
  #
10
10
 
11
11
  require 'stringio'
12
+ require 'bitclust/parseutils'
12
13
 
13
14
  # Utility class for line-wise file parsing
14
15
  class LineInput
@@ -34,7 +35,7 @@ class LineInput
34
35
  end
35
36
 
36
37
  def path
37
- @input.path
38
+ @input.path if @input.respond_to?(:path)
38
39
  end
39
40
 
40
41
  def name
@@ -52,12 +53,15 @@ class LineInput
52
53
  def gets
53
54
  unless @buf.empty?
54
55
  @lineno += 1
55
- return @buf.pop
56
+ line = @buf.pop
57
+ line&.location ||= BitClust::Location.new(path, @lineno)
58
+ return line
56
59
  end
57
60
  return nil if @eof_p # to avoid ARGF blocking.
58
61
  line = @input.gets
59
62
  @eof_p = true unless line
60
63
  @lineno += 1
64
+ line&.location ||= BitClust::Location.new(path, @lineno)
61
65
  line
62
66
  end
63
67
 
@@ -175,14 +175,17 @@ module BitClust
175
175
  end
176
176
 
177
177
  def copy_doc
178
+ root_path = Pathname.new(@root).expand_path
178
179
  Dir.glob("#{@root}/../../doc/**/*.rd").each do |f|
179
180
  if %r!\A#{Regexp.escape(@root)}/\.\./\.\./doc/([-\./\w]+)\.rd\z! =~ f
180
181
  id = libname2id($1)
181
182
  se = DocEntry.new(self, id)
182
183
  s = Preprocessor.read(f, properties)
183
184
  title, source = RRDParser.split_doc(s)
185
+ relative_path = Pathname.new(f).expand_path(@root).relative_path_from(root_path)
184
186
  se.title = title
185
187
  se.source = source
188
+ se.source_location = Location.new(relative_path, 1)
186
189
  se.save
187
190
  end
188
191
  end
@@ -29,6 +29,7 @@ module BitClust
29
29
  attr_reader :id
30
30
 
31
31
  def ==(other)
32
+ return false if self.class != other.class
32
33
  @id == other.id
33
34
  end
34
35
 
@@ -94,14 +95,15 @@ module BitClust
94
95
  attr_writer :klass
95
96
 
96
97
  persistent_properties {
97
- property :names, '[String]'
98
- property :visibility, 'Symbol' # :public | :private | :protected
99
- property :kind, 'Symbol' # :defined | :added | :redefined
100
- property :source, 'String'
98
+ property :names, '[String]'
99
+ property :visibility, 'Symbol' # :public | :private | :protected
100
+ property :kind, 'Symbol' # :defined | :added | :redefined
101
+ property :source, 'String'
102
+ property :source_location, 'Location'
101
103
  }
102
104
 
103
105
  def inspect
104
- c, t, m, lib = methodid2specparts(@id)
106
+ c, t, _m, _lib = methodid2specparts(@id)
105
107
  "\#<method #{c}#{t}#{names().join(',')}>"
106
108
  end
107
109
 
@@ -114,12 +116,12 @@ module BitClust
114
116
  end
115
117
 
116
118
  def label
117
- c, t, m, lib = methodid2specparts(@id)
119
+ c, t, m, _lib = methodid2specparts(@id)
118
120
  "#{t == '$' ? '' : c}#{t}#{m}"
119
121
  end
120
122
 
121
123
  def short_label
122
- c, t, m, lib = methodid2specparts(@id)
124
+ _c, t, m, _lib = methodid2specparts(@id)
123
125
  "#{t == '#' ? '' : t}#{m}"
124
126
  end
125
127
 
@@ -128,7 +130,7 @@ module BitClust
128
130
  end
129
131
 
130
132
  def labels
131
- c, t, m, lib = methodid2specparts(@id)
133
+ c, t, _m, _lib = methodid2specparts(@id)
132
134
  names().map {|name| "#{c}#{t}#{name}" }
133
135
  end
134
136
 
@@ -93,6 +93,7 @@ module BitClust
93
93
  end
94
94
 
95
95
  def ==(other)
96
+ return false if self.class != other.class
96
97
  @klass == other.klass and
97
98
  @type == other.type and
98
99
  @method == other.method
@@ -19,8 +19,8 @@ module BitClust
19
19
  LIBNAME_RE = %r<[\w\-]+(/[\w\-]+)*>
20
20
  CONST_RE = /[A-Z]\w*/
21
21
  CONST_PATH_RE = /#{CONST_RE}(?:::#{CONST_RE})*/
22
- CLASS_NAME_RE = /(?:#{CONST_RE}(?:::compatible)?|fatal|ARGF.class|main)/
23
- CLASS_PATH_RE = /(?:#{CONST_PATH_RE}(?:::compatible)?|fatal|ARGF.class|main)/
22
+ CLASS_NAME_RE = /(?:#{CONST_RE}(?:::compatible)?|fatal|ARGF\.class|main)/
23
+ CLASS_PATH_RE = /(?:#{CONST_PATH_RE}(?:::compatible)?|fatal|ARGF\.class|main)/
24
24
  METHOD_NAME_RE = /\w+[?!=]?|===|==|=~|<=>|<=|>=|!=|!~|!@|!|\[\]=|\[\]|\*\*|>>|<<|\+@|\-@|[~+\-*\/%&|^<>`]/
25
25
  TYPEMARK_RE = /(?:\.|\#|\.\#|::|\$)/
26
26
  METHOD_SPEC_RE = /#{CLASS_PATH_RE}#{TYPEMARK_RE}#{METHOD_NAME_RE}/
@@ -67,7 +67,7 @@ module BitClust
67
67
  end
68
68
 
69
69
  def methodid2specstring(id)
70
- c, t, m, lib = *split_method_id(id)
70
+ c, t, m, _lib = *split_method_id(id)
71
71
  classid2name(c) + typechar2mark(t) + decodename_url(m)
72
72
  end
73
73
 
@@ -77,32 +77,32 @@ module BitClust
77
77
  end
78
78
 
79
79
  def methodid2libid(id)
80
- c, t, m, lib = *split_method_id(id)
80
+ _c, _t, _m, lib = *split_method_id(id)
81
81
  lib
82
82
  end
83
83
 
84
84
  def methodid2classid(id)
85
- c, t, m, lib = *split_method_id(id)
85
+ c, _t, _m, _lib = *split_method_id(id)
86
86
  c
87
87
  end
88
88
 
89
89
  def methodid2typechar(id)
90
- c, t, m, lib = *split_method_id(id)
90
+ _c, t, _m, _lib = *split_method_id(id)
91
91
  t
92
92
  end
93
93
 
94
94
  def methodid2typename(id)
95
- c, t, m, lib = *split_method_id(id)
95
+ _c, t, _m, _lib = *split_method_id(id)
96
96
  typechar2name(t)
97
97
  end
98
98
 
99
99
  def methodid2typemark(id)
100
- c, t, m, lib = *split_method_id(id)
100
+ _c, t, _m, _lib = *split_method_id(id)
101
101
  typechar2mark(t)
102
102
  end
103
103
 
104
104
  def methodid2mname(id)
105
- c, t, m, lib = *split_method_id(id)
105
+ _c, _t, m, _lib = *split_method_id(id)
106
106
  decodename_url(m)
107
107
  end
108
108
 
@@ -120,10 +120,14 @@ module BitClust
120
120
  "#{cid}/#{typename2char(t)}.#{encodename_url(name)}.#{libid}"
121
121
  end
122
122
 
123
+ @@split_method_id = {}
124
+
123
125
  # private module function
124
126
  def split_method_id(id)
125
- c, rest = id.split("/")
126
- return *[c, *rest.split(%r<[/\.]>, 3)]
127
+ @@split_method_id[id] ||= begin
128
+ c, rest = id.split("/")
129
+ [c, *rest.split(%r<[/\.]>, 3)]
130
+ end
127
131
  end
128
132
 
129
133
  NAME_TO_MARK = {
@@ -71,11 +71,20 @@ module BitClust
71
71
  cond_init
72
72
  end
73
73
 
74
+ def path
75
+ @f.path if @f.respond_to?(:path)
76
+ end
77
+
74
78
  private
75
79
 
76
80
  def next_line(f)
77
81
  while line = f.gets
78
82
  case line
83
+ when /\A(?!\#@)/
84
+ if current_cond.processing?
85
+ @buf.push line
86
+ break
87
+ end
79
88
  when /\A\#@\#/ # preprocessor comment
80
89
  ;
81
90
  when /\A\#@todo/i
@@ -86,7 +95,7 @@ module BitClust
86
95
  file = $1.strip
87
96
  basedir = File.dirname(line.location.file)
88
97
  @buf.concat Preprocessor.process("#{basedir}/#{file}", @params)
89
- rescue Errno::ENOENT => err
98
+ rescue Errno::ENOENT => _err
90
99
  raise WrongInclude, "#{line.location}: \#@include'ed file not exist: #{file}"
91
100
  end
92
101
  when /\A\#@since\b/
@@ -107,13 +116,8 @@ module BitClust
107
116
  parse_error "no matching \#@if", line if cond_toplevel?
108
117
  cond_pop
109
118
  end
110
- when /\A\#@/
111
- parse_error "unknown preprocessor directive", line
112
119
  else
113
- if current_cond.processing?
114
- @buf.push line
115
- break
116
- end
120
+ parse_error "unknown preprocessor directive", line
117
121
  end
118
122
  end
119
123
  if @buf.empty?
@@ -149,7 +153,7 @@ module BitClust
149
153
  end
150
154
 
151
155
  def cond_init
152
- @state_stack = [State.new(nil, :toplevel)]
156
+ @state_stack = [State.new(true, :toplevel)]
153
157
  end
154
158
 
155
159
  def cond_toplevel?
@@ -158,13 +162,13 @@ module BitClust
158
162
 
159
163
  def cond_push(bool)
160
164
  last = @state_stack.last
161
- @state_stack.push(State.new(last.current, bool))
165
+ @state_stack.push(last.next(bool, :condition))
162
166
  end
163
167
 
164
168
  def cond_invert
165
169
  b = @state_stack.pop.processing?
166
170
  last = @state_stack.last
167
- @state_stack.push(State.new(last.current, !b))
171
+ @state_stack.push(last.next(!b, :condition))
168
172
  end
169
173
 
170
174
  def cond_pop
@@ -254,7 +258,7 @@ module BitClust
254
258
 
255
259
  def samplecode_push(description)
256
260
  last = @state_stack.last
257
- @state_stack.push(State.new(last.current, :samplecode))
261
+ @state_stack.push(last.next(true, :samplecode))
258
262
  end
259
263
 
260
264
  def samplecode_pop
@@ -276,24 +280,25 @@ module BitClust
276
280
  class State
277
281
  attr_reader :current
278
282
 
279
- def initialize(previous, current)
280
- @previous = previous
281
- @current = current
283
+ def initialize(is_processing, label)
284
+ @is_processing = is_processing
285
+ @label = label
286
+ end
287
+
288
+ def next(is_processing, label)
289
+ State.new(@is_processing && is_processing, label)
282
290
  end
283
291
 
284
292
  def toplevel?
285
- @current == :toplevel
293
+ @label == :toplevel
286
294
  end
287
295
 
288
296
  def processing?
289
- toplevel? ||
290
- (@current == true && @previous != false) ||
291
- (@current == :samplecode && @previous == true) ||
292
- (@current == :samplecode && @previous == :toplevel)
297
+ @is_processing
293
298
  end
294
299
 
295
300
  def samplecode?
296
- @current == :samplecode
301
+ @label == :samplecode
297
302
  end
298
303
  end
299
304
  end
@@ -320,7 +325,7 @@ module BitClust
320
325
  file = $1.strip
321
326
  basedir = File.dirname(line.location.file)
322
327
  @buf.concat LineCollector.process("#{basedir}/#{file}")
323
- rescue Errno::ENOENT => err
328
+ rescue Errno::ENOENT => _err
324
329
  raise WrongInclude, "#{line.location}: \#@include'ed file not exist: #{file}"
325
330
  end
326
331
  else
@@ -229,11 +229,9 @@ module BitClust
229
229
  case @f.peek
230
230
  when /\A$/
231
231
  @f.gets
232
- when /\A[ \t\z]/
232
+ when /\A[ \t]/
233
233
  line '<p>'
234
- @f.while_match(/\A[ \t\z]/) do |line|
235
- line compile_text(line.strip)
236
- end
234
+ line compile_text(text_node_from_lines(@f.span(/\A[ \t]/)))
237
235
  line '</p>'
238
236
  when %r!\A//emlist(?:\[(?:[^\[\]]+?)?\]\[\w+?\])?\{!
239
237
  emlist
@@ -249,10 +247,8 @@ module BitClust
249
247
  line '<dd>'
250
248
  while /\A[ \t]/ =~ @f.peek or %r!\A//emlist(?:\[(?:[^\[\]]+?)?\]\[\w+?\])?\{! =~ @f.peek
251
249
  case @f.peek
252
- when /\A[ \t\z]/
253
- @f.while_match(/\A[ \t\z]/) do |line|
254
- line compile_text(line.strip)
255
- end
250
+ when /\A[ \t]/
251
+ line compile_text(text_node_from_lines(@f.span(/\A[ \t]/)))
256
252
  when %r!\A//emlist(?:\[(?:[^\[\]]+?)?\]\[\w+?\])?\{!
257
253
  emlist
258
254
  end
@@ -264,6 +260,11 @@ module BitClust
264
260
  "<dt>#{s}</dt>"
265
261
  end
266
262
 
263
+ def stop_on_syntax_error?
264
+ return true unless @option.key?(:stop_on_syntax_error)
265
+ @option[:stop_on_syntax_error]
266
+ end
267
+
267
268
  def emlist
268
269
  command = @f.gets
269
270
  if %r!\A//emlist\[(?<caption>[^\[\]]+?)?\]\[(?<lang>\w+?)\]! =~ command
@@ -280,7 +281,11 @@ module BitClust
280
281
  string BitClust::SyntaxHighlighter.new(src, filename).highlight
281
282
  rescue BitClust::SyntaxHighlighter::Error => ex
282
283
  $stderr.puts ex.message
283
- exit(false)
284
+ if stop_on_syntax_error?
285
+ exit(false)
286
+ else
287
+ string src
288
+ end
284
289
  end
285
290
  else
286
291
  string src
@@ -313,9 +318,7 @@ module BitClust
313
318
 
314
319
  def paragraph
315
320
  line '<p>'
316
- read_paragraph(@f).each do |line|
317
- line compile_text(line.strip)
318
- end
321
+ line compile_text(text_node_from_lines(read_paragraph(@f)))
319
322
  line '</p>'
320
323
  end
321
324
 
@@ -325,16 +328,16 @@ module BitClust
325
328
 
326
329
  def see
327
330
  header = @f.gets
328
- cmd = header.slice!(/\A\@\w+/)
331
+ header.slice!(/\A\@\w+/)
329
332
  body = [header] + @f.span(/\A\s+\S/)
330
333
  line '<p>'
331
- line '[SEE_ALSO] ' + compile_text(body.join('').strip)
334
+ line '[SEE_ALSO] ' + compile_text(text_node_from_lines(body))
332
335
  line '</p>'
333
336
  end
334
337
 
335
338
  def todo
336
339
  header = @f.gets
337
- cmd = header.slice!(/\A\@\w+/)
340
+ header.slice!(/\A\@\w+/)
338
341
  body = header
339
342
  line '<p class="todo">'
340
343
  line '[TODO]' + body
@@ -368,9 +371,7 @@ module BitClust
368
371
  # FIXME: parse @param, @return, ...
369
372
  def entry_paragraph
370
373
  line '<p>'
371
- read_entry_paragraph(@f).each do |line|
372
- line compile_text(line.strip)
373
- end
374
+ line compile_text(text_node_from_lines(read_entry_paragraph(@f)))
374
375
  line '</p>'
375
376
  end
376
377
 
@@ -392,6 +393,10 @@ module BitClust
392
393
  string a_href(@urlmapper.method_url(methodid2specstring(@method.id)), "permalink")
393
394
  string ']['
394
395
  string rdoc_link(@method.id, @option[:database].properties["version"])
396
+ if @option[:edit_base_url] && @method.source_location
397
+ string ']['
398
+ string a_href(@urlmapper.edit_url(@method.source_location), 'edit')
399
+ end
395
400
  string ']</span>'
396
401
  end
397
402
  if @method and not @method.defined?
@@ -552,7 +557,7 @@ module BitClust
552
557
  end
553
558
 
554
559
  def rdoc_url(method_id, version)
555
- cname, tmark, mname, libname = methodid2specparts(method_id)
560
+ cname, tmark, mname, _libname = methodid2specparts(method_id)
556
561
  tchar = typemark2char(tmark) == 'i' ? 'i' : 'c'
557
562
  cname = cname.split(".").first
558
563
  cname = cname.gsub('::', '/')
@@ -591,6 +596,11 @@ module BitClust
591
596
  @out.puts
592
597
  end
593
598
 
599
+ def text_node_from_lines(lines)
600
+ lines.map(&:strip).join("\n").gsub(/(\P{ascii})\n(\P{ascii})/) do
601
+ "#{::Regexp.last_match(1)}#{::Regexp.last_match(2)}"
602
+ end
603
+ end
594
604
  end
595
605
 
596
606
  end
@@ -207,7 +207,7 @@ module BitClust
207
207
  end
208
208
 
209
209
  def defined_type?
210
- type, param = parse_path_info()
210
+ type, _param = parse_path_info()
211
211
  case type
212
212
  when 'library', 'class', 'method', 'function', 'search', 'opensearchdescription'
213
213
  true
@@ -217,7 +217,7 @@ module BitClust
217
217
  end
218
218
 
219
219
  def type_id
220
- type, param = parse_path_info()
220
+ type, _param = parse_path_info()
221
221
  type.intern if type
222
222
  end
223
223
 
@@ -256,7 +256,7 @@ module BitClust
256
256
  private
257
257
 
258
258
  def type_param
259
- type, param = parse_path_info()
259
+ _type, param = parse_path_info()
260
260
  return nil unless param
261
261
  return nil if param.empty?
262
262
  param