review 4.1.0 → 5.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (259) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby-tex.yml +35 -0
  3. data/.github/workflows/ruby-win.yml +19 -9
  4. data/.github/workflows/ruby.yml +7 -3
  5. data/.rubocop.yml +138 -34
  6. data/NEWS.ja.md +285 -0
  7. data/NEWS.md +285 -1
  8. data/README.md +7 -6
  9. data/Rakefile +7 -2
  10. data/bin/review +2 -4
  11. data/bin/review-catalog-converter +4 -4
  12. data/bin/review-check +8 -12
  13. data/bin/review-checkdep +2 -5
  14. data/bin/review-compile +18 -34
  15. data/bin/review-epub2html +1 -4
  16. data/bin/review-epubmaker +3 -4
  17. data/bin/review-idgxmlmaker +1 -3
  18. data/bin/review-index +5 -86
  19. data/bin/review-init +1 -4
  20. data/bin/review-pdfmaker +1 -3
  21. data/bin/review-preproc +30 -38
  22. data/bin/review-textmaker +1 -3
  23. data/bin/review-update +1 -4
  24. data/bin/review-validate +4 -4
  25. data/bin/review-vol +5 -82
  26. data/bin/review-webmaker +1 -3
  27. data/doc/config.yml.sample +45 -11
  28. data/doc/config.yml.sample-simple +3 -3
  29. data/doc/format.ja.md +103 -13
  30. data/doc/format.md +104 -16
  31. data/doc/makeindex.ja.md +2 -2
  32. data/doc/pdfmaker.ja.md +42 -0
  33. data/doc/pdfmaker.md +41 -0
  34. data/doc/quickstart.ja.md +19 -6
  35. data/doc/quickstart.md +18 -6
  36. data/doc/writing_vertical.ja.md +6 -0
  37. data/lib/review.rb +1 -1
  38. data/lib/review/book.rb +2 -2
  39. data/lib/review/book/base.rb +67 -29
  40. data/lib/review/book/bib.rb +21 -0
  41. data/lib/review/book/book_unit.rb +158 -0
  42. data/lib/review/book/chapter.rb +33 -26
  43. data/lib/review/book/index.rb +24 -185
  44. data/lib/review/book/index/item.rb +7 -1
  45. data/lib/review/book/page_metric.rb +7 -7
  46. data/lib/review/book/part.rb +26 -11
  47. data/lib/review/book/volume.rb +5 -5
  48. data/lib/review/builder.rb +121 -52
  49. data/lib/review/call_hook.rb +20 -0
  50. data/lib/review/catalog.rb +3 -2
  51. data/lib/review/compiler.rb +230 -111
  52. data/lib/review/configure.rb +91 -7
  53. data/lib/review/converter.rb +1 -1
  54. data/lib/review/epub2html.rb +6 -1
  55. data/lib/review/epubmaker.rb +124 -152
  56. data/lib/review/epubmaker/content.rb +113 -0
  57. data/lib/review/epubmaker/epubcommon.rb +372 -0
  58. data/lib/review/epubmaker/epubv2.rb +178 -0
  59. data/lib/review/epubmaker/epubv3.rb +231 -0
  60. data/lib/review/epubmaker/producer.rb +167 -0
  61. data/lib/review/epubmaker/reviewheaderlistener.rb +12 -2
  62. data/lib/review/epubmaker/zip_exporter.rb +84 -0
  63. data/lib/review/exception.rb +13 -0
  64. data/lib/review/htmlbuilder.rb +176 -89
  65. data/lib/review/htmlutils.rb +8 -11
  66. data/lib/review/i18n.rb +2 -1
  67. data/lib/review/idgxmlbuilder.rb +165 -75
  68. data/lib/review/idgxmlmaker.rb +24 -28
  69. data/lib/review/img_math.rb +238 -0
  70. data/lib/review/index_builder.rb +645 -0
  71. data/lib/review/init.rb +9 -17
  72. data/lib/review/latexbox.rb +58 -0
  73. data/lib/review/latexbuilder.rb +193 -75
  74. data/lib/review/latexutils.rb +9 -1
  75. data/lib/review/lineinput.rb +112 -2
  76. data/lib/review/loggable.rb +27 -0
  77. data/lib/review/logger.rb +90 -3
  78. data/lib/review/makerhelper.rb +17 -188
  79. data/lib/review/markdownbuilder.rb +54 -4
  80. data/lib/review/pdfmaker.rb +76 -84
  81. data/lib/review/plaintextbuilder.rb +106 -22
  82. data/lib/review/preprocessor.rb +107 -303
  83. data/lib/review/preprocessor/directive.rb +35 -0
  84. data/lib/review/preprocessor/line.rb +34 -0
  85. data/lib/review/preprocessor/repository.rb +177 -0
  86. data/lib/review/rstbuilder.rb +27 -8
  87. data/lib/review/sec_counter.rb +14 -0
  88. data/lib/review/template.rb +11 -1
  89. data/lib/review/textmaker.rb +27 -32
  90. data/lib/review/textutils.rb +3 -12
  91. data/lib/review/tocprinter.rb +242 -97
  92. data/lib/review/topbuilder.rb +98 -31
  93. data/lib/review/update.rb +12 -13
  94. data/lib/review/version.rb +1 -1
  95. data/lib/review/volumeprinter.rb +97 -0
  96. data/lib/review/webmaker.rb +40 -47
  97. data/lib/review/webtocprinter.rb +39 -35
  98. data/lib/review/yamlloader.rb +2 -1
  99. data/review.gemspec +5 -3
  100. data/samples/sample-book/src/config-epub2.yml +1 -1
  101. data/samples/sample-book/src/config.yml +3 -3
  102. data/samples/sample-book/src/lib/tasks/review.rake +19 -1
  103. data/samples/sample-book/src/lib/tasks/z01_copy_sty.rake +2 -1
  104. data/samples/syntax-book/Gemfile +1 -1
  105. data/samples/syntax-book/ch01.re +1 -1
  106. data/samples/syntax-book/ch02.re +21 -6
  107. data/samples/syntax-book/ch03.re +1 -1
  108. data/samples/syntax-book/config.yml +1 -1
  109. data/samples/syntax-book/images/img3-2.png +0 -0
  110. data/samples/syntax-book/lib/tasks/z01_copy_sty.rake +2 -1
  111. data/templates/html/_colophon.html.erb +23 -0
  112. data/templates/html/_colophon_history.html.erb +9 -0
  113. data/templates/html/_cover.html.erb +10 -0
  114. data/templates/html/_part_body.html.erb +6 -0
  115. data/templates/html/_titlepage.html.erb +20 -0
  116. data/templates/html/layout-html5.html.erb +6 -0
  117. data/templates/html/layout-xhtml1.html.erb +6 -0
  118. data/templates/latex/config.erb +35 -23
  119. data/templates/latex/review-jlreq/README.md +3 -1
  120. data/templates/latex/review-jlreq/review-base.sty +36 -23
  121. data/templates/latex/review-jlreq/review-jlreq.cls +18 -25
  122. data/templates/latex/review-jlreq/review-style.sty +6 -1
  123. data/templates/latex/review-jlreq/review-tcbox.sty +348 -0
  124. data/templates/latex/review-jlreq/reviewmacro.sty +5 -0
  125. data/templates/latex/review-jsbook/README.md +7 -5
  126. data/templates/latex/review-jsbook/review-base.sty +40 -24
  127. data/templates/latex/review-jsbook/review-jsbook.cls +13 -3
  128. data/templates/latex/review-jsbook/review-style.sty +6 -1
  129. data/templates/latex/review-jsbook/review-tcbox.sty +348 -0
  130. data/templates/latex/review-jsbook/reviewmacro.sty +5 -0
  131. data/templates/opf/epubv2.opf.erb +7 -7
  132. data/templates/opf/epubv3.opf.erb +7 -7
  133. data/templates/opf/opf_manifest_epubv2.opf.erb +10 -0
  134. data/templates/opf/opf_manifest_epubv3.opf.erb +10 -0
  135. data/templates/opf/opf_metainfo_epubv2.opf.erb +17 -0
  136. data/templates/opf/opf_metainfo_epubv3.opf.erb +49 -0
  137. data/templates/opf/opf_tocx_epubv2.opf.erb +9 -0
  138. data/templates/opf/opf_tocx_epubv3.opf.erb +17 -0
  139. data/templates/web/html/layout-html5.html.erb +9 -8
  140. data/templates/web/html/layout-xhtml1.html.erb +6 -0
  141. data/test/assets/header_listener.html +35 -0
  142. data/test/assets/img_math/img1.png +0 -0
  143. data/test/assets/img_math/img2.png +0 -0
  144. data/test/assets/img_math/img3.png +0 -0
  145. data/test/assets/syntax_book_index_detail.txt +58 -0
  146. data/test/assets/test_template.tex +6 -3
  147. data/test/assets/test_template_backmatter.tex +6 -3
  148. data/test/book_test_helper.rb +11 -5
  149. data/test/run_test.rb +1 -1
  150. data/test/test_book.rb +54 -63
  151. data/test/test_book_chapter.rb +95 -54
  152. data/test/test_book_part.rb +3 -3
  153. data/test/test_builder.rb +29 -20
  154. data/test/test_catalog_converter_cmd.rb +1 -1
  155. data/test/test_converter.rb +1 -0
  156. data/test/test_epub3maker.rb +170 -126
  157. data/test/test_epubmaker.rb +254 -129
  158. data/test/test_epubmaker_cmd.rb +15 -4
  159. data/test/test_helper.rb +12 -5
  160. data/test/test_htmlbuilder.rb +926 -76
  161. data/test/test_htmlutils.rb +0 -12
  162. data/test/test_i18n.rb +33 -33
  163. data/test/test_idgxmlbuilder.rb +531 -20
  164. data/test/test_idgxmlmaker_cmd.rb +7 -3
  165. data/test/test_img_math.rb +111 -0
  166. data/test/test_index.rb +62 -52
  167. data/test/test_indexbuilder.rb +52 -0
  168. data/test/test_latexbuilder.rb +891 -20
  169. data/test/test_latexbuilder_v2.rb +56 -10
  170. data/test/test_lineinput.rb +20 -93
  171. data/test/test_logger.rb +7 -7
  172. data/test/test_makerhelper.rb +0 -12
  173. data/test/test_markdownbuilder.rb +32 -0
  174. data/test/test_pdfmaker.rb +100 -11
  175. data/test/test_pdfmaker_cmd.rb +3 -3
  176. data/test/test_plaintextbuilder.rb +546 -32
  177. data/test/test_preprocessor.rb +188 -1
  178. data/test/test_review_ext.rb +2 -1
  179. data/test/test_reviewheaderlistener.rb +49 -0
  180. data/test/test_rstbuilder.rb +25 -1
  181. data/test/test_sec_counter.rb +156 -0
  182. data/test/test_template.rb +12 -2
  183. data/test/test_textmaker_cmd.rb +5 -1
  184. data/test/test_tocprinter.rb +46 -0
  185. data/test/test_topbuilder.rb +324 -20
  186. data/test/test_update.rb +44 -44
  187. data/test/test_webtocprinter.rb +75 -43
  188. data/test/test_zip_exporter.rb +5 -6
  189. data/vendor/gentombow/LICENSE +1 -1
  190. data/vendor/gentombow/Makefile +0 -1
  191. data/vendor/gentombow/bounddvi-en.pdf +0 -0
  192. data/vendor/gentombow/bounddvi-en.tex +1 -0
  193. data/vendor/gentombow/bounddvi.pdf +0 -0
  194. data/vendor/gentombow/bounddvi.sty +30 -7
  195. data/vendor/gentombow/bounddvi.tex +1 -0
  196. data/vendor/gentombow/create_archive.sh +1 -0
  197. data/vendor/gentombow/gentombow-ja.pdf +0 -0
  198. data/vendor/gentombow/gentombow-ja.tex +9 -0
  199. data/vendor/gentombow/gentombow.pdf +0 -0
  200. data/vendor/gentombow/gentombow.sty +32 -10
  201. data/vendor/gentombow/gentombow.tex +8 -0
  202. data/vendor/gentombow/tests/gentombow-01-pdfx.tex +8 -0
  203. data/vendor/gentombow/tests/gentombow-02-pdfx.tex +8 -0
  204. data/vendor/jsclasses/Makefile +3 -2
  205. data/vendor/jsclasses/create_archive.sh +5 -5
  206. data/vendor/jsclasses/jis/Makefile +3 -2
  207. data/vendor/jsclasses/jis/jsarticle.cls +22 -18
  208. data/vendor/jsclasses/jis/jsbook.cls +22 -18
  209. data/vendor/jsclasses/jis/jsclasses.dtx +94 -13
  210. data/vendor/jsclasses/jis/jsclasses.ins +15 -5
  211. data/vendor/jsclasses/jis/jslogo.ins +9 -0
  212. data/vendor/jsclasses/jis/jslogo.sty +1 -13
  213. data/vendor/jsclasses/jis/jspf.cls +22 -18
  214. data/vendor/jsclasses/jis/jsreport.cls +22 -18
  215. data/vendor/jsclasses/jis/jsverb.ins +9 -0
  216. data/vendor/jsclasses/jis/jsverb.sty +1 -13
  217. data/vendor/jsclasses/jis/kiyou.cls +22 -18
  218. data/vendor/jsclasses/jis/minijs.sty +65 -22
  219. data/vendor/jsclasses/jis/okumacro.ins +9 -0
  220. data/vendor/jsclasses/jis/okumacro.sty +1 -13
  221. data/vendor/jsclasses/jis/okuverb.ins +9 -0
  222. data/vendor/jsclasses/jis/okuverb.sty +1 -13
  223. data/vendor/jsclasses/jis/winjis.sty +23 -19
  224. data/vendor/jsclasses/jsarticle.cls +22 -18
  225. data/vendor/jsclasses/jsbook.cls +22 -18
  226. data/vendor/jsclasses/jsclasses.dtx +94 -13
  227. data/vendor/jsclasses/jsclasses.ins +15 -5
  228. data/vendor/jsclasses/jsclasses.pdf +0 -0
  229. data/vendor/jsclasses/jslogo.ins +9 -0
  230. data/vendor/jsclasses/jslogo.pdf +0 -0
  231. data/vendor/jsclasses/jslogo.sty +1 -13
  232. data/vendor/jsclasses/jspf.cls +22 -18
  233. data/vendor/jsclasses/jsreport.cls +22 -18
  234. data/vendor/jsclasses/jsverb.ins +9 -0
  235. data/vendor/jsclasses/jsverb.pdf +0 -0
  236. data/vendor/jsclasses/jsverb.sty +1 -13
  237. data/vendor/jsclasses/kiyou.cls +22 -18
  238. data/vendor/jsclasses/minijs.sty +68 -22
  239. data/vendor/jsclasses/okumacro.ins +9 -0
  240. data/vendor/jsclasses/okumacro.pdf +0 -0
  241. data/vendor/jsclasses/okumacro.sty +1 -13
  242. data/vendor/jsclasses/okuverb.ins +9 -0
  243. data/vendor/jsclasses/okuverb.pdf +0 -0
  244. data/vendor/jsclasses/okuverb.sty +1 -13
  245. data/vendor/jsclasses/tests/relfont.tex +10 -0
  246. data/vendor/jsclasses/winjis.sty +23 -19
  247. metadata +106 -22
  248. data/.rubocop_todo.yml +0 -7
  249. data/lib/epubmaker.rb +0 -23
  250. data/lib/epubmaker/content.rb +0 -110
  251. data/lib/epubmaker/epubcommon.rb +0 -441
  252. data/lib/epubmaker/epubv2.rb +0 -143
  253. data/lib/epubmaker/epubv3.rb +0 -233
  254. data/lib/epubmaker/producer.rb +0 -375
  255. data/lib/epubmaker/zip_exporter.rb +0 -81
  256. data/lib/lineinput.rb +0 -155
  257. data/lib/review/book/compilable.rb +0 -178
  258. data/lib/review/tocparser.rb +0 -275
  259. data/test/test_tocparser.rb +0 -25
@@ -9,119 +9,109 @@
9
9
 
10
10
  require 'review/textutils'
11
11
  require 'review/exception'
12
- require 'nkf'
12
+ require 'review/preprocessor/directive'
13
+ require 'review/preprocessor/line'
14
+ require 'review/preprocessor/repository'
15
+ require 'review/loggable'
16
+ require 'open3'
13
17
 
14
18
  module ReVIEW
15
- module ErrorUtils
16
- def init_errorutils(f)
17
- @errutils_file = f
18
- @errutils_err = false
19
- end
20
-
21
- def warn(msg)
22
- @logger.warn "#{location}: #{msg}"
23
- end
24
-
25
- def error(msg)
26
- @errutils_err = true
27
- raise ApplicationError, "#{location}: #{msg}"
28
- end
29
-
30
- def location
31
- "#{filename}:#{lineno}"
32
- end
33
-
34
- def filename
35
- @errutils_file.path
36
- end
37
-
38
- def lineno
39
- @errutils_file.lineno
40
- end
41
- end
42
-
43
19
  class Preprocessor
44
- include ErrorUtils
20
+ include Loggable
45
21
 
46
- def initialize(repo, param)
47
- @repository = repo
48
- @config = param
22
+ TYPES = %w[file range].freeze
23
+ KNOWN_DIRECTIVES = %w[require provide warn ok].freeze
24
+ INF_INDENT = 9999
25
+
26
+ def initialize(param)
27
+ @repository = ReVIEW::Preprocessor::Repository.new(param)
28
+ @config = param ## do not use params in this class; only used in Repository
49
29
  @logger = ReVIEW.logger
50
30
  @leave_content = nil
51
31
  end
52
32
 
53
- def process(inf, outf)
54
- init_errorutils(inf)
55
- @f = outf
56
- begin
57
- preproc(inf)
58
- rescue Errno::ENOENT => e
59
- error e.message
33
+ def process(path)
34
+ File.open(path) do |inf|
35
+ @inf = inf
36
+ @f = StringIO.new
37
+ begin
38
+ preproc(@inf)
39
+ rescue Errno::ENOENT => e
40
+ error! e.message
41
+ end
42
+ @f.string
60
43
  end
61
44
  end
62
45
 
63
46
  private
64
47
 
65
- TYPES = %w[file range].freeze
66
-
67
48
  def preproc(f)
68
- init_vars
69
- f.each_line do |line|
70
- case line
71
- when /\A\#@\#/, /\A\#\#\#\#/
72
- @f.print line
73
-
74
- when /\A\#@defvar/
75
- @f.print line
76
- direc = parse_directive(line, 2)
77
- defvar(*direc.args)
49
+ @vartable = {}
50
+ @has_errors = false
78
51
 
79
- when /\A\#@mapoutput/
80
- direc = parse_directive(line, 1, 'stderr')
81
- @f.print line
82
- get_output(expand(direc.arg), direc['stderr']).each { |out| @f.print out.string }
83
- skip_list(f)
84
-
85
- when /\A\#@mapfile/
86
- direc = parse_directive(line, 1, 'eval')
87
- path = expand(direc.arg)
88
- @leave_content = File.extname(path) == '.re'
89
- if direc['eval']
90
- ent = evaluate(path, ent)
91
- else
92
- ent = @repository.fetch_file(path)
93
- end
94
- replace_block(f, line, ent, false) # FIXME: turn off lineno: tmp
52
+ f.each_line do |line|
53
+ begin
54
+ case line
55
+ when /\A\#@\#/, /\A\#\#\#\#/
56
+ @f.print line
95
57
 
96
- when /\A\#@map(?:range)?/
97
- direc = parse_directive(line, 2, 'unindent')
98
- path = expand(direc.args[0])
99
- @leave_content = File.extname(path) == '.re'
100
- ent = @repository.fetch_range(path, direc.args[1]) or
101
- error "unknown range: #{path}: #{direc.args[1]}"
102
- ent = (direc['unindent'] ? unindent(ent, direc['unindent']) : ent)
103
- replace_block(f, line, ent, false) # FIXME: turn off lineno: tmp
58
+ when /\A\#@defvar/
59
+ @f.print line
60
+ direc = parse_directive(line, 2)
61
+ defvar(*direc.args)
104
62
 
105
- when /\A\#@end/
106
- error 'unbaranced #@end'
63
+ when /\A\#@mapoutput/
64
+ direc = parse_directive(line, 1, 'stderr')
65
+ @f.print line
66
+ get_output(expand(direc.arg), direc['stderr']).each { |out| @f.print out.string }
67
+ skip_list(f)
68
+
69
+ when /\A\#@mapfile/
70
+ direc = parse_directive(line, 1, 'eval')
71
+ path = expand(direc.arg)
72
+ @leave_content = File.extname(path) == '.re'
73
+ if direc['eval']
74
+ ent = evaluate(path, ent)
75
+ else
76
+ ent = @repository.fetch_file(path)
77
+ end
78
+ replace_block(f, line, ent, false) # FIXME: turn off lineno: tmp
79
+
80
+ when /\A\#@map(?:range)?/
81
+ direc = parse_directive(line, 2, 'unindent')
82
+ path = expand(direc.args[0])
83
+ @leave_content = File.extname(path) == '.re'
84
+ ent = @repository.fetch_range(path, direc.args[1]) or
85
+ app_error "unknown range: #{path}: #{direc.args[1]}"
86
+ ent = (direc['unindent'] ? unindent(ent, direc['unindent']) : ent)
87
+ replace_block(f, line, ent, false) # FIXME: turn off lineno: tmp
88
+
89
+ when /\A\#@end/
90
+ app_error 'unbaranced #@end'
91
+
92
+ when /\A\#@/
93
+ op = line.slice(/@(\w+)/, 1)
94
+ warn "unknown directive: #{line.strip}", location: location unless known_directive?(op)
95
+ if op == 'warn'
96
+ warn line.strip.sub(/\#@warn\((.+)\)/, '\1'), location: location
97
+ end
98
+ @f.print line
107
99
 
108
- when /\A\#@/
109
- op = line.slice(/@(\w+)/, 1)
110
- warn "unknown directive: #{line.strip}" unless known_directive?(op)
111
- if op == 'warn'
112
- warn line.strip.sub(/\#@warn\((.+)\)/, '\1')
100
+ when /\A\s*\z/ # empty line
101
+ @f.puts
102
+ else # rubocop:disable Lint/DuplicateBranch
103
+ @f.print line
113
104
  end
114
- @f.print line
115
-
116
- when /\A\s*\z/ # empty line
117
- @f.puts
118
- else
119
- @f.print line
105
+ rescue ApplicationError => e
106
+ @has_errors = true
107
+ error e.message, location: location
120
108
  end
121
109
  end
122
- end
123
110
 
124
- KNOWN_DIRECTIVES = %w[require provide warn ok].freeze
111
+ if @has_erros
112
+ error! 'preprocessor failed.'
113
+ end
114
+ end
125
115
 
126
116
  def known_directive?(op)
127
117
  KNOWN_DIRECTIVES.index(op)
@@ -151,60 +141,37 @@ module ReVIEW
151
141
  return nil
152
142
  when %r{\A//\}}
153
143
  unless @leave_content
154
- warn '//} seen in list'
144
+ warn '//} seen in list', location: location
155
145
  @f.print line
156
146
  return nil
157
147
  end
158
148
  when /\A\#@\w/
159
- warn "#{line.slice(/\A\#@\w+/)} seen in list"
149
+ warn "#{line.slice(/\A\#@\w+/)} seen in list", location: location
160
150
  @f.print line
161
151
  when /\A\#@/
162
152
  @f.print line
163
153
  end
164
154
  end
165
- error "list reached end of file (beginning line = #{begline})"
166
- end
167
-
168
- class Directive
169
- def initialize(op, args, opts)
170
- @op = op
171
- @args = args
172
- @opts = opts
173
- end
174
-
175
- attr_reader :op
176
- attr_reader :args
177
- attr_reader :opts
178
-
179
- def arg
180
- @args.first
181
- end
182
-
183
- def opt
184
- @opts.first
185
- end
186
-
187
- def [](key)
188
- @opts[key]
189
- end
155
+ app_error "list reached end of file (beginning line = #{begline})"
190
156
  end
191
157
 
192
158
  def parse_directive(line, argc, *optdecl)
193
159
  m = /\A\#@(\w+)\((.*?)\)(?:\[(.*?)\])?\z/.match(line.strip) or
194
- error "wrong directive: #{line.strip}"
160
+ app_error "wrong directive: #{line.strip}"
195
161
  op = m[1]
196
162
  args = m[2].split(/,\s*/)
197
163
  opts = parse_optargs(m[3])
198
- return if argc == 0 and args.empty?
164
+ return if (argc == 0) && args.empty?
165
+
199
166
  if argc == -1
200
167
  # Any number of arguments are allowed.
201
168
  elsif args.size != argc
202
- error 'wrong arg size'
169
+ app_error 'wrong arg size'
203
170
  end
204
171
  if opts
205
172
  wrong_opts = opts.keys - optdecl
206
173
  unless wrong_opts.empty?
207
- error "wrong option: #{wrong_opts.keys.join(' ')}"
174
+ app_error "wrong option: #{wrong_opts.keys.join(' ')}"
208
175
  end
209
176
  end
210
177
  Directive.new(op, args, opts || {})
@@ -212,6 +179,7 @@ module ReVIEW
212
179
 
213
180
  def parse_optargs(str)
214
181
  return nil unless str
182
+
215
183
  table = {}
216
184
  str.split(/,\s*/).each do |a|
217
185
  name, spec = a.split('=', 2)
@@ -222,20 +190,19 @@ module ReVIEW
222
190
 
223
191
  def optarg_value(spec)
224
192
  case spec
225
- when 'true' then true # [name=true]
226
- when 'false' then false # [name=false]
227
- when 'nil' then nil # [name=nil]
228
- when nil then true # [name]
229
- when /^\d+$/ then $&.to_i # [name=8]
193
+ when 'true' # [name=true], [name]
194
+ true
195
+ when 'false' # [name=false]
196
+ false
197
+ when 'nil' # [name=nil]
198
+ nil
199
+ when /^\d+$/ # [name=8]
200
+ $&.to_i
230
201
  else # [name=val]
231
202
  spec
232
203
  end
233
204
  end
234
205
 
235
- def init_vars
236
- @vartable = {}
237
- end
238
-
239
206
  def defvar(name, value)
240
207
  @vartable[name] = value
241
208
  end
@@ -253,15 +220,13 @@ module ReVIEW
253
220
  chunk.map { |line| line.edit { |s| s.sub(re, '') } }
254
221
  end
255
222
 
256
- INF_INDENT = 9999
257
-
258
223
  def minimum_indent(chunk)
259
224
  n = chunk.map { |line| line.empty? ? INF_INDENT : line.num_indent }.min
260
225
  n == INF_INDENT ? 0 : n
261
226
  end
262
227
 
263
228
  def evaluate(path, chunk)
264
- outputs = get_output("ruby #{path}", false).split(/\n/).map(&:strip)
229
+ outputs = get_output("ruby #{path}", false).split("\n").map(&:strip)
265
230
  chunk.map do |line|
266
231
  if /\# \$\d+/ =~ line.string
267
232
  # map result into source.
@@ -272,8 +237,6 @@ module ReVIEW
272
237
  end
273
238
  end
274
239
 
275
- require 'open3'
276
-
277
240
  def get_output(cmd, use_stderr)
278
241
  out = err = nil
279
242
  Open3.popen3(cmd) do |_stdin, stdout, stderr|
@@ -284,184 +247,25 @@ module ReVIEW
284
247
  err = stderr.readlines
285
248
  end
286
249
  end
287
- if err and !err.empty?
250
+ if err && !err.empty?
288
251
  $stderr.puts '[unexpected stderr message]'
289
252
  err.each { |line| $stderr.print line }
290
- error 'get_output: got unexpected output'
253
+ app_error 'get_output: got unexpected output'
291
254
  end
292
255
  num = 0
293
256
  out.map { |line| Line.new(num += 1, line) }
294
257
  end
295
- end
296
-
297
- class Line
298
- def initialize(number, string)
299
- @number = number
300
- @string = string
301
- end
302
-
303
- attr_reader :number
304
- attr_reader :string
305
- alias_method :to_s, :string
306
-
307
- def edit
308
- self.class.new(@number, yield(@string))
309
- end
310
-
311
- def empty?
312
- @string.strip.empty?
313
- end
314
-
315
- def num_indent
316
- @string.slice(/\A\s*/).size
317
- end
318
- end
319
-
320
- class Repository
321
- include TextUtils
322
- include ErrorUtils
323
-
324
- def initialize(param)
325
- @repository = {}
326
- @config = param
327
- @logger = ReVIEW.logger
328
- end
329
-
330
- def fetch_file(file)
331
- file_descripter(file)['file']
332
- end
333
-
334
- def fetch_range(file, name)
335
- fetch(file, 'range', name)
336
- end
337
-
338
- def fetch(file, type, name)
339
- table = file_descripter(file)[type] or return nil
340
- table[name]
341
- end
342
-
343
- private
344
-
345
- def file_descripter(fname)
346
- @leave_content = File.extname(fname) == '.re'
347
- return @repository[fname] if @repository[fname]
348
-
349
- @repository[fname] = git?(fname) ? parse_git_blob(fname) : parse_file(fname)
350
- end
351
-
352
- def git?(fname)
353
- fname.start_with?('git|')
354
- end
355
-
356
- def parse_git_blob(g_obj)
357
- IO.popen('git show ' + g_obj.sub(/\Agit\|/, ''), 'r') do |f|
358
- init_errorutils f
359
- return _parse_file(f)
360
- end
361
- end
362
-
363
- def parse_file(fname)
364
- File.open(fname, 'rt:BOM|utf-8') do |f|
365
- init_errorutils f
366
- return _parse_file(f)
367
- end
368
- end
369
-
370
- def _parse_file(f)
371
- whole = []
372
- repo = { 'file' => whole }
373
- curr = { 'WHOLE' => whole }
374
- lineno = 1
375
- yacchack = false # remove ';'-only lines.
376
- opened = [['(not opened)', '(not opened)']] * 3
377
-
378
- f.each do |line|
379
- case line
380
- when /(?:\A\#@|\#@@)([a-z]+)_(begin|end)\((.*)\)/
381
- type = check_type($1)
382
- direction = $2
383
- spec = check_spec($3)
384
- case direction
385
- when 'begin'
386
- key = "#{type}/#{spec}"
387
- if curr[key]
388
- error "begin x2: #{key}"
389
- end
390
- (repo[type] ||= {})[spec] = curr[key] = []
391
- when 'end'
392
- curr.delete("#{type}/#{spec}") or
393
- error "end before begin: #{type}/#{spec}"
394
- else
395
- raise 'must not happen'
396
- end
397
-
398
- when %r{(?:\A\#@|\#@@)([a-z]+)/(\w+)\{}
399
- type = check_type($1)
400
- spec = check_spec($2)
401
- key = "#{type}/#{spec}"
402
- if curr[key]
403
- error "begin x2: #{key}"
404
- end
405
- (repo[type] ||= {})[spec] = curr[key] = []
406
- opened.push([type, spec])
407
-
408
- when %r{(?:\A\#@|\#@@)([a-z]+)/(\w+)\}}
409
- type = check_type($1)
410
- spec = check_spec($2)
411
- curr.delete("#{type}/#{spec}") or
412
- error "end before begin: #{type}/#{spec}"
413
- opened.delete("#{type}/#{spec}")
414
-
415
- when /(?:\A\#@|\#@@)\}/
416
- type, spec = opened.last
417
- curr.delete("#{type}/#{spec}") or
418
- error "closed before open: #{type}/#{spec}"
419
- opened.pop
420
-
421
- when /(?:\A\#@|\#@@)yacchack/
422
- yacchack = true
423
-
424
- when /\A\#@-/ # does not increment line number.
425
- line = canonical($')
426
- curr.each_value { |list| list.push(Line.new(nil, line)) }
427
-
428
- else
429
- next if yacchack and line.strip == ';'
430
- line = canonical(line)
431
- curr.each_value { |list| list.push(Line.new(lineno, line)) }
432
- lineno += 1
433
- end
434
- end
435
- if curr.size > 1
436
- curr.delete('WHOLE')
437
- curr.each { |range, lines| @logger.warn "#{filename}: unclosed range: #{range} (begin @#{lines.first.number})" }
438
- raise ApplicationError, 'ERROR'
439
- end
440
-
441
- repo
442
- end
443
-
444
- def canonical(line)
445
- if @leave_content
446
- return line
447
- end
448
258
 
449
- tabwidth = @config['tabwidth'] || 8
450
- if tabwidth > 0
451
- detab(line, tabwidth).rstrip + "\n"
452
- else
453
- line
454
- end
259
+ def location
260
+ "#{filename}:#{lineno}"
455
261
  end
456
262
 
457
- def check_type(type)
458
- error "wrong type: #{type.inspect}" unless Preprocessor::TYPES.index(type)
459
- type
263
+ def filename
264
+ @inf.path
460
265
  end
461
266
 
462
- def check_spec(spec)
463
- error "wrong spec: #{spec.inspect}" unless /\A\w+\z/ =~ spec
464
- spec
267
+ def lineno
268
+ @inf.lineno
465
269
  end
466
270
  end
467
271
  end