lbt 0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/lbt +32 -0
- data/lib/lbt/build.rb +36 -0
- data/lib/lbt/create.rb +218 -0
- data/lib/lbt/part_typeset.rb +55 -0
- data/lib/lbt/renumber.rb +50 -0
- data/lib/lbt/utils.rb +142 -0
- data/lib/lbt.rb +11 -0
- metadata +50 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 61cb8ee73b25172d9eccfc116cd96cfb5c80fe8b5569bb070ecf8d5bb678bb19
|
4
|
+
data.tar.gz: 79854bfca082e2aadf712c89f91d514163eb87d9465105cb59d358004595dc7d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bdb858eec9763e0df398028d895d5f3091d2ff2b682246210ff2cf43bc508fdf0ed266a458811db29e47eec52ba1072e09710b2850951387a7c88a3bb118c548
|
7
|
+
data.tar.gz: b956421ce68031ed88d80c4a67c6c8b71a626aeb3cf31f8b4e1b3506906818337bcc55e96c00eeec1cfc1ba7ea6de1636e2decb97cf9b6ea2faf066c0df0d73c
|
data/bin/lbt
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'lbt'
|
4
|
+
include Lbt
|
5
|
+
case ARGV[0]
|
6
|
+
when "new"
|
7
|
+
case ARGV.size
|
8
|
+
when 2 then create ARGV[1]
|
9
|
+
when 3 then create ARGV[1], ARGV[2]
|
10
|
+
when 4 then create ARGV[1], ARGV[2], ARGV[3]
|
11
|
+
else return
|
12
|
+
end
|
13
|
+
when "build"
|
14
|
+
build
|
15
|
+
when "part_typeset"
|
16
|
+
return unless ARGV.size == 2
|
17
|
+
part_typeset ARGV[1]
|
18
|
+
when "renum"
|
19
|
+
renum
|
20
|
+
else
|
21
|
+
$stderr.print <<~EOS
|
22
|
+
Usage: lbt command [argument]
|
23
|
+
The command and argument are one of:
|
24
|
+
new directory [document_style [build_directory]]: create a new working directory.
|
25
|
+
document_style: article, book (default) or beamer
|
26
|
+
build_directory: It will be made under the directory (the first argument). The default is _build.
|
27
|
+
build: build a pdf file from all the source files.
|
28
|
+
part_typeset file_or_numbers: build a pdf file from a single source file.
|
29
|
+
example: part_typeset 1-2-2 => part_typeset part1/chap2/sec2.xxx
|
30
|
+
renum: renumber the source files.
|
31
|
+
EOS
|
32
|
+
end
|
data/lib/lbt/build.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative 'utils.rb'
|
2
|
+
|
3
|
+
module Lbt
|
4
|
+
# Typeset LaTeX source files into a PDF file.
|
5
|
+
def build
|
6
|
+
m = File.read(".config").match(/^build_dir = (.*)$/)
|
7
|
+
build_dir = m[1] ? m[1] : "_build"
|
8
|
+
raise "main.tex not exist." unless File.exist?('main.tex')
|
9
|
+
mkdir build_dir unless Dir.exist?(build_dir)
|
10
|
+
|
11
|
+
# Build main.tex
|
12
|
+
main_tex = File.read('main.tex')
|
13
|
+
m = /\\title(\[(.*?)\])?\s*\{(.*?)\}/.match(main_tex.remove_tex_comment)
|
14
|
+
# Beamer has \title[short title]{title} command.
|
15
|
+
# Other documentclasses don't have such short style option.
|
16
|
+
title = m[2] || m[3]
|
17
|
+
files = PCS.new.to_a
|
18
|
+
input_commands = files.map{|f| "\\input{#{f.ext('.tex')}}\n"}.flatten.join
|
19
|
+
main_tex = main_tex.sub(/\\end{document}/, "#{input_commands}\n\\end{document}")
|
20
|
+
File.write("#{build_dir}/main.tex", main_tex)
|
21
|
+
# copy or convert the files into build_dir
|
22
|
+
cp_conv build_dir
|
23
|
+
# Typeset
|
24
|
+
cur_dir = Dir.pwd
|
25
|
+
cd build_dir
|
26
|
+
system "latexmk -lualatex -pdflualatex=\"lualatex --halt-on-error %O %S\" main.tex"
|
27
|
+
cd cur_dir
|
28
|
+
|
29
|
+
# Copy the pdf file.
|
30
|
+
temp = "#{build_dir}/main.pdf"
|
31
|
+
target = "#{title}.pdf"
|
32
|
+
unless File.exist?(target) && File.mtime(temp) <= File.mtime(target)
|
33
|
+
cp temp, target
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/lbt/create.rb
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'base64'
|
3
|
+
|
4
|
+
module Lbt
|
5
|
+
=begin rdoc
|
6
|
+
The create method creates a source file directory and put some templates in the directory.
|
7
|
+
|
8
|
+
Parameters are:
|
9
|
+
|
10
|
+
[dir] The name of the source file directory
|
11
|
+
[document\_class] The document class of the LaTeX source file. For example, article, book and beamer.
|
12
|
+
[build\_dir] The working directory in which typeset is carried out.
|
13
|
+
=end
|
14
|
+
def create dir, document_class="book", build_dir="_build"
|
15
|
+
raise "Argument error." unless dir.is_a?(String) && dir =~ /[[:^space:]]+/
|
16
|
+
raise "#{dir} already exists." if Dir.exist?(dir)
|
17
|
+
mkdir_p(dir)
|
18
|
+
File.write("#{dir}/.config", "build_dir = #{build_dir}\n")
|
19
|
+
helper_tex = <<~EOS
|
20
|
+
\\usepackage{amsmath,amssymb}
|
21
|
+
\\usepackage[luatex]{graphicx}
|
22
|
+
\\usepackage{tikz}
|
23
|
+
\\usepackage[margin=2.4cm]{geometry}
|
24
|
+
\\usepackage[colorlinks=true,linkcolor=black]{hyperref}
|
25
|
+
% If your source includes Markdown, you probably need the following lines.
|
26
|
+
% It is because Pandoc generates some undefined commands.
|
27
|
+
% The Pandoc template file shows how to define them.
|
28
|
+
% You can see it by 'pandoc --print-default-template=latex'.
|
29
|
+
\\providecommand{\\tightlist}{%
|
30
|
+
\\setlength{\\itemsep}{0pt}\\setlength{\\parskip}{0pt}}
|
31
|
+
EOS
|
32
|
+
|
33
|
+
if ["book", "ltjsbook"].include? document_class
|
34
|
+
main_tex = <<~EOS
|
35
|
+
\\documentclass{#{document_class}}
|
36
|
+
\\input{helper.tex}
|
37
|
+
\\title{Title}
|
38
|
+
\\author{Author}
|
39
|
+
\\begin{document}
|
40
|
+
\\frontmatter
|
41
|
+
\\begin{titlepage}
|
42
|
+
\\input{cover.tex}
|
43
|
+
\\end{titlepage}
|
44
|
+
\\tableofcontents
|
45
|
+
\\mainmatter
|
46
|
+
|
47
|
+
\\end{document}
|
48
|
+
EOS
|
49
|
+
|
50
|
+
cover_tex = <<~EOS
|
51
|
+
\\newgeometry{margin=2.4cm}
|
52
|
+
\\begin{center}
|
53
|
+
\\begin{tikzpicture}
|
54
|
+
\\node at (0,0) {\\includegraphics[width=100pt]{gecko.png}};
|
55
|
+
\\node at (70pt,0) {\\includegraphics[width=100pt]{gecko.png}};
|
56
|
+
\\node at (140pt,0) {\\includegraphics[width=100pt]{gecko.png}};
|
57
|
+
\\node at (210pt,0) {\\includegraphics[width=100pt]{gecko.png}};
|
58
|
+
\\node at (280pt,0) {\\includegraphics[width=100pt]{gecko.png}};
|
59
|
+
\\node at (350pt,0) {\\includegraphics[width=100pt]{gecko.png}};
|
60
|
+
\\end{tikzpicture}
|
61
|
+
\\end{center}
|
62
|
+
|
63
|
+
\\vspace{2cm}
|
64
|
+
\\begin{center}
|
65
|
+
{\\fontsize{64}{0} \\selectfont Title}
|
66
|
+
\\end{center}
|
67
|
+
\\vspace{1cm}
|
68
|
+
\\begin{center}
|
69
|
+
{\\huge Author}
|
70
|
+
\\end{center}
|
71
|
+
|
72
|
+
\\vspace{9cm}
|
73
|
+
%\\vspace{6.5cm}
|
74
|
+
%\\begin{center}
|
75
|
+
%{\\Large Foobar University}
|
76
|
+
%\\end{center}
|
77
|
+
%\\begin{center}
|
78
|
+
%{\\Large School of Foobar}
|
79
|
+
%\\end{center}
|
80
|
+
|
81
|
+
\\vspace{3cm}
|
82
|
+
\\begin{center}
|
83
|
+
\\begin{tikzpicture}
|
84
|
+
\\node at (0,0) {\\includegraphics[width=100pt]{gecko.png}};
|
85
|
+
\\node at (70pt,0) {\\includegraphics[width=100pt]{gecko.png}};
|
86
|
+
\\node at (140pt,0) {\\includegraphics[width=100pt]{gecko.png}};
|
87
|
+
\\node at (210pt,0) {\\includegraphics[width=100pt]{gecko.png}};
|
88
|
+
\\node at (280pt,0) {\\includegraphics[width=100pt]{gecko.png}};
|
89
|
+
\\node at (350pt,0) {\\includegraphics[width=100pt]{gecko.png}};
|
90
|
+
\\end{tikzpicture}
|
91
|
+
\\end{center}
|
92
|
+
\\restoregeometry
|
93
|
+
EOS
|
94
|
+
|
95
|
+
File.write("#{dir}/main.tex", main_tex)
|
96
|
+
File.write("#{dir}/helper.tex", helper_tex)
|
97
|
+
File.write("#{dir}/cover.tex", cover_tex)
|
98
|
+
gecko_png = __dir__+"/../../images/gecko.png"
|
99
|
+
cp(gecko_png, "#{dir}/gecko.png")
|
100
|
+
elsif ["article", "ltjsarticle"].include? document_class
|
101
|
+
main_tex = <<~EOS
|
102
|
+
\\documentclass{#{document_class}}
|
103
|
+
\\input{helper.tex}
|
104
|
+
\\title{Title}
|
105
|
+
\\author{Author}
|
106
|
+
\\begin{document}
|
107
|
+
\\maketitle
|
108
|
+
\\tableofcontents
|
109
|
+
|
110
|
+
\\end{document}
|
111
|
+
EOS
|
112
|
+
File.write("#{dir}/main.tex", main_tex)
|
113
|
+
File.write("#{dir}/helper.tex", helper_tex)
|
114
|
+
elsif document_class == "beamer"
|
115
|
+
main_tex = <<~EOS
|
116
|
+
\\documentclass[utf8,aspectratio=149]{beamer}
|
117
|
+
\\mode<presentation>
|
118
|
+
{
|
119
|
+
\\usetheme{Warsaw}
|
120
|
+
\\setbeamercovered{transparent}
|
121
|
+
}
|
122
|
+
\\input{helper.tex}
|
123
|
+
% Don't show navigation symbol => If you want to show it, comment out the following line.
|
124
|
+
\\setbeamertemplate{navigation symbols}{}
|
125
|
+
\\title[short\\_title] % (optional, use only with long paper titles)
|
126
|
+
{titile}
|
127
|
+
\\subtitle
|
128
|
+
{substitile}
|
129
|
+
\\author[short\\_author] % (optional, use only with lots of authors)
|
130
|
+
{author \\\\ \\texttt{sample\\_address@email.com}}
|
131
|
+
% - Give the names in the same order as the appear in the paper.
|
132
|
+
% - Use the \\inst{?} command only if the authors have different
|
133
|
+
% affiliation.
|
134
|
+
\\institute[short\\_institute] % (optional, but mostly needed)
|
135
|
+
{
|
136
|
+
% \\inst{1}%
|
137
|
+
Department of Mathematics and Technology\\\\
|
138
|
+
School of Education and Humanities\\\\
|
139
|
+
XXXX University
|
140
|
+
}
|
141
|
+
% - Use the \\inst command only if there are several affiliations.
|
142
|
+
% - Keep it simple, no one is interested in your street address.
|
143
|
+
\\date[short\\_date] % (optional, should be abbreviation of conference name)
|
144
|
+
{XXXX meeting on Wednesday, April 27 2022}
|
145
|
+
% - Either use conference name or its abbreviation.
|
146
|
+
% - Not really informative to the audience, more for people (including
|
147
|
+
% yourself) who are reading the slides online
|
148
|
+
\\subject{subject}
|
149
|
+
% If you have a file called "university-logo-filename.xxx", where xxx
|
150
|
+
% is a graphic format that can be processed by lualatex,
|
151
|
+
% resp., then you can add a logo as follows:
|
152
|
+
% \\pgfdeclareimage[height=0.5cm]{university-logo}{university-logo-filename}
|
153
|
+
% \\logo{\\pgfuseimage{university-logo}}
|
154
|
+
\\begin{document}
|
155
|
+
\\begin{frame}
|
156
|
+
\\titlepage
|
157
|
+
\\end{frame}
|
158
|
+
\\begin{frame}{Outline}
|
159
|
+
\\tableofcontents
|
160
|
+
% \\begin{center}
|
161
|
+
% \\includegraphics[width=6cm,keepaspectratio]{photo.jpg}
|
162
|
+
% \\end{center}
|
163
|
+
\\end{frame}
|
164
|
+
|
165
|
+
\\end{document}
|
166
|
+
EOS
|
167
|
+
helper_tex = <<~EOS
|
168
|
+
\\usepackage{luatexja}
|
169
|
+
% 和文のデフォルトをゴシック体に
|
170
|
+
\\renewcommand{\\kanjifamilydefault}{\\gtdefault}
|
171
|
+
\\usepackage{amsmath,amssymb}
|
172
|
+
\\usepackage{tikz}
|
173
|
+
\\usepackage[absolute,overlay]{textpos}
|
174
|
+
EOS
|
175
|
+
sec1_tex = <<~EOS
|
176
|
+
% This is a sample latex file for the beamer documentclass.
|
177
|
+
\\begin{frame}{introduction}
|
178
|
+
About something
|
179
|
+
\\begin{itemize}
|
180
|
+
\\item item 1
|
181
|
+
\\item<2> item 2
|
182
|
+
\\end{itemize}
|
183
|
+
About another thing
|
184
|
+
\\begin{enumerate}
|
185
|
+
\\item<3> item 1
|
186
|
+
\\item<3-4> item 2
|
187
|
+
\\end{enumerate}
|
188
|
+
\\alert{alert message, which is red.}
|
189
|
+
\\end{frame}
|
190
|
+
% Show a photo that extends to the whole slide view.
|
191
|
+
\\begin{frame}
|
192
|
+
\\begin{textblock*}{128mm}(0pt,0pt)
|
193
|
+
\\includegraphics[width=128mm,height=96mm,keepaspectratio]{lagoon.jpg}
|
194
|
+
\\end{textblock*}
|
195
|
+
\\end{frame}
|
196
|
+
EOS
|
197
|
+
File.write("#{dir}/main.tex", main_tex)
|
198
|
+
File.write("#{dir}/helper.tex", helper_tex)
|
199
|
+
File.write("#{dir}/sec1.tex", sec1_tex)
|
200
|
+
lagoon_jpg = __dir__+"/../../images/lagoon.jpg"
|
201
|
+
cp(lagoon_jpg, "#{dir}/lagoon.jpg")
|
202
|
+
else
|
203
|
+
main_tex = <<~EOS
|
204
|
+
\\documentclass{#{document_class}}
|
205
|
+
\\input{helper.tex}
|
206
|
+
\\title{Title}
|
207
|
+
\\author{Author}
|
208
|
+
\\begin{document}
|
209
|
+
\\maketitle
|
210
|
+
\\tableofcontents
|
211
|
+
|
212
|
+
\\end{document}
|
213
|
+
EOS
|
214
|
+
File.write("#{dir}/main.tex", main_tex)
|
215
|
+
File.write("#{dir}/helper.tex", helper_tex)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require_relative 'utils.rb'
|
2
|
+
|
3
|
+
module Lbt
|
4
|
+
# Typeset one source file to check the PDF.
|
5
|
+
#
|
6
|
+
# Parameter:
|
7
|
+
# [file_or_number]
|
8
|
+
# It can be either a filename or the number of a filename.
|
9
|
+
# For example, part1/chap2/sec3.tex or 1-2-3
|
10
|
+
def part_typeset file_or_number
|
11
|
+
return unless file_or_number.is_a? String
|
12
|
+
if File.file?(file_or_number)
|
13
|
+
file = file_or_number
|
14
|
+
else
|
15
|
+
file = num2path(file_or_number)
|
16
|
+
return unless File.file? file
|
17
|
+
end
|
18
|
+
|
19
|
+
m = File.read(".config").match(/^build_dir = (.*)$/)
|
20
|
+
build_dir = m[1] ? m[1] : "_build"
|
21
|
+
raise "main.tex not exist." unless File.exist?('main.tex')
|
22
|
+
mkdir build_dir unless Dir.exist?(build_dir)
|
23
|
+
|
24
|
+
main_tex = File.read('main.tex')
|
25
|
+
main_tex = main_tex.sub(/\\end{document}/, "\\input{#{file.ext('.tex')}}\n\\end{document}")
|
26
|
+
File.write("#{build_dir}/main.tex", main_tex)
|
27
|
+
# copy or convert the files into build_dir
|
28
|
+
cp_conv build_dir
|
29
|
+
# Typeset
|
30
|
+
cur_dir = Dir.pwd
|
31
|
+
cd build_dir
|
32
|
+
system "latexmk -lualatex -pdflualatex=\"lualatex --halt-on-error %O %S\" main.tex"
|
33
|
+
cd cur_dir
|
34
|
+
end
|
35
|
+
|
36
|
+
# :nodoc:
|
37
|
+
def num2path n_n_n
|
38
|
+
return nil unless n_n_n.is_a? String
|
39
|
+
num_pcs = /^(\d+(\.\d+)?)-(\d+(\.\d+)?)-(\d+(\.\d+)?)$/
|
40
|
+
num_cs = /^(\d+(\.\d+)?)-(\d+(\.\d+)?)$/
|
41
|
+
num_s = /^(\d+(\.\d+)?)$/
|
42
|
+
if n_n_n =~ num_pcs
|
43
|
+
path = "part#{$1}/chap#{$3}/sec#{$5}"
|
44
|
+
elsif n_n_n =~ num_cs
|
45
|
+
path = "chap#{$1}/sec#{$3}"
|
46
|
+
elsif n_n_n =~ num_s
|
47
|
+
path = "sec#{$1}"
|
48
|
+
else
|
49
|
+
return nil
|
50
|
+
end
|
51
|
+
srcs = Dir.glob("#{path}.*")
|
52
|
+
return nil if srcs.size != 1
|
53
|
+
srcs[0]
|
54
|
+
end
|
55
|
+
end
|
data/lib/lbt/renumber.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
module Lbt
|
2
|
+
# Renumber the source files.
|
3
|
+
# For example,
|
4
|
+
# - sec1.tex, sec1.5.tex, sec2.tex => sec1.tex, sec2.tex, sec3.tex
|
5
|
+
# - chap1/sec1.tex, chap1/sec1.2.tex, chap1.3/sec10.tex => chap1/sec1.tex, chap1/sec2.tex, chap2/sec1.tex
|
6
|
+
def renum
|
7
|
+
if Dir.children(".").select{|d| d =~ /^part\d+(\.\d+)?$/}.size > 0
|
8
|
+
renumber "part"
|
9
|
+
elsif Dir.children(".").select{|d| d =~ /^chap\d+(\.\d+)?$/}.size > 0
|
10
|
+
renumber "chap"
|
11
|
+
else
|
12
|
+
renumber "sec"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# :nodoc:
|
17
|
+
def renumber pcs
|
18
|
+
case pcs
|
19
|
+
when "part", "chap"
|
20
|
+
files = Dir.children(".").select{|d| d =~ /^#{pcs}\d+(\.\d+)?$/}
|
21
|
+
when "sec"
|
22
|
+
files = Dir.children(".").select{|d| d =~ /^#{pcs}\d+(\.\d+)?\.\w+$/}
|
23
|
+
end
|
24
|
+
files.sort! do |a,b|
|
25
|
+
a.match(/^#{pcs}(\d+(\.\d+)?)/)[1] <=> b.match(/^#{pcs}(\d+(\.\d+)?)/)[1]
|
26
|
+
end
|
27
|
+
n = files.size
|
28
|
+
case pcs
|
29
|
+
when "part", "chap"
|
30
|
+
temp_files = (1..n).map{|i| "#{pcs}#{i}_temp"}
|
31
|
+
when "sec"
|
32
|
+
temp_files = (1..n).map{|i| "#{pcs}#{i}#{File.extname(files[i-1])}_temp"}
|
33
|
+
end
|
34
|
+
n.times do |i|
|
35
|
+
File.rename(files[i], temp_files[i])
|
36
|
+
end
|
37
|
+
n.times do |i|
|
38
|
+
File.rename(temp_files[i], temp_files[i].sub(/_temp$/, ""))
|
39
|
+
end
|
40
|
+
return if pcs == "sec"
|
41
|
+
Dir.children(".").select{|d| d =~ /^#{pcs}\d+(\.\d+)?$/}.each do |f|
|
42
|
+
cd f
|
43
|
+
case pcs
|
44
|
+
when "part" then renumber "chap"
|
45
|
+
when "chap" then renumber "sec"
|
46
|
+
end
|
47
|
+
cd ".."
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/lbt/utils.rb
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
include FileUtils
|
4
|
+
|
5
|
+
class String
|
6
|
+
# Remove verbatim environments and comments (including the following new line) from self (LaTeX source).
|
7
|
+
def remove_tex_comment
|
8
|
+
gsub(/\\begin\{verbatim\}.*\\end\{verbatim\}/m, '').gsub(/%.*\n/,'')
|
9
|
+
end
|
10
|
+
# Return a string with the new suffix.
|
11
|
+
# If the suffix is illegal, nil is returned.
|
12
|
+
# Be careful that the suffix begins with a period.
|
13
|
+
#
|
14
|
+
# It redefines itself if it has been defined. For example, rake defines ext method.
|
15
|
+
def ext(suffix)
|
16
|
+
return nil unless suffix.is_a?(String) && /^\.\w+$/ =~ suffix
|
17
|
+
s = File.extname(self)
|
18
|
+
self.sub(/#{s}$/, suffix)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module Lbt
|
23
|
+
=begin rdoc
|
24
|
+
When you create an instance of the PCS class, it keeps the structure of Part-Chapter-Section files.
|
25
|
+
For example,
|
26
|
+
+-part1-+-chap1-+-sec1.tex
|
27
|
+
| | +-sec2.tex`
|
28
|
+
| +-chap2-+-sec1.tex`
|
29
|
+
| | +-sec2.tex`
|
30
|
+
+-part2-+-chap1-+-sec1.tex
|
31
|
+
| +-sec2.tex`
|
32
|
+
If the files are as above, the PCS instance keeps the six filenames whch are sorted alphabetically.
|
33
|
+
=end
|
34
|
+
class PCS
|
35
|
+
# Type is one of :PCS, :CS and :S
|
36
|
+
# - :PCS => The file structure has part, chap directories.
|
37
|
+
# - :CS => The file structure has chap directories.
|
38
|
+
# - :S => The file structure doesn't have any directories.
|
39
|
+
attr_reader :type
|
40
|
+
# The name of the top direcotory
|
41
|
+
attr_reader :dir
|
42
|
+
# Create a new PCS instance.
|
43
|
+
# You can give a top directory as an argument.
|
44
|
+
def initialize dir="."
|
45
|
+
@dir = dir.dup
|
46
|
+
@dir.freeze
|
47
|
+
@files = Dir.glob("part*/chap*/sec*", base: @dir).select{|f| f.match?(/^part\d+(\.\d+)?\/chap\d+(\.\d+)?\/sec\d+(\.\d+)?\.\w+$/)}
|
48
|
+
unless @files.empty?
|
49
|
+
@type = :PCS
|
50
|
+
@files.sort! do |a, b|
|
51
|
+
m = /^part(\d+(\.\d+)?)\/chap(\d+(\.\d+)?)\/sec(\d+(\.\d+)?)\.\w*$/.match(a)
|
52
|
+
ap = m[1].to_f; ac= m[3].to_f; as = m[5].to_f
|
53
|
+
m = /^part(\d+(\.\d+)?)\/chap(\d+(\.\d+)?)\/sec(\d+(\.\d+)?)\.\w*$/.match(b)
|
54
|
+
bp = m[1].to_f; bc= m[3].to_f; bs = m[5].to_f
|
55
|
+
if ap != bp
|
56
|
+
ap <=> bp
|
57
|
+
elsif ac != bc
|
58
|
+
ac <=> bc
|
59
|
+
else
|
60
|
+
as <=> bs
|
61
|
+
end
|
62
|
+
end
|
63
|
+
return
|
64
|
+
end
|
65
|
+
@files = Dir.glob("chap*/sec*", base: @dir).select{|f| f.match?(/^chap\d+(\.\d+)?\/sec\d+(\.\d+)?\.\w+$/)}
|
66
|
+
unless @files.empty?
|
67
|
+
@type = :CS
|
68
|
+
@files.sort! do |a, b|
|
69
|
+
m = /^chap(\d+(\.\d+)?)\/sec(\d+(\.\d+)?)\.\w*$/.match(a)
|
70
|
+
ac= m[1].to_f; as = m[3].to_f
|
71
|
+
m = /^chap(\d+(\.\d+)?)\/sec(\d+(\.\d+)?)\.\w*$/.match(b)
|
72
|
+
bc= m[1].to_f; bs = m[3].to_f
|
73
|
+
if ac != bc
|
74
|
+
ac <=> bc
|
75
|
+
else
|
76
|
+
as <=> bs
|
77
|
+
end
|
78
|
+
end
|
79
|
+
return
|
80
|
+
end
|
81
|
+
@files = Dir.glob("sec*", base: @dir).select{|f| f.match?(/^sec\d+(\.\d+)?\.\w+$/)}
|
82
|
+
unless @files.empty?
|
83
|
+
@type = :S
|
84
|
+
@files.sort! do |a, b|
|
85
|
+
m = /^sec(\d+(\.\d+)?)\.\w*$/.match(a)
|
86
|
+
as = m[1].to_f
|
87
|
+
m = /^sec(\d+(\.\d+)?)\.\w*$/.match(b)
|
88
|
+
bs = m[1].to_f
|
89
|
+
as <=> bs
|
90
|
+
end
|
91
|
+
return
|
92
|
+
end
|
93
|
+
raise "No [[part/]chap/]sec files exist.\n" if @files.empty?
|
94
|
+
end
|
95
|
+
|
96
|
+
# Return an array of pathnames which are relative from the top directory.
|
97
|
+
# The returned pathnames are the copies.
|
98
|
+
# So, even if a user changes them, the original pathnames in the PCS instance are not changed.
|
99
|
+
def to_a
|
100
|
+
@files.map {|s| s.dup}
|
101
|
+
end
|
102
|
+
# Executes the block with each pathname.
|
103
|
+
def each
|
104
|
+
@files.each {|f| yield(f)}
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Return a hash (key: extension, value: Proc object) of converters.
|
109
|
+
def get_converters
|
110
|
+
converters = {'.md': lambda {|src, dst| system("pandoc -o #{dst} #{src}")} }
|
111
|
+
if File.file?("converters.rb")
|
112
|
+
c = eval(File.read("converters.rb"))
|
113
|
+
c.each {|key, val| converters[key] = val} if c.is_a?(Hash)
|
114
|
+
end
|
115
|
+
converters
|
116
|
+
end
|
117
|
+
|
118
|
+
# copy or convert source files into build directory.
|
119
|
+
def cp_conv build_dir
|
120
|
+
converters = get_converters
|
121
|
+
files = Dir.children(".").reject{|f| f == build_dir || f == "main.tex"}
|
122
|
+
cp_conv_0 ".", files, build_dir, converters
|
123
|
+
end
|
124
|
+
# :nodoc:
|
125
|
+
def cp_conv_0 sdir, files, ddir, converters
|
126
|
+
files.each do |f|
|
127
|
+
f1 = "#{sdir}/#{f}"; f2 = "#{ddir}/#{f}"; ext = File.extname(f).to_sym
|
128
|
+
if Dir.exist?(f1)
|
129
|
+
mkdir_p f2
|
130
|
+
f1_files = Dir.children(f1)
|
131
|
+
cp_conv_0 f1, f1_files, f2, converters
|
132
|
+
elsif converters.has_key?(ext)
|
133
|
+
f2 = f2.ext ".tex"
|
134
|
+
unless File.exist?(f2) && File.mtime(f1) <= File.mtime(f2)
|
135
|
+
converters[ext].call(f1, f2)
|
136
|
+
end
|
137
|
+
elsif File.file?(f1)
|
138
|
+
cp f1, f2
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
data/lib/lbt.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require_relative 'lbt/build.rb'
|
2
|
+
require_relative 'lbt/create.rb'
|
3
|
+
require_relative 'lbt/part_typeset.rb'
|
4
|
+
require_relative 'lbt/renumber.rb'
|
5
|
+
require_relative 'lbt/utils.rb'
|
6
|
+
|
7
|
+
# LaTeX-Buildtools provides Ruby script +lbt+ to create template, build it and do other tasks.
|
8
|
+
# The +lbt+ command includes Lbt module and calls its instance methods.
|
9
|
+
# All the methods are instance methods and Lbt module doesn't have any singleton methods.
|
10
|
+
module Lbt
|
11
|
+
end
|
metadata
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lbt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.5'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Toshio Sekiya
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-04-15 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Lbt is a build tool for LaTeX. It is useful for big documents.
|
14
|
+
email: lxboyjp@gmail.com
|
15
|
+
executables:
|
16
|
+
- lbt
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- bin/lbt
|
21
|
+
- lib/lbt.rb
|
22
|
+
- lib/lbt/build.rb
|
23
|
+
- lib/lbt/create.rb
|
24
|
+
- lib/lbt/part_typeset.rb
|
25
|
+
- lib/lbt/renumber.rb
|
26
|
+
- lib/lbt/utils.rb
|
27
|
+
homepage: https://github.com/ToshioCP/LaTeX-BuildTools
|
28
|
+
licenses:
|
29
|
+
- GPL-3.0
|
30
|
+
metadata: {}
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
requirements: []
|
46
|
+
rubygems_version: 3.4.11
|
47
|
+
signing_key:
|
48
|
+
specification_version: 4
|
49
|
+
summary: LaTeX Build Tools
|
50
|
+
test_files: []
|