Class: ReVIEW::Builder

Inherits:
Object show all
Includes:
TextUtils
Defined in:
lib/review/builder.rb

Constant Summary collapse

CAPTION_TITLES =
%w[note memo tip info warning important caution notice].freeze

Instance Method Summary collapse

Methods included from TextUtils

#split_paragraph

Constructor Details

#initialize(strict = false, *args) ⇒ Builder

Returns a new instance of Builder.



30
31
32
33
34
35
# File 'lib/review/builder.rb', line 30

def initialize(strict = false, *args)
  @strict = strict
  @output = nil
  @logger = ReVIEW.logger
  builder_init(*args)
end

Instance Method Details

#bibpaper(lines, id, caption) ⇒ Object



276
277
278
279
280
281
282
283
# File 'lib/review/builder.rb', line 276

def bibpaper(lines, id, caption)
  bibpaper_header id, caption
  unless lines.empty?
    puts
    bibpaper_bibpaper id, caption, lines
  end
  puts
end

#bind(compiler, chapter, location) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
# File 'lib/review/builder.rb', line 41

def bind(compiler, chapter, location)
  @compiler = compiler
  @chapter = chapter
  @location = location
  @output = StringIO.new
  @book = @chapter.book if @chapter.present?
  @tabwidth = nil
  @tsize = nil
  @tabwidth = @book.config['tabwidth'] if @book && @book.config && @book.config['tabwidth']
  builder_init_file
end

#captionblock(_type, _lines, _caption, _specialstyle = nil) ⇒ Object

Raises:

  • (NotImplementedError)


389
390
391
# File 'lib/review/builder.rb', line 389

def captionblock(_type, _lines, _caption, _specialstyle = nil)
  raise NotImplementedError
end

#compile_inline(s) ⇒ Object

def footnote(id, str)

@footnotes.push [id, str]

end

def flush_footnote

footnote_begin
@footnotes.each do |id, str|
  footnote_item(id, str)
end
footnote_end

end



186
187
188
# File 'lib/review/builder.rb', line 186

def compile_inline(s)
  @compiler.text(s)
end

#detab(str, num = nil) ⇒ Object

override TextUtils::detab



483
484
485
486
487
488
489
490
491
# File 'lib/review/builder.rb', line 483

def detab(str, num = nil)
  if num
    super(str, num)
  elsif @tabwidth
    super(str, @tabwidth)
  else
    super(str)
  end
end

#embed(lines, arg = nil) ⇒ Object



333
334
335
336
337
338
339
340
341
# File 'lib/review/builder.rb', line 333

def embed(lines, arg = nil)
  if arg
    builders = arg.gsub(/^\s*\|/, '').gsub(/\|\s*$/, '').gsub(/\s/, '').split(',')
    c = target_name
    print lines.join if builders.include?(c)
  else
    print lines.join
  end
end

#emtable(lines, caption = nil) ⇒ Object



170
171
172
# File 'lib/review/builder.rb', line 170

def emtable(lines, caption = nil)
  table(lines, nil, caption)
end

#error(msg) ⇒ Object

Raises:



347
348
349
350
# File 'lib/review/builder.rb', line 347

def error(msg)
  raise ApplicationError, msg if msg =~ /:\d+: error: /
  raise ApplicationError, "#{@location}: error: #{msg}"
end

#extract_chapter_id(chap_ref) ⇒ Object



383
384
385
386
387
# File 'lib/review/builder.rb', line 383

def extract_chapter_id(chap_ref)
  m = /\A([\w+-]+)\|(.+)/.match(chap_ref)
  return [@book.contents.detect { |chap| chap.id == m[1] }, m[2]] if m
  [@chapter, chap_ref]
end

#firstlinenum(num) ⇒ Object

for //firstlinenum



85
86
87
# File 'lib/review/builder.rb', line 85

def firstlinenum(num)
  @first_line_num = num.to_i
end

#get_chap(chapter = @chapter) ⇒ Object



375
376
377
378
379
380
381
# File 'lib/review/builder.rb', line 375

def get_chap(chapter = @chapter)
  if @book.config['secnolevel'] > 0 && !chapter.number.nil? && !chapter.number.to_s.empty?
    return I18n.t('part_short', chapter.number) if chapter.is_a?(ReVIEW::Book::Part)
    return chapter.format_number(nil)
  end
  nil
end

#graph(lines, id, command, caption = nil) ⇒ Object



401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
# File 'lib/review/builder.rb', line 401

def graph(lines, id, command, caption = nil)
  c = target_name
  dir = File.join(@book.basedir, @book.image_dir, c)
  Dir.mkdir(dir) unless File.exist?(dir)
  file = "#{id}.#{image_ext}"
  file_path = File.join(dir, file)

  line = self.unescape(lines.join("\n"))
  cmds = {
    graphviz: "echo '#{line}' | dot -T#{image_ext} -o#{file_path}",
    gnuplot: %Q(echo 'set terminal ) +
    "#{image_ext == 'eps' ? 'postscript eps' : image_ext}\n" +
    %Q(" set output "#{file_path}"\n#{line}' | gnuplot),
    blockdiag: "echo '#{line}' " +
    "| blockdiag -a -T #{image_ext} -o #{file_path} /dev/stdin",
    aafigure: "echo '#{line}' | aafigure -t#{image_ext} -o#{file_path}"
  }
  cmd = cmds[command.to_sym]
  warn cmd
  system cmd
  @chapter.image_index.image_finder.add_entry(file_path)

  image(lines, id, caption)
end

#handle_metric(str) ⇒ Object



352
353
354
# File 'lib/review/builder.rb', line 352

def handle_metric(str)
  str
end

#image(lines, id, caption, metric = nil) ⇒ Object



120
121
122
123
124
125
126
127
# File 'lib/review/builder.rb', line 120

def image(lines, id, caption, metric = nil)
  if @chapter.image(id).bound?
    image_image id, caption, metric
  else
    warn "image not bound: #{id}" if @strict
    image_dummy id, caption, lines
  end
end

#image_extObject

Raises:

  • (NotImplementedError)


426
427
428
# File 'lib/review/builder.rb', line 426

def image_ext
  raise NotImplementedError
end

#include(file_name) ⇒ Object



434
435
436
# File 'lib/review/builder.rb', line 434

def include(file_name)
  File.foreach(file_name) { |line| paragraph([line]) }
end

#inline_bou(str) ⇒ Object



249
250
251
# File 'lib/review/builder.rb', line 249

def inline_bou(str)
  text(str)
end

#inline_chap(id) ⇒ Object



197
198
199
200
201
202
# File 'lib/review/builder.rb', line 197

def inline_chap(id)
  @book.chapter_index.number(id)
rescue KeyError
  error "unknown chapter: #{id}"
  nofunc_text("[UnknownChapter:#{id}]")
end

#inline_chapref(id) ⇒ Object



190
191
192
193
194
195
# File 'lib/review/builder.rb', line 190

def inline_chapref(id)
  compile_inline @book.chapter_index.display_string(id)
rescue KeyError
  error "unknown chapter: #{id}"
  nofunc_text("[UnknownChapter:#{id}]")
end

#inline_column(id) ⇒ Object



298
299
300
301
302
303
304
305
306
307
308
309
# File 'lib/review/builder.rb', line 298

def inline_column(id)
  m = /\A([^|]+)\|(.+)/.match(id)
  chapter = @book.chapters.detect { |chap| chap.id == m[1] } if m && m[1]
  if chapter
    inline_column_chap(chapter, m[2])
  else
    inline_column_chap(@chapter, id)
  end
rescue KeyError
  error "unknown column: #{id}"
  nofunc_text("[UnknownColumn:#{id}]")
end

#inline_column_chap(chapter, id) ⇒ Object



311
312
313
# File 'lib/review/builder.rb', line 311

def inline_column_chap(chapter, id)
  chapter.column(id).caption
end

#inline_embed(args) ⇒ Object



469
470
471
472
473
474
475
476
477
478
479
480
# File 'lib/review/builder.rb', line 469

def inline_embed(args)
  if matched = args.match(/\|(.*?)\|(.*)/)
    builders = matched[1].split(',').map { |i| i.gsub(/\s/, '') }
    if builders.include?(target_name)
      matched[2]
    else
      ''
    end
  else
    args
  end
end

#inline_fn(id) ⇒ Object



242
243
244
245
246
247
# File 'lib/review/builder.rb', line 242

def inline_fn(id)
  @chapter.footnote(id).content
rescue KeyError
  error "unknown footnote: #{id}"
  nofunc_text("[UnknownFootnote:#{id}]")
end

#inline_hd(id) ⇒ Object



285
286
287
288
289
290
291
292
293
294
295
296
# File 'lib/review/builder.rb', line 285

def inline_hd(id)
  m = /\A([^|]+)\|(.+)/.match(id)
  chapter = @book.contents.detect { |chap| chap.id == m[1] } if m && m[1]
  if chapter
    inline_hd_chap(chapter, m[2])
  else
    inline_hd_chap(@chapter, id)
  end
rescue KeyError
  error "unknown hd: #{id}"
  nofunc_text("[UnknownHeader:#{id}]")
end

#inline_href(arg) ⇒ Object



265
266
267
268
269
270
# File 'lib/review/builder.rb', line 265

def inline_href(arg)
  url, label = *arg.scan(/(?:(?:(?:\\\\)*\\,)|[^,\\]+)+/).map(&:lstrip)
  url = url.gsub(/\\,/, ',').strip
  label = label.gsub(/\\,/, ',').strip if label
  compile_href(url, label)
end

#inline_img(id) ⇒ Object



218
219
220
221
222
223
# File 'lib/review/builder.rb', line 218

def inline_img(id)
  "#{I18n.t('image')}#{@chapter.image(id).number}"
rescue KeyError
  error "unknown image: #{id}"
  nofunc_text("[UnknownImage:#{id}]")
end

#inline_imgref(id) ⇒ Object



225
226
227
228
229
230
231
232
233
# File 'lib/review/builder.rb', line 225

def inline_imgref(id)
  img = inline_img(id)

  if @chapter.image(id).caption
    "#{img}#{I18n.t('image_quote', @chapter.image(id).caption)}"
  else
    img
  end
end

#inline_include(file_name) ⇒ Object



430
431
432
# File 'lib/review/builder.rb', line 430

def inline_include(file_name)
  compile_inline File.read(file_name)
end

#inline_kw(arg) ⇒ Object



260
261
262
263
# File 'lib/review/builder.rb', line 260

def inline_kw(arg)
  word, alt = *arg.split(',', 2)
  compile_kw(word, alt)
end

#inline_list(id) ⇒ Object



211
212
213
214
215
216
# File 'lib/review/builder.rb', line 211

def inline_list(id)
  "#{I18n.t('list')}#{@chapter.list(id).number}"
rescue KeyError
  error "unknown list: #{id}"
  nofunc_text("[UnknownList:#{id}]")
end

#inline_pageref(id) ⇒ Object



315
316
317
# File 'lib/review/builder.rb', line 315

def inline_pageref(id)
  "[link:#{id}]"
end

#inline_raw(args) ⇒ Object



455
456
457
458
459
460
461
462
463
464
465
466
467
# File 'lib/review/builder.rb', line 455

def inline_raw(args)
  if matched = args.match(/\|(.*?)\|(.*)/)
    builders = matched[1].split(',').map { |i| i.gsub(/\s/, '') }
    c = self.class.to_s.gsub('ReVIEW::', '').gsub('Builder', '').downcase
    if builders.include?(c)
      matched[2].gsub('\\n', "\n")
    else
      ''
    end
  else
    args.gsub('\\n', "\n")
  end
end

#inline_ruby(arg) ⇒ Object



253
254
255
256
257
258
# File 'lib/review/builder.rb', line 253

def inline_ruby(arg)
  base, *ruby = *arg.scan(/(?:(?:(?:\\\\)*\\,)|[^,\\]+)+/)
  base = base.gsub(/\\,/, ',') if base
  ruby = ruby.join(',').gsub(/\\,/, ',') if ruby
  compile_ruby(base, ruby)
end

#inline_table(id) ⇒ Object



235
236
237
238
239
240
# File 'lib/review/builder.rb', line 235

def inline_table(id)
  "#{I18n.t('table')}#{@chapter.table(id).number}"
rescue KeyError
  error "unknown table: #{id}"
  nofunc_text("[UnknownTable:#{id}]")
end

#inline_tcy(arg) ⇒ Object



319
320
321
# File 'lib/review/builder.rb', line 319

def inline_tcy(arg)
  "#{arg}[rotate 90 degree]"
end

#inline_title(id) ⇒ Object



204
205
206
207
208
209
# File 'lib/review/builder.rb', line 204

def inline_title(id)
  compile_inline @book.chapter_index.title(id)
rescue KeyError
  error "unknown chapter: #{id}"
  nofunc_text("[UnknownChapter:#{id}]")
end

#line_numObject



89
90
91
92
93
94
95
# File 'lib/review/builder.rb', line 89

def line_num
  return 1 unless @first_line_num
  line_n = @first_line_num
  @first_line_num = nil

  line_n
end

#list(lines, id, caption, lang = nil) ⇒ Object



97
98
99
100
101
102
103
104
# File 'lib/review/builder.rb', line 97

def list(lines, id, caption, lang = nil)
  begin
    list_header id, caption, lang
  rescue KeyError
    error "no such list: #{id}"
  end
  list_body id, lines, lang
end

#listnum(lines, id, caption, lang = nil) ⇒ Object



106
107
108
109
110
111
112
113
# File 'lib/review/builder.rb', line 106

def listnum(lines, id, caption, lang = nil)
  begin
    list_header id, caption, lang
  rescue KeyError
    error "no such list: #{id}"
  end
  listnum_body lines, lang
end

#parse_metric(type, metric) ⇒ Object



360
361
362
363
364
365
366
367
368
369
370
371
372
373
# File 'lib/review/builder.rb', line 360

def parse_metric(type, metric)
  return '' if metric.blank?
  params = metric.split(/,\s*/)
  results = []
  params.each do |param|
    if param =~ /\A.+?::/
      next unless param =~ /\A#{type}::/
      param.sub!(/\A#{type}::/, '')
    end
    param2 = handle_metric(param)
    results.push(param2)
  end
  result_metric(results)
end

#post_paragraphObject



26
27
28
# File 'lib/review/builder.rb', line 26

def post_paragraph
  nil
end

#pre_paragraphObject



22
23
24
# File 'lib/review/builder.rb', line 22

def pre_paragraph
  nil
end


64
65
66
# File 'lib/review/builder.rb', line 64

def print(*s)
  @output.print(*s)
end

#puts(*s) ⇒ Object



68
69
70
# File 'lib/review/builder.rb', line 68

def puts(*s)
  @output.puts(*s)
end

#raw(str) ⇒ Object



323
324
325
326
327
328
329
330
331
# File 'lib/review/builder.rb', line 323

def raw(str)
  if matched = str.match(/\|(.*?)\|(.*)/)
    builders = matched[1].split(',').map { |i| i.gsub(/\s/, '') }
    c = target_name
    print matched[2].gsub('\\n', "\n") if builders.include?(c)
  else
    print str.gsub('\\n', "\n")
  end
end

#resultObject Also known as: raw_result



58
59
60
# File 'lib/review/builder.rb', line 58

def result
  @output.string
end

#result_metric(array) ⇒ Object



356
357
358
# File 'lib/review/builder.rb', line 356

def result_metric(array)
  array.join(',')
end

#source(lines, caption, lang = nil) ⇒ Object



115
116
117
118
# File 'lib/review/builder.rb', line 115

def source(lines, caption, lang = nil)
  source_header caption
  source_body lines, lang
end

#table(lines, id = nil, caption = nil) ⇒ Object



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/review/builder.rb', line 129

def table(lines, id = nil, caption = nil)
  rows = []
  sepidx = nil
  lines.each_with_index do |line, idx|
    if /\A[\=\-]{12}/ =~ line
      # just ignore
      # error "too many table separator" if sepidx
      sepidx ||= idx
      next
    end
    rows.push(line.strip.split(/\t+/).map { |s| s.sub(/\A\./, '') })
  end
  rows = adjust_n_cols(rows)

  begin
    table_header id, caption if caption.present?
  rescue KeyError
    error "no such table: #{id}"
  end
  return if rows.empty?
  table_begin rows.first.size
  if sepidx
    sepidx.times { tr(rows.shift.map { |s| th(s) }) }
    rows.each { |cols| tr(cols.map { |s| td(s) }) }
  else
    rows.each do |cols|
      h, *cs = *cols
      tr([th(h)] + cs.map { |s| td(s) })
    end
  end
  table_end
end

#target_nameObject



72
73
74
# File 'lib/review/builder.rb', line 72

def target_name
  self.class.to_s.gsub(/ReVIEW::/, '').gsub(/Builder/, '').downcase
end

#text(str) ⇒ Object



272
273
274
# File 'lib/review/builder.rb', line 272

def text(str)
  str
end

#tsize(str) ⇒ Object



445
446
447
448
449
450
451
452
453
# File 'lib/review/builder.rb', line 445

def tsize(str)
  if matched = str.match(/\A\|(.*?)\|(.*)/)
    builders = matched[1].split(',').map { |i| i.gsub(/\s/, '') }
    c = self.class.to_s.gsub('ReVIEW::', '').gsub('Builder', '').downcase
    @tsize = matched[2] if builders.include?(c)
  else
    @tsize = str
  end
end

#ul_item_begin(lines) ⇒ Object



438
439
440
# File 'lib/review/builder.rb', line 438

def ul_item_begin(lines)
  ul_item(lines)
end

#ul_item_endObject



442
443
# File 'lib/review/builder.rb', line 442

def ul_item_end
end

#warn(msg) ⇒ Object



343
344
345
# File 'lib/review/builder.rb', line 343

def warn(msg)
  @logger.warn "#{@location}: #{msg}"
end