lib/review/latexbuilder.rb in review-2.4.0 vs lib/review/latexbuilder.rb in review-2.5.0

- old
+ new

@@ -1,8 +1,8 @@ # Copyright (c) 2002-2007 Minero Aoki # 2008-2009 Minero Aoki, Kenshi Muto -# 2010-2017 Minero Aoki, Kenshi Muto, TAKAHASHI Masayoshi +# 2010-2018 Minero Aoki, Kenshi Muto, TAKAHASHI Masayoshi # # This program is free software. # You can distribute or modify this program under the terms of # the GNU LGPL, Lesser General Public License version 2.1. # For details of the GNU LGPL, see the file "COPYING". @@ -15,11 +15,13 @@ module ReVIEW class LATEXBuilder < Builder include LaTeXUtils include TextUtils - %i[dtp hd_chap].each { |e| Compiler.definline(e) } + %i[dtp hd_chap].each do |e| + Compiler.definline(e) + end Compiler.defsingle(:latextsize, 1) def extname '.tex' @@ -32,21 +34,24 @@ @tsize = nil @table_caption = nil @ol_num = nil @first_line_num = nil @sec_counter = SecCounter.new(5, @chapter) + @foottext = {} setup_index initialize_metachars(@book.config['texcommand']) end private :builder_init_file def setup_index @index_db = {} @index_mecab = nil return true unless @book.config['pdfmaker']['makeindex'] - @index_db = load_idxdb(@book.config['pdfmaker']['makeindex_dic']) if @book.config['pdfmaker']['makeindex_dic'] + if @book.config['pdfmaker']['makeindex_dic'] + @index_db = load_idxdb(@book.config['pdfmaker']['makeindex_dic']) + end return true unless @book.config['pdfmaker']['makeindex_mecab'] begin require 'MeCab' require 'nkf' @index_mecab = MeCab::Tagger.new(@book.config['pdfmaker']['makeindex_mecab_opts']) @@ -97,19 +102,24 @@ }.freeze def headline(level, label, caption) _, anchor = headline_prefix(level) headline_name = HEADLINE[level] - headline_name = 'part' if @chapter.is_a? ReVIEW::Book::Part - prefix = if level > @book.config['secnolevel'] || (@chapter.number.to_s.empty? && level > 1) - '*' - else - '' - end + if @chapter.is_a? ReVIEW::Book::Part + headline_name = 'part' + end + prefix = '' + if level > @book.config['secnolevel'] || (@chapter.number.to_s.empty? && level > 1) + prefix = '*' + end blank unless @output.pos == 0 + @doc_status[:caption] = true puts macro(headline_name + prefix, compile_inline(caption)) - puts "\\addcontentsline{toc}{#{headline_name}}{#{compile_inline(caption)}}" if prefix == '*' && level <= @book.config['toclevel'].to_i + @doc_status[:caption] = nil + if prefix == '*' && level <= @book.config['toclevel'].to_i + puts "\\addcontentsline{toc}{#{headline_name}}{#{compile_inline(caption)}}" + end if level == 1 puts macro('label', chapter_label) else puts macro('label', sec_label(anchor)) puts macro('label', label) if label @@ -118,20 +128,24 @@ error "unknown level: #{level}" end def nonum_begin(level, _label, caption) blank unless @output.pos == 0 + @doc_status[:caption] = true puts macro(HEADLINE[level] + '*', compile_inline(caption)) + @doc_status[:caption] = nil puts macro('addcontentsline', 'toc', HEADLINE[level], compile_inline(caption)) end def nonum_end(level) end def notoc_begin(level, _label, caption) blank unless @output.pos == 0 + @doc_status[:caption] = true puts macro(HEADLINE[level] + '*', compile_inline(caption)) + @doc_status[:caption] = nil end def notoc_end(level) end @@ -145,40 +159,50 @@ def nodisp_end(level) end def column_begin(level, label, caption) blank + @doc_status[:column] = true puts "\\begin{reviewcolumn}\n" if label puts "\\hypertarget{#{column_label(label)}}{}" else puts "\\hypertarget{#{column_label(caption)}}{}" end + @doc_status[:caption] = true puts macro('reviewcolumnhead', nil, compile_inline(caption)) - puts "\\addcontentsline{toc}{#{HEADLINE[level]}}{#{compile_inline(caption)}}" if level <= @book.config['toclevel'].to_i + @doc_status[:caption] = nil + if level <= @book.config['toclevel'].to_i + puts "\\addcontentsline{toc}{#{HEADLINE[level]}}{#{compile_inline(caption)}}" + end end def column_end(_level) puts "\\end{reviewcolumn}\n" blank + @doc_status[:column] = nil end def captionblock(_type, lines, caption) puts "\\begin{reviewminicolumn}\n" - puts "\\reviewminicolumntitle{#{compile_inline(caption)}}\n" if caption + @doc_status[:caption] = true + puts "\\reviewminicolumntitle{#{compile_inline(caption)}}\n" if caption.present? + @doc_status[:caption] = nil blocked_lines = split_paragraph(lines) puts blocked_lines.join("\n\n") puts "\\end{reviewminicolumn}\n" end def box(lines, caption = nil) blank - puts macro('reviewboxcaption', compile_inline(caption)) if caption + puts macro('reviewboxcaption', compile_inline(caption)) if caption.present? puts '\begin{reviewbox}' - lines.each { |line| puts detab(line) } + lines.each do |line| + puts detab(line) + end puts '\end{reviewbox}' blank end def ul_begin @@ -236,11 +260,13 @@ blank end def paragraph(lines) blank - lines.each { |line| puts line } + lines.each do |line| + puts line + end blank end def parasep puts '\\parasep' @@ -303,11 +329,12 @@ common_code_block(nil, lines, 'reviewcmd', caption, lang) { |line, _idx| detab(line) + "\n" } end end def common_code_block(id, lines, command, caption, _lang) - if caption + @doc_status[:caption] = true + if caption.present? if command =~ /emlist/ || command =~ /cmd/ || command =~ /source/ puts macro(command + 'caption', compile_inline(caption)) else begin if get_chap.nil? @@ -318,20 +345,25 @@ rescue KeyError error "no such list: #{id}" end end end + @doc_status[:caption] = nil body = '' - lines.each_with_index { |line, idx| body.concat(yield(line, idx)) } + lines.each_with_index do |line, idx| + body.concat(yield(line, idx)) + end puts macro('begin', command) print body puts macro('end', command) blank end def common_code_block_lst(_id, lines, command, title, caption, lang, first_line_num: 1) - print '\vspace{-1.5em}' if title == 'title' && caption.blank? + if title == 'title' && caption.blank? + print '\vspace{-1.5em}' + end body = lines.inject('') { |i, j| i + detab(unescape_latex(j)) + "\n" } args = make_code_block_args(title, caption, lang, first_line_num: first_line_num) puts %Q(\\begin{#{command}}[#{args}]) print body puts %Q(\\end{#{command}}) @@ -348,11 +380,13 @@ else '' end lexer = lang if lang.present? args = %Q(#{title}={#{caption_str}},language={#{lexer}}) - args += ",firstnumber=#{first_line_num}" if first_line_num != 1 + if first_line_num != 1 + args += ",firstnumber=#{first_line_num}" + end args end def source(lines, caption = nil, lang = nil) if highlight_listings? @@ -377,29 +411,35 @@ end def image_image(id, caption, metric) metrics = parse_metric('latex', metric) # image is always bound here - puts '\begin{reviewimage}' + puts "\\begin{reviewimage}%%#{id}" if metrics.present? puts "\\includegraphics[#{metrics}]{#{@chapter.image(id).path}}" else puts "\\includegraphics[width=\\maxwidth]{#{@chapter.image(id).path}}" end + @doc_status[:caption] = true puts macro('caption', compile_inline(caption)) if caption.present? + @doc_status[:caption] = nil puts macro('label', image_label(id)) puts '\end{reviewimage}' end def image_dummy(id, caption, lines) warn "image not bound: #{id}" puts '\begin{reviewdummyimage}' # path = @chapter.image(id).path puts "--[[path = #{id} (#{existence(id)})]]--" - lines.each { |line| puts detab(line.rstrip) } + lines.each do |line| + puts detab(line.rstrip) + end puts macro('label', image_label(id)) - puts compile_inline(caption) + @doc_status[:caption] = true + puts macro('caption', compile_inline(caption)) if caption.present? + @doc_status[:caption] = nil puts '\end{reviewdummyimage}' end def existence(id) @chapter.image(id).bound? ? 'exist' : 'not exist' @@ -442,24 +482,28 @@ def indepimage(lines, id, caption = nil, metric = nil) metrics = parse_metric('latex', metric) if @chapter.image(id).path - puts '\begin{reviewimage}' + puts "\\begin{reviewimage}%%#{id}" if metrics.present? puts "\\includegraphics[#{metrics}]{#{@chapter.image(id).path}}" else puts "\\includegraphics[width=\\maxwidth]{#{@chapter.image(id).path}}" end else warn "image not bound: #{id}" puts '\begin{reviewdummyimage}' puts "--[[path = #{id} (#{existence(id)})]]--" - lines.each { |line| puts detab(line.rstrip) } + lines.each do |line| + puts detab(line.rstrip) + end end + @doc_status[:caption] = true puts macro('reviewindepimagecaption', %Q(#{I18n.t('numberless_image')}#{I18n.t('caption_prefix')}#{compile_inline(caption)})) if caption.present? + @doc_status[:caption] = nil if @chapter.image(id).path puts '\end{reviewimage}' else puts '\end{reviewdummyimage}' @@ -481,19 +525,23 @@ rows.push(line.strip.split(/\t+/).map { |s| s.sub(/\A\./, '') }) end rows = adjust_n_cols(rows) begin - table_header id, caption unless caption.nil? + 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) }) } + 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 @@ -503,18 +551,22 @@ def table_header(id, caption) if id.nil? if caption.present? @table_caption = true - puts '\begin{table}[h]' + @doc_status[:caption] = true + puts "\\begin{table}[h]%%#{id}" puts macro('reviewtablecaption*', compile_inline(caption)) + @doc_status[:caption] = nil end else if caption.present? @table_caption = true - puts '\begin{table}[h]' + @doc_status[:caption] = true + puts "\\begin{table}[h]%%#{id}" puts macro('reviewtablecaption', compile_inline(caption)) + @doc_status[:caption] = nil end puts macro('label', table_label(id)) end end @@ -540,11 +592,11 @@ # puts '\hline' end def th(s) ## use shortstack for @<br> - if /\\\\/i =~ s + if /\\\\/ =~ s macro('reviewth', macro('shortstack[l]', s)) else macro('reviewth', s) end end @@ -582,12 +634,14 @@ end begin if caption.present? @table_caption = true - puts '\begin{table}[h]' + @doc_status[:caption] = true + puts "\\begin{table}[h]%%#{id}" puts macro('reviewimgtablecaption', compile_inline(caption)) + @doc_status[:caption] = nil end puts macro('label', table_label(id)) rescue ReVIEW::KeyError error "no such table: #{id}" end @@ -599,11 +653,11 @@ end def imgtable_image(id, _caption, metric) metrics = parse_metric('latex', metric) # image is always bound here - puts '\begin{reviewimage}' + puts "\\begin{reviewimage}%%#{id}" if metrics.present? puts "\\includegraphics[#{metrics}]{#{@chapter.image(id).path}}" else puts "\\includegraphics[width=\\maxwidth]{#{@chapter.image(id).path}}" end @@ -625,11 +679,13 @@ end def texequation(lines) blank puts macro('begin', 'equation*') - lines.each { |line| puts unescape_latex(line) } + lines.each do |line| + puts unescape_latex(line) + end puts macro('end', 'equation*') blank end def latex_block(type, lines) @@ -642,16 +698,20 @@ end private :latex_block def direct(lines, fmt) return unless fmt == 'latex' - lines.each { |line| puts line } + lines.each do |line| + puts line + end end def comment(lines, comment = nil) lines ||= [] - lines.unshift comment unless comment.blank? + unless comment.blank? + lines.unshift comment + end return true unless @book.config['draft'] str = lines.join('\par ') puts macro('pdfcomment', escape(str)) end @@ -665,12 +725,12 @@ def pagebreak puts '\pagebreak' end - def linebreak - puts '\\\\' + def blankline + puts '\vspace*{\baselineskip}' end def noindent print '\noindent' end @@ -720,40 +780,53 @@ if get_chap(chapter).nil? macro('reviewlistref', I18n.t('format_number_without_chapter', [chapter.list(id).number])) else macro('reviewlistref', I18n.t('format_number', [get_chap(chapter), chapter.list(id).number])) end + rescue KeyError + error "unknown list: #{id}" end def inline_table(id) chapter, id = extract_chapter_id(id) if get_chap(chapter).nil? macro('reviewtableref', I18n.t('format_number_without_chapter', [chapter.table(id).number]), table_label(id, chapter)) else macro('reviewtableref', I18n.t('format_number', [get_chap(chapter), chapter.table(id).number]), table_label(id, chapter)) end + rescue KeyError + error "unknown table: #{id}" end def inline_img(id) chapter, id = extract_chapter_id(id) if get_chap(chapter).nil? macro('reviewimageref', I18n.t('format_number_without_chapter', [chapter.image(id).number]), image_label(id, chapter)) else macro('reviewimageref', I18n.t('format_number', [get_chap(chapter), chapter.image(id).number]), image_label(id, chapter)) end + rescue KeyError + error "unknown image: #{id}" end def footnote(id, content) - puts macro("footnotetext[#{@chapter.footnote(id).number}]", compile_inline(content.strip)) if @book.config['footnotetext'] + if @book.config['footnotetext'] || @foottext[id] + puts macro("footnotetext[#{@chapter.footnote(id).number}]", compile_inline(content.strip)) + end end def inline_fn(id) if @book.config['footnotetext'] macro("footnotemark[#{@chapter.footnote(id).number}]", '') + elsif @doc_status[:caption] || @doc_status[:table] || @doc_status[:column] + @foottext[id] = @chapter.footnote(id).number + macro('protect\\footnotemark', '') else macro('footnote', compile_inline(@chapter.footnote(id).content.strip)) end + rescue KeyError + error "unknown footnote: #{id}" end BOUTEN = '・'.freeze def inline_bou(str) @@ -850,9 +923,11 @@ def inline_column_chap(chapter, id) macro('reviewcolumnref', I18n.t('chapter_quote', compile_inline(chapter.column(id).caption)), column_label(id, chapter)) + rescue KeyError + error "unknown column: #{id}" end def inline_raw(str) super(str) end