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.
Files changed (47) hide show
  1. data/{call_rake4latex.rb → bin/call_rake4latex.rb} +6 -3
  2. data/{readme_call_rake4latex.txt → bin/readme_call_rake4latex.txt} +0 -0
  3. data/lib/rake4latex.rb +106 -42
  4. data/lib/rake4latex/analyse_texfile.rb +375 -0
  5. data/lib/rake4latex/base.rb +40 -10
  6. data/lib/rake4latex/latexrunner.rb +20 -7
  7. data/lib/rake4latex/rake4latex.yaml +4 -0
  8. data/lib/rake4latex/rules.rb +59 -26
  9. data/lib/rake4latex/tex_statistic.rb +405 -375
  10. data/lib/rake4latex_dtx.rb +83 -0
  11. data/readme.html +150 -28
  12. data/readme.txt +118 -20
  13. data/test/_expected/bibtex_test_build_rakefile.txt +49 -0
  14. data/test/_expected/dtx_test.txt +12 -0
  15. data/test/_expected/dtx_test_sty.txt +2 -0
  16. data/test/_expected/error_test.txt +4 -0
  17. data/test/_expected/error_test_ignore_error.txt +5 -0
  18. data/test/_expected/error_test_overview.txt +16 -0
  19. data/test/_expected/error_test_statistic.txt +3 -0
  20. data/test/_expected/gloss_test_build_rakefile.txt +56 -0
  21. data/test/_expected/includes_test_build_rakefile.txt +55 -0
  22. data/test/_expected/{rail_test_error.txt → rail_error_test.txt} +0 -0
  23. data/test/_expected/splitindex_test_build_rakefile.txt +56 -0
  24. data/test/_expected/supertabular_test_statistic.txt +2 -29
  25. data/test/_expected/varioref_test.txt +6 -0
  26. data/test/_expected/varioref_test_ignore_error.txt +11 -0
  27. data/test/_expected/z_complex_test_overview.txt +62 -0
  28. data/test/_expected/z_complex_test_statistic.txt +9 -0
  29. data/test/bibtex/rakefile.rb +6 -0
  30. data/test/dtx/rakefile.rb +31 -0
  31. data/test/error/rakefile.rb +32 -0
  32. data/test/error/testdocument.tex +14 -0
  33. data/test/gloss/rakefile.rb +9 -1
  34. data/test/includes/rakefile.rb +6 -0
  35. data/test/rail/rakefile.rb +1 -5
  36. data/test/rail_error/rakefile.rb +38 -0
  37. data/test/{rail → rail_error}/testrail_error.tex +0 -0
  38. data/test/splitindex/rakefile.rb +8 -1
  39. data/test/supertabular/rakefile.rb +2 -2
  40. data/test/unittest_rake4latex.rb +61 -72
  41. data/test/unittest_rake4latex_testcases.rb +79 -0
  42. data/test/varioref/rakefile.rb +37 -0
  43. data/test/varioref/testdocument.tex +33 -0
  44. data/test/z_complex/rakefile.rb +3 -1
  45. metadata +42 -10
  46. data/lib/rake4latex/latexdependencies.rb +0 -105
  47. data/lib/rake4latex/template.rb +0 -60
@@ -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.0'
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
- Load the Programs with parameters for Rake4LaTeX.build_cmd.
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
- #fixme: incremental reading: global + local overwrites
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
- Programms = YAML.load(File.read(setting_file))
73
- break
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
- configuration = Programms[programm]
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/latexdependencies'
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 looger for the LaTeX-Run.
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 fin clean.
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
- raise RuntimeError, "There where #@program errors. "\
192
- "See #{@main_file.ext('.log')} for details" unless @texerrors_allowed
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, :checksums => checksums, :logger => @logger)
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
@@ -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 |t|
60
- t.prerequisites.each{|pre|
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 |t|
96
+ rule '.dvi' => '.tex' do |task|
67
97
  runner = Rake4LaTeX::LaTeXRunner.new(
68
- :main_file => t.source,
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 |t|
77
- Rake4LaTeX::Logger.info("Call dvips for <#{t.source}>")
78
- cmd = Rake4LaTeX.build_cmd( 'dvips', :filename => t.source )
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 |t, args |
123
+ tex_postrule '.ind' => '.idx' do |task|
94
124
  #check for splitidx
95
- splitidx = Rake4LaTeX::Splitindex.new(t.source, Rake4LaTeX::Logger)
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 => t.source )
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 |t|
154
- cmd = Rake4LaTeX.build_cmd( 'bibtex', :source => t.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
- Rake4LaTeX::Logger.fatal("There where BibTeX errors. \n#{stdout}")
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 |t|
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 => t.source )
170
- Rake4LaTeX::Logger.debug("Call rail: #{cmd}")
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
- Rake4LaTeX::Logger.fatal("There where Rail errors.")
208
+ task.texrunner.logger.fatal("There where Rail errors.")
177
209
  error = true
178
210
  end
179
211
  stderr.each{|errline|
180
- Rake4LaTeX::Logger.error("Rail error: #{errline.strip}")
212
+ task.texrunner.logger.error("Rail error: #{errline.strip}")
181
213
  error = true
182
214
  }
183
215
  if error
184
- Rake4LaTeX::Logger.warn("No rail diagramms generated")
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(t.source.ext('rao'), 'w'){|f| f << stdout }
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 |t|
199
- puts "Statistics:"
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 stat
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
- @stat[@texfile.ext('log')] = log_analyse( File.read(@texfile.ext('log')))
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
- #Analyse the TeX-log file.
45
- #
46
- #The log-text is splitted into files and pages and analysed separatly.
47
- #
48
- # ----TESTVERSION----
49
- def log_analyse_by_file_page(logfilename)
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
- filecount = Hash.new(0) #numbers of open ( in file, needed to detect end of file
58
- filecontent = {nil => ''}#content of a file. The content of sub-includes are not part of this content.
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 = /\(((?:\.|c:)\/.*?)[\)\n]/
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}|\(|\)|#{page_pattern})/ ).each{|x|
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
- filecount[file] += 1
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 page_pattern
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
- filecount[file] += 1
84
- filecontent[file] << x
85
- when ')'
86
- filecount[file] = filecount[file] - 1
87
- if filecount[file] == 0
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
- stat = log_analyse_content(filecontent[file], file, page)
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
- filecontent[file] = ''
210
+ filelist[file].logcontent = ''
99
211
  file = filestack.last
100
212
  else
101
- filecontent[file] << x
213
+ filelist[file].logcontent << x
102
214
  end
103
215
  else
104
- filecontent[file] << x
216
+ filelist[file].logcontent << x
105
217
  end
106
218
  #~ puts "%6s : %s" % [page, file ]
107
219
  }
108
- puts filestack.inspect
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
- #Analyse the content of an extract of the TeX-log file.
112
- #
113
- def log_analyse_content(log, file, page)
114
- stat = {}
115
- filepage = [" (",
116
- file ? "in #{file}" : '',
117
- page ? " on page #{page}" : '',
118
- ")"].join
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
- stat[:package_error] ||= {}
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
- ( stat[:latex_error] ||= [] ) << $1
267
+ messages << TeXMessage.new(:latex_errors, lineno, $1, {}, page, file)
186
268
  when /Error:/
187
- (stat[:error] ||= [] ) << logline
188
- #~ puts "!#{logline}"
269
+ messages << TeXMessage.new(:error, lineno, logline, {}, page, file)
189
270
  when /Package (.*) Warning: (.*)/
190
- stat[:package_warning] ||= {}
191
- stat[:package_warning][$1] ||= [] << $2
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
- (stat[:latex_warning] ||= [] ) << $1
274
+ messages << TeXMessage.new(:latex_warnings, lineno, $1, {}, page, file)
194
275
  when /Warning/
195
- #~ puts "!#{logline}"
196
- (stat[:warnings] ||= [] ) << logline
197
- #~ when /Package (.*) Info: (.*)/ #A lot of messages
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
- stat[:output] = {
203
- :name => $1, :pages => $2, :bytes => $3,
204
- :kbytes => ($3.to_i / 1024 )
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
- ( stat[:overfull] ||= [] ) << "#{$1} at lines #{$2}"
208
- #~ next if $1.to_i() < @options[:overfull]
209
- #~ stat[:overfull] ||= [] << last_message = "#{$1} at lines #{$2}"
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
- #~ next if $1.to_i() < @options[:underfull]
213
- ( stat[:underfull] ||= [] )<< last_message = "badness #{$2} at lines #{$4}"
214
- #~ get_next_lines = 1 #?test
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
- stat
299
+ messages
220
300
  end #log_analyse
221
- #Analyse the BibTeX-Logfile
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[:info] ||= [] << "Database file #{$2} used"
310
+ stat[:source_information] ||= [] << "Database file #{$2} used"
228
311
  when /Warning--I didn't find a database entry for "(.*)"/
229
- stat[:warn] ||= [] << "Databaseentry #{$1} missing"
312
+ ( stat[:warnings] ||= [] ) << "Databaseentry #{$1} missing"
230
313
  when /Warning--Empty definition in (.*)/
231
- stat[:warn] ||= [] << "Empty definition #{$1}"
314
+ ( stat[:warnings] ||= [] ) << "Empty definition #{$1}"
232
315
  when /Warning--(.*)/
233
- stat[:warn] ||= [] << "#{$1}"
316
+ ( stat[:warnings] ||= [] ) << "#{$1}"
234
317
  when /I couldn't open (.*) file (.*)/
235
- stat[:error] ||= [] << "#{$1} #{$2} not found"
318
+ ( stat[:errors] ||= [] ) << "#{$1} #{$2} not found"
236
319
  when /I found no (.*) commands---while reading file(.*)/
237
- stat[:warn] ||= [] << "found no #{$1} in #{$2}"
320
+ ( stat[:warnings] ||= [] ) << "found no #{$1} in #{$2}"
238
321
  when /(.*)---line (.*) of file(.*)/
239
322
  #line-number ist unsinnig
240
- stat[:error] ||= [] << "#{$1} in #{$3}"
323
+ ( stat[:errors] ||= [] ) << "#{$1} in #{$3}"
241
324
  end
242
325
  }
243
326
  stat
244
- end #log_analyse
245
- #Analyse the makeindex-log
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[:error] ||= [] << "#{logline.chomp.sub(/.*--/, "")} #{error}"
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[:info] ||= [] << "input file #{$1} (#{$2} entries accepted, #{$3} rejected)"
257
- stat[:output] ||= []
258
- stat[:output] << "Input file: #{$1}"
259
- stat[:output] << "Entries accepted: #{$2}"
260
- stat[:output] << "Entries rejected: #{$3}"
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 #log_analyse
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
- def to_s()
273
- <<stat
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
- if $0 == __FILE__
283
- require 'rake'
284
- #~ puts TeX_Statistic.new('../testdocument.tex')
285
- #~ puts TeX_Statistic.new('C:/usr/Festo/_Projects/PriceCatalog/PriceCatalogTool_en.pdf')
286
- s = TeX_Statistic.new('logtest_pcat/PriceCatalogTool_en.pdf')
287
- #~ puts s.stat['logtest_pcat/PriceCatalogTool_en.log'].to_yaml
288
-
289
- #Test
290
- #~ s.log_analyse_file_page('logtest_pcat/PriceCatalogTool_en.log')
291
- s.log_analyse_by_file_page('logtest_pcat/PriceCatalogTool_en.log')
292
- end
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
- __END__
406
+ Each tool gets one line.
295
407
 
296
- TeX:
297
- logfile.each{|logline|
298
- #The previous message is continued, get the rest here
299
- if get_next_lines > 0
300
- get_next_lines -= 1
301
- case logline
302
- #Get the line number
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
- last_message = nil
333
- $logline = logline #Only for test surposes
334
- case logline
335
- when /^! (.*)/
336
- case $1
337
- #Error messages with line code
338
- when /LaTeX Error:\s*(.*)/,
339
- /(Undefined control sequence.)/,
340
- /(Missing [\$|\{|\}|\\cr] inserted.)/,
341
- /(Dimension too large.)/,
342
- /(Text line contains an invalid utf-8 sequence.)/, #pdflualatex
343
- /(Argument of .* has an extra \})./,
344
- /(Paragraph ended before .* was complete.)/,
345
- /(Misplaced .+)/,
346
- /(Extra \}, or forgotten [\$|\\\\endgroup])/,
347
- /You can't use `\\\\end' in internal vertical mode/
348
- #~ /(! Emergency stop.)/,
349
- #~ /(! Huge page cannot be shipped out.)/
350
- :last_entry_to_avoid_comma_error
351
- result[:error] << last_message = $1
352
- jump_to_numberline = true;
353
- #LaTeX-Errors without line.
354
- when /(Emergency stop|Huge page cannot be.*)/,
355
- /(File ended while scanning use of .*)/,
356
- /(==> Fatal error occurred, no output PDF file produced!)/
357
- result[:error] << last_message = $1
358
- when /Package (.*) Error: (.*)/
359
- result[:error] << last_message = "#{$1}.sty:\t#{$2}"
360
- jump_to_numberline = true
361
- when /Extra alignment tab has been changed to \\cr./
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
- #Add minitocs to helpfiles
472
- when /\(minitoc\)\s*Writing (.*\.mtc\d*)/
473
- @job.log.debug( "#{@step} Found minitoc-helpfile") if @job.log.debug?
474
- @job.helpfiles << $1
475
- when /Output written on (.*) \((.*) pages?, (.*) bytes\)/
476
- result[:file] = $1
477
- result[:pages] = $2.to_i
478
- result[:size] = "#{$3.to_i / 1024}KB"
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
- filedata = []
481
- filedata << "#{result[:file]}"
482
- filedata << "#{result[:pages]} Page#{'s' if result[:pages] > 1}" if result[:pages]
483
- filedata << result[:size] if result[:size]
484
- filedata << "#{result[:error].size} Error#{'s' if result[:error].size > 1}" unless result[:error].empty?
485
- filedata << "#{result[:overfull].size} Overfull box#{'es' if result[:overfull].size > 1} (> #{@options[:overfull]})" unless result[:overfull].empty?
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
- stdout.each{ |stdout_line|
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