rake4latex 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,156 @@
1
+ =begin rdoc
2
+ call_rake4latex.rb offers an easy and fast interface
3
+ to rake4latex.
4
+
5
+ Just call it from the shell:
6
+ call_rake4latex.rb my_file
7
+
8
+ my_file.tex will be compiled to my_file.pdf.
9
+
10
+ For details, please use the help:
11
+ call_rake4latex.rb -h
12
+
13
+ For complex documents you may want define your own rakefile
14
+ and use rake.
15
+
16
+ It is recommended to copy this file to a location in your
17
+ search path for executable files.
18
+ =end
19
+
20
+ require 'rake4latex'
21
+ require 'optparse'
22
+
23
+ #Anlegen des Parsers
24
+ opts = OptionParser.new()
25
+ opts.banner = "Usage: call_rake4latex.rb [options] filename" #Usage-zeile
26
+ opts.separator "Call LaTeX as often as needed."
27
+ opts.separator ""
28
+ opts.separator "Examples:"
29
+ opts.separator "call_rake4latex testdocument.pdf"
30
+ opts.separator " Create testdocument.pdf via pdflatex"
31
+ opts.separator " Starts only if testdocument.tex is newer then testdocument.pdf."
32
+ opts.separator ""
33
+ opts.separator "call_rake4latex -f testdocument"
34
+ opts.separator " Touch 'testdocument.tex' (set the modification date)"
35
+ opts.separator " Create testdocument.pdf via pdflatex"
36
+ opts.separator ""
37
+ opts.separator "Specific options:"
38
+
39
+ #
40
+ #List of task to be done after the TeX-call.
41
+ #
42
+ TASK_BEFORE_TeX = [] #only task where we need the filenem
43
+ TASK_AFTER_TeX = []
44
+ PARSE_MESSAGES = true
45
+
46
+
47
+ =begin
48
+ Shortcuts
49
+ =end
50
+ opts.on('-f', "--force", "Force an initial TeX-run") { |v|
51
+ TASK_BEFORE_TeX << :force
52
+ }
53
+
54
+ #
55
+ #fixme:
56
+ #Warum gibt es immer einen TeX-Lauf mit dieser Option?
57
+ #
58
+ opts.on('-d', '--dep', "--dependecies", "Build dependecies") { |v|
59
+ TASK_BEFORE_TeX << :dependecies
60
+ }
61
+ opts.on("-i", "--ignore", "--ignore-error", "Allow LaTeX errors") { |v|
62
+ puts "Allow LaTeX errors" if PARSE_MESSAGES
63
+ Rake.application.set_latexrunner_default(:texerrors_allowed, true)
64
+ }
65
+
66
+ opts.on("-s", "--statistic", "Show the statistic after TeX-run") { |v|
67
+ puts "Show the statistic after TeX-run" if PARSE_MESSAGES
68
+ TASK_BEFORE_TeX << :statistic #Set filename
69
+ TASK_AFTER_TeX << :statistic
70
+ }
71
+ opts.on("-c", "--clean", "Clean after TeX-run (delete auxiliary files)") { |v|
72
+ puts "Clean after TeX-run" if PARSE_MESSAGES
73
+ TASK_AFTER_TeX << :clean
74
+ }
75
+
76
+ =begin
77
+ Main options
78
+ =end
79
+ # Soll der Parameter Optional sein, kann [] verwendet werden.
80
+ opts.on("--touch FILE", "Touch FILE") { |v|
81
+ puts "Touch #{v.inspect}" if PARSE_MESSAGES
82
+ task :touch => v
83
+ task :default => :touch
84
+ }
85
+
86
+
87
+ #
88
+ opts.on("--task TASK", "Define a rake-task") { |v|
89
+ puts "Set task #{v.inspect}" if PARSE_MESSAGES
90
+ task :default => v
91
+ }
92
+
93
+ #
94
+ opts.on("--task_after TASK", "Define a rake-task after the TeX-run") { |v|
95
+ puts "Set task #{v.inspect} after LaTeX" if PARSE_MESSAGES
96
+ TASK_AFTER_TeX << v
97
+ }
98
+
99
+ =begin
100
+ LaTeXRunner-options
101
+ =end
102
+ #
103
+ opts.on("--maxrun MAXRUN", "Maximum MAXRUN TeX calls") { |v|
104
+ puts "Set maximum TeX-Runs #{v.inspect}" if PARSE_MESSAGES
105
+ Rake.application.set_latexrunner_default(:maxruns, v.to_i)
106
+ #~ LaTeXRunner::DEFAULT_SETTINGS[:maxruns] =
107
+ }
108
+
109
+ opts.on("-l", "--loglevel LEVEL", "Log Level for the logger (1=debug, 2=info(default), 3=warn 4=error)") { |v|
110
+ puts "Set loglevel to #{v.inspect}" if PARSE_MESSAGES
111
+ Rake.application.set_latexrunner_default(:loglevel, v.to_i)
112
+ }
113
+
114
+
115
+
116
+ #Parsen der Parameter mit Exception bei ung�ltigen Parametern
117
+ begin
118
+ opts.parse!
119
+ ARGV.each{|arg|
120
+ target = arg.ext('pdf')
121
+ puts "Define target #{target}"
122
+ set4clean(arg)
123
+ TASK_BEFORE_TeX.each{|task|
124
+ case task
125
+ when :force
126
+ puts "Force an initial TeX-run (touch #{target.ext('tex')})" if PARSE_MESSAGES
127
+ task (:touch => target.ext('tex'))
128
+ task (:default => :touch)
129
+ when :dependecies
130
+ puts "Build dependecies for #{target.ext('tex')}" if PARSE_MESSAGES
131
+ LaTeXDependencies.get_dependecies(target.ext('tex'), :inputs, :flat).each{|dep|
132
+ puts " => #{dep.inspect}" if PARSE_MESSAGES
133
+ task (target => dep)
134
+ }
135
+ when :statistic
136
+ task (:statistic => target.ext('tex'))
137
+ else
138
+ raise ArgumentError, "Undefined option #{task.inspect}"
139
+ end
140
+ }
141
+ task( :default => target )
142
+ }
143
+ rescue OptionParser::MissingArgument, OptionParser::InvalidOption => err
144
+ puts "Error:\t#{err}"
145
+ #Ausgabe der Schnittstelle
146
+ puts opts
147
+ end
148
+
149
+ #
150
+ #Set tasks after the LaTeX-call
151
+ TASK_AFTER_TeX.each{|task|
152
+ task (:default => task)
153
+ }
154
+
155
+ app = Rake.application
156
+ app[:default].invoke
data/lib/rake4latex.rb ADDED
@@ -0,0 +1,377 @@
1
+ =begin rdoc
2
+ ==Introduction
3
+ This file contains definitions to build a rakefile for LaTeX-documents.
4
+
5
+ A not-so minimal rakefile looks like this:
6
+ require 'rake4latex'
7
+ #Needed for some actions without a previous TeX-call
8
+ task :basefile => 'testdocument.tex'
9
+ #We want to build a PDF
10
+ file 'testdocument.pdf' => 'testdocument.tex'
11
+
12
+ #Force the compilation
13
+ task :touch => 'testdocument.tex'
14
+
15
+ #Define the default tasks
16
+ task :default => :touch
17
+ task :default => 'testdocument.pdf'
18
+ task :default => :statistic
19
+ task :default => :clean
20
+
21
+ #Make the rakefile self-executable
22
+ if $0 == __FILE__
23
+ app = Rake.application
24
+ app[:default].invoke
25
+ end
26
+
27
+ You can generate this template with:
28
+ require 'rake4latex'
29
+ puts Rake4LaTeX.template( [basename] )
30
+
31
+ ==Multiple runs
32
+ One of the problems with writing a Makefile for LaTeX is that often latex needs
33
+ to be run more than once on the same file, before obtaining the final output.
34
+ Moreover, every LaTeX package may require other runs basing on different conditions
35
+ and maybe even requiring some other program to be run between latex invocations.
36
+
37
+ Makefile normally expect a defined sequence of prerequisites.
38
+ Prerequisites are known before the action takes care.
39
+ Some dependecies of (La)TeX-documents creates ther prerequisites after the
40
+ (La)TeX-run (e.g. new index entries).
41
+
42
+ The approach followed here is to define "Post-Prerequisites".
43
+ The virtual target :latex_dependecies contains all this "Post-Prerequisites".
44
+ After a TeX-run, each Post-Prerequisites is checked.
45
+ For each post-prerequisites you must define a rule (in the following called postprereq.
46
+
47
+ The prerequisites of postprereq are checked for changes.
48
+ To detect changes, the Hash-Code of the prerequisite-files before and after
49
+ the TeX-run are compared (the comparison of the time stamp makes no sense,
50
+ TeX always(*) recreate the files).
51
+
52
+ <small>*) Forget the \nofiles-command</small>
53
+
54
+ See the examples-section hot to define your own custom action.
55
+
56
+ To avoid problems of endless loops, a there's a maximum number of runs, which is
57
+ 5 by default. The user can change it in the runner.
58
+
59
+ ==Dependencies
60
+ You must define your dependencies your own (but there is a help to do so, see next next section)
61
+
62
+ Example:
63
+ file 'testdocument.dvi' => ['testdocument.tex', 'testincludes/testinclude1.tex']
64
+
65
+
66
+ ===Determine Dependecies: LaTeXDependencies.get_dependecies( )
67
+ You can automatically compute dependencies for the latex task:
68
+ LaTeXDependencies.new(filename).get_dependecies( *options )
69
+ Options may be:
70
+ * :inputs:
71
+
72
+ The input file (the one which is passed to latex) is read, and the arguments of the
73
+ <tt>\includeonly</tt>, <tt>\include</tt> and <tt>\input</tt> latex commands are
74
+ extracted. Each of this these files is scanned again for dependecies.
75
+
76
+ The result is a nested array with all dependecies.
77
+
78
+ * :flat:
79
+ The (nested) result is flatted and double entries are deleted.
80
+
81
+ You can use it already direct in your dependecies definition:
82
+ file 'testdocument.dvi' => LaTeXDependencies.new('testdocument.tex').get_dependecies( *options )
83
+
84
+ ===Dependecies for BibTeX
85
+ BibTeX depends on two files:
86
+ * aux file with the list of the cites.
87
+ * bib-file(s) with the data of the literature.
88
+
89
+ You can define the dependecies of bib-file in your rakefile:
90
+ file 'testdocument.pdf' => 'testdocument.bib'
91
+ file 'testdocument.bbl' => 'testdocument.bib'
92
+ You need both definietions.
93
+ The pdf-dependecy is needed to start a new TeX-run,
94
+ The bbl-dependecy is needed to start a new BibTeX-run.
95
+
96
+ ==Supported tools and packages
97
+
98
+ ===Supported tools
99
+ The following tools are supported by rake4latex:
100
+ * Makeindex with makeidx.sty
101
+ * BibTeX
102
+
103
+ ===Supported (checked) packages
104
+ The rake process to generate the document is independent of any
105
+ package.
106
+ But some packages requires additional TeX-runs.
107
+ The following packages are tested and work fine:
108
+ * minitoc
109
+ * longtable
110
+ * supertabular
111
+ * splitindex (splitindex is replaced by internal routines)
112
+
113
+ Untested packages:
114
+ * glossary
115
+ * multiind/index (not planned to check, please use splitindex or inform me about your need)
116
+
117
+ ==Adding new tasks
118
+ ===Normal tasks
119
+ Task to generate pictures or other stuff needed to
120
+ build your LaTeX project can be added like normal
121
+ rake-tasks.
122
+
123
+ ===TeX-related tasks
124
+ Some task must be executed after a TeX-run.
125
+ This tasks must be created with <tt>tex_postrule</tt>
126
+ instead of the rake-method <tt>rule</tt>.
127
+
128
+ The tasks for makeindex and bibTeX are already defined.
129
+
130
+ ====Example makeindex
131
+ An example for this tasks is makeindex.
132
+ After a TeX-run you must check, if there are are new or changed
133
+ index entries.
134
+
135
+ The makeindex-task looks like this:
136
+ desc "Call Makeindex"
137
+ tex_postrule '.ind' => '.idx' do |t|
138
+ sh "makeindex #{t.source}"
139
+ end
140
+
141
+ That's it to get an index.
142
+
143
+ After a TeX-run, the prerequisites of rule '.ind' is checked for changes
144
+ (Hash-Code of the idx-file before and after the TeX-Run).
145
+ If there is a change, the rule is called.
146
+ And if the .ind-file changed, an additional TeX-call is forced.
147
+
148
+ ====Example BibTeX
149
+ BibTeX is a bit more complicated:
150
+ tex_postrule '.bbl' => '.aux' do |t, args |
151
+ sh "bibtex #{t.source}"
152
+ end
153
+
154
+ With this rule, BibTeX is called every times the aux-file changed
155
+ (if we use BibTeX or not).
156
+ We need a modified pre-check, if the BibTeX-call is necessary:
157
+ tex_postrule_check '.bbl' do |args|
158
+ auxfile = args[:task].name.ext('aux')
159
+ File.exist?(auxfile) and #there is a aux-file
160
+ ( args[:checksums][auxfile] == :changed ) and #the aux-file changed
161
+ ( necessary and File.read(auxfile) =~ /bibdata/ )#and we use bibtex
162
+ end
163
+
164
+
165
+ See also section 'Multiple runs'
166
+
167
+ ==Known Bugs and Problems
168
+ *Only pdflatex/xelatex/lualatex/latex to create the target,
169
+ no ps-files, no ps2pdf.
170
+ **Intended for the next release
171
+ * Two runs for new documents, when only one is needed.\\
172
+ After the first run, the aux-file is created,
173
+ so rake4latex detect a reason to rerun.
174
+ Solution would be to make a log-file analyse.
175
+ ** No plan to solve it.
176
+ Not a big problem, and why you need a rakefile for such simple tex-files?
177
+ * No usage of kpsewhich\\
178
+ LaTeXDependencies#get_dependecies checks dependecies only relative to
179
+ the file location.
180
+ kpsewhich is not used.
181
+ ** Would be nice escpecially for BibTeX and scan for \bibliography{xxx}
182
+ ** Low priority
183
+
184
+ =end
185
+
186
+ <<weiter
187
+ fixmes
188
+ == weiterer Aufbau rake abh�ngigkeiten
189
+ - glossary
190
+ rule '.glo' => '.aux' '.glo' do |t|
191
+ (glossaries?)
192
+
193
+ ==task statistic/log-analyse
194
+
195
+ ==application::texrunner als array?
196
+
197
+ Rake.template(basename) erzeugt rakefile
198
+ app = Rake.application
199
+ #~ app.set_latexrunner_default(:maxruns, 1)
200
+ #~ app.set_latexrunner_default(:loglevel, Log4r::DEBUG)
201
+ #~ app.set_latexrunner_default(:texerrors_allowed, true)
202
+ app[:default].invoke
203
+
204
+ rail �berarbeiten
205
+
206
+ Compilierungswege dvi -> ps -> pdf
207
+
208
+ prob:
209
+ wie erkennen ob
210
+ - dvi2ps + ps2pdf
211
+ - dvipdfm
212
+
213
+ weiter
214
+
215
+
216
+ #~ ==Problems
217
+ #~ * the action which checks for changed references causes a second latex invocation
218
+ #~ every time the .aux file changes.
219
+ #~ I don't know enough of the contents of the
220
+ #~ .aux file to parse it, but I need to base the decision on it, because messages
221
+ #~ such as "rerun to get cross-references right" in the latex log file aren't
222
+ #~ reliable (for example, the when the hyperref package is used, they aren't
223
+ #~ produced)
224
+
225
+ require 'log4r'
226
+ #Create a dummy-Logger to define the constants Log4r::DEBUG...
227
+
228
+ Log4r::Logger.new("test")
229
+ #~ gem 'rake', '=0.8.7'
230
+ require 'rake'
231
+ require 'md5'
232
+
233
+ class Rake::Application
234
+ =begin rdoc
235
+ Sets a default option for the LaTeXRunner.
236
+
237
+ The options are stored and used for new LaTeXRunners.
238
+
239
+ Example:
240
+ app.set_latexrunner_default(:loglevel, Log4r::DEBUG)
241
+
242
+ You could also access LaTeXRunner::DEFAULT_SETTINGS directly.
243
+ But with this method you get also a check if the option exists.
244
+ =end
245
+ def set_latexrunner_default( key, option )
246
+ if ! LaTeXRunner::DEFAULT_SETTINGS.keys.include?(key)
247
+ raise ArgumentError, "Undefined key #{key.inspect} for LaTeXRunner" unless @latexrunner
248
+ @latexrunner.logger.warn("Undefined key #{key.inspect} for LaTeXRunner")
249
+ end
250
+ LaTeXRunner::DEFAULT_SETTINGS[key] = option
251
+ end
252
+ =begin rdoc
253
+ Get the related actual LaTeXRunner.
254
+ =end
255
+ attr_reader :latexrunner
256
+ =begin rdoc
257
+ Define a LaTeXRunner.
258
+
259
+ This LaTeXRunner may be used via Rake#application#latexrunner to get the logger.
260
+ =end
261
+ def latexrunner=( latexrunner )
262
+ raise ArgumentError, "LaTeXRunner is no LaTeXRunner but #{t.class}" unless latexrunner.is_a?(LaTeXRunner)
263
+ if @latexrunner
264
+ @latexrunner.logger.warn( "LaTeXRunner replaced by other runner")
265
+ end
266
+ @latexrunner = latexrunner
267
+ @latexrunner.logger.debug( "Set LaTeXRunner #{@latexrunner.main_file} as default runner in Rake::Application")
268
+ end
269
+ end #Rake::Application
270
+
271
+ =begin rdoc
272
+ Define the files to be deleted with clean and clobber.
273
+
274
+ There is no global definition to delete all files,
275
+ only the help file for the selected basename is taken.
276
+
277
+ Helpfiles for splitindex are not added. You can do it manual:
278
+ CLEAN.add("testdocument-*") #splitidx-helpfiles
279
+
280
+ This method is called by task 'basename'
281
+ =end
282
+ def set4clean( basename )
283
+ #fixme splitindex-dateien
284
+ FileList["#{basename.ext('*')}"].each do |file|
285
+ #Set the cleaning actions
286
+ case file
287
+ when /\.(tex)\Z/
288
+ when /\.(aux|log|out|toc|lot|lof|nav|snm)\Z/
289
+ CLEAN.include(file)
290
+ when /\.(maf|ptc\d*|mtc\d*|stc\d*)\Z/ #minitoc
291
+ CLEAN.include(file)
292
+ when /\.(ilg|idx|ind)\Z/ #Index-Files
293
+ CLEAN.include(file)
294
+ when /\.(blg|bbl)\Z/ #BibTeX-Files
295
+ CLEAN.include(file)
296
+ when /\.(rai|rao|RAO)\Z/ #Rail-Files
297
+ CLEAN.include(file)
298
+ when /\.(dvi|pdf|ps)\Z/
299
+ CLOBBER.include(file)
300
+ else
301
+ #~ @logger.warn("Unknown help file #{file}")
302
+ end
303
+ end
304
+ CLEAN.uniq!
305
+ CLOBBER.uniq!
306
+ end
307
+
308
+ =begin rdoc
309
+ Define a task to be executed after each TeX run.
310
+
311
+ The task name is added to LaTeXRunner::Post_Prerequisites.
312
+ LaTeXRunner#run_latex_once will loop on all tasks in LaTeXRunner::Post_Prerequisites.
313
+ =end
314
+ def tex_postrule(*args, &block)
315
+ #~ rules = rule(*args, &block)
316
+ Rake::Task.create_rule(*args, &block) #@rules << [pattern, deps, block]
317
+ #
318
+ if args.size == 1 #normal rule without arguments
319
+ LaTeXRunner::Post_Prerequisites << args.first.keys.first
320
+ else #rule with arguments (args.last is a hash with :needs)
321
+ LaTeXRunner::Post_Prerequisites << args.first
322
+ end
323
+ end
324
+ =begin rdoc
325
+ Define a procedure to decide, if the post process should be
326
+ called.
327
+
328
+ The task name is added to LaTeXRunner::Post_Prerequisites_check.
329
+ LaTeXRunner#run_latex_once will loop on all tasks in LaTeXRunner::Post_Prerequisites_check.
330
+
331
+ The block will be called with a hash, the block must accept this one parameter.
332
+
333
+ Inside the block you have access to:
334
+ * :task: The task for which you test.
335
+ * :checksums: the checksums of the files before the TeX-run.
336
+ * :logger: the logger of the related task
337
+
338
+ The block must return false or the reason for a call (e.g. "testdocument.aux changed")
339
+
340
+ Example: See BibTeX-definition.
341
+ =end
342
+ def tex_postrule_check(rulename, &block)
343
+ raise "No block for postrule_check #{rulename}" unless block_given?
344
+ raise "Wrong number of arguments for postrule_check #{rulename}" unless block.arity == 1
345
+ LaTeXRunner::Post_Prerequisites_check[rulename] ||= [] << block
346
+ end
347
+
348
+ #
349
+ #Load the sub-files
350
+ #
351
+ require 'rake4latex/clean' #modified rake/clean
352
+ require 'rake4latex/latexrunner'
353
+ require 'rake4latex/latexdependencies'
354
+ require 'rake4latex/splitindex'
355
+ require 'rake4latex/rules'
356
+ require 'rake4latex/tex_statistic'
357
+ require 'rake4latex/template'
358
+
359
+
360
+ #Do some development tests
361
+ if $0 == __FILE__
362
+ #~ require 'yaml'
363
+ #~ puts LaTeXRunner.find_included_files( 'test/testdocument.tex' ).to_yaml
364
+
365
+ task :acroread => 'test/testdocument.pdf'
366
+ #~ task :default => :acroread
367
+
368
+ #~ app = Rake.application
369
+ #~ app[:default].invoke
370
+
371
+ #~ LaTeXRunner.new(
372
+ #~ :main_file => 'test/testdocument.tex',
373
+ #~ :maxruns => 1.0/0,
374
+ #~ :program => :latex,
375
+ #~ :dummy => nil
376
+ #~ )
377
+ end