rake4latex 0.1.0 → 0.1.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.
- 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
|