bitclust-core 1.6.1 → 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 (90) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -0
  3. data/data/bitclust/catalog/ja_JP.UTF-8 +4 -2
  4. data/data/bitclust/template/class-index +0 -1
  5. data/data/bitclust/template/function-index +1 -0
  6. data/data/bitclust/template/layout +1 -0
  7. data/data/bitclust/template.epub/class +5 -5
  8. data/data/bitclust/template.epub/class-index +0 -1
  9. data/data/bitclust/template.epub/contents +7 -4
  10. data/data/bitclust/template.epub/layout +4 -4
  11. data/data/bitclust/template.offline/class-index +0 -1
  12. data/data/bitclust/template.offline/function-index +1 -0
  13. data/data/bitclust/template.offline/layout +3 -0
  14. data/lib/bitclust/classentry.rb +1 -1
  15. data/lib/bitclust/docentry.rb +1 -1
  16. data/lib/bitclust/functionentry.rb +1 -1
  17. data/lib/bitclust/generators/epub.rb +69 -5
  18. data/lib/bitclust/irb.rb +74 -0
  19. data/lib/bitclust/markdown_bridge.rb +11 -6
  20. data/lib/bitclust/markdown_exporter.rb +311 -0
  21. data/lib/bitclust/markdown_tree.rb +118 -11
  22. data/lib/bitclust/mdcompiler.rb +15 -1
  23. data/lib/bitclust/mdparser.rb +42 -1
  24. data/lib/bitclust/methoddatabase.rb +17 -4
  25. data/lib/bitclust/methodentry.rb +24 -0
  26. data/lib/bitclust/methodsignature.rb +1 -1
  27. data/lib/bitclust/nameutils.rb +13 -0
  28. data/lib/bitclust/preprocessor.rb +4 -37
  29. data/lib/bitclust/rbs_overload_matcher.rb +179 -0
  30. data/lib/bitclust/rbs_sig_importer.rb +276 -0
  31. data/lib/bitclust/rbs_signatures.rb +125 -0
  32. data/lib/bitclust/rdcompiler.rb +12 -1
  33. data/lib/bitclust/remote.rb +405 -0
  34. data/lib/bitclust/runner.rb +7 -10
  35. data/lib/bitclust/screen.rb +6 -1
  36. data/lib/bitclust/search_index_generator.rb +28 -10
  37. data/lib/bitclust/searcher.rb +54 -25
  38. data/lib/bitclust/subcommands/chm_command.rb +1 -1
  39. data/lib/bitclust/subcommands/epub_command.rb +2 -2
  40. data/lib/bitclust/subcommands/extract_command.rb +7 -0
  41. data/lib/bitclust/subcommands/htmlfile_command.rb +7 -0
  42. data/lib/bitclust/subcommands/methods_command.rb +5 -28
  43. data/lib/bitclust/subcommands/query_command.rb +1 -0
  44. data/lib/bitclust/subcommands/rbssig_command.rb +99 -0
  45. data/lib/bitclust/subcommands/server_command.rb +21 -10
  46. data/lib/bitclust/subcommands/setup_command.rb +32 -11
  47. data/lib/bitclust/subcommands/statichtml_command.rb +59 -0
  48. data/lib/bitclust/syntax_highlighter.rb +65 -4
  49. data/lib/bitclust/user_dirs.rb +62 -0
  50. data/lib/bitclust/version.rb +1 -1
  51. data/lib/bitclust-irb.rb +2 -0
  52. data/test/test_chm_command.rb +22 -0
  53. data/test/test_epub_command.rb +60 -0
  54. data/test/test_epub_generator.rb +330 -0
  55. data/test/test_extract_command.rb +45 -0
  56. data/test/test_irb_plugin.rb +212 -0
  57. data/test/test_link_checker.rb +1 -1
  58. data/test/test_markdown_bridge.rb +35 -0
  59. data/test/test_markdown_exporter.rb +260 -0
  60. data/test/test_markdown_tree.rb +144 -0
  61. data/test/test_mdcompiler.rb +47 -5
  62. data/test/test_mdparser.rb +223 -4
  63. data/test/test_methodentry.rb +111 -0
  64. data/test/test_methods_command.rb +32 -0
  65. data/test/test_methodsignature.rb +3 -1
  66. data/test/test_opensearchdescription_screen.rb +39 -0
  67. data/test/test_preprocessor.rb +26 -0
  68. data/test/test_query_command.rb +30 -0
  69. data/test/test_rbs_overload_matcher.rb +170 -0
  70. data/test/test_rbs_sig_importer.rb +237 -0
  71. data/test/test_rbssig_command.rb +186 -0
  72. data/test/test_rdcompiler.rb +99 -1
  73. data/test/test_remote.rb +374 -0
  74. data/test/test_runner.rb +61 -1
  75. data/test/test_search_index_generator.rb +81 -0
  76. data/test/test_searcher.rb +63 -0
  77. data/test/test_server_command.rb +41 -0
  78. data/test/test_setup_command.rb +164 -0
  79. data/test/test_statichtml_command.rb +137 -0
  80. data/test/test_syntax_highlighter.rb +124 -0
  81. data/test/test_user_dirs.rb +62 -0
  82. data/theme/default/js/run.js +14 -0
  83. data/theme/default/js/search_init.js +3 -1
  84. data/theme/default/js/search_page.js +7 -1
  85. data/theme/default/js/version_switcher.js +147 -0
  86. data/theme/default/search.css +21 -0
  87. data/theme/default/style.css +83 -7
  88. data/theme/lillia/style.css +26 -0
  89. metadata +71 -2
  90. data/lib/bitclust/ridatabase.rb +0 -359
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8c50953e0ecaf38a9d4c6187b22eaccedd4b9f52029bb638e026fbbfc655d8a2
4
- data.tar.gz: c5ce94f2931f5472651e6bd425c766ba19b9ff4acc87d8fd5ae8e57f384db3d6
3
+ metadata.gz: 299762c07571e6e3b72eebe00c9d1e1d520ef9f5c3b68de759adc0c173d2ee18
4
+ data.tar.gz: beab538e8caec8fb1f7265808adceaa5574b22793dfb11a521651687204416d1
5
5
  SHA512:
6
- metadata.gz: 4766a837042d881e63e96264338d7e04aa6e10e63db1b2ff22ca0e53e6f6e97f766efadbe9c1a6ff8c4b89bfac996eb4c060c9b9abfd8c4aff420c57a987a3f7
7
- data.tar.gz: e64091ccdeddf09ed18339d2be46af88abc28c6d9aaf6ae9da888c4125c5ab47b526c315d9f630e76389258fe56f950600b1265d42c10d98a2d595b3892f02d8
6
+ metadata.gz: a4d23713bd97acaa6cb98de51e95766c87f09329c0dba4c2b42152838023ec4ce681f1c7f38db582b7e3e20809a2749152da84a74399741dc113ad9251f0875d
7
+ data.tar.gz: ce441c5b5a4abc9cbef8a46bf9efa2a57a5cae8bdd827c9edf7af095e60bea9c95a85ceee54baa73e850b0a7a4682b1d5afd41ce41e386040e78761ca88038fd
data/Rakefile CHANGED
@@ -21,6 +21,7 @@ namespace :test do
21
21
  sh 'qjs', 'test/js/test_run.mjs'
22
22
  sh 'qjs', 'test/js/test_script.mjs'
23
23
  sh 'qjs', 'test/js/test_search.mjs'
24
+ sh 'qjs', 'test/js/test_version_switcher.mjs'
24
25
  end
25
26
  end
26
27
 
@@ -7,7 +7,7 @@ Added/Redefined Methods
7
7
  All Classes
8
8
  クラス一覧
9
9
  All Functions
10
- 関数一覧
10
+ C API 関数一覧
11
11
  All Libraries
12
12
  ライブラリ一覧
13
13
  Ancestor Methods
@@ -51,7 +51,7 @@ File
51
51
  FileFormat
52
52
  ファイルフォーマット
53
53
  Function Index
54
- 関数一覧
54
+ C API 関数一覧
55
55
  Index
56
56
  目次
57
57
  I/O
@@ -112,6 +112,8 @@ Text
112
112
  テキスト
113
113
  Thread
114
114
  スレッド
115
+ This is a list of functions provided by the Ruby C API for developing Ruby itself and C extension libraries. These functions cannot be called directly from Ruby programs.
116
+ Ruby の C API(C 言語 API)の関数の一覧です。Ruby 本体や拡張ライブラリの開発に使うもので、Ruby プログラムから直接呼び出す関数ではありません。
115
117
  This reference manual is for a version of Ruby that is no longer maintained.
116
118
  このマニュアルは既にメンテナンスが終了したバージョンの Ruby を対象としています。
117
119
  Undefined Methods for Explanation
@@ -29,5 +29,4 @@
29
29
  end
30
30
  headline_pop
31
31
  %>
32
- </ul>
33
32
 
@@ -8,6 +8,7 @@
8
8
  headline_init
9
9
  %>
10
10
  <%= headline(_("Function Index")) %>
11
+ <p><%= _('This is a list of functions provided by the Ruby C API for developing Ruby itself and C extension libraries. These functions cannot be called directly from Ruby programs.') %></p>
11
12
  <table class="entries functions">
12
13
  <%
13
14
  headline_push
@@ -13,6 +13,7 @@
13
13
  <link rel="search" type="application/opensearchdescription+xml" title="<%= _('Ruby %s Reference Manual', ruby_version()) %>" href="<%=h opensearchdescription_url() %>">
14
14
  <% if run_ruby_wasm_url %>
15
15
  <meta name="rurema-run-ruby-wasm" content="<%=h run_ruby_wasm_url %>">
16
+ <meta name="rurema-run-help" content="<%=h document_url('help') %>#run">
16
17
  <script type="module" src="<%=h custom_js_url('js/run.js') %>"></script>
17
18
  <% end %>
18
19
  </head>
@@ -24,20 +24,20 @@
24
24
  <% end %>
25
25
 
26
26
  <% unless @entry.extended.empty? %>
27
- <br>extend: <%= @entry.extended.map {|c| class_link(c.name) }.join(', ') %>
27
+ <br />extend: <%= @entry.extended.map {|c| class_link(c.name) }.join(', ') %>
28
28
  <% end %>
29
29
  <% unless @entry.aliases.empty? %>
30
- <br>aliases: <%=h @entry.aliases.map{|c| c.name}.join(', ') %>
30
+ <br />aliases: <%=h @entry.aliases.map{|c| c.name}.join(', ') %>
31
31
  <% end %>
32
32
  <% unless @entry.dynamically_included.empty? %>
33
- <br> dynamic include:
33
+ <br /> dynamic include:
34
34
  <%= @entry.dynamically_included.map{|m|
35
35
  class_link(m.name) + " (by " + library_link(m.library.name) + ")"
36
36
  }.join(", ")
37
37
  %>
38
38
  <% end %>
39
39
  <% unless @entry.dynamically_extended.empty? %>
40
- <br> dynamic extend:
40
+ <br /> dynamic extend:
41
41
  <%= @entry.dynamically_extended.map{|m|
42
42
  class_link(m.name) + " (by " + library_link(m.library.name) + ")"
43
43
  }.join(", ")
@@ -72,7 +72,7 @@
72
72
  entries.each do |m|
73
73
  m.names.each do |mname|
74
74
  %>
75
- <a href="#<%= m.index_id %>"><%= "#{prefix}#{mname}" %></a>
75
+ <a href="#<%= m.index_id %>"><%= escape_html "#{prefix}#{mname}" %></a>
76
76
  <%
77
77
  end
78
78
  end
@@ -25,4 +25,3 @@
25
25
  end
26
26
  headline_pop
27
27
  %>
28
- </ul>
@@ -8,15 +8,18 @@
8
8
  </metadata>
9
9
  <manifest>
10
10
  <item id="toc" properties="nav" href="nav.xhtml" media-type="application/xhtml+xml" />
11
- <item id="index" href="OEBPS/doc/index.html" media-type="application/xhtml+xml" />
12
- <% items.each do |item| -%>
13
- <item id="<%= item[:id] %>" href="<%= item[:path] %>" media-type="application/xhtml+xml" />
11
+ <item id="index" href="OEBPS/doc/index.xhtml" media-type="application/xhtml+xml" />
12
+ <% class_items.each do |item| -%>
13
+ <item id="<%= item[:id] %>" href="<%= item[:path] %>" media-type="<%= item[:media_type] %>" />
14
+ <% end -%>
15
+ <% other_items.each do |item| -%>
16
+ <item id="<%= item[:id] %>" href="<%= item[:path] %>" media-type="<%= item[:media_type] %>" />
14
17
  <% end -%>
15
18
  </manifest>
16
19
  <spine>
17
20
  <itemref idref="toc" />
18
21
  <itemref idref="index" />
19
- <% items.each do |item| -%>
22
+ <% class_items.each do |item| -%>
20
23
  <itemref idref="<%= item[:id] %>" />
21
24
  <% end -%>
22
25
  </spine>
@@ -2,10 +2,10 @@
2
2
  <!DOCTYPE html>
3
3
  <html lang="ja-JP">
4
4
  <head>
5
- <meta http-equiv="Content-Type" content="text/html; charset=<%=h charset() %>">
6
- <meta http-equiv="Content-Language" content="ja-JP">
7
- <link rel="stylesheet" type="text/css" href="<%=h css_url() %>">
8
- <link rel="icon" type="image/png" href="<%=h favicon_url() %>">
5
+ <meta http-equiv="Content-Type" content="text/html; charset=<%=h charset() %>" />
6
+ <meta http-equiv="Content-Language" content="ja-JP" />
7
+ <link rel="stylesheet" type="text/css" href="<%=h css_url() %>" />
8
+ <link rel="icon" type="image/png" href="<%=h favicon_url() %>" />
9
9
  <title><%=h @title %> (Ruby <%=h ruby_version %>)</title>
10
10
  </head>
11
11
  <body>
@@ -54,5 +54,4 @@
54
54
  end
55
55
  headline_pop
56
56
  %>
57
- </ul>
58
57
  </main>
@@ -36,6 +36,7 @@
36
36
  </header>
37
37
 
38
38
  <main>
39
+ <p><%= _('This is a list of functions provided by the Ruby C API for developing Ruby itself and C extension libraries. These functions cannot be called directly from Ruby programs.') %></p>
39
40
  <table class="entries functions">
40
41
  <%
41
42
  headline_push
@@ -21,8 +21,10 @@
21
21
  <script src="<%=h custom_js_url('js/search_ranker.js') %>"></script>
22
22
  <script src="<%=h custom_js_url('js/search_controller.js') %>"></script>
23
23
  <script src="<%=h custom_js_url('js/search_init.js') %>"></script>
24
+ <script defer src="<%=h custom_js_url('js/version_switcher.js') %>"></script>
24
25
  <% if run_ruby_wasm_url %>
25
26
  <meta name="rurema-run-ruby-wasm" content="<%=h run_ruby_wasm_url %>">
27
+ <meta name="rurema-run-help" content="<%=h document_url('help') %>#run">
26
28
  <script type="module" src="<%=h custom_js_url('js/run.js') %>"></script>
27
29
  <% end %>
28
30
  </head>
@@ -35,6 +37,7 @@
35
37
  <% end %>
36
38
  <div id="rurema-topbar">
37
39
  <div id="rurema-brand"><%= manual_home_link %></div>
40
+ <div id="version-switcher"></div>
38
41
  <div id="search-section" role="search">
39
42
  <input id="search-field" type="text" autocomplete="off" spellcheck="false"
40
43
  placeholder="クラス・メソッドを検索 (/)"
@@ -452,7 +452,7 @@ module BitClust
452
452
  end
453
453
 
454
454
  def description
455
- description_text(source.split(/\n\n+/, 2)[0].strip)
455
+ description_text(source.split(/\n\n+/, 2)[0].to_s.strip)
456
456
  end
457
457
 
458
458
  def clear_cache
@@ -84,7 +84,7 @@ module BitClust
84
84
  end
85
85
 
86
86
  def description
87
- description_text(source.split(/\n\n/, 2)[0].strip)
87
+ description_text(source.split(/\n\n/, 2)[0].to_s.strip)
88
88
  end
89
89
  end
90
90
  end
@@ -83,7 +83,7 @@ module BitClust
83
83
  end
84
84
 
85
85
  def description
86
- description_text(source.split(/\n\n+/, 2)[0].strip)
86
+ description_text(source.split(/\n\n+/, 2)[0].to_s.strip)
87
87
  end
88
88
  end
89
89
  end
@@ -24,11 +24,17 @@ module BitClust
24
24
 
25
25
  CONTENTS_DIR_NAME = 'OEBPS'
26
26
 
27
+ # StatichtmlCommand が出力ルートに書く 2 行のリダイレクト用スタブ
28
+ # (<meta http-equiv="refresh"> と <a>)。ルート要素が無く XHTML として
29
+ # 整形式でない。EPUB の入口は nav.xhtml なのでスタブは同梱せず削除する
30
+ INDEX_STUB_NAME = 'index.xhtml'
31
+
27
32
  def generate
28
33
  make_epub_directory do |epub_directory|
29
34
  contents_directory = epub_directory + CONTENTS_DIR_NAME
30
35
  copy_static_files(epub_directory)
31
36
  generate_xhtml_files(contents_directory)
37
+ remove_index_stub(contents_directory)
32
38
  generate_contents_opf(epub_directory)
33
39
  pack_epub(epub_directory)
34
40
  end
@@ -71,15 +77,45 @@ module BitClust
71
77
  cmd.exec(argv, options)
72
78
  end
73
79
 
80
+ # manifest に id="index" で固定的に載せる doc/index ページの href
81
+ # (epub_directory 相対)。other_items からは除いて二重掲載を避ける
82
+ INDEX_PATH = Pathname.new("#{CONTENTS_DIR_NAME}/doc/index.xhtml")
83
+
84
+ MEDIA_TYPES = {
85
+ '.xhtml' => 'application/xhtml+xml',
86
+ '.css' => 'text/css',
87
+ '.js' => 'application/javascript',
88
+ '.png' => 'image/png',
89
+ '.jpg' => 'image/jpeg',
90
+ '.jpeg' => 'image/jpeg',
91
+ '.gif' => 'image/gif',
92
+ '.svg' => 'image/svg+xml',
93
+ }.freeze
94
+
74
95
  def generate_contents_opf(epub_directory)
75
- items = [] #: Array[{:id => String, :path => Pathname}]
96
+ class_items = [] #: Array[{:id => String, :path => Pathname, :media_type => String}]
76
97
  glob_relative_path(epub_directory, "#{CONTENTS_DIR_NAME}/class/*.xhtml").each do |path|
77
- items << {
78
- :id => decodename_package(path.basename(".*").to_s),
79
- :path => path
98
+ class_items << {
99
+ :id => "class-#{decodename_package(path.basename(".*").to_s)}",
100
+ :path => path,
101
+ :media_type => media_type_for(path),
80
102
  }
81
103
  end
82
- items.sort_by!{|item| item[:path] }
104
+ class_items.sort_by!{|item| item[:path] }
105
+
106
+ excluded_paths = class_items.map{|item| item[:path] } + [INDEX_PATH]
107
+ other_items = [] #: Array[{:id => String, :path => Pathname, :media_type => String}]
108
+ oebps_file_paths(epub_directory).each do |path|
109
+ next if excluded_paths.include?(path)
110
+
111
+ other_items << {
112
+ :id => manifest_id_for(path),
113
+ :path => path,
114
+ :media_type => media_type_for(path),
115
+ }
116
+ end
117
+ other_items.sort_by!{|item| item[:path] }
118
+
83
119
  template = (@templatedir + "contents").read
84
120
  if ::ERB.instance_method(:initialize).parameters.last.first == :key
85
121
  erb = ::ERB.new(template, trim_mode: '-')
@@ -92,6 +128,34 @@ module BitClust
92
128
  end
93
129
  end
94
130
 
131
+ # OEBPS 配下の通常ファイル全部(method/library/doc/function ページと、
132
+ # statichtml がコピーした CSS・画像)を epub_directory 相対で返す。
133
+ # class ページも含む(呼び出し側で class_items と重複排除する)
134
+ def oebps_file_paths(epub_directory)
135
+ glob_relative_path(epub_directory, "#{CONTENTS_DIR_NAME}/**/*").select do |relative_path|
136
+ (epub_directory + relative_path).file?
137
+ end
138
+ end
139
+
140
+ def media_type_for(path)
141
+ MEDIA_TYPES[path.extname.downcase] || 'application/octet-stream'
142
+ end
143
+
144
+ # class ページ以外("OEBPS/method/Array/i/each.xhtml" 等)の manifest
145
+ # item id。XML の NCName として妥当で一意になるよう、使えない文字は "-" に
146
+ # 置き換え、ディレクトリ境界は "--" にして encodename 由来の "-" と
147
+ # 区別する
148
+ def manifest_id_for(path)
149
+ relative = path.to_s.sub(%r{\A#{Regexp.escape(CONTENTS_DIR_NAME)}/}, "")
150
+ segments = relative.split("/").map{|segment| segment.gsub(/[^A-Za-z0-9_.-]/, "-") }
151
+ "item-#{segments.join('--')}"
152
+ end
153
+
154
+ def remove_index_stub(contents_directory)
155
+ stub_path = contents_directory + INDEX_STUB_NAME
156
+ FileUtils.rm_f(stub_path.to_s, :verbose => @verbose) if stub_path.file?
157
+ end
158
+
95
159
  def pack_epub(epub_directory)
96
160
  epub_filename = @outputdir + @filename
97
161
  Dir.chdir(epub_directory.to_s) do
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # irb からるりま(Ruby リファレンスマニュアル)を引く refe コマンド。
4
+ # ~/.irbrc に `require "bitclust/irb"` と書くと irb に `refe` コマンドが
5
+ # 登録される。検索対象の DB は refe コマンドと同じ場所(bitclust setup が
6
+ # 作る設定ファイル)から探し、DB が無ければ docs.ruby-lang.org の検索索引と
7
+ # Markdown 配信から取得する(BitClust::Remote)。
8
+
9
+ require 'stringio'
10
+ require 'bitclust'
11
+ require 'bitclust/searcher'
12
+
13
+ module BitClust
14
+ module Irb
15
+ USAGE = <<~USAGE
16
+ Usage: refe <pattern>
17
+
18
+ 例:
19
+ refe String#gsub インスタンスメソッド
20
+ refe Array.new 特異メソッド
21
+ refe Comparable クラス・モジュール
22
+ refe each 名前だけでの検索(該当が複数なら一覧)
23
+
24
+ DB が無い場合は docs.ruby-lang.org から取得します(1 日キャッシュ)。
25
+ `bitclust setup` で DB を作ると手元で検索できます。
26
+ USAGE
27
+
28
+ # pattern を検索して整形済みテキストを io へ書く。db が nil なら
29
+ # 既定の場所から探し、そこにも無ければ remote(省略時は
30
+ # Remote.default。nil ならフォールバックしない)で検索する。
31
+ # 検索の失敗は例外にせず io へメッセージを書く(irb セッションを
32
+ # 止めないため)
33
+ def self.lookup(pattern, io: $stdout, db: nil, remote: Remote.default)
34
+ words = pattern.to_s.split
35
+ if words.empty?
36
+ io.puts USAGE
37
+ return
38
+ end
39
+ view = TerminalView.new(Plain.new,
40
+ { describe_all: false, line: false, encoding: nil },
41
+ io: io)
42
+ searcher = Searcher.new
43
+ searcher.remote = remote
44
+ searcher.run_query(db, words, view)
45
+ rescue BitClust::UserError => err
46
+ io.puts err.message
47
+ end
48
+
49
+ begin
50
+ require 'irb/command'
51
+ rescue LoadError
52
+ # irb が無い(または irb < 1.13 で公開コマンド API が無い)環境では
53
+ # コマンド登録だけを諦め、Irb.lookup は使えるままにする
54
+ else
55
+ class RefeCommand < ::IRB::Command::Base
56
+ category 'Documentation'
57
+ description 'るりま(Ruby リファレンスマニュアル)を検索して表示します'
58
+ help_message USAGE
59
+
60
+ def execute(arg)
61
+ content = StringIO.new
62
+ BitClust::Irb.lookup(arg, io: content)
63
+ if ::IRB.const_defined?(:Pager)
64
+ ::IRB::Pager.page_content(content.string)
65
+ else
66
+ $stdout.puts content.string
67
+ end
68
+ end
69
+ end
70
+
71
+ ::IRB::Command.register(:refe, RefeCommand)
72
+ end
73
+ end
74
+ end
@@ -134,12 +134,17 @@ module BitClust
134
134
  reopen_only = members[path][:kinds].all? { |kind, _| %w[reopen redefine].include?(kind) }
135
135
  [reopen_only ? 1 : 0, path]
136
136
  end
137
- "\n" + sorted.map { |path|
138
- m = members[path][:memberships].find { |mm| mm[:library] == libname } || raise
139
- inc = "\#@include(#{relative(emitted[path], base)})\n"
140
- inc = "\#@since #{m[:since]}\n#{inc}\#@end\n" if m[:since]
141
- inc = "\#@until #{m[:until]}\n#{inc}\#@end\n" if m[:until]
142
- inc
137
+ # 同じライブラリへの membership が複数ある(#%version A...B の #%else =
138
+ # A 未満と B 以上)ときは、それぞれのゲートで include サイトを繰り返す
139
+ "\n" + sorted.flat_map { |path|
140
+ members[path][:memberships].select { |mm| mm[:library] == libname }.map { |m|
141
+ inc = "\#@include(#{relative(emitted[path], base)})\n"
142
+ inc = "\#@since #{m[:since]}\n#{inc}\#@end\n" if m[:since]
143
+ inc = "\#@until #{m[:until]}\n#{inc}\#@end\n" if m[:until]
144
+ inc = "\#@if (version == \"#{m[:version]}\")\n#{inc}\#@end\n" if m[:version]
145
+ (m[:except] || []).each { |x| inc = "\#@if (version != \"#{x}\")\n#{inc}\#@end\n" }
146
+ inc
147
+ }
143
148
  }.join
144
149
  end
145
150