# encoding: utf-8 # # Copyright (c) 2002-2007 Minero Aoki # 2008-2009 Minero Aoki, Kenshi Muto # 2010 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". # require 'review/builder' require 'review/latexutils' require 'review/textutils' module ReVIEW class LATEXBuilder < Builder include LaTeXUtils include TextUtils [:icon, :dtp, :hd_chap].each {|e| Compiler.definline(e) } Compiler.defblock(:memo, 0..1) Compiler.defsingle(:latextsize, 1) def extname '.tex' end def builder_init_file #@index = indexes[:latex_index] @blank_needed = false @latex_tsize = nil @tsize = nil @table_caption = nil end private :builder_init_file def blank @blank_needed = true end private :blank def print(*s) if @blank_needed @output.puts @blank_needed = false end super end private :print def puts(*s) if @blank_needed @output.puts @blank_needed = false end super end private :puts HEADLINE = { 1 => 'chapter', 2 => 'section', 3 => 'subsection', 4 => 'subsubsection' } def headline(level, label, caption) prefix = "" if level > ReVIEW.book.param["secnolevel"] prefix = "*" end blank unless @output.pos == 0 puts macro(HEADLINE[level]+prefix, compile_inline(caption)) end def nonum_begin(level, label, caption) blank unless @output.pos == 0 puts macro(HEADLINE[level]+"*", compile_inline(caption)) end def nonum_end(level) end def column_begin(level, label, caption) blank ## puts '\vspace{2zw}' ## puts '\begin{center}' ## puts '\begin{minipage}{1.0\linewidth}' ## puts '\begin{framed}' ## puts '\setlength{\FrameSep}{1zw}' ## nonum_begin(3, label, caption) # FIXME puts "\\begin{reviewcolumn}\n" puts macro('reviewcolumnhead', nil, compile_inline(caption)) end def column_end(level) ## puts '\end{framed}' ## puts '\end{minipage}' ## puts '\end{center}' ## ## puts '\vspace{2zw}' puts "\\end{reviewcolumn}\n" blank end def minicolumn(type, lines, caption) puts "\\begin{reviewminicolumn}\n" unless caption.nil? puts "\\reviewminicolumntitle{#{compile_inline(caption)}}\n" end lines.each {|l| puts l } puts "\\end{reviewminicolumn}\n" end def memo(lines, caption = nil) minicolumn("memo", lines, caption) end def ul_begin blank puts '\begin{itemize}' end def ul_item(lines) puts '\item ' + lines.join("\n") end def ul_end puts '\end{itemize}' blank end def ol_begin blank puts '\begin{enumerate}' end def ol_item(lines, num) puts '\item ' + lines.join("\n") end def ol_end puts '\end{enumerate}' blank end def dl_begin blank puts '\begin{description}' end def dt(str) puts '\item[' + str + '] \mbox{} \\\\' end def dd(lines) lines.each do |line| puts line end end def dl_end puts '\end{description}' blank end def paragraph(lines) blank lines.each do |line| puts line end blank end def parasep() puts '\\parasep' end def read(lines) latex_block 'quotation', lines end alias lead read def emlist(lines) blank puts '\begin{reviewemlist}' puts '\begin{alltt}' lines.each do |line| puts line end puts '\end{alltt}' puts '\end{reviewemlist}' blank end def emlistnum(lines) blank puts '\begin{reviewemlist}' puts '\begin{alltt}' lines.each_with_index do |line, i| puts detab((i+1).to_s.rjust(2) + ": " + line) end puts '\end{alltt}' puts '\end{reviewemlist}' blank end def listnum_body(lines) puts '\begin{reviewlist}' puts '\begin{alltt}' lines.each_with_index do |line, i| puts detab((i+1).to_s.rjust(2) + ": " + line) end puts '\end{alltt}' puts '\end{reviewlist}' puts end def cmd(lines) blank puts '\begin{reviewcmd}' puts '\begin{alltt}' lines.each do |line| puts line end puts '\end{alltt}' puts '\end{reviewcmd}' blank end def list_header(id, caption) puts macro('reviewlistcaption', "リスト#{@chapter.number}.#{@chapter.list(id).number}: #{compile_inline(caption)}") end def list_body(lines) puts '\begin{reviewlist}' puts '\begin{alltt}' lines.each do |line| puts line end puts '\end{alltt}' puts '\end{reviewlist}' puts "" end def source(lines, caption) puts '\begin{reviewlist}' source_header caption source_body lines puts '\end{reviewlist}' puts "" end def source_header(caption) puts macro('reviewlistcaption', compile_inline(caption)) end def source_body(lines) puts '\begin{alltt}' lines.each do |line| puts line end puts '\end{alltt}' end def image_header(id, caption) end def image_image(id, caption, metric) # image is always bound here puts '\begin{reviewimage}' if metric puts "\\includegraphics[#{metric}]{#{@chapter.image(id).path}}" else puts macro('includegraphics', @chapter.image(id).path) end puts macro('label', image_label(id)) if !caption.empty? puts macro('caption', compile_inline(caption)) end puts '\end{reviewimage}' end def image_dummy(id, caption, lines) puts '\begin{reviewdummyimage}' puts '\begin{alltt}' path = @chapter.image(id).path puts "--[[path = #{path} (#{existence(id)})]]--" lines.each do |line| puts detab(line.rstrip) end puts '\end{alltt}' puts macro('label', image_label(id)) puts compile_inline(caption) puts '\end{reviewdummyimage}' end def existence(id) @chapter.image(id).bound? ? 'exist' : 'not exist' end private :existence def image_label(id) "image:#{@chapter.id}:#{id}" end private :image_label def indepimage(id, caption=nil, metric=nil) puts '\begin{reviewimage}' if metric puts "\\includegraphics[#{metric}]{#{@chapter.image(id).path}}" else puts macro('includegraphics', @chapter.image(id).path) end if !caption.nil? && !caption.empty? puts macro('caption', compile_inline(caption)) end puts '\end{reviewimage}' end alias :numberlessimage indepimage def table_header(id, caption) if caption && !caption.empty? @table_caption = true puts '\begin{table}[h]' ## puts macro('reviewtablecaption', "表#{@chapter.number}.#{@chapter.table(id).number} #{compile_inline(caption)}") puts macro('reviewtablecaption', compile_inline(caption)) end end def table_begin(ncols) if @latex_tsize puts macro('begin', 'reviewtable', @latex_tsize) elsif @tsize cellwidth = @tsize.split(/\s*,\s*/) puts macro('begin', 'reviewtable', '|'+(cellwidth.collect{|i| "p{#{i}mm}"}.join('|'))+'|') else puts macro('begin', 'reviewtable', (['|'] * (ncols + 1)).join('l')) end puts '\hline' @tsize = nil @latex_tsize = nil end def table_separator #puts '\hline' end def th(s) ## use shortstack for @
if /\\\\/i =~ s macro('textgt', macro('shortstack[l]', s)) else macro('textgt', s) end end def td(s) ## use shortstack for @
if /\\\\/ =~ s macro('shortstack[l]', s) else s end end def tr(rows) print rows.join(' & ') puts ' \\\\ \hline' end def table_end puts macro('end', 'reviewtable') if @table_caption puts '\end{table}' end @table_caption = nil blank end def quote(lines) latex_block 'quote', lines end def center(lines) latex_block 'center', lines end def flushright(lines) latex_block 'flushright', lines end def texequation(lines) blank puts macro('begin','equation*') lines.each do |line| puts unescape_latex(line) end puts macro('end', 'equation*') blank end def latex_block(type, lines) blank puts macro('begin', type) if ReVIEW.book.param["deprecated-blocklines"].nil? blocked_lines = split_paragraph(lines) puts blocked_lines.join("\n\n") else lines.each do |line| puts line end end puts macro('end', type) blank end private :latex_block def direct(lines, fmt) return unless fmt == 'latex' lines.each do |line| puts line end end def comment(str) puts "% #{str}" end def label(id) puts macro('label', id) end def pagebreak puts '\pagebreak' end def linebreak puts '\\\\' end def noindent puts '\noindent' end # FIXME: use TeX native label/ref. def inline_list(id) chapter, id = extract_chapter_id(id) macro('reviewlistref', "#{chapter.number}.#{chapter.list(id).number}") end def inline_table(id) chapter, id = extract_chapter_id(id) macro('reviewtableref', "#{chapter.number}.#{chapter.table(id).number}") end def inline_img(id) chapter, id = extract_chapter_id(id) macro('reviewimageref', "#{chapter.number}.#{chapter.image(id).number}") end def footnote(id, content) end def inline_fn(id) macro('footnote', compile_inline(@chapter.footnote(id).content.strip)) end BOUTEN = "・" def inline_bou(str) str.split(//).map {|c| macro('ruby', escape(c), macro('textgt', BOUTEN)) }.join('\allowbreak') end def inline_ruby(str) base, ruby = *str.split(/,/) macro('ruby', base, ruby) end # math def inline_m(str) " $#{str}$ " end # hidden index def inline_hi(str) index(str) end # index -> italic def inline_i(str) macro('textit', escape(str)) end # index def inline_idx(str) text(str) + index(str) end # hidden index?? def inline_hidx(str) index(str) end # bold def inline_b(str) macro('textbf', escape(str)) end # line break def inline_br(str) "\\\\\n" end def inline_dtp(str) # ignore "" end ## @ is same as @ def inline_code(str) macro('texttt', escape(str)) end def nofunc_text(str) escape(str) end def inline_tt(str) str_escaped = escape(str).gsub(/\-\-/, "{-}{-}") macro('texttt', str_escaped) end def inline_tti(str) macro('texttt', macro('textit', escape(str))) end def inline_ttb(str) macro('texttt', macro('textbf', escape(str))) end def inline_hd_chap(chap, id) "「#{chap.headline_index.number(id)} #{chap.headline(id).caption}」" end def inline_raw(str) escape(str) end def inline_sub(str) macro('textsubscript', escape(str)) end def inline_sup(str) macro('textsuperscript', escape(str)) end def inline_em(str) macro('textbf', escape(str)) end def inline_strong(str) macro('textbf', escape(str)) end def inline_u(str) macro('Underline', escape(str)) end def inline_icon(id) macro('includegraphics', @chapter.image(id).path) end def inline_uchar(str) # with otf package macro('UTF', escape(str)) end def index(str) str.sub!(/\(\)/, '') decl = '' if /@\z/ =~ str str.chop! decl = '|IndexDecl' end unless /[^ -~]/ =~ str if /\^/ =~ str macro('index', escape_index(str.gsub(/\^/, '')) + '@' + escape_index(text(str)) + decl) else '\index{' + escape_index(text(str)) + decl + '}' end else '\index{' + escape_index(@index_db[str]) + '@' + escape_index(text(str)) + '}' end end def compile_kw(word, alt) if alt macro('reviewkw', escape(word)) + "(#{escape(alt.strip)})" else macro('reviewkw', escape(word)) end end def compile_href(url, label) label ||= url if /\A[a-z]+:\/\// =~ url macro("href", url, escape(label)) else macro("ref", url) end end def tsize(str) @tsize = str end def latextsize(str) @latex_tsize = str end end end