class ReVIEW::Builder

Constants

CAPTION_TITLES

Attributes

doc_status[RW]

Public Class Methods

new(strict = false, *args) click to toggle source
# File lib/review/builder.rb, line 35
def initialize(strict = false, *args)
  @strict = strict
  @output = nil
  @logger = ReVIEW.logger
  @doc_status = {}
  @dictionary = {}
  builder_init(*args)
end

Public Instance Methods

bibpaper(lines, id, caption) click to toggle source
# File lib/review/builder.rb, line 343
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) click to toggle source
# File lib/review/builder.rb, line 48
def bind(compiler, chapter, location)
  @compiler = compiler
  @chapter = chapter
  @location = location
  @output = StringIO.new
  if @chapter.present?
    @book = @chapter.book
  end
  @tabwidth = nil
  @tsize = nil
  if @book && @book.config
    if @book.config['words_file']
      load_words(@book.config['words_file'])
    end
    if @book.config['tabwidth']
      @tabwidth = @book.config['tabwidth']
    end
  end
  builder_init_file
end
blankline() click to toggle source

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

# File lib/review/builder.rb, line 224
def blankline
  puts ''
end
captionblock(_type, _lines, _caption, _specialstyle = nil) click to toggle source
# File lib/review/builder.rb, line 488
def captionblock(_type, _lines, _caption, _specialstyle = nil)
  raise NotImplementedError
end
compile_inline(s) click to toggle source
# File lib/review/builder.rb, line 228
def compile_inline(s)
  @compiler.text(s)
end
detab(str, num = nil) click to toggle source

override TextUtils::detab

Calls superclass method ReVIEW::TextUtils#detab
# File lib/review/builder.rb, line 624
def detab(str, num = nil)
  if num
    super(str, num)
  elsif @tabwidth
    super(str, @tabwidth)
  else
    super(str)
  end
end
embed(lines, arg = nil) click to toggle source
# File lib/review/builder.rb, line 422
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) click to toggle source
# File lib/review/builder.rb, line 208
def emtable(lines, caption = nil)
  table(lines, nil, caption)
end
error(msg) click to toggle source
# File lib/review/builder.rb, line 436
def error(msg)
  if msg =~ /:\d+: error: /
    raise ApplicationError, msg
  else
    raise ApplicationError, "#{@location}: error: #{msg}"
  end
end
escape(str) click to toggle source
# File lib/review/builder.rb, line 634
def escape(str)
  str
end
extract_chapter_id(chap_ref) click to toggle source
# File lib/review/builder.rb, line 478
def extract_chapter_id(chap_ref)
  m = /\A([\w+-]+)\|(.+)/.match(chap_ref)
  if m
    ch = @book.contents.detect { |chap| chap.id == m[1] }
    raise KeyError unless ch
    return [ch, m[2]]
  end
  [@chapter, chap_ref]
end
firstlinenum(num) click to toggle source

for //firstlinenum[num]

# File lib/review/builder.rb, line 111
def firstlinenum(num)
  @first_line_num = num.to_i
end
get_chap(chapter = @chapter) click to toggle source
# File lib/review/builder.rb, line 467
def get_chap(chapter = @chapter)
  if @book.config['secnolevel'] > 0 && !chapter.number.nil? && !chapter.number.to_s.empty?
    if chapter.is_a?(ReVIEW::Book::Part)
      return I18n.t('part_short', chapter.number)
    else
      return chapter.format_number(nil)
    end
  end
  nil
end
graph(lines, id, command, caption = '') click to toggle source
# File lib/review/builder.rb, line 500
def graph(lines, id, command, caption = '')
  c = target_name
  dir = File.join(@book.imagedir, c)
  FileUtils.mkdir_p(dir)
  file = "#{id}.#{image_ext}"
  file_path = File.join(dir, file)

  line = self.unescape(lines.join("\n"))

  tf = Tempfile.new('review_graph')
  tf.puts line
  tf.close
  begin
    file_path = send("graph_#{command}".to_sym, id, file_path, line, tf.path)
  ensure
    tf.unlink
  end
  @chapter.image_index.image_finder.add_entry(file_path)

  image(lines, id, caption)
end
graph_aafigure(id, file_path, _line, tf_path) click to toggle source
# File lib/review/builder.rb, line 549
def graph_aafigure(id, file_path, _line, tf_path)
  system_graph(id, 'aafigure', '-t', image_ext, '-o', file_path, tf_path)
  file_path
end
graph_blockdiag(id, file_path, _line, tf_path) click to toggle source
# File lib/review/builder.rb, line 544
def graph_blockdiag(id, file_path, _line, tf_path)
  system_graph(id, 'blockdiag', '-a', '-T', image_ext, '-o', file_path, tf_path)
  file_path
end
graph_gnuplot(id, file_path, line, tf_path) click to toggle source
# File lib/review/builder.rb, line 532
    def graph_gnuplot(id, file_path, line, tf_path)
      File.open(tf_path, 'w') do |tf|
        tf.puts <<EOTGNUPLOT
set terminal #{image_ext == 'eps' ? 'postscript eps' : image_ext}
set output "#{file_path}"
#{line}
EOTGNUPLOT
      end
      system_graph(id, 'gnuplot', tf_path)
      file_path
    end
graph_graphviz(id, file_path, _line, tf_path) click to toggle source
# File lib/review/builder.rb, line 527
def graph_graphviz(id, file_path, _line, tf_path)
  system_graph(id, 'dot', "-T#{image_ext}", "-o#{file_path}", tf_path)
  file_path
end
graph_plantuml(id, file_path, _line, tf_path) click to toggle source
# File lib/review/builder.rb, line 554
def graph_plantuml(id, file_path, _line, tf_path)
  ext = image_ext
  if ext == 'pdf'
    ext = 'eps'
    file_path.sub!(/\.pdf\Z/, '.eps')
  end
  system_graph(id, 'java', '-jar', 'plantuml.jar', "-t#{ext}", '-charset', 'UTF-8', tf_path)
  FileUtils.mv "#{tf_path}.#{ext}", file_path
  file_path
end
handle_metric(str) click to toggle source
# File lib/review/builder.rb, line 444
def handle_metric(str)
  str
end
image(lines, id, caption, metric = nil) click to toggle source
# File lib/review/builder.rb, line 146
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_ext() click to toggle source
# File lib/review/builder.rb, line 565
def image_ext
  raise NotImplementedError
end
inline_balloon(arg) click to toggle source
# File lib/review/builder.rb, line 392
def inline_balloon(arg)
  "← #{arg}"
end
inline_bou(str) click to toggle source
# File lib/review/builder.rb, line 310
def inline_bou(str)
  text(str)
end
inline_chap(id) click to toggle source
# File lib/review/builder.rb, line 238
def inline_chap(id)
  @book.chapter_index.number(id)
rescue KeyError
  error "unknown chapter: #{id}"
end
inline_chapref(id) click to toggle source
# File lib/review/builder.rb, line 232
def inline_chapref(id)
  compile_inline @book.chapter_index.display_string(id)
rescue KeyError
  error "unknown chapter: #{id}"
end
inline_column(id) click to toggle source
# File lib/review/builder.rb, line 366
def inline_column(id)
  m = /\A([^|]+)\|(.+)/.match(id)
  if m && m[1]
    chapter = @book.chapters.detect { |chap| chap.id == m[1] }
  end
  if chapter
    inline_column_chap(chapter, m[2])
  else
    inline_column_chap(@chapter, id)
  end
rescue KeyError
  error "unknown column: #{id}"
end
inline_column_chap(chapter, id) click to toggle source
# File lib/review/builder.rb, line 380
def inline_column_chap(chapter, id)
  I18n.t('column', chapter.column(id).caption)
end
inline_embed(args) click to toggle source
# File lib/review/builder.rb, line 606
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_eq(id) click to toggle source
# File lib/review/builder.rb, line 293
def inline_eq(id)
  chapter, id = extract_chapter_id(id)
  if get_chap(chapter)
    %Q(#{I18n.t('equation')}#{I18n.t('format_number', [get_chap(chapter), chapter.equation(id).number])})
  else
    %Q(#{I18n.t('equation')}#{I18n.t('format_number_without_chapter', [chapter.equation(id).number])})
  end
rescue KeyError
  error "unknown equation: #{id}"
end
inline_fn(id) click to toggle source
# File lib/review/builder.rb, line 304
def inline_fn(id)
  @chapter.footnote(id).content
rescue KeyError
  error "unknown footnote: #{id}"
end
inline_hd(id) click to toggle source
# File lib/review/builder.rb, line 352
def inline_hd(id)
  m = /\A([^|]+)\|(.+)/.match(id)
  if m && m[1]
    chapter = @book.contents.detect { |chap| chap.id == m[1] }
  end
  if chapter
    inline_hd_chap(chapter, m[2])
  else
    inline_hd_chap(@chapter, id)
  end
rescue KeyError
  error "unknown headline: #{id}"
end
inline_href(arg) click to toggle source
# File lib/review/builder.rb, line 330
def inline_href(arg)
  url, label = *arg.scan(/(?:(?:(?:\\\\)*\\,)|[^,\\]+)+/).map(&:lstrip)
  url = url.gsub(/\\,/, ',').strip
  if label
    label = label.gsub(/\\,/, ',').strip
  end
  compile_href(url, label)
end
inline_img(id) click to toggle source
# File lib/review/builder.rb, line 261
def inline_img(id)
  chapter, id = extract_chapter_id(id)
  if get_chap(chapter)
    %Q(#{I18n.t('image')}#{I18n.t('format_number', [get_chap(chapter), chapter.image(id).number])})
  else
    %Q(#{I18n.t('image')}#{I18n.t('format_number_without_chapter', [chapter.image(id).number])})
  end
rescue KeyError
  error "unknown image: #{id}"
end
inline_imgref(id) click to toggle source
# File lib/review/builder.rb, line 272
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) click to toggle source
# File lib/review/builder.rb, line 569
def inline_include(file_name)
  compile_inline File.read(file_name, mode: 'rt:BOM|utf-8').chomp
end
inline_kw(arg) click to toggle source
# File lib/review/builder.rb, line 325
def inline_kw(arg)
  word, alt = *arg.split(',', 2)
  compile_kw(word, alt)
end
inline_list(id) click to toggle source
# File lib/review/builder.rb, line 250
def inline_list(id)
  chapter, id = extract_chapter_id(id)
  if get_chap(chapter)
    %Q(#{I18n.t('list')}#{I18n.t('format_number', [get_chap(chapter), chapter.list(id).number])})
  else
    %Q(#{I18n.t('list')}#{I18n.t('format_number_without_chapter', [chapter.list(id).number])})
  end
rescue KeyError
  error "unknown list: #{id}"
end
inline_pageref(id) click to toggle source
# File lib/review/builder.rb, line 384
def inline_pageref(id)
  "[link:#{id}]"
end
inline_raw(args) click to toggle source
# File lib/review/builder.rb, line 592
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) click to toggle source
# File lib/review/builder.rb, line 314
def inline_ruby(arg)
  base, *ruby = *arg.scan(/(?:(?:(?:\\\\)*\\,)|[^,\\]+)+/)
  if base
    base = base.gsub(/\\,/, ',')
  end
  if ruby
    ruby = ruby.join(',').gsub(/\\,/, ',')
  end
  compile_ruby(base, ruby)
end
inline_table(id) click to toggle source
# File lib/review/builder.rb, line 282
def inline_table(id)
  chapter, id = extract_chapter_id(id)
  if get_chap(chapter)
    %Q(#{I18n.t('table')}#{I18n.t('format_number', [get_chap(chapter), chapter.table(id).number])})
  else
    %Q(#{I18n.t('table')}#{I18n.t('format_number_without_chapter', [chapter.table(id).number])})
  end
rescue KeyError
  error "unknown table: #{id}"
end
inline_tcy(arg) click to toggle source
# File lib/review/builder.rb, line 388
def inline_tcy(arg)
  "#{arg}[rotate 90 degree]"
end
inline_title(id) click to toggle source
# File lib/review/builder.rb, line 244
def inline_title(id)
  compile_inline @book.chapter_index.title(id)
rescue KeyError
  error "unknown chapter: #{id}"
end
inline_w(s) click to toggle source
# File lib/review/builder.rb, line 396
def inline_w(s)
  translated = @dictionary[s]
  if translated
    escape(translated)
  else
    warn "word not bound: #{s}"
    escape("[missing word: #{s}]")
  end
end
inline_wb(s) click to toggle source
# File lib/review/builder.rb, line 406
def inline_wb(s)
  inline_b(unescape(inline_w(s)))
end
line_num() click to toggle source
# File lib/review/builder.rb, line 115
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) click to toggle source
# File lib/review/builder.rb, line 123
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) click to toggle source
# File lib/review/builder.rb, line 132
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
load_words(file) click to toggle source
# File lib/review/builder.rb, line 92
def load_words(file)
  if File.exist?(file)
    if file =~ /\.csv\Z/i
      CSV.foreach(file) do |row|
        @dictionary[row[0]] = row[1]
      end
    end
  end
end
over_secnolevel?(n) click to toggle source
# File lib/review/builder.rb, line 619
def over_secnolevel?(n)
  @book.config['secnolevel'] >= n.to_s.split('.').size
end
parse_metric(type, metric) click to toggle source
# File lib/review/builder.rb, line 452
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_paragraph() click to toggle source
# File lib/review/builder.rb, line 29
def post_paragraph
  nil
end
pre_paragraph() click to toggle source
# File lib/review/builder.rb, line 25
def pre_paragraph
  nil
end
raw(str) click to toggle source
# File lib/review/builder.rb, line 410
def raw(str)
  if matched = str.match(/\|(.*?)\|(.*)/)
    builders = matched[1].split(',').map { |i| i.gsub(/\s/, '') }
    c = target_name
    if builders.include?(c)
      print matched[2].gsub('\\n', "\n")
    end
  else
    print str.gsub('\\n', "\n")
  end
end
raw_result()
Alias for: result
result() click to toggle source
# File lib/review/builder.rb, line 74
def result
  @output.string
end
Also aliased as: raw_result
result_metric(array) click to toggle source
# File lib/review/builder.rb, line 448
def result_metric(array)
  array.join(',')
end
source(lines, caption, lang = nil) click to toggle source
# File lib/review/builder.rb, line 141
def source(lines, caption, lang = nil)
  source_header caption
  source_body lines, lang
end
system_graph(id, *args) click to toggle source
# File lib/review/builder.rb, line 522
def system_graph(id, *args)
  @logger.info args.join(' ')
  Kernel.system(*args) or @logger.error("failed to run command for id #{id}: #{args.join(' ')}")
end
table(lines, id = nil, caption = nil) click to toggle source
# File lib/review/builder.rb, line 155
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)
  error 'no rows in the table' if rows.empty?

  begin
    if caption.present?
      table_header id, caption
    end
  rescue KeyError
    error "no such table: #{id}"
  end
  table_begin rows.first.size
  if sepidx
    sepidx.times do
      tr(rows.shift.map { |s| th(s) })
    end
    rows.each do |cols|
      tr(cols.map { |s| td(s) })
    end
  else
    rows.each do |cols|
      h, *cs = *cols
      tr([th(h)] + cs.map { |s| td(s) })
    end
  end
  table_end
end
target_name() click to toggle source
# File lib/review/builder.rb, line 88
def target_name
  self.class.to_s.gsub(/ReVIEW::/, '').gsub(/Builder/, '').downcase
end
text(str) click to toggle source
# File lib/review/builder.rb, line 339
def text(str)
  str
end
tsize(str) click to toggle source
# File lib/review/builder.rb, line 580
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
    if builders.include?(c)
      @tsize = matched[2]
    end
  else
    @tsize = str
  end
end
ul_item_begin(lines) click to toggle source
# File lib/review/builder.rb, line 573
def ul_item_begin(lines)
  ul_item(lines)
end
ul_item_end() click to toggle source
# File lib/review/builder.rb, line 577
def ul_item_end
end
unescape(str) click to toggle source
# File lib/review/builder.rb, line 638
def unescape(str)
  str
end
warn(msg) click to toggle source
# File lib/review/builder.rb, line 432
def warn(msg)
  @logger.warn "#{@location}: #{msg}"
end

Private Instance Methods

adjust_n_cols(rows) click to toggle source
# File lib/review/builder.rb, line 194
def adjust_n_cols(rows)
  rows.each do |cols|
    while cols.last and cols.last.strip.empty?
      cols.pop
    end
  end
  n_maxcols = rows.map(&:size).max
  rows.each do |cols|
    cols.concat [''] * (n_maxcols - cols.size)
  end
  rows
end
builder_init(*args) click to toggle source
# File lib/review/builder.rb, line 44
def builder_init(*args)
end
builder_init_file() click to toggle source
# File lib/review/builder.rb, line 69
def builder_init_file
  @sec_counter = SecCounter.new(5, @chapter)
end
headline_prefix(level) click to toggle source
# File lib/review/builder.rb, line 102
def headline_prefix(level)
  @sec_counter.inc(level)
  anchor = @sec_counter.anchor(level)
  prefix = @sec_counter.prefix(level, @book.config['secnolevel'])
  [prefix, anchor]
end
print(*s) click to toggle source
puts(*s) click to toggle source
# File lib/review/builder.rb, line 84
def puts(*s)
  @output.puts(*s)
end