bitclust-core 1.2.6 → 1.6.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 (160) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -0
  3. data/README.md +65 -0
  4. data/Rakefile +32 -0
  5. data/data/bitclust/catalog/ja_JP.UTF-8 +19 -1
  6. data/data/bitclust/searchpage/index.html +90 -0
  7. data/data/bitclust/template/class +69 -8
  8. data/data/bitclust/template/function +2 -2
  9. data/data/bitclust/template/layout +11 -3
  10. data/data/bitclust/template/method +2 -2
  11. data/data/bitclust/template/search +1 -1
  12. data/data/bitclust/template.epub/class +22 -1
  13. data/data/bitclust/template.epub/function +2 -2
  14. data/data/bitclust/template.epub/layout +1 -3
  15. data/data/bitclust/template.epub/method +2 -2
  16. data/data/bitclust/template.lillia/class +26 -5
  17. data/data/bitclust/template.lillia/layout +1 -3
  18. data/data/bitclust/template.lillia/method +2 -2
  19. data/data/bitclust/template.offline/class +49 -5
  20. data/data/bitclust/template.offline/function +2 -2
  21. data/data/bitclust/template.offline/layout +27 -3
  22. data/data/bitclust/template.offline/method +2 -2
  23. data/lib/bitclust/app.rb +17 -17
  24. data/lib/bitclust/capi_converter.rb +20 -0
  25. data/lib/bitclust/classentry.rb +68 -17
  26. data/lib/bitclust/compat.rb +3 -2
  27. data/lib/bitclust/completion.rb +59 -27
  28. data/lib/bitclust/crossrubyutils.rb +9 -5
  29. data/lib/bitclust/database.rb +29 -8
  30. data/lib/bitclust/doc_converter.rb +63 -0
  31. data/lib/bitclust/docentry.rb +2 -1
  32. data/lib/bitclust/entity_splitter.rb +221 -0
  33. data/lib/bitclust/entry.rb +48 -7
  34. data/lib/bitclust/exception.rb +1 -0
  35. data/lib/bitclust/functiondatabase.rb +14 -1
  36. data/lib/bitclust/functionentry.rb +6 -1
  37. data/lib/bitclust/functionreferenceparser.rb +5 -4
  38. data/lib/bitclust/generators/epub.rb +11 -3
  39. data/lib/bitclust/htmlutils.rb +2 -1
  40. data/lib/bitclust/include_graph.rb +375 -0
  41. data/lib/bitclust/include_pruner.rb +144 -0
  42. data/lib/bitclust/interface.rb +2 -1
  43. data/lib/bitclust/libraryentry.rb +9 -7
  44. data/lib/bitclust/lineinput.rb +8 -5
  45. data/lib/bitclust/link_checker.rb +179 -0
  46. data/lib/bitclust/markdown_bridge.rb +186 -0
  47. data/lib/bitclust/markdown_orchestrator.rb +267 -0
  48. data/lib/bitclust/markdown_to_rrd.rb +824 -0
  49. data/lib/bitclust/markdown_tree.rb +217 -0
  50. data/lib/bitclust/mdcompiler.rb +883 -0
  51. data/lib/bitclust/mdparser.rb +347 -0
  52. data/lib/bitclust/messagecatalog.rb +4 -3
  53. data/lib/bitclust/method_since_calculator.rb +117 -0
  54. data/lib/bitclust/methoddatabase.rb +125 -14
  55. data/lib/bitclust/methodentry.rb +130 -7
  56. data/lib/bitclust/methodid.rb +13 -11
  57. data/lib/bitclust/methodsignature.rb +11 -4
  58. data/lib/bitclust/nameutils.rb +42 -22
  59. data/lib/bitclust/parseutils.rb +1 -0
  60. data/lib/bitclust/preprocessor.rb +70 -32
  61. data/lib/bitclust/progress_bar.rb +1 -0
  62. data/lib/bitclust/rdcompiler.rb +197 -96
  63. data/lib/bitclust/refsdatabase.rb +24 -8
  64. data/lib/bitclust/reloadable_request_handler.rb +72 -0
  65. data/lib/bitclust/requesthandler.rb +22 -16
  66. data/lib/bitclust/ridatabase.rb +11 -4
  67. data/lib/bitclust/rrd_to_markdown.rb +925 -0
  68. data/lib/bitclust/rrdparser.rb +197 -30
  69. data/lib/bitclust/runner.rb +18 -2
  70. data/lib/bitclust/screen.rb +81 -11
  71. data/lib/bitclust/search_index_generator.rb +288 -0
  72. data/lib/bitclust/searcher.rb +72 -22
  73. data/lib/bitclust/server.rb +6 -1
  74. data/lib/bitclust/silent_progress_bar.rb +1 -0
  75. data/lib/bitclust/simplesearcher.rb +25 -12
  76. data/lib/bitclust/subcommand.rb +8 -1
  77. data/lib/bitclust/subcommands/ancestors_command.rb +10 -2
  78. data/lib/bitclust/subcommands/checklink_command.rb +54 -0
  79. data/lib/bitclust/subcommands/chm_command.rb +16 -7
  80. data/lib/bitclust/subcommands/classes_command.rb +6 -0
  81. data/lib/bitclust/subcommands/epub_command.rb +1 -0
  82. data/lib/bitclust/subcommands/extract_command.rb +6 -0
  83. data/lib/bitclust/subcommands/htmlfile_command.rb +22 -7
  84. data/lib/bitclust/subcommands/init_command.rb +5 -1
  85. data/lib/bitclust/subcommands/list_command.rb +13 -4
  86. data/lib/bitclust/subcommands/lookup_command.rb +29 -9
  87. data/lib/bitclust/subcommands/methods_command.rb +11 -2
  88. data/lib/bitclust/subcommands/methodsince_command.rb +80 -0
  89. data/lib/bitclust/subcommands/preproc_command.rb +6 -0
  90. data/lib/bitclust/subcommands/property_command.rb +3 -1
  91. data/lib/bitclust/subcommands/query_command.rb +1 -0
  92. data/lib/bitclust/subcommands/searchpage_command.rb +102 -0
  93. data/lib/bitclust/subcommands/server_command.rb +16 -10
  94. data/lib/bitclust/subcommands/setup_command.rb +25 -10
  95. data/lib/bitclust/subcommands/statichtml_command.rb +132 -6
  96. data/lib/bitclust/subcommands/update_command.rb +111 -2
  97. data/lib/bitclust/syntax_highlighter.rb +52 -5
  98. data/lib/bitclust/textutils.rb +4 -3
  99. data/lib/bitclust/version.rb +2 -1
  100. data/lib/bitclust/version_badges.rb +90 -0
  101. data/lib/bitclust/whole_file_gate.rb +137 -0
  102. data/lib/bitclust.rb +1 -0
  103. data/test/test_app.rb +269 -0
  104. data/test/test_bitclust.rb +2 -0
  105. data/test/test_capi_converter.rb +91 -0
  106. data/test/test_class_screen.rb +413 -0
  107. data/test/test_copy_doc_md.rb +53 -0
  108. data/test/test_doc_converter.rb +78 -0
  109. data/test/test_entity_splitter.rb +231 -0
  110. data/test/test_entry.rb +207 -2
  111. data/test/test_eol_warning.rb +43 -0
  112. data/test/test_functionreferenceparser.rb +11 -0
  113. data/test/test_include_graph.rb +640 -0
  114. data/test/test_include_pruner.rb +133 -0
  115. data/test/test_link_checker.rb +114 -0
  116. data/test/test_lookup_command.rb +135 -0
  117. data/test/test_markdown_bridge.rb +217 -0
  118. data/test/test_markdown_orchestrator.rb +478 -0
  119. data/test/test_markdown_to_rrd.rb +757 -0
  120. data/test/test_markdown_tree.rb +369 -0
  121. data/test/test_mdcompiler.rb +1276 -0
  122. data/test/test_mdparser.rb +538 -0
  123. data/test/test_method_screen.rb +166 -0
  124. data/test/test_method_since_calculator.rb +290 -0
  125. data/test/test_methoddatabase.rb +16 -0
  126. data/test/test_methodentry.rb +328 -0
  127. data/test/test_methodsignature.rb +3 -1
  128. data/test/test_methodsince_command.rb +168 -0
  129. data/test/test_nameutils.rb +22 -0
  130. data/test/test_preprocessor.rb +215 -0
  131. data/test/test_rdcompiler.rb +429 -27
  132. data/test/test_refsdatabase.rb +32 -0
  133. data/test/test_rrd_to_markdown.rb +968 -0
  134. data/test/test_rrdparser.rb +295 -2
  135. data/test/test_run_ruby_wasm.rb +54 -0
  136. data/test/test_run_worker_prelude.rb +83 -0
  137. data/test/test_runner.rb +51 -0
  138. data/test/test_search_index_generator.rb +513 -0
  139. data/test/test_search_screen.rb +48 -0
  140. data/test/test_searcher.rb +153 -0
  141. data/test/test_searchpage_command.rb +167 -0
  142. data/test/test_simplesearcher.rb +28 -0
  143. data/test/test_statichtml_command.rb +204 -0
  144. data/test/test_syntax_highlighter.rb +60 -0
  145. data/test/test_whole_file_gate.rb +175 -0
  146. data/theme/default/js/NOTICE +42 -0
  147. data/theme/default/js/run-worker.js +111 -0
  148. data/theme/default/js/run.js +350 -0
  149. data/theme/default/js/search_controller.js +134 -0
  150. data/theme/default/js/search_init.js +176 -0
  151. data/theme/default/js/search_navigation.js +110 -0
  152. data/theme/default/js/search_page.js +202 -0
  153. data/theme/default/js/search_ranker.js +244 -0
  154. data/theme/default/script.js +91 -18
  155. data/theme/default/search.css +149 -0
  156. data/theme/default/style.css +193 -21
  157. data/theme/default/syntax-highlight.css +8 -0
  158. data/theme/lillia/style.css +45 -1
  159. metadata +178 -21
  160. data/README +0 -32
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'bitclust'
2
3
  require 'bitclust/crossrubyutils'
3
4
 
@@ -44,10 +45,15 @@ Options:
44
45
  }
45
46
  end
46
47
 
48
+ # DB はサブコマンド自身の -d/--database オプションで受ける
49
+ def needs_database?
50
+ false
51
+ end
52
+
47
53
  def exec(argv, options)
48
54
  classname = argv[0]
49
- db = MethodDatabase.new(@prefix)
50
- ruby = get_ruby(@version)
55
+ db = MethodDatabase.new(@prefix || raise)
56
+ ruby = get_ruby(@version) || raise
51
57
  if classname && !@all
52
58
  check_ancestors(db, ruby, @requires, classname)
53
59
  else
@@ -82,6 +88,7 @@ Options:
82
88
  rescue ClassNotFound => ex
83
89
  $stderr.puts ex.backtrace
84
90
  $stderr.puts "class not found in database : #{classname}"
91
+ # @type var b: Array[String]
85
92
  b = []
86
93
  end
87
94
  unless a.to_set == b.to_set
@@ -94,6 +101,7 @@ Options:
94
101
  end
95
102
 
96
103
  def check_all_ancestors(db, ruby, requires)
104
+ # @type var classnames: Array[String]
97
105
  classnames = []
98
106
  requires.each do |lib|
99
107
  classnames.push(*defined_classes(ruby, lib, []))
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # bitclust/subcommands/checklink_command.rb
4
+ #
5
+ # DB 中の全ソースをコンパイル経路で走査し、[[c:]]/[[m:]]/[[lib:]]/[[d:]]/
6
+ # [[f:]] 参照のリンク切れを報告する:
7
+ #
8
+ # bitclust -d db-3.4 checklink
9
+ # bitclust -d db-3.4 checklink --capi-database=db-3.4-capi
10
+ #
11
+ # リンク切れが1件でもあれば exit 1(CI 組み込み用)。
12
+ # [[f:]](C API 関数)は --capi-database 指定時のみ検証し、
13
+ # 未指定ならスキップ数だけ報告する。
14
+
15
+ require 'bitclust'
16
+ require 'bitclust/subcommand'
17
+ require 'bitclust/link_checker'
18
+
19
+ module BitClust
20
+ module Subcommands
21
+ class ChecklinkCommand < Subcommand
22
+ def initialize
23
+ super
24
+ @capi_prefix = nil
25
+ @parser.banner = "Usage: #{File.basename($0, '.*')} --database=PATH checklink [options]"
26
+ @parser.on('--capi-database=PATH', 'C API (function) database for [[f:]] refs.') {|path|
27
+ @capi_prefix = path
28
+ }
29
+ end
30
+
31
+ def exec(argv, options)
32
+ super
33
+ db = @db
34
+ unless db.is_a?(MethodDatabase)
35
+ error 'checklink is for method databases (do not use --capi; pass --capi-database instead)'
36
+ end
37
+ capi_prefix = @capi_prefix
38
+ fdb = capi_prefix ? BitClust::FunctionDatabase.new(capi_prefix) : nil
39
+ checker = LinkChecker.new(db, function_database: fdb)
40
+ checker.check_all
41
+ # 同一エントリ内の同一参照の繰り返しは1行にまとめる
42
+ checker.findings.map {|f| "#{f.location}: [[#{f.ref}]] #{f.message}" }.uniq.each do |line|
43
+ puts line
44
+ end
45
+ if fdb.nil? && checker.skipped_function_refs > 0
46
+ puts "note: #{checker.skipped_function_refs} [[f:]] refs skipped (no --capi-database)"
47
+ end
48
+ version = @db.properties['version']
49
+ puts "#{checker.broken_count} broken link(s) in #{version ? "db (version #{version})" : 'db'}"
50
+ exit 1 unless checker.broken_count.zero?
51
+ end
52
+ end
53
+ end
54
+ end
@@ -1,4 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'bitclust'
4
5
  require 'bitclust/subcommand'
@@ -133,7 +134,7 @@ EOS
133
134
  end
134
135
 
135
136
  def method_url(spec)
136
- cname, tmark, mname = *split_method_spec(spec)
137
+ cname, tmark, mname = split_method_spec(spec)
137
138
  "/method/#{encodename_fs(cname)}/#{typemark2char(tmark)}/#{encodename_fs(mname)}.html"
138
139
  end
139
140
 
@@ -169,6 +170,7 @@ EOS
169
170
  manager = ScreenManager.new(@manager_config)
170
171
  @html_files = []
171
172
  db.transaction do
173
+ # @type var methods: Hash[String, Array[MethodEntry]]
172
174
  methods = {}
173
175
  db.methods.each do |entry|
174
176
  method_name = entry.klass.name + entry.typemark + entry.name
@@ -183,6 +185,7 @@ EOS
183
185
  e = c.is_a?(Array) ? c.sort.first : c
184
186
  case e.type_id
185
187
  when :library
188
+ # @type var e: LibraryEntry
186
189
  content = Sitemap::Content.new(e.name.to_s, filename)
187
190
  if e.name.to_s != '_builtin'
188
191
  @sitemap[:library][1] << content
@@ -190,6 +193,7 @@ EOS
190
193
  end
191
194
  @index_contents << Sitemap::Content.new(e.name.to_s, filename)
192
195
  when :class
196
+ # @type var e: ClassEntry
193
197
  content = Sitemap::Content.new(e.name.to_s, filename)
194
198
  if e.library.name.to_s == '_builtin'
195
199
  @sitemap[:library][0] << content
@@ -198,12 +202,15 @@ EOS
198
202
  end
199
203
  @index_contents << Sitemap::Content.new("#{e.name} (#{e.library.name})", filename)
200
204
  when :method
205
+ # @type var e: MethodEntry
201
206
  e.names.each do |e_name|
202
207
  name = e.typename == :special_variable ? "$#{e_name}" : e_name
203
208
  @index_contents <<
204
209
  Sitemap::Content.new("#{name} (#{e.library.name} - #{e.klass.name})", filename)
210
+ # bitclust#250: CHM の索引(.hhk)に出る表示ラベル。4.0 以降の
211
+ # ドキュメントでは module function を "?." で表示する
205
212
  @index_contents <<
206
- Sitemap::Content.new("#{e.klass.name}#{e.typemark}#{name} (#{e.library.name})", filename)
213
+ Sitemap::Content.new("#{e.klass.name}#{e.display_typemark}#{name} (#{e.library.name})", filename)
207
214
  end
208
215
  end
209
216
  pb.title = align_progress_bar_title(e.name)
@@ -218,7 +225,7 @@ EOS
218
225
  create_file(@outputdir + 'library/index.html', manager.library_index_screen(db.libraries.sort, {:database => db}).body)
219
226
  create_file(@outputdir + 'class/index.html', manager.class_index_screen(db.classes.sort, {:database => db}).body)
220
227
  FileUtils.cp(@manager_config[:themedir] + @manager_config[:css_url],
221
- @outputdir.to_s, {:verbose => true, :preserve => true})
228
+ @outputdir.to_s, verbose: true, preserve: true)
222
229
  end
223
230
 
224
231
  private
@@ -242,15 +249,17 @@ EOS
242
249
  "\u0308" => "\u2025",
243
250
  "\u2014" => "\u2015",
244
251
  "\u2212" => "\uff0d",
245
- "\u301c" => "\uff5e" }
252
+ "\u301c" => "\uff5e" }
246
253
 
247
254
  def create_html_file(entry, manager, outputdir, db)
248
255
  html = manager.entry_screen(entry, {:database => db}).body
249
256
  e = entry.is_a?(Array) ? entry.sort.first : entry
250
257
  path = case e.type_id
251
258
  when :library, :class, :doc
252
- outputdir + e.type_id.to_s + (NameUtils.encodename_fs(e.name) + '.html')
259
+ # @type var e: LibraryEntry | ClassEntry | DocEntry
260
+ outputdir + e.type_id.to_s + (NameUtils.encodename_fs(e.name) + '.html')
253
261
  when :method
262
+ # @type var e: MethodEntry
254
263
  outputdir + e.type_id.to_s + NameUtils.encodename_fs(e.klass.name) +
255
264
  e.typechar + (NameUtils.encodename_fs(e.name) + '.html')
256
265
  else
@@ -260,7 +269,7 @@ EOS
260
269
 
261
270
  begin
262
271
  new_html = html.gsub(/charset=utf-8/i, 'charset=Windows-31J').
263
- encode('windows-31j', { :fallback => FIX_UNDEF })
272
+ encode('windows-31j', fallback: FIX_UNDEF)
264
273
  mode = 'w:windows-31j'
265
274
  rescue
266
275
  new_html = html # write file as it is, utf-8
@@ -276,7 +285,7 @@ EOS
276
285
  $stderr.print("creating #{path} ...")
277
286
  str = ERB.new(skel).result(binding).
278
287
  gsub(/charset=utf-8/i, 'charset=Windows-31J').
279
- encode('windows-31j', { :fallback => FIX_UNDEF } )
288
+ encode('windows-31j', fallback: FIX_UNDEF)
280
289
  path.open('w:windows-31j') do |f|
281
290
  f.write(str)
282
291
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'pathname'
2
3
  require 'optparse'
3
4
 
@@ -26,6 +27,11 @@ module BitClust
26
27
  option_error('wrong number of arguments') unless argv.size == 1
27
28
  end
28
29
 
30
+ # システムの ruby を調べるだけで DB を使わない
31
+ def needs_database?
32
+ false
33
+ end
34
+
29
35
  def exec(argv, options)
30
36
  lib = argv[0]
31
37
  print_crossruby_table {|ruby| defined_classes(ruby, lib, @rejects) }
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'fileutils'
2
3
  require 'date'
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'pathname'
2
3
  require 'optparse'
3
4
 
@@ -16,6 +17,11 @@ module BitClust
16
17
  }
17
18
  end
18
19
 
20
+ # ソースファイルを処理するだけで DB を使わない
21
+ def needs_database?
22
+ false
23
+ end
24
+
19
25
  def exec(argv, options)
20
26
  success = true
21
27
  argv.each do |path|
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # Copyright (c) 2006-2007 Minero Aoki
2
3
  #
3
4
  # This program is free software.
@@ -15,13 +16,13 @@ module BitClust
15
16
  @target = nil
16
17
  @templatedir = srcdir_root + "data/bitclust/template.offline"
17
18
  @baseurl = "file://" + srcdir_root.to_s
18
- @version = "2.0.0"
19
+ @version = RUBY_VERSION
19
20
  @parser.banner = "Usage: #{File.basename($0, '.*')} htmlfile [options] rdfile"
20
21
  @parser.on('--target=NAME', 'Compile NAME to HTML.') {|name|
21
22
  @target = name
22
23
  }
23
- @parser.on('--force', '-f', 'Force to use rd_file template.') {|name|
24
- @rd_file = true
24
+ @parser.on('--[no-]force', '-f', 'Force to use rd_file template.') {|bool|
25
+ @rd_file = bool
25
26
  }
26
27
  @parser.on('--ruby_version=VER', '--ruby=VER', 'Set Ruby version') {|version|
27
28
  @version = version
@@ -34,6 +35,11 @@ module BitClust
34
35
  }
35
36
  end
36
37
 
38
+ # DB は与えられれば使うが必須ではない (--database は任意)
39
+ def needs_database?
40
+ false
41
+ end
42
+
37
43
  def exec(argv, options)
38
44
  db = MethodDatabase.dummy({'version' => @version})
39
45
  if options[:prefix]
@@ -41,7 +47,10 @@ module BitClust
41
47
  end
42
48
  @capi = options[:capi]
43
49
  target_file = argv[0]
44
- options = { 'version' => @version }
50
+ if /refm\/doc\// =~ target_file
51
+ @rd_file = true if @rd_file.nil?
52
+ end
53
+ options = { 'version' => @version } #: Database::database_properties
45
54
  manager = ScreenManager.new(:templatedir => @templatedir,
46
55
  :base_url => @baseurl,
47
56
  :cgi_url => @baseurl,
@@ -58,11 +67,11 @@ module BitClust
58
67
  lib = RRDParser.parse_stdlib_file(target_file, options)
59
68
  end
60
69
  entry = @target ? lookup(lib, @target) : lib
61
- puts manager.entry_screen(entry, { :database => db }).body
70
+ puts manager.entry_screen(entry, { :database => db, :target_version => @version }).body
62
71
  return
63
72
  rescue ParseError => ex
64
73
  $stderr.puts ex.message
65
- $stderr.puts ex.backtrace[0], ex.backtrace[1..-1].map{|s| "\tfrom " + s}
74
+ $stderr.puts ex.backtrace[0], ex.backtrace[1..-1]&.map{|s| "\tfrom " + s}
66
75
  end
67
76
  end
68
77
 
@@ -82,8 +91,12 @@ module BitClust
82
91
  def lookup(lib, key)
83
92
  case
84
93
  when @capi && NameUtils.functionname?(key)
85
- lib.find {|func| func.name == key}
94
+ # @type var lib: Array[FunctionEntry]
95
+ lib.is_a?(Array) or raise
96
+ lib.find {|func| func.name == key} or raise
86
97
  when NameUtils.method_spec?(key)
98
+ # @type var lib: LibraryEntry
99
+ lib.is_a?(LibraryEntry) or raise
87
100
  spec = MethodSpec.parse(key)
88
101
  if spec.constant?
89
102
  begin
@@ -95,6 +108,8 @@ module BitClust
95
108
  lib.fetch_methods(spec)
96
109
  end
97
110
  when NameUtils.classname?(key)
111
+ # @type var lib: LibraryEntry
112
+ lib.is_a?(LibraryEntry) or raise
98
113
  lib.fetch_class(key)
99
114
  else
100
115
  raise InvalidKey, "wrong search key: #{key.inspect}"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'pathname'
2
3
  require 'erb'
3
4
  require 'find'
@@ -19,12 +20,15 @@ module BitClust
19
20
  STANDARD_PROPERTIES = %w( encoding version )
20
21
 
21
22
  def exec(argv, options)
22
- prefix = options[:prefix]
23
+ prefix = options[:prefix] || raise
23
24
  db = MethodDatabase.new(prefix)
24
25
  db.init
25
26
  db.transaction {
26
27
  argv.each do |kv|
27
28
  k, v = kv.split('=', 2)
29
+ if k.nil? || v.nil?
30
+ raise "argument must be KEY=VALUE, but #{kv.inspect}"
31
+ end
28
32
  db.propset k, v
29
33
  end
30
34
  }
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'pathname'
2
3
  require 'erb'
3
4
  require 'find'
@@ -40,21 +41,29 @@ module BitClust
40
41
  super
41
42
  case @mode
42
43
  when :library
43
- @db.libraries.map {|lib| lib.name }.sort.each do |name|
44
+ db = @db
45
+ db.is_a?(MethodDatabase) or raise "invalid database given. Use without --capi option"
46
+ db.libraries.map {|lib| lib.name }.sort.each do |name|
44
47
  puts name
45
48
  end
46
49
  when :class
47
- @db.classes.map {|c| c.name }.sort.each do |name|
50
+ db = @db
51
+ db.is_a?(MethodDatabase) or raise "invalid database given. Use without --capi option"
52
+ db.classes.map {|c| c.name }.sort.each do |name|
48
53
  puts name
49
54
  end
50
55
  when :method
51
- @db.classes.sort_by {|c| c.name }.each do |c|
56
+ db = @db
57
+ db.is_a?(MethodDatabase) or raise "invalid database given. Use without --capi option"
58
+ db.classes.sort_by {|c| c.name }.each do |c|
52
59
  c.entries.sort_by {|m| m.id }.each do |m|
53
60
  puts m.label
54
61
  end
55
62
  end
56
63
  when :function
57
- @db.functions.sort_by {|f| f.name }.each do |f|
64
+ db = @db
65
+ db.is_a?(FunctionDatabase) or raise "invalid database given. Use with --capi option"
66
+ db.functions.sort_by {|f| f.name }.each do |f|
58
67
  puts f.name
59
68
  end
60
69
  else
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'pathname'
2
3
  require 'erb'
3
4
  require 'find'
@@ -50,19 +51,23 @@ module BitClust
50
51
 
51
52
  def exec(argv, options)
52
53
  super
53
- entry = fetch_entry(@db, @type, @key)
54
- puts fill_template(get_template(@type, @format), entry)
54
+ entry = fetch_entry(@db, @type, @key || raise)
55
+ puts fill_template(get_template(@type || raise, @format || raise), entry)
55
56
  end
56
57
 
57
58
  def fetch_entry(db, type, key)
58
59
  case type
59
60
  when :library
61
+ # @type var db: MethodDatabase
60
62
  db.fetch_library(key)
61
63
  when :class
64
+ # @type var db: MethodDatabase
62
65
  db.fetch_class(key)
63
66
  when :method
67
+ # @type var db: MethodDatabase
64
68
  db.fetch_method(MethodSpec.parse(key))
65
69
  when :function
70
+ # @type var db: FunctionDatabase
66
71
  db.fetch_function(key)
67
72
  else
68
73
  raise "must not happen: #{type.inspect}"
@@ -95,7 +100,7 @@ module BitClust
95
100
  <dt>classes</dt><dd><%= entry.classes.map {|c| c.name }.sort.join(', ') %></dd>
96
101
  <dt>methods</dt><dd><%= entry.methods.map {|m| m.name }.sort.join(', ') %></dd>
97
102
  </dl>
98
- <%= compile_rd(entry.source) %>
103
+ <%= compile_rd(entry) %>
99
104
  End
100
105
  },
101
106
  :class => {
@@ -118,7 +123,7 @@ module BitClust
118
123
  <dt>singleton_methods</dt><dd><%= entry.singleton_methods.map {|m| m.name }.sort.join(', ') %></dd>
119
124
  <dt>instance_methods</dt><dd><%= entry.instance_methods.map {|m| m.name }.sort.join(', ') %></dd>
120
125
  </dl>
121
- <%= compile_rd(entry.source) %>
126
+ <%= compile_rd(entry) %>
122
127
  End
123
128
  },
124
129
  :method => {
@@ -141,7 +146,7 @@ module BitClust
141
146
  <dt>kind</dt><dd><%= entry.kind %></dd>
142
147
  <dt>library</dt><dd><%= entry.library.name %></dd>
143
148
  </dl>
144
- <%= compile_rd(entry.source) %>
149
+ <%= compile_rd(entry) %>
145
150
  End
146
151
  },
147
152
  :function => {
@@ -158,16 +163,31 @@ module BitClust
158
163
  <dt>header</dt><dd><%= entry.header %></dd>
159
164
  <dt>filename</dt><dd><%= entry.filename %></dd>
160
165
  </dl>
161
- <%= compile_rd(entry.source) %>
166
+ <%= compile_rd(entry) %>
162
167
  End
163
168
  }
164
169
  }
165
170
 
166
- def compile_rd(src)
171
+ def compile_rd(entry)
167
172
  umap = URLMapper.new(:base_url => 'http://example.com',
168
173
  :cgi_url => 'http://example.com/view')
169
- compiler = RDCompiler.new(umap, 2)
170
- compiler.compile(src)
174
+ if @db.properties['source_format'] == 'markdown'
175
+ # md ソースの DB は screen.rb と同じく MDCompiler(GFM)で描画する
176
+ Kernel.require 'bitclust/mdcompiler'
177
+ compiler = MDCompiler.new(umap, 2, { :gfm => true, :database => @db })
178
+ else
179
+ compiler = RDCompiler.new(umap, 2, { :database => @db })
180
+ end
181
+ # シグネチャ行の描画(permalink の id 等)はエントリ文脈を要求する
182
+ # ので、compile ではなくエントリ種別ごとの compile_* を使う
183
+ case entry
184
+ when MethodEntry
185
+ compiler.compile_method(entry)
186
+ when FunctionEntry
187
+ compiler.compile_function(entry)
188
+ else
189
+ compiler.compile(entry.source)
190
+ end
171
191
  end
172
192
  end
173
193
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'pathname'
2
3
  require 'optparse'
3
4
 
@@ -45,6 +46,11 @@ module BitClust
45
46
  option_error("wrong number of arguments") unless argv.size == 1
46
47
  end
47
48
 
49
+ # システムの ruby とリファレンスファイルを比較するだけで DB を使わない
50
+ def needs_database?
51
+ false
52
+ end
53
+
48
54
  def exec(argv, options)
49
55
  classname = argv[0]
50
56
  case @mode
@@ -59,6 +65,7 @@ module BitClust
59
65
  c = lib.fetch_class(classname)
60
66
  list0 = lib.classes.find_all{|c0| /\A#{classname}\b/o =~ c0.name }
61
67
  list0 = c.entries + list0
68
+ # @type var list: Array[String]
62
69
  list = list0.map {|ent| ent.labels.map {|n| expand_mf(n) } }.flatten
63
70
  if @content
64
71
  ri = @ri_path ? RiDatabase.open(@ri_path, nil) : RiDatabase.open_system_db
@@ -71,7 +78,7 @@ module BitClust
71
78
  puts fmt.method_info(mthd.entry)
72
79
  else
73
80
  name = name.sub(/\A\w+#/, '')
74
- puts "--- #{name}\n\#@todo\n\n"
81
+ puts "--- #{name}\n#%todo\n\n"
75
82
  end
76
83
  end
77
84
  else
@@ -83,7 +90,7 @@ module BitClust
83
90
  end
84
91
  end
85
92
  else
86
- raise "must not happen: #{mode.inspect}"
93
+ raise "must not happen: #{@mode.inspect}"
87
94
  end
88
95
  end
89
96
 
@@ -103,6 +110,8 @@ module BitClust
103
110
 
104
111
  def m_order(m)
105
112
  m, t = *m.reverse.split(/(\#|\.|::)/, 2)
113
+ m or raise
114
+ t or raise
106
115
  [ORDER[t] || 0, m.reverse]
107
116
  end
108
117
 
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # bitclust/subcommands/methodsince_command.rb
4
+ #
5
+ # Fills per-name since/until into method entries by scanning a version
6
+ # ladder of databases:
7
+ #
8
+ # bitclust methodsince --update=db-3.4 db-1.8.7 db-1.9.3 ... db-3.3 db-3.4
9
+ #
10
+ # Every positional argument and every --update path together form the
11
+ # version ladder used to compute presence; --update paths are additionally
12
+ # written back to (see bitclust/method_since_calculator.rb, bitclust#132 P2).
13
+ #
14
+
15
+ require 'bitclust'
16
+ require 'bitclust/subcommand'
17
+ require 'bitclust/method_since_calculator'
18
+ require 'tmpdir'
19
+ require 'fileutils'
20
+
21
+ module BitClust
22
+ module Subcommands
23
+ class MethodsinceCommand < Subcommand
24
+ def initialize
25
+ super
26
+ @updates = []
27
+ @dry_run = false
28
+ @parser.banner = "Usage: #{File.basename($0, '.*')} methodsince [options] <dbpath>..."
29
+ @parser.on('--update=PATH', 'Writable target database to fill in-place (repeatable).') {|path|
30
+ @updates.push path
31
+ }
32
+ @parser.on('--dry-run', 'Compute and print stats without saving.') {
33
+ @dry_run = true
34
+ }
35
+ end
36
+
37
+ # DB パスは自前の引数(位置引数 + --update)で受けるので、
38
+ # グローバル --database は不要
39
+ def needs_database?
40
+ false
41
+ end
42
+
43
+ def exec(argv, options)
44
+ error("no --update given (nothing to write to)") if @updates.empty?
45
+
46
+ ladder_paths = (argv + @updates).uniq {|path| File.expand_path(path) }
47
+ calculator = MethodSinceCalculator.new(ladder_paths.map {|path| MethodDatabase.new(path) })
48
+ calculator.scan
49
+
50
+ @updates.each do |path|
51
+ stats, version = @dry_run ? apply_dry_run(calculator, path) : apply_and_save(calculator, path)
52
+ puts "#{File.basename(path)} (version #{version}): " \
53
+ "entries_updated=#{stats[:entries_updated]} since_filled=#{stats[:since_filled]} " \
54
+ "until_filled=#{stats[:until_filled]} floor_skipped=#{stats[:floor_skipped]}"
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def apply_and_save(calculator, path)
61
+ target = MethodDatabase.new(path)
62
+ version = target.propget('version') or
63
+ error("#{path}: no version property (not a bitclust database?)")
64
+ [calculator.apply(target), version]
65
+ end
66
+
67
+ # --dry-run: 実際のデータベースには一切書き込まず、複製に対して
68
+ # apply した結果の統計だけを見せる
69
+ def apply_dry_run(calculator, path)
70
+ version = MethodDatabase.new(path).propget('version') or
71
+ error("#{path}: no version property (not a bitclust database?)")
72
+ Dir.mktmpdir do |tmp|
73
+ copy = File.join(tmp, 'db')
74
+ FileUtils.cp_r(path, copy)
75
+ [calculator.apply(MethodDatabase.new(copy)), version]
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'pathname'
2
3
  require 'optparse'
3
4
 
@@ -17,6 +18,11 @@ module BitClust
17
18
  }
18
19
  end
19
20
 
21
+ # ソースファイルを処理するだけで DB を使わない
22
+ def needs_database?
23
+ false
24
+ end
25
+
20
26
  def exec(argv, options)
21
27
  argv.each do |path|
22
28
  File.open(path) {|file|
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'pathname'
2
3
  require 'erb'
3
4
  require 'find'
@@ -48,7 +49,7 @@ module BitClust
48
49
  end
49
50
 
50
51
  def exec(argv, options)
51
- prefix = options[:prefix]
52
+ prefix = options[:prefix] || raise
52
53
  db = MethodDatabase.new(prefix)
53
54
  case @mode
54
55
  when :list
@@ -61,6 +62,7 @@ module BitClust
61
62
  end
62
63
  when :set
63
64
  key, val = *argv
65
+ key || raise; val || raise
64
66
  db.transaction {
65
67
  db.propset key, val
66
68
  }
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'pathname'
2
3
  require 'erb'
3
4
  require 'find'