class Rake4LaTeX::LaTeXRunner

Extend the class by accessors for glossaries.sty.

end

Class which encapsulates all the information needed to call latex as often as needed. It calls (pdf|xe|lua)LaTeX and checks if additional tools are needed.

end

Constants

Infinity

Define Infinity (needed for option maxruns.

PROGRAMS
The default programs to use to process latex files, depending on the extension
of the file to generate. To add a default program for another extension, simply
add the corresponding entry here. To change the default program for a given 
extension for all the latex tasks, change it here. To change the program used
in a specific task, change it in the corresponding runner

end

Post_Prerequisites

All tasks, which should be executed after a TeX-call.

The constant is filled via LaTeXRunner#tex_postrule, LaTeXRunner#run_latex_once will loop on all this tasks and execute them if necessary.

end

Post_Prerequisites_check

Defines an optional check routine to check if a Post_Prerequisites is necessary. Should return true or false.

end

Attributes

full_input_dir[R]

The full path of the input directory. It is determined automatically during initialization

glossaries[RW]

Store information from glossaries.sty to transport it from tex_postrule_check to tex_postrule for ‘gls’-task.

end

glossaries_format[RW]

Format for the makefindex call neeeded for glossaries.sty.

end

input_dir[R]

The directory where the input file is located. It is determined automatically during initialization

logger[R]

The logger for the LaTeX-Run.

main_file[RW]
The name of the file on which latex should be invoked. The input directory is
determined from this.

end

maxruns[RW]
The maximum number of times latex can be run. 
If you want to remove the limit, you can set it to infinity
(LaTeXRunner::Infinity)

end rdoc

options[R]

An array of the options to pass to latex. Defaults to ['-interaction=batchmode']

programms[R]

Hash with Programm settings. by default Rake4LaTeX::Programms.

Public Class Methods

new( settings ) click to toggle source

Define a new runner.

The settings must contain:

It may contain the following values:

Defaults are defined in Rake4LaTeX::Basefile#settings4LaTeXRunner

end

# File lib/rake4latex/latexrunner.rb, line 53
def initialize( settings )
  
  @main_file = settings[:main_file]
  raise MainfileError, "main_file missing" unless @main_file
  #Define or get Basefile
  basefile = Rake4LaTeX::Basefile.set( @main_file )

  @logger = basefile.logger
  #~ @logger = Log4r::Logger.new("LaTeXRunner #{settings[:main_file]}")
  #~ @logger.outputters = Log4r::StdoutOutputter.new('log_stdout')
  
  #Copy the programms.
  #This allows us to overwrite the program settings for a special LaTeXRunner.
  @programms = Programms.dup
  
  basefile.settings4LaTeXRunner.merge(settings).each{|key, value|
    #~ puts "#{key}: #{value}"
    case key
    when :main_file; @main_file = value
    when :maxruns; @maxruns = value
    when :program;  self.program = value
    when :programms;  @programms.merge!(value)
    when :options;  @options = value
    when :loglevel;  @logger.level = value
    when :texerrors_allowed;  @texerrors_allowed = value
    when :dummy #dummy
    else
      raise ArgumentError, "Undefined key #{key} for LaTeXRunner"
    end
  }

  raise MainfileError, "main_file #{@main_file} not found" unless File.exist?(@main_file)
  raise ArgumentError, "Maxrun is no number" unless @maxruns.is_a?( Fixnum ) or @maxruns == Infinity

  @basename = File.basename(@main_file)
  @input_dir = File.dirname(@main_file)
  @full_input_dir = File.expand_path(@input_dir)

  @logger.info( "StartLaTeXRunner for #{@main_file}")

  @rerun_necessary = true #initialize
end

Public Instance Methods

execute() click to toggle source
Starts the build process for the output file.
It determines the latex command line and calls <tt>run_latex_as_needed</tt>.

end

# File lib/rake4latex/latexrunner.rb, line 147
def execute()

  cmd = Rake4LaTeX.build_cmd( @program, :filename => @basename )
  Dir.chdir(@input_dir) do
    @texruns = 0
    while rerun_necessary?
      @texruns += 1
      @rerun_necessary = false
      run_latex_once(cmd)
    end
  end
  
  plural_s = "#{@texruns} run#{@texruns>1 ? 's': ''}"
  if @rerun_necessary
    @logger.warn("TeX-run stopped after #{plural_s}, but more runs are necessary" )
  else
    @logger.info("TeX-run stopped after #{plural_s}" )
  end
end
inspect() click to toggle source
# File lib/rake4latex/latexrunner.rb, line 96
def inspect()
  return  "#<LaTeXRunner: #{@main_file}>"
end
program=(key) click to toggle source
The program to use to process the .tex files for this runner. 
Default is :pdflatex, but can be redefined by the task definition.

end

# File lib/rake4latex/latexrunner.rb, line 133
def program=(key)
  raise ArgumentError, "Programm key #{key.inspect} unknown" unless PROGRAMS[key]
  @program = PROGRAMS[key]
end
rerun_necessary?() click to toggle source

Flag if TeX should be started again.

# File lib/rake4latex/latexrunner.rb, line 125
def rerun_necessary?()
  @rerun_necessary and ( maxruns > @texruns )
end
run_latex_once(cmd) click to toggle source
Manages a single invocation of latex. This means:
* Get the MD5 digest of help-files.
* executes latex
* Invokes the following tasks like Index...
This method is expected to be started in @input_dir

end

# File lib/rake4latex/latexrunner.rb, line 174
def run_latex_once(cmd)

  checksums = {}
  FileList["#{@basename.ext('*')}"].each do |file|
      # Computes a MD5 digest for the given file, reading the file.
      File.open(file){|f| checksums[file] = Digest::MD5.hexdigest(f.read) }
  end

  @logger.info("Excute #{cmd}")
  latex_output = `#{cmd}`
  if $? != 0
    @logger.fatal("There where #@program errors. See #{@main_file.ext('.log')} for details")
    #~ @logger.fatal("Errors: #{TeX_Statistic.new(@main_file.ext('.log')).stat[@main_file.ext('.log')][:latex_errors].inspect}")
    #~ raise RuntimeError, "There where #@program errors. "\
        #~ "See #{@main_file.ext('.log')} for details"  unless @texerrors_allowed
    exit unless @texerrors_allowed
  end
  
  helpfiles = %w{aux toc lof lot}
  #Build the checksums.
  FileList["#{@basename.ext('*')}"].each do |file|
    # Compare old and new MD5 digest for the given file.
    File.open(file){|f| 
        case checksums[file]
        when nil
          @logger.debug("new file #{file}")
          checksums[file] = :changed
        when File.open(file){|f|  Digest::MD5.hexdigest(f.read) }
          #no message needed
          #~ @logger.debug("Unchanged file #{file}")
        else
          @logger.debug("  Changed file #{file}" )
          checksums[file] = :changed
        end
      }
    #Special rules for additional files
    case file
      #Build by gloss.sty
      when /#{@basename.ext()}\.(.+)\.aux/
        gloss_name = $1
        helpfiles << "#{$1}.aux"
        @logger.debug("Detected additional aux-file <#{file}>" )
        if ! Post_Prerequisites_check["#{gloss_name}.bbl"] 
          @logger.info("Define additional rule <#{gloss_name}.bbl> (gloss.sty)" )
          Post_Prerequisites_check[".#{gloss_name}.bbl"] = Post_Prerequisites_check[".bbl"] 
          tex_postrule ".#{gloss_name}.bbl" => ".#{gloss_name}.aux"
        end
    end
  end
 
  #check changes in some files.
   helpfiles.each{|ext|
    next unless checksums[@basename.ext(ext)] == :changed
    @rerun_necessary = true
    @logger.info("Rerun necessary (#{ext}-file changed)" ) if @rerun_necessary
    break #stop after the first reason for an additional run.
  }

  #Loop on all Post_Prerequisites (e.g. makeindex, BibTeX...)
  Post_Prerequisites.each{|pre|
    @logger.debug("Check Post-prerequisite #{pre}" )
    #Get the Post-prerequisites.
    #Stops if it does not exist.
    begin
      if ! post_prereq = Rake.application[@basename.ext(pre)]
        @logger.fatal("No rule for Post-prerequisites #{pre}" )
        next
      end
    rescue RuntimeError => err
      @logger.debug("No Post-prerequisite #{pre}" )
      next
    end
    
    post_prereq.texrunner = self  #Set the connection to the TeXRunner
    
    #Starts only, if prerequisites of post_prereq exist and was regenerated by TeX.
    #Here we make an additional check if we need the post_prereq.
    post_prereq.prerequisites.each{|post_prereq_pre|
      reason4call = false
      #Check special rules (e.g. for BibTeX)
      if Post_Prerequisites_check[pre]
        @logger.debug("Make precheck for #{pre}" )
        Post_Prerequisites_check[pre].each{|precheck|
          #Call the pre-check with the task...
          reason4call = precheck.call(  :task => post_prereq, 
                                                  :checksums => checksums, 
                                                  :texrunner => self,
                                                  :logger => @logger)
          break if reason4call  #we need only one reason to start the task.
        }
      else  #make the standard check (
        reason4call = "#{post_prereq_pre} changed" if ( checksums[post_prereq_pre] == :changed )
      end
      if reason4call  #We have to run the task for the post_prereq
        #One of the sources of post_prereq changes
        @logger.info("Call target #{post_prereq.name} (#{reason4call})" )
        post_prereq.invoke() 
        if File.exist?(post_prereq.name)
          File.open(post_prereq.name){|f|
              @rerun_necessary = ( Digest::MD5.hexdigest(f.read) != checksums[f.path])
              @logger.info("Rerun necessary (#{f.path} changed)" ) if @rerun_necessary
          } unless @rerun_necessary #check not necessary, if we already need an additional run
        else
          @logger.info("Rerun necessary (#{post_prereq.name} did not exist)" )
          @rerun_necessary = true
        end
        break #Only one call necessary
      end #source changed
    } ##prerequisites of  post_prereq
  } #Post_Prerequisites

  #fixme: get info for next run (global?, adabp invoke?
  #set again task??
  #call rake again? creaite new app?
end