#!/usr/bin/env ruby
#encoding: ASCII-8BIT

banner = ['TeXExec', 'version 6.2.1', '1997-2009', 'PRAGMA ADE/POD']

$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!

require 'fileutils'
# require 'ftools'     # needed ?

require 'base/switch'
require 'base/logger'
require 'base/variables'
require 'base/system'

require 'base/state' # needed ?
require 'base/file'  # needed ?

require 'base/tex'
require 'base/texutil'
require 'base/kpse'

class Commands

    include CommandBase

    def make
        if job = TEX.new(logger) then
            prepare(job)
            # bonus, overloads language switch !
            job.setvariable('language','all') if @commandline.option('all')
            if @commandline.arguments.length > 0 then
                if @commandline.arguments.first == 'all' then
                    job.setvariable('texformats',job.defaulttexformats)
                    job.setvariable('mpsformats',job.defaultmpsformats)
                else
                    job.setvariable('texformats',@commandline.arguments)
                    job.setvariable('mpsformats',@commandline.arguments)
                end
            end
            job.makeformats
            job.inspect && Kpse.inspect if @commandline.option('verbose')
            seterror if job.error?
        end
    end

    def check
        if job = TEX.new(logger) then
            job.checkcontext
            job.inspect && Kpse.inspect  if @commandline.option('verbose')
        end
    end

    def main
        if @commandline.arguments.length>0 then
            process
        else
            help
        end
    end

    def process
        if job = TEX.new(logger) then
            job.setvariable('files',@commandline.arguments)
            prepare(job)
            job.processtex
            job.inspect && Kpse.inspect if @commandline.option('verbose')
            seterror if job.error?
        end
    end

    def mptex
        if job = TEX.new(logger) then
            job.setvariable('files',@commandline.arguments)
            prepare(job)
            job.processmptex
            job.inspect && Kpse.inspect  if @commandline.option('verbose')
            seterror if job.error?
        end
    end

    def mpxtex
        if job = TEX.new(logger) then
            job.setvariable('files',@commandline.arguments)
            prepare(job)
            job.processmpxtex
            job.inspect && Kpse.inspect  if @commandline.option('verbose')
            seterror if job.error?
        end
    end

    def mpgraphic
        if job = TEX.new(logger) then
            job.setvariable('files',@commandline.arguments)
            prepare(job)
            job.processmpgraphic
            job.inspect && Kpse.inspect  if @commandline.option('verbose')
            seterror if job.error?
        end
    end

    def mpstatic
        if job = TEX.new(logger) then
            job.setvariable('filename',@commandline.arguments.first)
            prepare(job)
            job.processmpstatic
            job.inspect && Kpse.inspect  if @commandline.option('verbose')
            seterror if job.error?
        end
    end

    # hard coded goodies # to be redone as s-ctx-.. with vars passed as such

    def listing
        if job = TEX.new(logger) then
            prepare(job)
            job.cleanuptemprunfiles
            files =  if @commandline.option('sort') then @commandline.arguments.sort else @commandline.arguments end
            if files.length > 0 then
                if f = File.open(job.tempfilename('tex'),'w') then
                    backspace = @commandline.checkedoption('backspace', '1.5cm')
                    topspace  = @commandline.checkedoption('topspace', '1.5cm')
                    pretty    = @commandline.option('pretty')
                    f << "% interface=english\n"
                    f << "\\setupbodyfont[11pt,tt]\n"
                    f << "\\setuplayout\n"
                    f << "  [topspace=#{topspace},backspace=#{backspace},\n"
                    f << "   header=0cm,footer=1.5cm,\n"
                    f << "   width=middle,height=middle]\n"
                    f << "\\setuptyping[lines=yes]\n"
                    f << "\\setuptyping[option=color]\n" if pretty
                    f << "\\starttext\n";
                    files.each do |filename|
                        report("list file: #{filename}")
                        cleanname = cleantexfilename(filename).downcase
                        f << "\\page\n"
                        f << "\\setupfootertexts[\\tttf #{cleanname}][\\tttf \\pagenumber]\n"
                        f << "\\typefile{#{filename}}\n"
                    end
                    f << "\\stoptext\n"
                    f.close
                    job.setvariable('interface','english')
                    job.setvariable('simplerun',true)
                    # job.setvariable('nooptionfile',true)
                    job.setvariable('files',[job.tempfilename])
                    job.processtex
                else
                    report('no files to list')
                end
            else
                report('no files to list')
            end
            job.cleanuptemprunfiles
        end
    end

    def figures
        # we replaced "texutil --figures ..."
        if job = TEX.new(logger) then
            prepare(job)
            job.cleanuptemprunfiles
            fast = @commandline.option('fast')
            files =  if @commandline.option('sort') then @commandline.arguments.sort else @commandline.arguments end
            if fast or (files.length > 0) then
                if f = File.open(job.tempfilename('tex'),'w') then
                    files.delete("texexec.pdf")
                    Kpse.runscript('rlxtools', ['--identify','--collect'], files.join(' ')) unless fast
                    figures     = @commandline.checkedoption('method', 'a').downcase
                    paperoffset = @commandline.checkedoption('paperoffset', '0pt')
                    backspace   = @commandline.checkedoption('backspace', '1.5cm')
                    topspace    = @commandline.checkedoption('topspace', '1.5cm')
                    boxtype     = @commandline.checkedoption('boxtype','')
                    f << "% format=english\n";
                    f << "\\usemodule[res-20]\n"
                    f << "\\setuplayout\n";
                    f << "  [topspace=#{topspace},backspace=#{backspace},\n"
                    f << "   header=1.5cm,footer=0pt,\n";
                    f << "   width=middle,height=middle]\n";
                    if @commandline.option('fullscreen') then
                        f << "\\setupinteraction\n";
                        f << "  [state=start]\n";
                        f << "\\setupinteractionscreen\n";
                        f << "  [option=max]\n";
                    end
                    boxtype += "box" unless boxtype.empty? || (boxtype =~ /box$/io)
                    f << "\\starttext\n";
                    f << "\\showexternalfigures[alternative=#{figures},offset=#{paperoffset},size=#{boxtype}]\n";
                    f << "\\stoptext\n";
                    f.close
                    job.setvariable('interface','english')
                    job.setvariable('simplerun',true)
                    job.setvariable('files',[job.tempfilename])
                    job.processtex
                    # File.silentdelete('rlxtools.rli') unless job.getvariable('keep')
                else
                    report('no figures to show')
                end
            else
                report('no figures to show')
            end
            job.cleanuptemprunfiles
        end
    end

    def modules
        if job = TEX.new(logger) then
            prepare(job)
            job.cleanuptemprunfiles
            files =  if @commandline.option('sort') then @commandline.arguments.sort else @commandline.arguments end
            msuffixes = ['tex','mkii','mkiv','mp','pl','pm','rb']
            if files.length > 0 then
                files.each do |fname|
                    fnames = Array.new
                    if FileTest.file?(fname) then
                        fnames << fname
                    else
                        msuffixes.each do |fsuffix|
                            fnames << File.suffixed(fname,fsuffix)
                        end
                    end
                    fnames.each do |ffname|
                        if msuffixes.include?(File.splitname(ffname)[1]) && FileTest.file?(ffname) then
                            if mod = File.open(job.tempfilename('tex'),'w') then
                                if File.suffix(ffname) =~ /^(mkii|mkiv)$/o then
                                    markfile = $1
                                else
                                    markfile = nil
                                end
                                Kpse.runscript('ctxtools',ffname,'--document')
                                if ted = File.silentopen(File.suffixed(ffname,'ted')) then
                                    firstline = ted.gets
                                    if firstline =~ /interface=/o then
                                        mod << firstline
                                    else
                                        mod << "% interface=en\n"
                                    end
                                    ted.close
                                else
                                    mod << "% interface=en\n"
                                end
                                mod << "\\usemodule[mod-01]\n"
                                mod << "\\def\\ModuleNumber{1}\n"
                                mod << "\\starttext\n"
                                # todo: global file too
                                mod << "\\readlocfile{#{File.suffixed(ffname,'ted')}}{}{}\n"
                                mod << "\\stoptext\n"
                                mod.close
                                job.setvariable('interface','english') # redundant
                                # job.setvariable('simplerun',true)
                                # job.setvariable('nooptionfile',true)
                                job.setvariable('files',[job.tempfilename])
                                result = File.unsuffixed(File.basename(ffname))
                                if markfile then
                                    result = result+'-'+markfile
                                end
                                job.setvariable('result',result)
                                job.processtex
                                # ["dvi", "pdf","ps"].each do |s|
                                    # File.silentrename(job.tempfilename(s),File.suffixed(ffname,s));
                                # end
                            end
                        end
                    end
                end
            else
                report('no modules to process')
            end
            job.cleanuptemprunfiles
        end
    end

    def pdfsplit
        if job = TEX.new(logger) then
            prepare(job)
            job.cleanuptemprunfiles
            filename = File.expand_path(@commandline.arguments.first)
            if FileTest.file?(filename) then
                basename = filename.sub(/\..*?$/,'')
                tempfile = File.suffixed(job.tempfilename,'tex')
                if basename != filename then
                    info = `pdfinfo #{filename}`
                    if info =~ /Pages:\s*(\d+)/ then
                        nofpages = $1.to_i
                        result = @commandline.checkedoption('result','texexec')
                        nofpages.times do |i|
                            if f = File.open(tempfile,"w") then
                                n = i + 1
                                report("extracting page #{n}")
                                f << "\\starttext\\startTEXpage\n"
                                f << "\\externalfigure[#{filename}][object=no,page=#{n}]\n"
                                f << "\\stopTEXpage\\stoptext\n"
                                f.close
                                job.setvariable('result',"#{result}-#{n}")
                                job.setvariable('interface','english') # redundant
                                job.setvariable('simplerun',true)
                                job.setvariable('purge',true)
                                job.setvariable('files',[tempfile])
                                job.processtex
                            end
                        end
                    end
                end
            end
            job.cleanuptemprunfiles
        end
    end

    def arrangeoutput
        if job = TEX.new(logger) then
            prepare(job)
            job.cleanuptemprunfiles
            files =  if @commandline.option('sort') then @commandline.arguments.sort else @commandline.arguments end
            if files.length > 0 then
                if f = File.open(job.tempfilename('tex'),'w') then
                    emptypages  = @commandline.checkedoption('addempty', '')
                    paperoffset = @commandline.checkedoption('paperoffset', '0cm')
                    textwidth   = @commandline.checkedoption('textwidth', '0cm')
                    backspace   = @commandline.checkedoption('backspace', '0cm')
                    topspace    = @commandline.checkedoption('topspace', '0cm')
                    f << "\\definepapersize\n"
                    f << "  [offset=#{paperoffset}]\n"
                    f << "\\setuplayout\n"
                    f << "  [backspace=#{backspace},\n"
                    f << "    topspace=#{topspace},\n"
                    f << "     marking=on,\n" if @commandline.option('marking')
                    f << "       width=middle,\n"
                    f << "      height=middle,\n"
                    f << "    location=middle,\n"
                    f << "      header=0pt,\n"
                    f << "      footer=0pt]\n"
                    unless @commandline.option('noduplex') then
                        f << "\\setuppagenumbering\n"
                        f << "  [alternative=doublesided]\n"
                    end
                    f << "\\starttext\n"
                    files.each do |filename|
                        report("arranging file #{filename}")
                        f << "\\insertpages\n"
                        f << "  [#{filename}]\n"
                        f << "  [#{emptypages}]\n" unless emptypages.empty?
                        f << "  [width=#{textwidth}]\n"
                    end
                    f << "\\stoptext\n"
                    f.close
                    job.setvariable('interface','english')
                    job.setvariable('simplerun',true)
                    job.setvariable('arrange',true)
                    # job.setvariable('nooptionfile',true)
                    job.setvariable('files',[job.tempfilename])
                    job.processtex
                else
                    report('no files to arrange')
                end
            else
                report('no files to arrange')
            end
            job.cleanuptemprunfiles
        end
    end

    def selectoutput
        if job = TEX.new(logger) then
            prepare(job)
            job.cleanuptemprunfiles
            files =  if @commandline.option('sort') then @commandline.arguments.sort else @commandline.arguments end
            if files.length > 0 then
                if f = File.open(job.tempfilename('tex'),'w') then
                    selection   = @commandline.checkedoption('selection', '')
                    paperoffset = @commandline.checkedoption('paperoffset', '0cm')
                    textwidth   = @commandline.checkedoption('textwidth', '0cm')
                    backspace   = @commandline.checkedoption('backspace', '0cm')
                    topspace    = @commandline.checkedoption('topspace', '0cm')
                    paperformat = @commandline.checkedoption('paperformat', 'A4*A4').split(/[\*x]/o)
                    from, to = paperformat[0] || 'A4', paperformat[1] || paperformat[0] || 'A4'
                    if from == 'fit' or to == 'fit' then
                        f << "\\getfiguredimensions[#{files.first}]\n"
                        if from == 'fit' then
                            f << "\\expanded{\\definepapersize[from-fit][width=\\figurewidth,height=\\figureheight]}\n"
                            from = 'from-fit'
                        end
                        if to == 'fit' then
                            f << "\\expanded{\\definepapersize[to-fit][width=\\figurewidth,height=\\figureheight]}\n"
                            to = 'to-fit'
                        end
                    end
                    job.setvariable('paperformat','') # else overloaded later on
                    f << "\\setuppapersize[#{from}][#{to}]\n"
                    f << "\\definepapersize\n";
                    f << "  [offset=#{paperoffset}]\n";
                    f << "\\setuplayout\n";
                    f << "  [backspace=#{backspace},\n";
                    f << "    topspace=#{topspace},\n";
                    f << "     marking=on,\n" if @commandline.option('marking')
                    f << "       width=middle,\n";
                    f << "      height=middle,\n";
                    f << "    location=middle,\n";
                    f << "      header=0pt,\n";
                    f << "      footer=0pt]\n";
                    f << "\\setupexternalfigures\n";
                    f << "  [directory=]\n";
                    f << "\\starttext\n";
                    unless selection.empty? then
                        f << "\\filterpages\n"
                        f << "  [#{files.first}][#{selection}][width=#{textwidth}]\n"
                    end
                    f << "\\stoptext\n"
                    f.close
                    job.setvariable('interface','english')
                    job.setvariable('simplerun',true)
                    # job.setvariable('nooptionfile',true)
                    job.setvariable('files',[job.tempfilename])
                    job.processtex
                else
                    report('no files to selectt')
                end
            else
                report('no files to select')
            end
            job.cleanuptemprunfiles
        end
    end

    def copyoutput
        copyortrim(false,'copy')
    end

    def trimoutput
        copyortrim(true,'trim')
    end

    def copyortrim(trim=false,what='unknown')
        if job = TEX.new(logger) then
            prepare(job)
            job.cleanuptemprunfiles
            files =  if @commandline.option('sort') then @commandline.arguments.sort else @commandline.arguments end
            if files.length > 0 then
                if f = File.open(job.tempfilename('tex'),'w') then
                    scale = @commandline.checkedoption('scale')
                    begin
                        scale = (scale.to_f * 1000.0).to_i if scale.to_i < 10
                    rescue
                        scale = 1000
                    end
                    scale = scale.to_i
                    paperoffset = @commandline.checkedoption('paperoffset', '0cm')
                    f << "\\starttext\n"
                    files.each do |filename|
                        result = @commandline.checkedoption('result','texexec')
                        begin
                            if (filename !~ /^texexec/io) && (filename !~ /^#{result}/) then
                                report("copying file: #{filename}")
                                f <<  "\\getfiguredimensions\n"
                                f <<  "  [#{filename}]\n"
                                f <<  "  [scale=#{scale},\n"
                                f <<  "   page=1,\n"
                                f <<  "   size=trimbox\n" if trim
                                f <<  "]\n"
                                f <<  "\\definepapersize\n"
                                f <<  "  [copy]\n"
                                f <<  "  [width=\\figurewidth,\n"
                                f <<  "   height=\\figureheight]\n"
                                f <<  "\\setuppapersize\n"
                                f <<  "  [copy][copy]\n"
                                f <<  "\\setuplayout\n"
                                f <<  "  [page]\n"
                                f <<  "\\setupexternalfigures\n"
                                f <<  "  [directory=]\n"
                                f <<  "\\copypages\n"
                                f <<  "  [#{filename}]\n"
                                f <<  "  [scale=#{scale},\n"
                                f <<  "   marking=on,\n" if @commandline.option('markings')
                                f <<  "   size=trimbox,\n" if trim
                                f <<  "   offset=#{paperoffset}]\n"
                            end
                        rescue
                            report("wrong specification")
                        end
                    end
                    f << "\\stoptext\n"
                    f.close
                    job.setvariable('interface','english')
                    job.setvariable('simplerun',true)
                    # job.setvariable('nooptionfile',true)
                    job.setvariable('files',[job.tempfilename])
                    job.processtex
                else
                    report("no files to #{what}")
                end
            else
                report("no files to #{what}")
            end
            job.cleanuptemprunfiles
        end
    end

    # todo: make this styles

    def combineoutput
        if job = TEX.new(logger) then
            prepare(job)
            job.cleanuptemprunfiles
            files =  if @commandline.option('sort') then @commandline.arguments.sort else @commandline.arguments end
            if files.length > 0 then
                if f = File.open(job.tempfilename('tex'),'w') then
                    paperoffset = @commandline.checkedoption('paperoffset', '0cm')
                    combination = @commandline.checkedoption('combination','2*2').split(/[\*x]/o)
                    paperformat = @commandline.checkedoption('paperformat', 'A4*A4').split(/[\*x]/o)
                    bannerheight = @commandline.checkedoption('bannerheight', '')
                    nx, ny = combination[0] || '2', combination[1] || combination[0] || '2'
                    from, to = paperformat[0] || 'A4', paperformat[1] || paperformat[0] || 'A4'
                    f << "\\setuppapersize[#{from}][#{to}]\n"
                    f << "\\setuplayout\n"
                    f << "  [topspace=#{paperoffset},backspace=#{paperoffset},\n"
                    f << "   header=0pt,footer=0pt,\n"
                    f << "   width=middle,height=middle]\n"
                    if bannerheight.empty? then
                        f << "\\setuplayout[footer=1cm]\n"
                    else
                        f << "\\definelayer[page][width=\\paperwidth,height=\\paperheight]\n"
                        f << "\\setupbackgrounds[page][background=page]\n"
                    end
                    if @commandline.option('nobanner') then
                        f << "\\setuplayout[footer=0cm]\n"
                        f << "\\setupbackgrounds[page][background=]\n"
                    end
                    f << "\\setupexternalfigures\n"
                    f << "  [directory=]\n"
                    f << "\\starttext\n"
                    files.each do |filename|
                        result = @commandline.checkedoption('result','texexec')
                        if (filename !~ /^texexec/io) && (filename !~ /^#{result}/) then
                            report("combination file: #{filename}")
                            cleanname = cleantexfilename(filename).downcase
                            bannerstring = "\\tttf #{cleanname}\\quad\\quad\\currentdate\\quad\\quad\\pagenumber"
                            if bannerheight.empty? then
                                f << "\\setupfootertexts\n"
                                f << "  [#{bannerstring}]\n"
                            else
                                # for the moment we lack a better hook
                                f << "\\setuptexttexts\n"
                                f << "  [{\\setlayerframed[page][preset=middlebottom][frame=off,height=#{bannerheight}]{#{bannerstring}}}]\n"
                            end
                            f << "\\combinepages[#{filename}][nx=#{nx},ny=#{ny}]\n"
                            f << "\\page\n"
                        end
                    end
                    f << "\\stoptext\n"
                    f.close
                    job.setvariable('interface','english')
                    job.setvariable('simplerun',true)
                    # job.setvariable('nooptionfile',true)
                    job.setvariable('files',[job.tempfilename])
                    job.processtex
                else
                    report('no files to list')
                end
            else
                report('no files to list')
            end
            job.cleanuptemprunfiles
        end
    end

    private

    def prepare(job)

        job.booleanvars.each do |k|
            job.setvariable(k,@commandline.option(k))
        end
        job.stringvars.each do |k|
            job.setvariable(k,@commandline.option(k)) unless @commandline.option(k).empty?
        end
        job.standardvars.each do |k|
            job.setvariable(k,@commandline.option(k)) unless @commandline.option(k).empty?
        end
        job.knownvars.each do |k|
            job.setvariable(k,@commandline.option(k)) unless @commandline.option(k).empty?
        end

job.setvariable('given.backend',job.getvariable('backend'))

        if (str = @commandline.option('engine')) && ! str.standard? && ! str.empty? then
            job.setvariable('texengine',str)
        elsif @commandline.oneof('luatex') then
            job.setvariable('texengine','luatex')
        elsif @commandline.oneof('pdfetex','pdftex','pdf') then
            job.setvariable('texengine','pdftex')
        elsif @commandline.oneof('xetex','xtx') then
            job.setvariable('texengine','xetex')
        elsif @commandline.oneof('aleph') then
            job.setvariable('texengine','aleph')
        elsif @commandline.oneof('petex') then
            job.setvariable('texengine','petex')
        else
            job.setvariable('texengine','standard')
        end

        if (str = @commandline.option('backend')) && ! str.standard? && ! str.empty? then
            job.setvariable('backend',str)
        elsif @commandline.oneof('pdfetex','pdftex','pdf','luatex') then
            job.setvariable('backend','pdftex')
        elsif @commandline.oneof('dvipdfmx','dvipdfm','dpx','dpm') then
            job.setvariable('backend','dvipdfmx')
        elsif @commandline.oneof('xetex','xtx') then
            job.setvariable('backend','xetex')
        elsif @commandline.oneof('aleph') then
            job.setvariable('backend','dvipdfmx')
        elsif @commandline.oneof('petex') then
            job.setvariable('backend','dvipdfmx')
        elsif @commandline.oneof('dvips','ps') then
            job.setvariable('backend','dvips')
        elsif @commandline.oneof('xdv') then
            job.setvariable('backend','xdv')
        else
            case job.getvariable('texengine')
                when 'pdfetex'  then job.setvariable('backend','pdftex')
                when 'pdftex'   then job.setvariable('backend','pdftex')
                when 'luatex'   then job.setvariable('backend','pdftex')
                when 'xetex'    then job.setvariable('backend','xetex')
                when 'petex'    then job.setvariable('backend','dvipdfmx')
                when 'aleph'    then job.setvariable('backend','dvipdfmx')
            else
                job.setvariable('backend','standard')
            end
        end

        if (str = @commandline.option('engine')) && ! str.standard? && ! str.empty? then
            job.setvariable('mpsengine',@commandline.option('engine'))
        else
            job.setvariable('mpsengine','standard')
        end

    end

    def cleantexfilename(filename)
        filename.gsub(/([\$\_\#])/) do "\\$1" end.gsub(/([\~])/) do "\\string$1" end
    end

end

# we will make this pluggable, i.e. load plugins from base/tex that
# extend the class and may even add switches
#
# commandline.load_plugins('base/tex')
#
# maybe it's too slow so for a while keep the --pdf* in here

logger      = Logger.new(banner.shift)
commandline = CommandLine.new

commandline.registeraction('make',      'make formats')
commandline.registeraction('check',     'check versions')
commandline.registeraction('process',   'process file')
commandline.registeraction('mptex',     'process mp file')
commandline.registeraction('mpxtex',    'process mpx file')
commandline.registeraction('mpgraphic', 'process mp file to stand-alone graphics')
commandline.registeraction('mpstatic',  'process mp/ctx file to stand-alone graphics')

commandline.registeraction('listing',    'list of file content')
commandline.registeraction('figures',    'generate overview of figures')
commandline.registeraction('modules',    'generate module documentation')
commandline.registeraction('pdfarrange', 'impose pages (booklets)')
commandline.registeraction('pdfselect',  'select pages from file(s)')
commandline.registeraction('pdfcopy',    'copy pages from file(s)')
commandline.registeraction('pdftrim',    'trim pages from file(s)')
commandline.registeraction('pdfcombine', 'combine multiple pages')
commandline.registeraction('pdfsplit',   'split file in pages')

# compatibility switch

class Commands

    include CommandBase

    alias pdfarrange :arrangeoutput
    alias pdfselect  :selectoutput
    alias pdfcopy    :copyoutput
    alias pdftrim    :trimoutput
    alias pdfcombine :combineoutput

end

# so far for compatibility, will move to tex

@@extrastringvars = [
    'pages', 'background', 'backspace', 'topspace', 'boxtype', 'tempdir','bannerheight',
    'printformat', 'method', 'scale', 'selection',
    'combination', 'textwidth', 'addempty', 'logfile',
    'startline', 'endline', 'startcolumn', 'endcolumn', 'scale'
]

@@extrabooleanvars = [
    'centerpage', 'noduplex', 'color', 'pretty',
    'fullscreen', 'screensaver', 'markings'
]

if job = TEX.new(logger) then

    job.setextrastringvars(@@extrastringvars)
    job.setextrabooleanvars(@@extrabooleanvars)

    job.booleanvars.each do |k|
        commandline.registerflag(k)
    end
    job.stringvars.each do |k|
        commandline.registervalue(k,'')
    end
    job.standardvars.each do |k|
        commandline.registervalue(k,'standard')
    end
    job.knownvars.each do |k|
        commandline.registervalue(k,'')
    end

end

class Commands

    alias saved_help help

    def wrap_help(title, vars)
        report("")
        report(title)
        report("")
        r, n = '', 0
        vars.sort.each do |s|
            if n == 5 then
                report(r)
                r, n = '', 1
            else
                n += 1
            end
            r << '  ' + s
        end
        report(r) unless r.empty?
    end

    def help
        saved_help
        if @commandline.option('all') then
            if job = TEX.new(logger) then
                wrap_help("boolean switches:", job.allbooleanvars)
                wrap_help("string switches:", job.allstringvars)
            end
        else
            report('')
            report('--help --all   shows all switches')
        end
    end

end

# todo: register flags -> first one true

commandline.registerflag('pdf')
commandline.registerflag('pdftex')
commandline.registerflag('pdfetex')
commandline.registerflag('luatex')

commandline.registerflag('dvipdfmx')
commandline.registerflag('dvipdfm')
commandline.registerflag('dpx')
commandline.registerflag('dpm')

commandline.registerflag('dvips')
commandline.registerflag('ps')

commandline.registerflag('xetex')
commandline.registerflag('xtx')
commandline.registerflag('xdv')

commandline.registerflag('aleph')

commandline.registerflag('petex')

commandline.registerflag('all')
commandline.registerflag('fast')
commandline.registerflag('sort')

# generic

commandline.registeraction('help')
commandline.registeraction('version')

commandline.registerflag('verbose')

commandline.expand

Commands.new(commandline,logger,banner).execute(commandline.action || 'main') # or just execute()
