rake4latex 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/{call_rake4latex.rb → bin/call_rake4latex.rb} +6 -3
- data/{readme_call_rake4latex.txt → bin/readme_call_rake4latex.txt} +0 -0
- data/lib/rake4latex.rb +106 -42
- data/lib/rake4latex/analyse_texfile.rb +375 -0
- data/lib/rake4latex/base.rb +40 -10
- data/lib/rake4latex/latexrunner.rb +20 -7
- data/lib/rake4latex/rake4latex.yaml +4 -0
- data/lib/rake4latex/rules.rb +59 -26
- data/lib/rake4latex/tex_statistic.rb +405 -375
- data/lib/rake4latex_dtx.rb +83 -0
- data/readme.html +150 -28
- data/readme.txt +118 -20
- data/test/_expected/bibtex_test_build_rakefile.txt +49 -0
- data/test/_expected/dtx_test.txt +12 -0
- data/test/_expected/dtx_test_sty.txt +2 -0
- data/test/_expected/error_test.txt +4 -0
- data/test/_expected/error_test_ignore_error.txt +5 -0
- data/test/_expected/error_test_overview.txt +16 -0
- data/test/_expected/error_test_statistic.txt +3 -0
- data/test/_expected/gloss_test_build_rakefile.txt +56 -0
- data/test/_expected/includes_test_build_rakefile.txt +55 -0
- data/test/_expected/{rail_test_error.txt → rail_error_test.txt} +0 -0
- data/test/_expected/splitindex_test_build_rakefile.txt +56 -0
- data/test/_expected/supertabular_test_statistic.txt +2 -29
- data/test/_expected/varioref_test.txt +6 -0
- data/test/_expected/varioref_test_ignore_error.txt +11 -0
- data/test/_expected/z_complex_test_overview.txt +62 -0
- data/test/_expected/z_complex_test_statistic.txt +9 -0
- data/test/bibtex/rakefile.rb +6 -0
- data/test/dtx/rakefile.rb +31 -0
- data/test/error/rakefile.rb +32 -0
- data/test/error/testdocument.tex +14 -0
- data/test/gloss/rakefile.rb +9 -1
- data/test/includes/rakefile.rb +6 -0
- data/test/rail/rakefile.rb +1 -5
- data/test/rail_error/rakefile.rb +38 -0
- data/test/{rail → rail_error}/testrail_error.tex +0 -0
- data/test/splitindex/rakefile.rb +8 -1
- data/test/supertabular/rakefile.rb +2 -2
- data/test/unittest_rake4latex.rb +61 -72
- data/test/unittest_rake4latex_testcases.rb +79 -0
- data/test/varioref/rakefile.rb +37 -0
- data/test/varioref/testdocument.tex +33 -0
- data/test/z_complex/rakefile.rb +3 -1
- metadata +42 -10
- data/lib/rake4latex/latexdependencies.rb +0 -105
- data/lib/rake4latex/template.rb +0 -60
data/lib/rake4latex/base.rb
CHANGED
@@ -9,8 +9,20 @@ require 'rake'
|
|
9
9
|
require 'md5'
|
10
10
|
require 'log4r' #1.0.5
|
11
11
|
|
12
|
+
module Rake
|
13
|
+
class Task
|
14
|
+
=begin rdoc
|
15
|
+
Define and get the related TeXRunner.
|
16
|
+
The value is set by Rake4LaTeX::LaTeXRunner#run_latex_once
|
17
|
+
and can be used by the tex_postrule.
|
18
|
+
=end
|
19
|
+
attr_accessor :texrunner
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
12
24
|
module Rake4LaTeX
|
13
|
-
VERSION = '0.1.
|
25
|
+
VERSION = '0.1.1'
|
14
26
|
|
15
27
|
#With this creation we define the constants Log4r::DEBUG...
|
16
28
|
Logger = Log4r::Logger.new("LaTeXRunner")
|
@@ -47,7 +59,11 @@ But with this method you get also a check if the option exists.
|
|
47
59
|
end
|
48
60
|
|
49
61
|
=begin rdoc
|
50
|
-
|
62
|
+
Definition of the programms and there call parameters.
|
63
|
+
|
64
|
+
There is a basic definition, you may redefine the values with your
|
65
|
+
local definitions.
|
66
|
+
You can define your local definition in a file 'rake4latex.yaml'.
|
51
67
|
|
52
68
|
Each program is a Hash:
|
53
69
|
program:
|
@@ -59,18 +75,22 @@ Each program is a Hash:
|
|
59
75
|
optional: flag, if the parameter is optional.
|
60
76
|
space_separated: between name and value is a space.
|
61
77
|
=end
|
78
|
+
Programms = {}
|
62
79
|
|
63
|
-
|
80
|
+
=begin rdoc
|
81
|
+
Load the Programs with parameters for Rake4LaTeX.build_cmd.
|
82
|
+
=end
|
64
83
|
[
|
65
84
|
"#{File.dirname(__FILE__)}/rake4latex.yaml",
|
66
85
|
#ocra-settings:
|
67
86
|
#a src\lib\rake4latex\rake4latex.yaml
|
68
87
|
#a lib\ruby\gems\1.8\gems\rake4latex-0.1.0\lib\rake4latex\base.rb
|
69
88
|
"#{File.dirname(__FILE__)}/../../../../../../../../src/lib/rake4latex/rake4latex.yaml", #for ocra-version (exe)
|
89
|
+
"./rake4latex.yaml", #local re-definition
|
70
90
|
].each{| setting_file |
|
71
91
|
if File.exist?(setting_file)
|
72
|
-
|
73
|
-
|
92
|
+
#Take the "more local" definition.
|
93
|
+
Programms.replace(YAML.load(File.read(setting_file)).merge(Programms))
|
74
94
|
end
|
75
95
|
}
|
76
96
|
if ! defined? Programms
|
@@ -86,9 +106,13 @@ Bases is the configuration in Programms.
|
|
86
106
|
'parameters' contains the parameters for the call.
|
87
107
|
The keys must fit to the settings in Rake4LaTeX::Programms .
|
88
108
|
=end
|
89
|
-
def self.build_cmd( programm, parameters = {} )
|
109
|
+
def self.build_cmd( programm, parameters = {}, task = nil )
|
90
110
|
|
91
|
-
|
111
|
+
if task #take the LaTeXRunner specific settings
|
112
|
+
configuration = task.texrunner.programms[programm]
|
113
|
+
else #take the global settings
|
114
|
+
configuration = Programms[programm]
|
115
|
+
end
|
92
116
|
if ! configuration
|
93
117
|
Rake4LaTeX::Logger.fatal( "No configuration for #{programm.inspect}") if Rake4LaTeX::Logger.fatal?
|
94
118
|
return false
|
@@ -122,7 +146,7 @@ only the help file for the selected basename is taken.
|
|
122
146
|
Helpfiles for splitindex are not added. You can do it manual:
|
123
147
|
CLEAN.add("testdocument-*") #splitidx-helpfiles
|
124
148
|
|
125
|
-
This method is called by task 'basename'
|
149
|
+
This method is called by task 'basename'.
|
126
150
|
=end
|
127
151
|
def self.set4clean( basename )
|
128
152
|
#fixme splitindex-dateien
|
@@ -136,12 +160,16 @@ This method is called by task 'basename'
|
|
136
160
|
CLEAN.include(file)
|
137
161
|
when /\.(ilg|idx|ind)\Z/ #Index-Files
|
138
162
|
CLEAN.include(file)
|
163
|
+
when /\.(glo|gls)\Z/ #Glossary-Files
|
164
|
+
CLEAN.include(file)
|
139
165
|
when /\.(blg|bbl)\Z/ #BibTeX-Files
|
140
166
|
CLEAN.include(file)
|
141
167
|
when /\.(rai|rao|RAO)\Z/ #Rail-Files
|
142
168
|
CLEAN.include(file)
|
143
169
|
when /\.(dvi|pdf|ps)\Z/
|
144
170
|
CLOBBER.include(file)
|
171
|
+
when /\.overview.txt\Z/ #rake4latex, task :log_overview
|
172
|
+
CLOBBER.include(file)
|
145
173
|
else
|
146
174
|
#~ @logger.warn("Unknown help file #{file}")
|
147
175
|
end
|
@@ -158,6 +186,8 @@ Define a task to be executed after each TeX run.
|
|
158
186
|
|
159
187
|
The task name is added to LaTeXRunner::Post_Prerequisites.
|
160
188
|
LaTeXRunner#run_latex_once will loop on all tasks in LaTeXRunner::Post_Prerequisites.
|
189
|
+
|
190
|
+
In the task definition you have access to the TeXRunner via Rake::Task#texrunner .
|
161
191
|
=end
|
162
192
|
def tex_postrule(*args, &block)
|
163
193
|
#~ rules = rule(*args, &block)
|
@@ -181,6 +211,7 @@ The block will be called with a hash, the block must accept this one parameter.
|
|
181
211
|
Inside the block you have access to:
|
182
212
|
* :task: The task for which you test.
|
183
213
|
* :checksums: the checksums of the files before the TeX-run.
|
214
|
+
* :texrunner: The actual TeXRunner, calling the pre-check.
|
184
215
|
* :logger: the logger of the related task
|
185
216
|
|
186
217
|
The block must return false or the reason for a call (e.g. "testdocument.aux changed")
|
@@ -198,8 +229,7 @@ end
|
|
198
229
|
#
|
199
230
|
require 'rake4latex/clean' #modified rake/clean
|
200
231
|
require 'rake4latex/latexrunner'
|
201
|
-
require 'rake4latex/
|
232
|
+
require 'rake4latex/analyse_texfile'
|
202
233
|
require 'rake4latex/splitindex'
|
203
234
|
require 'rake4latex/rules'
|
204
235
|
require 'rake4latex/tex_statistic'
|
205
|
-
require 'rake4latex/template'
|
@@ -1,5 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
1
|
module Rake4LaTeX
|
4
2
|
=begin rdoc
|
5
3
|
Class which encapsulates all the information needed to call latex
|
@@ -70,12 +68,17 @@ The settings contain the following values:
|
|
70
68
|
#~ @logger = Log4r::Logger.new("LaTeXRunner #{settings[:main_file]}")
|
71
69
|
#~ @logger.outputters = Log4r::StdoutOutputter.new('log_stdout')
|
72
70
|
|
71
|
+
#Copy the programms.
|
72
|
+
#This allows us to overwrite the program settings for a special LaTeXRunner.
|
73
|
+
@programms = Programms.dup
|
74
|
+
|
73
75
|
DEFAULT_SETTINGS.merge(settings).each{|key, value|
|
74
76
|
#~ puts "#{key}: #{value}"
|
75
77
|
case key
|
76
78
|
when :main_file; @main_file = value
|
77
79
|
when :maxruns; @maxruns = value
|
78
80
|
when :program; self.program = value
|
81
|
+
when :programms; @programms.merge!(value)
|
79
82
|
when :options; @options = value
|
80
83
|
when :loglevel; @logger.level = value
|
81
84
|
when :texerrors_allowed; @texerrors_allowed = value
|
@@ -121,9 +124,12 @@ The settings contain the following values:
|
|
121
124
|
# The full path of the input directory. It is determined automatically during initialization
|
122
125
|
attr_reader :full_input_dir
|
123
126
|
|
124
|
-
# The
|
127
|
+
# The logger for the LaTeX-Run.
|
125
128
|
attr_reader :logger
|
126
129
|
|
130
|
+
# Hash with Programm settings. by default Rake4LaTeX::Programms.
|
131
|
+
attr_reader :programms
|
132
|
+
|
127
133
|
# Flag if TeX should be started again.
|
128
134
|
def rerun_necessary?()
|
129
135
|
@rerun_necessary and ( maxruns > @texruns )
|
@@ -158,7 +164,7 @@ The settings contain the following values:
|
|
158
164
|
run_latex_once(cmd)
|
159
165
|
end
|
160
166
|
end
|
161
|
-
#Guarentee that help files are deleted
|
167
|
+
#Guarentee that help files are deleted in clean.
|
162
168
|
Rake4LaTeX.set4clean( @basename )
|
163
169
|
|
164
170
|
plural_s = "#{@texruns} run#{@texruns>1 ? 's': ''}"
|
@@ -188,8 +194,10 @@ The settings contain the following values:
|
|
188
194
|
latex_output = `#{cmd}`
|
189
195
|
if $? != 0
|
190
196
|
@logger.fatal("There where #@program errors. See #{@main_file.ext('.log')} for details")
|
191
|
-
|
192
|
-
|
197
|
+
#~ @logger.fatal("Errors: #{TeX_Statistic.new(@main_file.ext('.log')).stat[@main_file.ext('.log')][:latex_errors].inspect}")
|
198
|
+
#~ raise RuntimeError, "There where #@program errors. "\
|
199
|
+
#~ "See #{@main_file.ext('.log')} for details" unless @texerrors_allowed
|
200
|
+
exit unless @texerrors_allowed
|
193
201
|
end
|
194
202
|
|
195
203
|
helpfiles = %w{aux toc lof lot}
|
@@ -247,6 +255,8 @@ The settings contain the following values:
|
|
247
255
|
next
|
248
256
|
end
|
249
257
|
|
258
|
+
post_prereq.texrunner = self #Set the connection to the TeXRunner
|
259
|
+
|
250
260
|
#Starts only, if prerequisites of post_prereq exist and was regenerated by TeX.
|
251
261
|
#Here we make an additional check if we need the post_prereq.
|
252
262
|
post_prereq.prerequisites.each{|post_prereq_pre|
|
@@ -256,7 +266,10 @@ The settings contain the following values:
|
|
256
266
|
@logger.debug("Make precheck for #{pre}" )
|
257
267
|
Post_Prerequisites_check[pre].each{|precheck|
|
258
268
|
#Call the pre-check with the task...
|
259
|
-
reason4call = precheck.call(:task => post_prereq,
|
269
|
+
reason4call = precheck.call( :task => post_prereq,
|
270
|
+
:checksums => checksums,
|
271
|
+
:texrunner => self,
|
272
|
+
:logger => @logger)
|
260
273
|
break if reason4call #we need only one reason to start the task.
|
261
274
|
}
|
262
275
|
else #make the standard check (
|
@@ -20,16 +20,20 @@ latex:
|
|
20
20
|
- value_key: :filename
|
21
21
|
makeindex:
|
22
22
|
cmd: makeindex
|
23
|
+
comment: makeindex -s style.ist -t base.glg -o base.gls base.glo
|
23
24
|
parameters:
|
24
25
|
- name: -s
|
25
26
|
value_key: :format
|
26
27
|
optional: true
|
28
|
+
space_separated: true
|
27
29
|
- name: -o
|
28
30
|
value_key: :file_out
|
29
31
|
optional: true
|
32
|
+
space_separated: true
|
30
33
|
- name: -t
|
31
34
|
value_key: :file_log
|
32
35
|
optional: true
|
36
|
+
space_separated: true
|
33
37
|
- value_key: :file_in
|
34
38
|
pdflatex:
|
35
39
|
cmd: pdflatex
|
data/lib/rake4latex/rules.rb
CHANGED
@@ -51,21 +51,51 @@ task :basefile do |task|
|
|
51
51
|
end
|
52
52
|
task :default => :basefile
|
53
53
|
|
54
|
+
desc "Build a log-overview file"
|
55
|
+
task :log_overview => :basefile do
|
56
|
+
Rake.application[:statistic].prerequisites.each{|pre|
|
57
|
+
next if pre == 'basefile' #exclude task :basefile
|
58
|
+
stat = Rake4LaTeX::TeX_Statistic.new(pre)
|
59
|
+
#Filename also used in set4clean
|
60
|
+
File.open("#{pre.ext()}.overview.txt", 'w'){|f|
|
61
|
+
f << stat.overview()
|
62
|
+
}
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
desc "Archive all log-files to zip-file"
|
67
|
+
task :log_archive => :basefile do
|
68
|
+
require 'zip/zipfilesystem'
|
69
|
+
Zip::ZipFile.open("rake4latex_log_archive.zip", Zip::ZipFile::CREATE ){|zip|
|
70
|
+
puts "Pack #{zip.name}"
|
71
|
+
#Store all Files to be deleted
|
72
|
+
CLEAN.each{|filename|
|
73
|
+
zip.file.open(File.basename(filename), 'w'){|f| f << File.open(filename,"rb") {|io| io.read} }
|
74
|
+
}
|
75
|
+
Rake.application[:statistic].prerequisites.each{|pre|
|
76
|
+
next if pre == 'basefile' #exclude task :basefile
|
77
|
+
stat = Rake4LaTeX::TeX_Statistic.new(pre)
|
78
|
+
zip.file.open("#{pre}.overview.txt", 'w'){|f|
|
79
|
+
f << stat.overview()
|
80
|
+
}
|
81
|
+
}
|
82
|
+
} #close zip-file
|
83
|
+
end
|
54
84
|
|
55
85
|
#
|
56
86
|
#Reset the timestamp of a file (can be used to force the first compilation)
|
57
87
|
#
|
58
88
|
desc "Touch - reset timestamp"
|
59
|
-
task :touch do |
|
60
|
-
|
89
|
+
task :touch do |task|
|
90
|
+
task.prerequisites.each{|pre|
|
61
91
|
FileUtils.touch(pre)
|
62
92
|
}
|
63
93
|
end
|
64
94
|
|
65
95
|
desc "Build a dvi-file with LaTeX"
|
66
|
-
rule '.dvi' => '.tex' do |
|
96
|
+
rule '.dvi' => '.tex' do |task|
|
67
97
|
runner = Rake4LaTeX::LaTeXRunner.new(
|
68
|
-
:main_file =>
|
98
|
+
:main_file => task.source,
|
69
99
|
:program => :latex,
|
70
100
|
:dummy => nil
|
71
101
|
)
|
@@ -73,9 +103,9 @@ rule '.dvi' => '.tex' do |t|
|
|
73
103
|
end
|
74
104
|
|
75
105
|
desc "Build a ps-file from dvi"
|
76
|
-
rule '.ps' => '.dvi' do |
|
77
|
-
Rake4LaTeX::Logger.info("Call dvips for <#{
|
78
|
-
cmd = Rake4LaTeX.build_cmd( 'dvips', :filename =>
|
106
|
+
rule '.ps' => '.dvi' do |task|
|
107
|
+
Rake4LaTeX::Logger.info("Call dvips for <#{task.source}>")
|
108
|
+
cmd = Rake4LaTeX.build_cmd( 'dvips', :filename => task.source )
|
79
109
|
|
80
110
|
stdout, stderr = catch_screen_output{
|
81
111
|
sh cmd
|
@@ -90,12 +120,13 @@ end
|
|
90
120
|
|
91
121
|
|
92
122
|
desc "Call Makeindex"
|
93
|
-
tex_postrule '.ind' => '.idx' do |
|
123
|
+
tex_postrule '.ind' => '.idx' do |task|
|
94
124
|
#check for splitidx
|
95
|
-
splitidx = Rake4LaTeX::Splitindex.new(
|
125
|
+
splitidx = Rake4LaTeX::Splitindex.new(task.source, Rake4LaTeX::Logger)
|
96
126
|
if splitidx.makeindex? #standard index, no splitidx
|
97
127
|
#makeindex writes to stderr -> catch it
|
98
|
-
cmd = Rake4LaTeX.build_cmd( 'makeindex', :file_in =>
|
128
|
+
cmd = Rake4LaTeX.build_cmd( 'makeindex', { :file_in => task.source }, task )
|
129
|
+
task.texrunner.logger.debug("\t#{cmd}")
|
99
130
|
stdout, stderr = catch_screen_output{
|
100
131
|
sh cmd
|
101
132
|
}
|
@@ -150,57 +181,59 @@ tex_postrule_check '.bbl' do |args|
|
|
150
181
|
end
|
151
182
|
|
152
183
|
#Define the rule
|
153
|
-
tex_postrule '.bbl' => '.aux' do |
|
154
|
-
cmd = Rake4LaTeX.build_cmd( 'bibtex', :source =>
|
184
|
+
tex_postrule '.bbl' => '.aux' do |task|
|
185
|
+
cmd = Rake4LaTeX.build_cmd( 'bibtex', {:source => task.source}, task )
|
186
|
+
task.texrunner.logger.debug("Call bibTeX: #{cmd}")
|
155
187
|
stdout, stderr = catch_screen_output{
|
156
188
|
puts `#{cmd}`
|
157
189
|
}
|
158
190
|
if $? != 0
|
159
|
-
|
191
|
+
task.texrunner.logger.fatal("There where BibTeX errors. \n#{stdout}")
|
160
192
|
end
|
161
193
|
end
|
162
194
|
|
163
195
|
#Support for rail
|
164
196
|
#http://www.ctan.org/tex-archive/support/rail/
|
165
197
|
desc "Call Rail"
|
166
|
-
tex_postrule '.rao' => '.rai' do |
|
198
|
+
tex_postrule '.rao' => '.rai' do |task|
|
167
199
|
#Rail works only with filenames with 8 characters.
|
168
200
|
#So we use stdin.
|
169
|
-
cmd = Rake4LaTeX.build_cmd( 'rail', :railfile =>
|
170
|
-
|
201
|
+
cmd = Rake4LaTeX.build_cmd( 'rail', :railfile => task.source )
|
202
|
+
task.texrunner.logger.debug("Call rail: #{cmd}")
|
171
203
|
stdout, stderr = catch_screen_output{
|
172
204
|
puts `#{cmd}`
|
173
205
|
}
|
174
206
|
error = false
|
175
207
|
if $? != 0
|
176
|
-
|
208
|
+
task.texrunner.logger.fatal("There where Rail errors.")
|
177
209
|
error = true
|
178
210
|
end
|
179
211
|
stderr.each{|errline|
|
180
|
-
|
212
|
+
task.texrunner.logger.error("Rail error: #{errline.strip}")
|
181
213
|
error = true
|
182
214
|
}
|
183
215
|
if error
|
184
|
-
|
216
|
+
task.texrunner.logger.warn("No rail diagramms generated")
|
185
217
|
else
|
186
218
|
#Now we have to save the result and delete some stuff.
|
187
219
|
stdout.sub!(/^(This is Rail.*)/, '%\1') #%This is Rail, Version 1.1 #0
|
188
220
|
stdout.sub!(/^(\(stdin.*)/, '%\1')
|
189
221
|
stdout.sub!(/^\)/, '%\1)') #last line
|
190
|
-
File.open(
|
222
|
+
File.open(task.source.ext('rao'), 'w'){|f| f << stdout }
|
191
223
|
end
|
224
|
+
CLEAN.include(task.source)
|
225
|
+
CLEAN.include(task.name)
|
192
226
|
end
|
193
227
|
|
194
228
|
|
195
|
-
|
196
|
-
|
197
229
|
desc "Build a statistic for TeX project"
|
198
|
-
task :statistic => :basefile do |
|
199
|
-
|
200
|
-
t.prerequisites.each{|pre|
|
230
|
+
task :statistic => :basefile do |task|
|
231
|
+
task.prerequisites.each{|pre|
|
201
232
|
next if pre == 'basefile' #exclude task :basefile
|
202
233
|
stat = Rake4LaTeX::TeX_Statistic.new(pre)
|
203
|
-
puts
|
234
|
+
puts "Statistic for #{pre}:"
|
235
|
+
puts stat.stat_summary.map{|e| " #{e}"}
|
236
|
+
#~ puts stat
|
204
237
|
}
|
205
238
|
end
|
206
239
|
|
@@ -7,11 +7,92 @@ begin
|
|
7
7
|
rescue LoadError
|
8
8
|
require 'yaml'
|
9
9
|
end
|
10
|
+
|
11
|
+
=begin fixmes
|
12
|
+
under/overfull:
|
13
|
+
* Grouping
|
14
|
+
* Grenzwert
|
15
|
+
|
16
|
+
Filesplit verbessern (testcase equal_log_analyse)
|
17
|
+
=end
|
18
|
+
|
19
|
+
|
10
20
|
module Rake4LaTeX
|
21
|
+
=begin
|
22
|
+
Informations about one TeX-Message
|
23
|
+
=end
|
24
|
+
class TeXMessage
|
25
|
+
#List of supported message types.
|
26
|
+
TYPES = [
|
27
|
+
:latex_errors,
|
28
|
+
:latex_warnings,
|
29
|
+
:package_errors,
|
30
|
+
:package_warnings,
|
31
|
+
:warnings,
|
32
|
+
:output, :source_information, #for statistic
|
33
|
+
:overfull_boxes, :underfull_boxes,
|
34
|
+
]
|
35
|
+
@@seq = 0
|
36
|
+
=begin rdoc
|
37
|
+
Define a new TeX-Message.
|
38
|
+
|
39
|
+
line: Source code line of the tex-file, where the message was created.
|
40
|
+
No number, may be something line '621-625'.
|
41
|
+
=end
|
42
|
+
def initialize(type, logline, message, details = {}, page = nil, source = nil, line = nil)
|
43
|
+
@type = type
|
44
|
+
#~ Rake4LaTeX::Logger.error("undefined TeX-message type #{@type.inspect}") if ! TYPES.include?(@type)
|
45
|
+
@message = message
|
46
|
+
@details = details
|
47
|
+
@page = page
|
48
|
+
@source = source
|
49
|
+
@line = line
|
50
|
+
@logline = logline
|
51
|
+
@nextlines = []
|
52
|
+
end
|
53
|
+
#Type of the message
|
54
|
+
#* Error
|
55
|
+
#* Warning
|
56
|
+
#* ...
|
57
|
+
attr_reader :type
|
58
|
+
#Message text of the message
|
59
|
+
attr_reader :message
|
60
|
+
#Hash with details for the message (special informations...)
|
61
|
+
attr_reader :details
|
62
|
+
#Next page in the generated document.
|
63
|
+
#The previous page should be the location, where the effect of the error should be visible.
|
64
|
+
attr_reader :page
|
65
|
+
#TeX-Sourcefile. Place, where the error should be corrected.
|
66
|
+
attr_reader :source
|
67
|
+
#Line in the TeX-Sourcefile. Place, where the error should be corrected.
|
68
|
+
#No number, may be something line '621-625'.
|
69
|
+
attr_accessor :line
|
70
|
+
#Line in the log line
|
71
|
+
attr_reader :logline
|
72
|
+
#Sort by line of occurence in the log.
|
73
|
+
def <=> ( mess )
|
74
|
+
@logline <=> mess.logline
|
75
|
+
end
|
76
|
+
#collect additional lines for the message.
|
77
|
+
attr_reader :nextlines
|
78
|
+
#Add the following line(s) to the message
|
79
|
+
def << (logline)
|
80
|
+
@nextlines << logline
|
81
|
+
end
|
82
|
+
end #TeXMessage
|
83
|
+
|
84
|
+
=begin rdoc
|
85
|
+
Get an overview on status of a generated TeX-Project.
|
86
|
+
* Analoyse log for
|
87
|
+
*LaTeX
|
88
|
+
*BibTeX if used
|
89
|
+
*makeindex if used
|
90
|
+
=end
|
11
91
|
class TeX_Statistic
|
12
92
|
#Define the main file for the log-analyse.
|
13
93
|
def initialize( filename )
|
14
94
|
@stat = {}
|
95
|
+
@texmessages = []
|
15
96
|
|
16
97
|
@texfile = filename.ext('tex')
|
17
98
|
if ! File.exist?(@texfile)
|
@@ -21,10 +102,10 @@ class TeX_Statistic
|
|
21
102
|
|
22
103
|
#Analyse TeX-log
|
23
104
|
if File.exist?(@texfile.ext('log'))
|
24
|
-
@
|
105
|
+
@texmessages = log_analyse_content( File.read(@texfile.ext('log')),nil,nil)
|
106
|
+
@stat[@texfile.ext('log')] = texmessages2hash(:messages => @texmessages) #option , :page_info ??
|
25
107
|
else
|
26
|
-
@stat['
|
27
|
-
@stat['_'][:log] = "No log-file #{File.read(@texfile.ext('log'))} found"
|
108
|
+
@stat[@texfile.ext('log')] ||= [ "No log-file #{@texfile.ext('log')} found" ]
|
28
109
|
end #File.exist?(@texfile.ext('log'))
|
29
110
|
|
30
111
|
#Analyse BibTeX-log
|
@@ -39,225 +120,229 @@ class TeX_Statistic
|
|
39
120
|
}
|
40
121
|
|
41
122
|
end
|
42
|
-
#
|
123
|
+
#Hash with a status overview on the logs of the TeX-project.
|
43
124
|
attr_reader :stat
|
44
|
-
#
|
45
|
-
|
46
|
-
|
47
|
-
#
|
48
|
-
#
|
49
|
-
|
125
|
+
#Array with TeXMessage-object. Contains messages of the TeX-log.
|
126
|
+
attr_reader :texmessages
|
127
|
+
|
128
|
+
#Regexp to detect new pages in result file.
|
129
|
+
#New pages looks like "[1.1\n" or [9.9]
|
130
|
+
PAGE_PATTERN = /^\[(\d+\.\d+)[\]\s]/
|
131
|
+
#Container for some data
|
132
|
+
#* count: numbers of open ( in file, needed to detect end of file
|
133
|
+
#* logcontent: Extract of the log-file, contains only the parts for the actual source file
|
134
|
+
#* logstart: Line in log-file
|
135
|
+
FILEDATA_STRUCT = Struct.new('FILEDATA', :name, :startpage, :logstart, :count, :logcontent )
|
136
|
+
|
137
|
+
=begin rdoc
|
138
|
+
Analyse the TeX-log file.
|
139
|
+
|
140
|
+
The log-text is splitted into files and pages and analysed separatly.
|
141
|
+
|
142
|
+
----TESTVERSION----
|
143
|
+
Errors:
|
144
|
+
Somewhere is an offset 4 loglines
|
145
|
+
=end
|
146
|
+
def log_analyse_by_file(logfilename)
|
50
147
|
log = File.read(logfilename)
|
51
148
|
stat = {}
|
149
|
+
texmessages = []
|
150
|
+
|
52
151
|
|
53
152
|
#Analyse log for page and source file
|
54
153
|
page = nil #store the actual page
|
55
154
|
file = nil #store the actual file
|
56
155
|
filestack = [] #
|
57
|
-
|
58
|
-
|
156
|
+
filelist = { nil => FILEDATA_STRUCT.new(nil, 0, 0, 1, '' ) }
|
157
|
+
logline = 0
|
158
|
+
#~ filecount = Hash.new(0) #numbers of open ( in file, needed to detect end of file
|
159
|
+
#~ filestartpage = {} #Page, where the source is started.
|
160
|
+
#~ filecontent = {nil => ''}#content of a file. The content of sub-includes are not part of this content.
|
59
161
|
|
60
|
-
#New pages looks like "[1.1\n" or [9.9]
|
61
|
-
page_pattern = /^\[(\d+\.\d+)[\]\s]/
|
62
162
|
# inputs looks like "(./filename_en.toc \n" or "(./filename.lot)"
|
63
|
-
file_pattern =
|
163
|
+
file_pattern = %r{\((?:\.|c:)\/.*?[\)\n]}
|
64
164
|
|
65
165
|
#Splitt at the file- and page-patterns and at ( and )
|
66
166
|
#If the ( ) are balanced, then we can detect a file end with )
|
67
167
|
#
|
68
|
-
log.split(/(#{file_pattern}|\(|\)|#{
|
168
|
+
log.split(/(#{file_pattern}|\(|\)|#{PAGE_PATTERN})/ ).each{|x|
|
169
|
+
logline += x.count("\n")
|
69
170
|
case x #x[0]
|
70
171
|
when file_pattern
|
71
172
|
if x[-1,1] == ')'
|
72
173
|
#~ puts "open and close #{file} on page #{page} #{filestack.inspect}" if file =~ /^\./
|
174
|
+
filelist[file].logcontent << x
|
73
175
|
else
|
176
|
+
filelist[file].logcontent << x
|
74
177
|
file = x.strip.sub(/\(/,'')
|
75
178
|
filestack << file
|
76
|
-
|
77
|
-
filecontent[file] = ''
|
179
|
+
filelist[file] = FILEDATA_STRUCT.new(file, page, logline, 1, '' )
|
78
180
|
#~ puts "open #{file} on page #{page} #{filestack.inspect}" if file =~ /^\./
|
79
181
|
end
|
80
|
-
when
|
182
|
+
when PAGE_PATTERN
|
81
183
|
page = $1
|
184
|
+
#~ if x =~ /76/
|
185
|
+
#~ puts x.inspect
|
186
|
+
#~ puts page.inspect
|
187
|
+
#~ puts logline
|
188
|
+
#~ puts file
|
189
|
+
#~ end
|
190
|
+
filelist[file].logcontent << x
|
191
|
+
#Add page to all open log collection.
|
192
|
+
#Without this, we would ignore all pages between the insertion of an include.
|
193
|
+
filelist.each{| name, filedata | filedata.logcontent << "\n#{x} ##ADDED to log #{logline + 1}##\n" }
|
82
194
|
when '('
|
83
|
-
|
84
|
-
|
85
|
-
when ')'
|
86
|
-
|
87
|
-
if
|
195
|
+
filelist[file].count+= 1
|
196
|
+
filelist[file].logcontent << x
|
197
|
+
when ')'
|
198
|
+
filelist[file].count = filelist[file].count - 1
|
199
|
+
if filelist[file].count == 0
|
88
200
|
filestack.pop
|
89
201
|
#~ puts "close #{file} on page #{page} #{filestack.inspect}" if file =~ /^\./
|
90
|
-
|
202
|
+
texmessages.concat(log_analyse_content(filelist[file].logcontent, filelist[file].name, filelist[file].startpage, filelist[file].logstart ))
|
91
203
|
if ! stat.empty?
|
92
204
|
#hier stats sammeln (je vor/hinter input gab es meldungen)
|
93
|
-
puts '============'
|
94
|
-
puts file
|
95
|
-
puts stat.to_yaml
|
205
|
+
#~ puts '============'
|
206
|
+
#~ puts file
|
207
|
+
#~ puts stat.to_yaml
|
96
208
|
end
|
97
209
|
#~ filecontent.delete(file)
|
98
|
-
|
210
|
+
filelist[file].logcontent = ''
|
99
211
|
file = filestack.last
|
100
212
|
else
|
101
|
-
|
213
|
+
filelist[file].logcontent << x
|
102
214
|
end
|
103
215
|
else
|
104
|
-
|
216
|
+
filelist[file].logcontent << x
|
105
217
|
end
|
106
218
|
#~ puts "%6s : %s" % [page, file ]
|
107
219
|
}
|
108
|
-
|
220
|
+
#Get unclear messages (top file?)
|
221
|
+
texmessages.concat(log_analyse_content(filelist[nil].logcontent, filelist[nil].name, filelist[nil].startpage, filelist[nil].logstart ))
|
222
|
+
#~ puts filestack.inspect
|
223
|
+
texmessages
|
109
224
|
end
|
225
|
+
=begin rdoc
|
226
|
+
Analyse the content of an extract of the TeX-log file and
|
227
|
+
collect the messages as TeXMessage-objects.
|
110
228
|
|
111
|
-
|
112
|
-
|
113
|
-
def log_analyse_content(log, file,
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
log.each{|logline|
|
121
|
-
logline.strip!
|
122
|
-
case logline
|
123
|
-
when /Package (.*) Error: (.*)/
|
124
|
-
stat[:package_error] ||= {}
|
125
|
-
stat[:package_error][$1] ||= [] << $2
|
126
|
-
stat[:package_error][$1].last << filepage
|
127
|
-
when /LaTeX Error:\s*(.*)/
|
128
|
-
( stat[:latex_error] ||= [] ) << $1
|
129
|
-
stat[:latex_error].last << filepage
|
130
|
-
when /Error:/
|
131
|
-
(stat[:error] ||= [] ) << logline
|
132
|
-
stat[:error].last << filepage
|
133
|
-
#~ puts "!#{logline}"
|
134
|
-
when /Package (.*) Warning: (.*)/
|
135
|
-
stat[:package_warning] ||= {}
|
136
|
-
stat[:package_warning][$1] ||= [] << $2
|
137
|
-
stat[:package_warning][$1].last << filepage
|
138
|
-
when /LaTeX Warning:\s*(.*)/
|
139
|
-
(stat[:latex_warning] ||= [] ) << $1
|
140
|
-
stat[:latex_warning].last << filepage
|
141
|
-
when /Warning/
|
142
|
-
#~ puts "!#{logline}"
|
143
|
-
(stat[:warnings] ||= [] ) << logline
|
144
|
-
stat[:warnings].last << filepage
|
145
|
-
#~ when /Package (.*) Info: (.*)/ #A lot of messages
|
146
|
-
#~ stat[:package_info] ||= {}
|
147
|
-
#~ stat[:package_info][$1] ||= [] << $2
|
148
|
-
when /Output written on (.*) \((\d*) pages, (\d*) bytes\)/
|
149
|
-
raise "Double output in #{logfilename}" if stat[:output]
|
150
|
-
stat[:output] = {
|
151
|
-
:name => $1, :pages => $2, :bytes => $3,
|
152
|
-
:kbytes => ($3.to_i / 1024 )
|
153
|
-
}
|
154
|
-
when /Overfull \\hbox \((.*) too wide\) in paragraph at lines (.*)/
|
155
|
-
( stat[:overfull] ||= [] ) << "#{$1} at lines #{$2}"
|
156
|
-
stat[:overfull].last << filepage
|
157
|
-
#~ next if $1.to_i() < @options[:overfull]
|
158
|
-
#~ stat[:overfull] ||= [] << last_message = "#{$1} at lines #{$2}"
|
159
|
-
#~ get_next_lines = 1 #?test
|
160
|
-
when /Underfull (.*box) \(badness (.*)\) (detected|in paragraph) at lines? (.*)/
|
161
|
-
#~ next if $1.to_i() < @options[:underfull]
|
162
|
-
( stat[:underfull] ||= [] )<< last_message = "badness #{$2} at lines #{$4}"
|
163
|
-
stat[:underfull].last << filepage
|
164
|
-
#~ get_next_lines = 1 #?test
|
165
|
-
else
|
166
|
-
#~ puts " #{logline}"
|
167
|
-
end
|
168
|
-
}
|
169
|
-
stat
|
170
|
-
end #log_analyse
|
171
|
-
|
172
|
-
|
173
|
-
#Analyse the content of a TeX-log file.
|
174
|
-
#
|
175
|
-
def log_analyse(log)
|
176
|
-
stat = {}
|
177
|
-
|
178
|
-
log.each{|logline|
|
229
|
+
file, startpage and logstart are only needed for the splitted analyse to get the initial values.
|
230
|
+
=end
|
231
|
+
def log_analyse_content(log, file, startpage, logstart = 0)
|
232
|
+
page = startpage
|
233
|
+
messages =[]
|
234
|
+
linecorrection = logstart + 1
|
235
|
+
get_next_lines = nil
|
236
|
+
log.each_with_index{|logline, loc_lineno|
|
179
237
|
logline.strip!
|
238
|
+
#Check if the message is continued on next line
|
239
|
+
case get_next_lines
|
240
|
+
when Numeric #Counter to add the next x lines to the previous message
|
241
|
+
messages.last << logline
|
242
|
+
if get_next_lines ==1
|
243
|
+
get_next_lines = nil
|
244
|
+
else
|
245
|
+
get_next_lines = get_next_lines - 1
|
246
|
+
end
|
247
|
+
next
|
248
|
+
when Regexp
|
249
|
+
if logline =~ get_next_lines
|
250
|
+
messages.last << $~.post_match
|
251
|
+
messages.last.line = $1 if logline =~ /on input line (\d+)/
|
252
|
+
next
|
253
|
+
else
|
254
|
+
get_next_lines = nil
|
255
|
+
end
|
256
|
+
end
|
257
|
+
lineno = loc_lineno + linecorrection
|
180
258
|
case logline
|
259
|
+
when PAGE_PATTERN
|
260
|
+
page = $1
|
261
|
+
if logline =~ /##ADDED to log (\d+)##/
|
262
|
+
linecorrection = $1.to_i - loc_lineno - 1 #resync the log line number
|
263
|
+
end
|
181
264
|
when /Package (.*) Error: (.*)/
|
182
|
-
|
183
|
-
stat[:package_error][$1] ||= [] << $2
|
265
|
+
messages << TeXMessage.new(:package_errors, lineno, $2, {:package => $1 }, page, file)
|
184
266
|
when /LaTeX Error:\s*(.*)/
|
185
|
-
(
|
267
|
+
messages << TeXMessage.new(:latex_errors, lineno, $1, {}, page, file)
|
186
268
|
when /Error:/
|
187
|
-
(
|
188
|
-
#~ puts "!#{logline}"
|
269
|
+
messages << TeXMessage.new(:error, lineno, logline, {}, page, file)
|
189
270
|
when /Package (.*) Warning: (.*)/
|
190
|
-
|
191
|
-
|
271
|
+
get_next_lines = /\(#{$1}\)\s*/
|
272
|
+
messages << TeXMessage.new(:package_warnings, lineno, $2, {:package => $1 }, page, file)
|
192
273
|
when /LaTeX Warning:\s*(.*)/
|
193
|
-
(
|
274
|
+
messages << TeXMessage.new(:latex_warnings, lineno, $1, {}, page, file)
|
194
275
|
when /Warning/
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
#~ stat[:package_info] ||= {}
|
199
|
-
#~ stat[:package_info][$1] ||= [] << $2
|
276
|
+
messages << TeXMessage.new(:warnings, lineno, logline, {}, page, file)
|
277
|
+
when /Package (.*) Info: (.*)/ #A lot of messages
|
278
|
+
messages << TeXMessage.new(:package_info, lineno, $2, {:package => $1 }, page, file)
|
200
279
|
when /Output written on (.*) \((\d*) pages, (\d*) bytes\)/
|
201
280
|
raise "Double output in #{logfilename}" if stat[:output]
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
}
|
281
|
+
messages << TeXMessage.new(:output, lineno, logline, {
|
282
|
+
:name => $1, :pages => $2, :bytes => $3, :kbytes => ($3.to_i / 1024 )},
|
283
|
+
page, file)
|
206
284
|
when /Overfull \\hbox \((.*) too wide\) in paragraph at lines (.*)/
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
#~ get_next_lines = 1 #?test
|
285
|
+
#~ messages << TeXMessage.new(:overfull_boxes, lineno, "#{$1} at lines #{$2}", {:wide => $1.to_i }, page, file, $2)
|
286
|
+
messages << TeXMessage.new(:overfull_boxes, lineno, logline, {:wide => $1.to_i }, page, file, $2)
|
287
|
+
get_next_lines = 1
|
211
288
|
when /Underfull (.*box) \(badness (.*)\) (detected|in paragraph) at lines? (.*)/
|
212
|
-
#~
|
213
|
-
(
|
214
|
-
|
289
|
+
#~ messages << TeXMessage.new(:underfull_boxes, lineno, "badness #{$2} at lines #{$4}", {:badness => $2.to_i }, page, file, $4)
|
290
|
+
messages << TeXMessage.new(:underfull_boxes, lineno, logline, {:badness => $2.to_i }, page, file, $4)
|
291
|
+
get_next_lines = 1 #oder bis / []/
|
292
|
+
#fixme...
|
293
|
+
when /^!\s*(.*)/ #Undefined control sequence.
|
294
|
+
messages << TeXMessage.new(:latex_errors, lineno, $1, {}, page, file)
|
215
295
|
else
|
216
296
|
#~ puts " #{logline}"
|
217
297
|
end
|
218
298
|
}
|
219
|
-
|
299
|
+
messages
|
220
300
|
end #log_analyse
|
221
|
-
|
301
|
+
|
302
|
+
=begin rdoc
|
303
|
+
Analyse a bibTeX-log.
|
304
|
+
=end
|
222
305
|
def blg_analyse(logfilename)
|
223
306
|
stat = {}
|
224
307
|
File.readlines(logfilename).each{ |logline|
|
225
308
|
case logline
|
226
309
|
when /Database file #(.*): (.*)/
|
227
|
-
stat[:
|
310
|
+
stat[:source_information] ||= [] << "Database file #{$2} used"
|
228
311
|
when /Warning--I didn't find a database entry for "(.*)"/
|
229
|
-
stat[:
|
312
|
+
( stat[:warnings] ||= [] ) << "Databaseentry #{$1} missing"
|
230
313
|
when /Warning--Empty definition in (.*)/
|
231
|
-
stat[:
|
314
|
+
( stat[:warnings] ||= [] ) << "Empty definition #{$1}"
|
232
315
|
when /Warning--(.*)/
|
233
|
-
stat[:
|
316
|
+
( stat[:warnings] ||= [] ) << "#{$1}"
|
234
317
|
when /I couldn't open (.*) file (.*)/
|
235
|
-
stat[:
|
318
|
+
( stat[:errors] ||= [] ) << "#{$1} #{$2} not found"
|
236
319
|
when /I found no (.*) commands---while reading file(.*)/
|
237
|
-
stat[:
|
320
|
+
( stat[:warnings] ||= [] ) << "found no #{$1} in #{$2}"
|
238
321
|
when /(.*)---line (.*) of file(.*)/
|
239
322
|
#line-number ist unsinnig
|
240
|
-
stat[:
|
323
|
+
( stat[:errors] ||= [] ) << "#{$1} in #{$3}"
|
241
324
|
end
|
242
325
|
}
|
243
326
|
stat
|
244
|
-
end #
|
245
|
-
|
327
|
+
end #blg_analyse
|
328
|
+
=begin rdoc
|
329
|
+
Analyse the makeindex-log.
|
330
|
+
=end
|
246
331
|
def ilg_analyse(logfilename)
|
247
332
|
stat = {}
|
248
333
|
error = nil
|
249
334
|
File.readlines(logfilename).each{ |logline|
|
250
335
|
if error #Index error announced in previous line
|
251
|
-
stat[:
|
336
|
+
( stat[:errors] ||= [] ) << "#{logline.chomp.sub(/.*--/, "")} #{error}"
|
252
337
|
error = nil
|
253
338
|
else
|
254
339
|
case logline
|
255
340
|
when /Scanning input file (.*)\...done \((.*) entries accepted, (.*) rejected\)./
|
256
|
-
#~ stat[:
|
257
|
-
stat[:
|
258
|
-
stat[:
|
259
|
-
stat[:
|
260
|
-
stat[:
|
341
|
+
#~ stat[:source_information] ||= [] << "input file #{$1} (#{$2} entries accepted, #{$3} rejected)"
|
342
|
+
stat[:source_information] ||= []
|
343
|
+
stat[:source_information] << "Input file: #{$1}"
|
344
|
+
stat[:source_information] << "Entries accepted: #{$2}"
|
345
|
+
stat[:source_information] << "Entries rejected: #{$3}"
|
261
346
|
#~ when /done \((.*) entries accepted, (.*) rejected\)./
|
262
347
|
#~ result[:rejected] += $2.to_i() if $2.to_i() > 0
|
263
348
|
when /!! Input index error \(file = (.*), line = (.*)\):/
|
@@ -267,248 +352,193 @@ class TeX_Statistic
|
|
267
352
|
end #if error
|
268
353
|
}
|
269
354
|
stat
|
270
|
-
end #
|
355
|
+
end #ilg_analyse
|
356
|
+
|
357
|
+
=begin rdoc
|
358
|
+
Define the defaults for TeX_Statistic#texmessages2hash
|
359
|
+
=end
|
360
|
+
Defaults_texmessages2hash = {
|
361
|
+
:messages => :texmessages, #replaced with @texmessages
|
362
|
+
:page_info => true,
|
363
|
+
:source_info => false,
|
364
|
+
:loglineno_info => true,
|
365
|
+
:nextlines_info => false,
|
366
|
+
}
|
271
367
|
|
272
|
-
|
273
|
-
|
274
|
-
#{@texfile}:
|
275
|
-
#{@stat.to_yaml}
|
276
|
-
stat
|
277
|
-
end
|
278
|
-
end #TeX_Statistic
|
279
|
-
end #Rake4LaTeX
|
368
|
+
=begin rdoc
|
369
|
+
Take messages and convert them into a hash for quick analyses.
|
280
370
|
|
371
|
+
Options is a hash with flags, which informations should be added.
|
372
|
+
Defaults can be seen in Defaults_texmessages2hash.
|
373
|
+
=end
|
374
|
+
def texmessages2hash( options )
|
375
|
+
options = Defaults_texmessages2hash.dup.merge(options)
|
376
|
+
options[:messages] = @texmessages if options[:messages] == :texmessages
|
281
377
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
378
|
+
#Return-Hash.
|
379
|
+
#Collects the datas.
|
380
|
+
stat = {}
|
381
|
+
options[:messages].sort.each{|mess|
|
382
|
+
text = [ mess.message ]
|
383
|
+
if mess.source and options[:source_info]
|
384
|
+
text << " (#{mess.source}#{mess.line ? ":#{mess.line}" : '' })"
|
385
|
+
end
|
386
|
+
text << " [page#{mess.page}]" if mess.page and options[:page_info]
|
387
|
+
text << " [log##{mess.logline}]" if options[:loglineno_info]
|
388
|
+
text << " - #{mess.nextlines}" if options[:nextlines_info]
|
389
|
+
text = text.join()
|
390
|
+
|
391
|
+
case mess.type
|
392
|
+
when :package_info
|
393
|
+
next
|
394
|
+
when :package_warnings, :package_errors
|
395
|
+
stat[mess.type] ||= {}
|
396
|
+
(stat[mess.type][mess.details[:package]] ||= [] ) << text
|
397
|
+
else
|
398
|
+
( stat[mess.type] ||= [] ) << text
|
399
|
+
end
|
400
|
+
}
|
401
|
+
stat
|
402
|
+
end #texmessages2hash
|
403
|
+
=begin rdoc
|
404
|
+
Build a very quick overview on actual status.
|
293
405
|
|
294
|
-
|
406
|
+
Each tool gets one line.
|
295
407
|
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
when /l\.([0-9]*) (.*)/
|
304
|
-
last_message << " #{$2} (line #{$1})".strip
|
305
|
-
#fixme: get also next line (pdflualatex/invalid utf?)
|
306
|
-
else
|
307
|
-
last_message << " (#{logline.chomp()})"
|
308
|
-
end
|
309
|
-
last_message = nil
|
310
|
-
next #continue with the next warning/error
|
311
|
-
end #last_message
|
312
|
-
|
313
|
-
#In case of errors, get the line number where it happens
|
314
|
-
if jump_to_numberline
|
315
|
-
case logline
|
316
|
-
#skip text
|
317
|
-
when /Type H <return> for immediate help./,
|
318
|
-
/^[\.\s]*$/ #empty line
|
319
|
-
#Get the line number
|
320
|
-
when /l\.([0-9]*) (.*)/
|
321
|
-
last_message << " #{$2} (line #{$1})".strip
|
322
|
-
jump_to_numberline = false #numberline reached, continue with log-analyses
|
323
|
-
#fixme: collect text in between?
|
324
|
-
when /See the (.*) package documentation for explanation./
|
325
|
-
last_message << " (package #{$1})"
|
326
|
-
else
|
327
|
-
last_message << " #{logline.strip} ||"
|
328
|
-
end
|
329
|
-
next #continue with the next warning/error
|
330
|
-
end #jump_to_numberline = true; last_message = result[:error].last
|
408
|
+
Example:
|
409
|
+
- "Document: 14 errors, 15 warnings, 44 overfull boxes, 70 underfull boxes (testdocument.log)"
|
410
|
+
- "Bibliography: 1 error (testdocument.blg)"
|
411
|
+
- "Index: 21 entries (testdocument-changes.ilg)"
|
412
|
+
- "Index: 38 entries (testdocument-BMEcat.ilg)"
|
413
|
+
- "Index: 1 error (testdocument-idx.ilg)"
|
414
|
+
- "Index: 139 entries (testdocument-Fields.ilg)"
|
331
415
|
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
result[:error] << last_message = "tabular: wrong alignment"
|
363
|
-
when /pdfTeX warning .*?: (.*)/
|
364
|
-
result[:warning] << last_message = "pdftex: #{$1}"
|
365
|
-
else
|
366
|
-
result[:error] << last_message = "New error to runtex: #{logline.strip}"
|
367
|
-
#~ jump_to_numberline = true; last_message = result[:error].last = result[:error].last
|
368
|
-
@job.log.warn( "#{__FILE__} Uncatched error? <#{$1.inspect}>") if @job.log.warn?
|
369
|
-
end
|
370
|
-
when /(job aborted, no legal \\end found)/,
|
371
|
-
/(==> Fatal error occurred, no output PDF file produced!)/
|
372
|
-
result[:error] << last_message = $1
|
373
|
-
when /Package gloss Info: Writing gloss file (.*).aux/ #Check for gloss.sty
|
374
|
-
@job << BibTeX.new( @job, :source => "#{$1}.aux", :target => "#{$1}.bbl", :log => "#{$1}.blg" )
|
375
|
-
when /Package hyperref Warning: old toc file detected, not used; run LaTeX again/
|
376
|
-
@job.please_rerun("(old toc)")
|
377
|
-
when /LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right./
|
378
|
-
@job.please_rerun("Labels/Toc changed")
|
379
|
-
when /Package longtable Warning: Table widths have changed. Rerun LaTeX./
|
380
|
-
@job.please_rerun("Longtable requires additional calculation)")
|
381
|
-
when /LaTeX Warning: Label (.*)/
|
382
|
-
result[:label]<< last_message = $1
|
383
|
-
when /LaTeX Warning: (Reference .*)/
|
384
|
-
result[:label]<< last_message = $1
|
385
|
-
when /LaTeX Warning: Citation (.*)/
|
386
|
-
result[:citation]<< last_message = $1
|
387
|
-
when /LaTeX Warning: (.*)/
|
388
|
-
result[:warning] << last_message = $1
|
389
|
-
when /Package hyperref Warning: (.*)/
|
390
|
-
result[:warning_hyper]<< last_message = "#{$1}"
|
391
|
-
when /Package rail Warning: Railroad diagram \{(\d*)\} doesn't match on input line (\d*)./
|
392
|
-
@job.log.debug( "#{@step} Rerun necessary (Rail diagram #{$1} on line #{$2})") if @job.log.debug?
|
393
|
-
if @job.stop_rerun?(:rail)
|
394
|
-
@job.log.warn( "#{@step} Rail-Rerun blocked by previous error") if @job.log.warn?
|
395
|
-
else
|
396
|
-
@job.please_rerun( "Rail diagram #{$1} on line #{$2} changed")
|
397
|
-
@job << Rail.new( @job, :source => "#{@job.basename}.rai", :target => "#{@job.basename}.rao" )
|
398
|
-
end
|
399
|
-
when /Package rail Warning: Railroad diagram\(s\) may have changed./
|
400
|
-
@job.log.debug( "#{@step} Rerun necessary (Rail diagram changed)") if @job.log.debug?
|
401
|
-
if @job.stop_rerun?(:rail)
|
402
|
-
@job.log.warn( "#{@step} Rail-Rerun blocked by previous error") if @job.log.warn?
|
403
|
-
else
|
404
|
-
@job.please_rerun( "Rail diagram changed")
|
405
|
-
@job << Rail.new( @job, :source => "#{@job.basename}.rai", :target => "#{@job.basename}.rao" )
|
406
|
-
end
|
407
|
-
#~ when /Package: rail / #Package: rail 1998/05/19
|
408
|
-
#~ @job.log.debug( "#{@step} Package rail detected") if @job.log.debug?
|
409
|
-
#~ @job << Rail.new( @job ) ??
|
410
|
-
when /Package (.*) Warning: (.*)/
|
411
|
-
result[:warning] << last_message = "#{$1}:\t#{$2}"
|
412
|
-
when /Using splitted index at (.*)/ ##Find Splittindex
|
413
|
-
@job.log.debug( "#{@step} Found splitindex for #{$1}") if @job.log.debug?
|
414
|
-
@job << Splitindex.new(@job, :source => $1 )
|
415
|
-
#This message is posted, if index2 is used.
|
416
|
-
#I hope the responsible person for index.sty will take my changes.
|
417
|
-
#If the name is very long, there is a break in the Filename.
|
418
|
-
when /Package index2 Info: (.*) (.*)/
|
419
|
-
@job.log.debug( "#{@step} Index #{$1} detected (->#{$2})") if @job.log.debug?
|
420
|
-
@job.log.warn( "#{@step} Warning: Name #{$2} perhaps cutted") if @job.log.warn? and $1.size != $2.size
|
421
|
-
@job << Makeindex.new( @job,
|
422
|
-
:name => "Index2-#{$1}",
|
423
|
-
:file_in => $1, #"#{@job.basename}.idx",
|
424
|
-
:file_out => $2, #"#{@job.basename}.ind",
|
425
|
-
:file_log => "#{$1}.ilg"
|
426
|
-
#~ :format => glossaries_format
|
427
|
-
)
|
428
|
-
#If you use index.sty:
|
429
|
-
#Unfortenalty there are some missing information to complete the task.
|
430
|
-
#Please use index2.sty
|
431
|
-
when /Writing index file (\S*)/
|
432
|
-
@job.log.debug( "#{@step} Index #{$1} detected") if @job.log.debug?
|
433
|
-
|
434
|
-
if $1 == @job.basename + '.idx' #'normal' standard index
|
435
|
-
name = 'Index'
|
436
|
-
format = nil
|
437
|
-
if @job.filename =~ /\.dtx$/
|
438
|
-
name << '/dtx'
|
439
|
-
format = 'gind.ist'
|
440
|
-
end
|
441
|
-
@job << Makeindex.new( @job,
|
442
|
-
:name => name,
|
443
|
-
:file_in => "#{@job.basename}.idx",
|
444
|
-
:file_out => "#{@job.basename}.ind",
|
445
|
-
:file_log => "#{@job.basename}.ilg",
|
446
|
-
:format => format
|
447
|
-
)
|
448
|
-
else
|
449
|
-
@job.log.warn( "#{@step} Warning: index.sty is not supported, please use index2 (#{$1})") if @job.log.warn?
|
450
|
-
@job.helpfiles << $1
|
451
|
-
end
|
452
|
-
#This message is created by
|
453
|
-
#- glossaries (-> already catched by aux-analyses)
|
454
|
-
#- ltxdoc.cls (for dtx.files)
|
455
|
-
when /Writing glossary file (\S*)/
|
456
|
-
glossfile = $1
|
457
|
-
@job.log.debug( "#{@step} Glossary #{glossfile} detected") if @job.log.debug?
|
458
|
-
|
459
|
-
if @job.filename =~ /\.dtx$/ and glossfile =~ /.glo$/ #ltxdoc.cls
|
460
|
-
@job << Makeindex.new( @job,
|
461
|
-
:name => 'Glossary/dtx',
|
462
|
-
:file_in => glossfile,
|
463
|
-
:file_out => "#{@job.basename}.gls",
|
464
|
-
:file_log => "#{@job.basename}.glg",
|
465
|
-
:format => 'gglo.ist'
|
466
|
-
)
|
467
|
-
else
|
468
|
-
#Possible with usage of glossaries.sty -> catched by aux-analyses
|
469
|
-
@job.log.debug( "#{@step} Glossary in non-dtx found #{glossfile}") if @job.log.debug?
|
416
|
+
=end
|
417
|
+
def stat_summary()
|
418
|
+
result = []
|
419
|
+
@stat.each{|key, values|
|
420
|
+
stat = {}
|
421
|
+
values.each{|logkey,logvalues|
|
422
|
+
stat[key] ||= []
|
423
|
+
case logkey
|
424
|
+
when :source_information, :output
|
425
|
+
logvalues.each{|mess|
|
426
|
+
case mess
|
427
|
+
when /Entries accepted: (\d*)/
|
428
|
+
stat[:ok] = $1.to_i unless $1 == '0'
|
429
|
+
when /Entries rejected: (\d*)/
|
430
|
+
stat[:reject] = $1.to_i unless $1 == '0'
|
431
|
+
when /Database file (.+) used/
|
432
|
+
( stat[:source] ||= [] ) << $1
|
433
|
+
when /Output written on .* \((\d*) pages, (\d*) bytes\)/
|
434
|
+
stat[:pages] = $1.to_i
|
435
|
+
when /Input file:/
|
436
|
+
else
|
437
|
+
#~ puts mess.inspect
|
438
|
+
end
|
439
|
+
}
|
440
|
+
when String
|
441
|
+
#~ stat[key] = logkey
|
442
|
+
puts logkey.inspect
|
443
|
+
raise "?Undefined String-Handling in stat_overview"
|
444
|
+
else #count messages
|
445
|
+
stat[logkey] = logvalues.size
|
470
446
|
end
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
447
|
+
} #values
|
448
|
+
|
449
|
+
#Build summary line
|
450
|
+
summary = []
|
451
|
+
if stat[:pages]
|
452
|
+
summary << "#{stat[:pages]} page"
|
453
|
+
summary.last << "s" if stat[:pages] > 1
|
454
|
+
end
|
455
|
+
if stat[:source]
|
456
|
+
summary << "Used #{stat[:source].join(', ')}"
|
457
|
+
end
|
458
|
+
errors = (stat[:error] ? stat[:error] : 0 ) +
|
459
|
+
(stat[:latex_errors] ? stat[:latex_errors] : 0 ) +
|
460
|
+
(stat[:package_errors] ? stat[:package_errors] : 0 )
|
461
|
+
if errors > 0
|
462
|
+
summary << "#{errors} error"
|
463
|
+
summary.last << 's' if errors > 1
|
464
|
+
end
|
465
|
+
case stat[:ok]
|
466
|
+
when 0, nil #no report
|
467
|
+
when 1; summary << "#{stat[:ok]} entry"
|
468
|
+
else; summary << "#{stat[:ok]} entries"
|
469
|
+
end
|
470
|
+
case stat[:reject]
|
471
|
+
when 0, nil
|
472
|
+
when 1; summary << "#{stat[:reject]} rejected entry"
|
473
|
+
else; summary << "#{stat[:reject]} rejected entries"
|
474
|
+
end
|
479
475
|
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
filedata << "#{result[:underfull].size} Underfull box#{'es' if result[:underfull].size > 1} (> #{@options[:underfull]})" unless result[:underfull].empty?
|
487
|
-
#~ result[:fileinfo] = "#{result[:file]} (#{filedata.join(', ')})" unless filedata.empty?
|
488
|
-
result[:fileinfo] = filedata
|
489
|
-
last_message = nil
|
490
|
-
end #case logline
|
491
|
-
} #each.loglines
|
492
|
-
return result
|
493
|
-
end #analyse_logfile
|
494
|
-
|
495
|
-
|
496
|
-
Rail:
|
497
|
-
stderr.each{ |errline|
|
498
|
-
case errline
|
499
|
-
when /(.*), line (.*): (.*)/
|
500
|
-
#$1: Filename (e.g. 'stdin')
|
501
|
-
@result[:error] << "Line #{$2}: #{$3}"
|
502
|
-
@job.stop_rerun( :rail, "Rail: #{$3} on line #{$2}") #block rerun for rail
|
476
|
+
warnings = (stat[:warnings] ? stat[:warnings] : 0 ) +
|
477
|
+
(stat[:latex_warnings] ? stat[:latex_warnings] : 0 ) +
|
478
|
+
(stat[:package_warnings] ? stat[:package_warnings] : 0 )
|
479
|
+
if warnings > 0
|
480
|
+
summary << "#{warnings} warning"
|
481
|
+
summary.last << 's' if warnings > 1
|
503
482
|
end
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
case stdout_line
|
508
|
-
when /This is Rail, Version (.*)\s/
|
509
|
-
@result[:info] << "Rail version #{$1} was called"
|
510
|
-
when /(Der Prozess kann nicht auf die Datei zugreifen, .*)/
|
511
|
-
@result[:error] << "#{$1}"
|
483
|
+
if stat[:overfull_boxes]
|
484
|
+
summary << "#{stat[:overfull_boxes]} overfull box"
|
485
|
+
summary.last << 'es' if stat[:overfull_boxes] > 1
|
512
486
|
end
|
513
|
-
|
487
|
+
if stat[:underfull_boxes]
|
488
|
+
summary << "#{stat[:underfull_boxes]} underfull box"
|
489
|
+
summary.last << 'es' if stat[:underfull_boxes] > 1
|
490
|
+
end
|
491
|
+
|
492
|
+
#Put summary to result-array
|
493
|
+
#The result contains a sort-number, which is deleted in the end
|
494
|
+
case key
|
495
|
+
when /log\Z/; result << "%-13s: %s (%s)" % [ '1Document', summary.join(', '), key]
|
496
|
+
when /blg\Z/; result << "%-13s: %s (%s)" % [ '2Bibliography', summary.join(', '), key]
|
497
|
+
when /ilg\Z/; result << "%-13s: %s (%s)" % [ '3Index', summary.join(', '), key]
|
498
|
+
else
|
499
|
+
#fixme
|
500
|
+
puts "#{__FILE__}##{__LINE__}: Unknown #{key}"
|
501
|
+
result << "?? #{key}: #{summary.join(', ') }"
|
502
|
+
end
|
503
|
+
} #@stat
|
504
|
+
#Retrun the result in the wanted order, but without the sort-number.
|
505
|
+
result.sort.map{|e| e[1..-1] }
|
506
|
+
end
|
507
|
+
=begin rdoc
|
508
|
+
Build a more complex overview.
|
509
|
+
Contains:
|
510
|
+
* Summary (method #stat_summary)
|
511
|
+
* All errors and warnings from TeX and the tools.
|
512
|
+
* A detailed analyses for the TeX-log (including some buge in the analyse).
|
513
|
+
=end
|
514
|
+
def overview()
|
515
|
+
overview = []
|
516
|
+
overview << "Log-overview for #{@texfile}"
|
517
|
+
overview << stat_summary.map{|e| " #{e}"}
|
518
|
+
overview << stat.to_yaml
|
519
|
+
#And the TeX-errors in details (buggy)
|
520
|
+
overview << "========\n Detailed analyse of #{@texfile.ext('log')}\n========"
|
521
|
+
overview << "###########\n##The following list may contain wrong line assignments\n###########"
|
522
|
+
overview << texmessages2hash({
|
523
|
+
:messages => log_analyse_by_file(@texfile.ext('log')),
|
524
|
+
:page_info => true, #add page information
|
525
|
+
:loglineno_info => true,
|
526
|
+
:nextlines_info => true,
|
527
|
+
:source_info => true, #add source code information, only in log_analyse_by_file_page
|
528
|
+
}).to_yaml
|
529
|
+
overview.join("\n")
|
530
|
+
end #overview()
|
531
|
+
|
532
|
+
=begin rdoc
|
533
|
+
Return a quick overview. See stat_overview()
|
534
|
+
=end
|
535
|
+
def to_s()
|
536
|
+
stat_overview()
|
537
|
+
end
|
538
|
+
end #TeX_Statistic
|
539
|
+
end #Rake4LaTeX
|
540
|
+
|
514
541
|
|
542
|
+
#~ if $0 == __FILE__
|
543
|
+
#~ Dir.chdir('../../test/'){ require 'test_tex_statistic.rb' }
|
544
|
+
#~ end
|