=begin * Name: SiSU * Description: a framework for document structuring, publishing and search * Author: Ralph Amissah * Copyright: (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Ralph Amissah All Rights Reserved. * License: GPL 3 or later: SiSU, a framework for document structuring, publishing and search Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Ralph Amissah This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . If you have Internet connection, the latest version of the GPL should be available at these locations: * SiSU uses: * Standard SiSU markup syntax, * Standard SiSU meta-markup syntax, and the * Standard SiSU object citation numbering and system * Hompages: * Download: * Ralph Amissah ** Description: LaTeX generation =end module SiSU_TeX require 'pstore' require "#{SiSU_lib}/defaults" require "#{SiSU_lib}/param" include SiSU_Param include SiSU_Viz require "#{SiSU_lib}/texpdf_format" include SiSU_TeX_Pdf @tex_file=@@tex_footnote_array=@@tex_col_w=[] @@tex_backslash ||="\\\\" @@tilde='\\\\\\~' #?? debug crazy @@tabular="{tabular}" @@column_instruct=@@squigle_close=@@tex_line_mode=@@tex_word_mode=@@line_mode='' @@tex_debug_counter=@@table_pagebreak_counter=@@tex_footnote_call_counter=@@tex_table_flag=@@tex_counter=@@tex_column=@@tex_columns=@@tex_columns=@@counting=0 @@tex_pattern_margin_number="\\\\begin\\\{tiny\\\}~\\\\end\\\{tiny\\\}\\\{\\\\marginpar.+?\s+" #@@tex_pattern_margin_number="\\\\marginpar.+?\s+" @@n=@@tableheader=@@rights=nil @@date ||=SiSU_Env::Info_date.new class Source #Songsheet #') tell.dark_grey_title_hi if @md.cmd =~/[MVv]/ tex_fn_base=@texfilename.gsub(/\.tex$/,'') cmd=SiSU_Env::System_call.new("#{tex_fn_base}.tex",'',@md.cmd) tell=SiSU_Screen::Ansi.new(@md.cmd) tell.grey_open unless @md.cmd =~/q/ 2.times { |i| cmd.latex2pdf unless ("#{tex_fn_base}.tex" !~/\w+/) } tell.p_off unless @md.cmd =~/q/ tell=SiSU_Screen::Ansi.new(@md.cmd,'landscape ->') tell.dark_grey_title_hi if @md.cmd =~/[MVv]/ cmd=SiSU_Env::System_call.new("#{tex_fn_base}.landscape.tex",'',@md.cmd) tell.grey_open 2.times { |i| cmd.latex2pdf unless ("#{tex_fn_base}.landscape.tex" !~/\w+/) } tell.p_off unless @md.cmd =~/q/ pwd=Dir.pwd portrait_pdf="#{pwd}/#{tex_fn_base}.pdf" landscape_pdf="#{pwd}/#{tex_fn_base}.landscape.pdf" if FileTest.file?(portrait_pdf) File.install(portrait_pdf,"#@dir_sisu/#{@md.fnb}/#{@md.fn[:pdf_p]}") File.unlink(portrait_pdf) end if FileTest.file?(landscape_pdf) File.install(landscape_pdf,"#@dir_sisu/#{@md.fnb}/#{@md.fn[:pdf_l]}") File.unlink(landscape_pdf) end tell=SiSU_Screen::Ansi.new(@md.cmd,@@n_lpdf,'processed (SiSU LaTeX to pdf - using pdfetex aka. pdftex or pdflatex)') tell.generic_number unless @md.cmd =~/q/ end def latexrun_selective begin pwd=Dir.pwd Dir.chdir(pwd) #watch @tex_f_no=0 info={} if FileTest.file?(@env.source_file_with_path) if @md.fns =~/\.(?:-|ssm\.)?sst$/ @dirout=SiSU_Env::Info_env.new(@md.fns) case @md.fns when /\.(?:-|ssm\.)?sst$/ if FileTest.directory?(@env.path.tex)==true Dir.chdir(@env.path.tex) @dir_sisu=@dirout.path.output texfile=@md.fns.gsub(/$/,'.tex') texfile=texfile.gsub(/~/,'-') if File.exist?(texfile) \ and File.size(texfile) > 0 @tex_f_no+=1 latex_do(texfile) else puts "\tzero file size #{@env.path.tex}/#{@md.fns}" end end end end else tell=SiSU_Screen::Ansi.new(@md.cmd,"FILE NOT FOUND: << #{@md.fns} >> - requested latex system processing skipped") tell.warn end lst=Dir["*.{aux,log,out}"] lst.each {|file| File.unlink(file)} if lst #touch("#{@dir_pdf}index.html") #correct @dir_pdf appears to contain slash / and should not rescue; SiSU_Errors::Info_error.new($!,$@,@md.fns,@md.cmd).error end end end class LaTeX_create include SiSU_Param @@tex_backslash ||="\\\\" @@tilde='\\\\\\~' #?? debug crazy @@tex_head_portrait,@@tex_head_landscape=nil,nil @@flag_alt,@@flag_group,@@flag_code=false,false,false @@dp,@@prefix_b=nil,nil def initialize(data,md,orientation) @data,@md,@orientation=data,md,orientation @env=SiSU_Env::Info_env.new(@md.fns) @st={ :tex=>{} } @tex=SiSU_TeX_Pdf::Use_TeX.new(@md,@orientation) @vz=SiSU_Env::Get_init.instance.skin @dp=@@dp ||=SiSU_Env::Info_env.new.digest.pattern vz=SiSU_Env::Get_init.instance.skin @skin_no_ocn=if defined? vz.ocn_display_off \ and vz.ocn_display_off == true true else false end end def songsheet begin data=@data @@tex_footnote_array=[] @@rights=nil tell=SiSU_Screen::Ansi.new(@md.cmd,"pdfTex #@orientation") tell.txt_grey unless @md.cmd =~/q/ if @md.dc_rights use=@md.dc_rights.dup #dup is necessary, else contents of :rights changed do_mono=SiSU_TeX_Pdf::Format_text_object.new(@md,use) copymark=if @md.creator_copymark; '{\\begin{small}\\raisebox{1ex}{\\copyright}\\end{small}} ' else '' end copymark='Copyright {\\begin{small}\\raisebox{1ex}{\\copyright}\\end{small}} ' copyright=do_mono.special_characters_safe.gsub(/^\s*Copyright \(C\)/, copymark) @@rights||="\n #{@@tex_backslash*2}[3]\\ \\linebreak #{copyright}" end if @md.prefix_b do_mono=SiSU_TeX_Pdf::Format_text_object.new(@md,@md.prefix_b) prefix_b=do_mono.special_characters_safe @@prefix_b="\n #{@@tex_backslash*2}[3]\\ \\linebreak \\ #{prefix_b}\n" unless @@prefix_b end data=pre(data) data=footnote(data) if @md.flag_tables data=tables(data) end ocn=if @md.markup.inspect =~/no_ocn/ \ or @md.mod.inspect =~/--no-ocn/ \ or @skin_no_ocn false else true end data=number_paras(data,ocn) data=markup(data) output(data) rescue; SiSU_Errors::Info_error.new($!,$@,@md.fns,@md.cmd).error ensure end end protected def pre(data) @tex_file=[] data.each do |para| # DEBUG 2003w16 this is a kludge, because i could not get parameters # from param, Sort out ... revert to more elegant solution # even more of a kludge as had to insert newlines where code is used not satisfactory, think about para=if para =~/<:br>|\n/; para.split(/<:br>|\n/) else para end if para.class == String @md.flag_tables=true if para =~/\\\}\\~/m,"\\footnote[\\1]{%\n \\2} ") #removed space before \\footnote 2004w21, watch para.gsub!(/\\~\[([*+]\d+)\s+(.+?)<#@dp>\]\\~/m,"\\FootnoteA{\\1}{%\n \\2} ") #work on asterisk footnotes para.gsub!(/\\~\\\{([*+]+)\s+(.+?)<#@dp>\\\}\\~/m,"\\FootnoteA{\\1}{%\n \\2} ") #work on asterisk footnotes end @tex_file << para end @tex_file end def tables(data) @tex_file=[] @@tableheader=0 data.each do |para| if para =~/¡||<\/\s*(br|p)>|<(br|p)\s*\/>|\\\\/,' - ') #no line splitting in heading neither html nor latex title=@md.title.gsub(/<(br|p)>|<\/\s*(br|p)>|<(br|p)\s*\/>|\\\\/,' - ') #no line splitting in heading neither html nor latex subtitle=@md.subtitle.gsub(/<(br|p)>|<\/\s*(br|p)>|<(br|p)\s*\/>|\\\\/,' - ') if @md.subtitle #no line splitting in heading neither html nor latex orient=SiSU_TeX_Pdf::Format_text_object.new(@md,@orientation,"#{home}: - #{title} #{subtitle}") #.new if @orientation =~/portrait/ @@tex_head_portrait=orient.document_head_with_orientation elsif @orientation =~/landscape/ @@tex_head_landscape=orient.document_head_with_orientation end @tex_file <<</ \ or @@flag_alt if para =~/<:(code|alt|verse|group)>/ @lineone=case para when /<:(alt|verse|group)>/; para when /<:code>/; "#{@tex.paraskip_small} \\begin{scriptsize} " + para else 'error' #should never occur end end if para =~/<=curly/ #takes care of escaped curly braces, expand do_mono=SiSU_TeX_Pdf::Format_text_object.new(@md,para) para=do_mono.special_characters_curly(para) end regx=/<:((?:code|alt|verse|group)(?:-end)?)>/m x=regx.match(para)[1] if para =~regx x=$1 para.gsub!(/\n<:(?:code|alt|verse|group)>\n/m,'') para=enclose(para,'code') unless para =~/^$/ if x =~/(?:alt|verse|group)/; @@flag_alt=true if x =~/group/; @@flag_group=true end elsif x =~/code/; @@flag_alt,@@flag_code=true,true elsif @@flag_alt; if para =~ /\}(?:https?|file|ftp)/m para=mono.http(@orientation) end @group_collect << para #<< "\n\n" end if x =~/(?:code|alt|verse|group)-end/m regx=/(\\+marginpar\{\\+begin\{tiny\}\d+\\+end\{tiny\}\})/ y=if para =~regx regx.match(para)[1] else '' end para.gsub!(regx,'') #@group_collect.each{ |x| x.gsub!(/(<:\S+>||)/,' ') } group_collect=[] group_collect << '\begin{footnotesize} ' unless @@flag_code @group_collect.each do |x| x.gsub!(/(<:\S+>||)/,' ') x=x.split(/ \\\\ /) group_collect << x end group_collect << ' \end{footnotesize} ' unless @@flag_code @group_collect=group_collect.flatten @lineone.gsub!(/(<:\S+>||)/,' ') #@group_collect.each{ |x| x.gsub!(/(.#{@@tilde}\S*\s*|<:\S+>||)/,' ') } #@lineone.gsub!(/(.#{@@tilde}\S*\s*|<:\S+>||)/,' ') insert=[] if para =~/<:code-end>/m insert << y + @lineone << @group_collect << ' \end{scriptsize}' << " #{@tex.paraskip_normal}" else insert << y + @lineone << @group_collect end @@flag_alt,@@flag_group,@@flag_code=false,false,false @group_collect=[] para.gsub!(/(<:\S+>||)/,' ') #para.gsub!(/(.#{@@tilde}\S*\s*|<:\S+>||)/,' ') @tex_file << insert.flatten end else if para =~ /\}(?:https?|file|ftp)/ para=mono.http(@orientation) end case para when /^1#{@@tilde}/; mono.level1 when /^2#{@@tilde}/; mono.level2 when /^3#{@@tilde}/; mono.level3 when /^4#{@@tilde}/; mono.level4 when /^5#{@@tilde}/; mono.level5 when /^6#{@@tilde}/; mono.level6 when /^<:i([1-9])>/; mono.indent($1) when /<:=/; mono.symbol_graphic #watch when /^\s*<:image\s+/; mono.image when /\}image/; mono.png else para.strip! para=enclose(para) unless para =~/^$/ end para.gsub!(/(\.#{@@tilde}\S*\s*|<:\S+>||)/,' ') #% tread with care #para.gsub!(/(.#{@@tilde}(?:\\~\S+)?\s*|<:\S+>||)/,' ') #KEEP reference, problem escaping open curly braces \{ if para =~/<=curly/ #takes care of escaped curly braces, expand do_mono=SiSU_TeX_Pdf::Format_text_object.new(@md,para) para=do_mono.special_characters_curly(para) end @tex_file << para end end @tex_file << "\n\\newpage\n" # was \\pagebreak\n @md.subtitle_tex=@md.subtitle.dup if @md.subtitle # kludge ... look again later @tex_file << if @md.doc_skin !~/skin_mail/; @tex.doc_tail else @tex.mail_tail end if defined? @md.lnk \ and @md.lnk @md.lnk.each do |l| if l[:say] url=%<#{l[:url]}> url.gsub!(/(?:\\)*([$&~%_#}{^])/,"\\\\\\1") #latex special chars s_lnk=l[:say] s_lnk.gsub!(/(
|
|

|

)/,'') s_lnk.gsub!(/(?:\\)*([$&~%_#}{^])/,"\\\\\\1") #latex special chars if url !~/^\.(\.)?\// s_lnk_url=%<\\begin{scriptsize}\\href{#{url}}{#{url}}\\end{scriptsize}> # note this bit of dereferencing magic else url.gsub!(/\.\.\//,'') s_lnk_url="(#{@tex.site}) \\\\\n" + ' ' + "\\begin{scriptsize}" + %<\\href\{#{@vz.url_root_http}/#{url}\}\{#{@vz.url_root_http}/#{url}\}> + # note this bit of dereferencing magic "\\end{scriptsize}" end @tex_file << " #{s_lnk} \\\\\n #{s_lnk_url} \n" unless @md.doc_skin =~/skin_mail/ s_lnk=s_lnk_url=nil end end end @tex_file << " #{@tex.sitename} home: \\\\ \\begin{bfseries}#{@tex.site}\\end{bfseries} " #Stamp.stamp #removed 200408 but watch #% code for inclusion of addresses of promulgating authority @st[:tex][:stmp]||=@md.stmpd stamp=@st[:tex][:stmp] if @st[:tex][:stmp] if stamp use=stamp.gsub(/\n/,"#{@@tex_backslash*2}\n") @tex_file << "\n\\newpage\n" @tex_file << "\\section*" + "{#{@tex.owner_chapter}}\n" + "\\addcontentsline{toc}" + "{section}{#{@tex.owner_chapter}}\n" @tex_file << "#{use}\n" @tex_file << @@rights if @@rights end @tex_file << "\n\\end{document}" end def number_paras(data,ocn) @tex_file=[] data.each do |para| if para =~/<\\~(\d+);(?:[oh]|[0-6]:)\d+;\w\d+><#@dp:#@dp>$/ \ and para !~/\\end\{longtable\}|/ #catch m=/(.+?)<\\~(\d+);(?:[oh]|[0-6]:)\d+;\w\d+><#@dp:#@dp>$/m parablock=para[m,1] paranum=if ocn; para[m,2] else '' end do_duo=SiSU_TeX_Pdf::Format_text_object.new(@md,parablock,paranum) para=do_duo.para_num if parablock elsif para =~/^<~\d+;(?:[oh]|[0-6]:)\d+;\w\d+><#@dp:#@dp>$/ #2005 this is added for tables, rationalise m=/<~(\d+);(?:[oh]|[0-6]:)\d+;\w\d+><#@dp:#@dp>$/m paranum=para[m,1] para.gsub!(/<~\d+;(?:[oh]|[0-6]:)\d+;\w\d+><#@dp:#@dp>/,'') para="\\marginpar{\\begin{tiny}#{paranum}\\end{tiny}}" + para #para="\\marginpar{\\begin{tiny}#{paranum}\\end{tiny}}" #elsif para =~// elsif para =~/^<~\d+;(?:[oh]|[0-6]:)\d+;\w\d+>/ #extra 2005 this is added for tables, rationalise m=/<~(\d+);[oh]\d+;\w\d+>/m paranum=para[m,1] para.gsub!(/<~\d+;(?:[oh]|[0-6]:)\d+;\w\d+>/,'') para="\\marginpar{\\begin{tiny}#{paranum}\\end{tiny}}" + para elsif para =~/\\end\{longtable\}/ #catch para.gsub!(/<\\~\d+>|<\\~(\d+);(?:[ohm]|[0-6]:)\d+;\w\d+><#@dp:#@dp>/,'') para.gsub!(/<\\~\d+>|<\\~(\d+);(?:[ohm]|[0-6]:)\d+;\w\d+>/,'') #extra end @tex_file << para end @tex_file end def output(data) data.flatten! data.compact! fns_l=@md.fns.gsub(/~/,'-') #this is a sorry fix, but necessary as it appears latex programs like not ~ if @orientation =~/landscape/ filename_tex_landscape=File.new("#{@env.path.tex}/#{fns_l}.landscape.tex",'w+') filename_tex_landscape << @@tex_head_landscape data.each do |para| para.gsub!(/^\s+/,'') filename_tex_landscape.puts para,"\n" if para !~/\A\s*\Z/ end filename_tex_landscape.close @@tex_head_landscape=[] elsif @orientation =~/portrait/ filename_tex_portrait=File.new("#{@env.path.tex}/#{fns_l}.tex",'w+') filename_tex_portrait << @@tex_head_portrait data.each do |para| para.gsub!(/^\s+/,'') filename_tex_portrait.puts para,"\n" if para !~/\A\s*\Z/ end filename_tex_portrait.close @@tex_head_portrait=[] end data=[] end end end end __END__