module Lbt
LaTeX-Buildtools provides Ruby script lbt
to create template, build it and do other tasks. The lbt
command includes Lbt
module and calls its instance methods. All the methods are instance methods and Lbt
module doesn’t have any singleton methods.
Public Instance Methods
Typeset LaTeX source files into a PDF file.
# File lib/lbt/build.rb, line 5 def build m = get_config[:'build_dir'] build_dir = m ? m : "_build" raise "main.tex not exist." unless File.exist?('main.tex') mkdir build_dir unless Dir.exist?(build_dir) # Build main.tex main_tex = File.read('main.tex') m = /\\title(\[(.*?)\])?\s*\{(.*?)\}/.match(main_tex.remove_tex_comment) # Beamer has \title[short title]{title} command. # Other documentclasses don't have such short style option. title = m[2] || m[3] files = PCS.new.to_a input_commands = files.map{|f| "\\input{#{f.ext('.tex')}}\n"}.flatten.join main_tex = main_tex.sub(/\\end{document}/, "#{input_commands}\n\\end{document}") File.write("#{build_dir}/main.tex", main_tex) # copy or convert the files into build_dir cp_conv build_dir # Typeset cur_dir = Dir.pwd cd build_dir system "latexmk -lualatex -pdflualatex=\"lualatex --halt-on-error %O %S\" main.tex" cd cur_dir # Copy the pdf file. temp = "#{build_dir}/main.pdf" target = "#{title}.pdf" unless File.exist?(target) && File.mtime(temp) <= File.mtime(target) cp temp, target end end
copy or convert source files into build directory.
# File lib/lbt/utils.rb, line 127 def cp_conv build_dir converters = get_converters files = Dir.children(".").reject{|f| f == build_dir || f == "main.tex"} cp_conv_0 ".", files, build_dir, converters end
The create method creates a source file directory and put some templates in the directory.
Parameters are:
- dir
-
The name of the source file directory
- document_class
-
The document class of the LaTeX source file. For example, article, book and beamer.
- build_dir
-
The working directory in which typeset is carried out.
# File lib/lbt/create.rb, line 14 def create dir, document_class="book", build_dir="_build" raise "Argument error." unless dir.is_a?(String) && dir =~ /[[:^space:]]+/ raise "#{dir} already exists." if Dir.exist?(dir) mkdir_p(dir) File.write("#{dir}/.config", "build_dir = #{build_dir}\n") helper_tex = <<~EOS \\usepackage{amsmath,amssymb} \\usepackage[luatex]{graphicx} \\usepackage{tikz} \\usepackage[margin=2.4cm]{geometry} \\usepackage[colorlinks=true,linkcolor=black]{hyperref} % If your source includes Markdown, you probably need the following lines. % It is because Pandoc generates some undefined commands. % The Pandoc template file shows how to define them. % You can see it by 'pandoc --print-default-template=latex'. \\providecommand{\\tightlist}{% \\setlength{\\itemsep}{0pt}\\setlength{\\parskip}{0pt}} EOS if ["book", "ltjsbook"].include? document_class main_tex = <<~EOS \\documentclass{#{document_class}} \\input{helper.tex} \\title{Title} \\author{Author} \\begin{document} \\frontmatter \\begin{titlepage} \\input{cover.tex} \\end{titlepage} \\tableofcontents \\mainmatter \\end{document} EOS cover_tex = <<~EOS \\newgeometry{margin=2.4cm} \\begin{center} \\begin{tikzpicture} \\node at (0,0) {\\includegraphics[width=100pt]{gecko.png}}; \\node at (70pt,0) {\\includegraphics[width=100pt]{gecko.png}}; \\node at (140pt,0) {\\includegraphics[width=100pt]{gecko.png}}; \\node at (210pt,0) {\\includegraphics[width=100pt]{gecko.png}}; \\node at (280pt,0) {\\includegraphics[width=100pt]{gecko.png}}; \\node at (350pt,0) {\\includegraphics[width=100pt]{gecko.png}}; \\end{tikzpicture} \\end{center} \\vspace{2cm} \\begin{center} {\\fontsize{64}{0} \\selectfont Title} \\end{center} \\vspace{1cm} \\begin{center} {\\huge Author} \\end{center} \\vspace{9cm} %\\vspace{6.5cm} %\\begin{center} %{\\Large Foobar University} %\\end{center} %\\begin{center} %{\\Large School of Foobar} %\\end{center} \\vspace{3cm} \\begin{center} \\begin{tikzpicture} \\node at (0,0) {\\includegraphics[width=100pt]{gecko.png}}; \\node at (70pt,0) {\\includegraphics[width=100pt]{gecko.png}}; \\node at (140pt,0) {\\includegraphics[width=100pt]{gecko.png}}; \\node at (210pt,0) {\\includegraphics[width=100pt]{gecko.png}}; \\node at (280pt,0) {\\includegraphics[width=100pt]{gecko.png}}; \\node at (350pt,0) {\\includegraphics[width=100pt]{gecko.png}}; \\end{tikzpicture} \\end{center} \\restoregeometry EOS File.write("#{dir}/main.tex", main_tex) File.write("#{dir}/helper.tex", helper_tex) File.write("#{dir}/cover.tex", cover_tex) gecko_png = __dir__+"/../../images/gecko.png" cp(gecko_png, "#{dir}/gecko.png") elsif ["article", "ltjsarticle"].include? document_class main_tex = <<~EOS \\documentclass{#{document_class}} \\input{helper.tex} \\title{Title} \\author{Author} \\begin{document} \\maketitle \\tableofcontents \\end{document} EOS File.write("#{dir}/main.tex", main_tex) File.write("#{dir}/helper.tex", helper_tex) elsif document_class == "beamer" main_tex = <<~EOS \\documentclass[utf8,aspectratio=169]{beamer} \\mode<presentation> { \\usetheme{Warsaw} \\setbeamercovered{transparent} } \\input{helper.tex} % Don't show navigation symbol => If you want to show it, comment out the following line. \\setbeamertemplate{navigation symbols}{} \\title[short\\_title] % (optional, use only with long paper titles) {titile} \\subtitle {substitile} \\author[short\\_author] % (optional, use only with lots of authors) {author \\\\ \\texttt{sample\\_address@email.com}} % - Give the names in the same order as the appear in the paper. % - Use the \\inst{?} command only if the authors have different % affiliation. \\institute[short\\_institute] % (optional, but mostly needed) { % \\inst{1}% Department of Mathematics and Technology\\\\ School of Education and Humanities\\\\ XXXX University } % - Use the \\inst command only if there are several affiliations. % - Keep it simple, no one is interested in your street address. \\date[short\\_date] % (optional, should be abbreviation of conference name) {XXXX meeting on Wednesday, April 27 2022} % - Either use conference name or its abbreviation. % - Not really informative to the audience, more for people (including % yourself) who are reading the slides online \\subject{subject} % If you have a file called "university-logo-filename.xxx", where xxx % is a graphic format that can be processed by lualatex, % resp., then you can add a logo as follows: % \\pgfdeclareimage[height=0.5cm]{university-logo}{university-logo-filename} % \\logo{\\pgfuseimage{university-logo}} \\begin{document} \\begin{frame} \\titlepage \\end{frame} \\begin{frame}{Outline} \\tableofcontents % \\begin{center} % \\includegraphics[width=6cm,keepaspectratio]{photo.jpg} % \\end{center} \\end{frame} \\end{document} EOS helper_tex = <<~EOS \\usepackage{luatexja} % 和文のデフォルトをゴシック体に \\renewcommand{\\kanjifamilydefault}{\\gtdefault} \\usepackage{amsmath,amssymb} \\usepackage{tikz} \\usepackage[absolute,overlay]{textpos} % 数式フォントを設定(これなしだとsansになる) \\usefonttheme{professionalfonts} EOS sec1_tex = <<~EOS % This is a sample latex file for the beamer documentclass. \\section{Section Title} \\begin{frame} \\frametitle{introduction} About something \\begin{itemize} \\item item 1 \\item<2> item 2 \\end{itemize} About another thing \\begin{enumerate} \\item<3> item 1 \\item<3-4> item 2 \\end{enumerate} \\alert{alert message, which is red.} \\end{frame} % Show a photo that extends to the whole slide view. % The aspect ratio is 16:9. \\begin{frame} \\begin{textblock*}{128mm}(0pt,0pt) \\includegraphics[width=160mm,height=90mm,keepaspectratio]{lagoon.jpg} \\end{textblock*} \\end{frame} EOS File.write("#{dir}/main.tex", main_tex) File.write("#{dir}/helper.tex", helper_tex) File.write("#{dir}/sec1.tex", sec1_tex) lagoon_jpg = __dir__+"/../../images/lagoon.jpg" cp(lagoon_jpg, "#{dir}/lagoon.jpg") else main_tex = <<~EOS \\documentclass{#{document_class}} \\input{helper.tex} \\title{Title} \\author{Author} \\begin{document} \\maketitle \\tableofcontents \\end{document} EOS File.write("#{dir}/main.tex", main_tex) File.write("#{dir}/helper.tex", helper_tex) end end
Convert ‘.config’ file into a Hash
# File lib/lbt/utils.rb, line 109 def get_config return {} unless File.exist?(".config") File.read(".config").split(/\n/).map{|s| s.split('=')}.map{|key, val| [key.strip.to_sym, val.strip]}.to_h end
Return a hash (key: extension, value: Proc object) of converters.
# File lib/lbt/utils.rb, line 115 def get_converters tld = get_config[:'top-level-division'] tld = tld ? tld : "default" converters = {'.md': lambda {|src, dst| system("pandoc --top-level-division=#{tld} -o #{dst} #{src}")} } if File.file?("converters.rb") c = eval(File.read("converters.rb")) c.each {|key, val| converters[key] = val} if c.is_a?(Hash) end converters end
Typeset one source file to check the PDF.
Parameter:
- file_or_number
-
It can be either a filename or the number of a filename. For example, part1/chap2/sec3.tex or 1-2-3
# File lib/lbt/part_typeset.rb, line 10 def part_typeset file_or_number return unless file_or_number.is_a? String if File.file?(file_or_number) file = file_or_number else file = num2path(file_or_number) return unless File.file? file end m = get_config[:'build_dir'] build_dir = m ? m : "_build" raise "main.tex not exist." unless File.exist?('main.tex') mkdir build_dir unless Dir.exist?(build_dir) main_tex = File.read('main.tex') main_tex = main_tex.sub(/\\end{document}/, "\\input{#{file.ext('.tex')}}\n\\end{document}") File.write("#{build_dir}/main.tex", main_tex) # copy or convert the files into build_dir cp_conv build_dir # Typeset cur_dir = Dir.pwd cd build_dir system "latexmk -lualatex -pdflualatex=\"lualatex --halt-on-error %O %S\" main.tex" cd cur_dir end
Renumber the source files. For example,
-
sec1.tex, sec1.5.tex, sec2.tex => sec1.tex, sec2.tex, sec3.tex
-
chap1/sec1.tex, chap1/sec1.2.tex, chap1.3/sec10.tex => chap1/sec1.tex, chap1/sec2.tex, chap2/sec1.tex
# File lib/lbt/renumber.rb, line 6 def renum if Dir.children(".").select{|d| d =~ /^part\d+(\.\d+)?$/}.size > 0 renumber "part" elsif Dir.children(".").select{|d| d =~ /^chap\d+(\.\d+)?$/}.size > 0 renumber "chap" else renumber "sec" end end