texexec.rb / last modification: 2020-01-30 14:16
#!/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,&#39;lib') ; $:.uniq!

require &#39;fileutils'
# require 'ftools'     # needed ?

require &#39;base/switch'
require &#39;base/logger'
require &#39;base/variables'
require &#39;base/system'

require &#39;base/state' # needed ?
require &#39;base/file'  # needed ?

require &#39;base/tex'
require &#39;base/texutil'
require &#39;base/kpse'

class Commands

    include CommandBase

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

    def check
        if job = TEX.new(logger) then
            job.checkcontext
            job.inspect && Kpse.inspect  if @commandline.option(&#39;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(&#39;files',@commandline.arguments)
            prepare(job)
            job.processtex
            job.inspect && Kpse.inspect if @commandline.option(&#39;verbose')
            seterror if job.error?
        end
    end

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

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

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

    def mpstatic
        if job = TEX.new(logger) then
            job.setvariable(&#39;filename',@commandline.arguments.first)
            prepare(job)
            job.processmpstatic
            job.inspect && Kpse.inspect  if @commandline.option(&#39;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(&#39;sort') then @commandline.arguments.sort else @commandline.arguments end
            if files.length > 0 then
                if f = File.open(job.tempfilename(&#39;tex'),'w') then
                    backspace = @commandline.checkedoption(&#39;backspace', '1.5cm')
                    topspace  = @commandline.checkedoption(&#39;topspace', '1.5cm')
                    pretty    = @commandline.option(&#39;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(&#39;interface','english')
                    job.setvariable(&#39;simplerun',true)
                    # job.setvariable('nooptionfile',true)
                    job.setvariable(&#39;files',[job.tempfilename])
                    job.processtex
                else
                    report(&#39;no files to list')
                end
            else
                report(&#39;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(&#39;fast')
            files =  if @commandline.option(&#39;sort') then @commandline.arguments.sort else @commandline.arguments end
            if fast or (files.length > 0) then
                if f = File.open(job.tempfilename(&#39;tex'),'w') then
                    files.delete("texexec.pdf")
                    # Kpse.runscript('rlxtools', ['--identify','--collect'], files.join(' 9;)) unless fast
                    system("texmfstart rlxtools --identify --collect #{files.join(' ')}")
                    figures     = @commandline.checkedoption(&#39;method', 'a').downcase
                    paperoffset = @commandline.checkedoption(&#39;paperoffset', '0pt')
                    backspace   = @commandline.checkedoption(&#39;backspace', '1.5cm')
                    topspace    = @commandline.checkedoption(&#39;topspace', '1.5cm')
                    boxtype     = @commandline.checkedoption(&#39;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(&#39;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(&#39;interface','english')
                    job.setvariable(&#39;simplerun',true)
                    job.setvariable(&#39;files',[job.tempfilename])
                    job.processtex
                    # File.silentdelete('rlxtools.rli') unless job.getvariable('keep')
                else
                    report(&#39;no figures to show')
                end
            else
                report(&#39;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(&#39;sort') then @commandline.arguments.sort else @commandline.arguments end
            msuffixes = [&#39;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(&#39;tex'),'w') then
                                if File.suffix(ffname) =~ /^(mkii|mkiv)$/o then
                                    markfile = $1
                                else
                                    markfile = nil
                                end
                                # Kpse.runscript('ctxtools',['--document'],ffname)
                                system("texmfstart ctxtools --document #{ffname}")
                                if ted = File.silentopen(File.suffixed(ffname,&#39;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(&#39;interface','english') # redundant
                                # job.setvariable('simplerun',true)
                                # job.setvariable('nooptionfile',true)
                                job.setvariable(&#39;files',[job.tempfilename])
                                result = File.unsuffixed(File.basename(ffname))
                                if markfile then
                                    result = result+&#39;-'+markfile
                                end
                                job.setvariable(&#39;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(&#39;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(/\..*?$/,&#39;')
                tempfile = File.suffixed(job.tempfilename,&#39;tex')
                if basename != filename then
                    info = `pdfinfo #{filename}`
                    if info =~ /Pages:\s*(\d+)/ then
                        nofpages = $1.to_i
                        result = @commandline.checkedoption(&#39;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(&#39;result',"#{result}-#{n}")
                                job.setvariable(&#39;interface','english') # redundant
                                job.setvariable(&#39;simplerun',true)
                                job.setvariable(&#39;purge',true)
                                job.setvariable(&#39;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(&#39;sort') then @commandline.arguments.sort else @commandline.arguments end
            if files.length > 0 then
                if f = File.open(job.tempfilename(&#39;tex'),'w') then
                    emptypages  = @commandline.checkedoption(&#39;addempty', '')
                    paperoffset = @commandline.checkedoption(&#39;paperoffset', '0cm')
                    textwidth   = @commandline.checkedoption(&#39;textwidth', '0cm')
                    backspace   = @commandline.checkedoption(&#39;backspace', '0cm')
                    topspace    = @commandline.checkedoption(&#39;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(&#39;marking')
                    f << "       width=middle,\n"
                    f << "      height=middle,\n"
                    f << "    location=middle,\n"
                    f << "      header=0pt,\n"
                    f << "      footer=0pt]\n"
                    unless @commandline.option(&#39;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(&#39;interface','english')
                    job.setvariable(&#39;simplerun',true)
                    job.setvariable(&#39;arrange',true)
                    # job.setvariable('nooptionfile',true)
                    job.setvariable(&#39;files',[job.tempfilename])
                    job.processtex
                else
                    report(&#39;no files to arrange')
                end
            else
                report(&#39;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(&#39;sort') then @commandline.arguments.sort else @commandline.arguments end
            if files.length > 0 then
                if f = File.open(job.tempfilename(&#39;tex'),'w') then
                    selection   = @commandline.checkedoption(&#39;selection', '')
                    paperoffset = @commandline.checkedoption(&#39;paperoffset', '0cm')
                    textwidth   = @commandline.checkedoption(&#39;textwidth', '0cm')
                    backspace   = @commandline.checkedoption(&#39;backspace', '0cm')
                    topspace    = @commandline.checkedoption(&#39;topspace', '0cm')
                    paperformat = @commandline.checkedoption(&#39;paperformat', 'A4*A4').split(/[\*x]/o)
                    from, to = paperformat[0] || &#39;A4', paperformat[1] || paperformat[0] || 'A4'
                    if from == &#39;fit' or to == 'fit' then
                        f << "\\getfiguredimensions[#{files.first}]\n"
                        if from == &#39;fit' then
                            f << "\\expanded{\\definepapersize[from-fit][width=\\figurewidth,height=\\figureheight]}\n"
                            from = &#39;from-fit'
                        end
                        if to == &#39;fit' then
                            f << "\\expanded{\\definepapersize[to-fit][width=\\figurewidth,height=\\figureheight]}\n"
                            to = &#39;to-fit'
                        end
                    end
                    job.setvariable(&#39;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(&#39;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(&#39;interface','english')
                    job.setvariable(&#39;simplerun',true)
                    # job.setvariable('nooptionfile',true)
                    job.setvariable(&#39;files',[job.tempfilename])
                    job.processtex
                else
                    report(&#39;no files to selectt')
                end
            else
                report(&#39;no files to select')
            end
            job.cleanuptemprunfiles
        end
    end

    def copyoutput
        copyortrim(false,&#39;copy')
    end

    def trimoutput
        copyortrim(true,&#39;trim')
    end

    def copyortrim(trim=false,what=&#39;unknown')
        if job = TEX.new(logger) then
            prepare(job)
            job.cleanuptemprunfiles
            files =  if @commandline.option(&#39;sort') then @commandline.arguments.sort else @commandline.arguments end
            if files.length > 0 then
                if f = File.open(job.tempfilename(&#39;tex'),'w') then
                    scale = @commandline.checkedoption(&#39;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(&#39;paperoffset', '0cm')
                    f << "\\starttext\n"
                    files.each do |filename|
                        result = @commandline.checkedoption(&#39;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(&#39;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(&#39;interface','english')
                    job.setvariable(&#39;simplerun',true)
                    # job.setvariable('nooptionfile',true)
                    job.setvariable(&#39;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(&#39;sort') then @commandline.arguments.sort else @commandline.arguments end
            if files.length > 0 then
                if f = File.open(job.tempfilename(&#39;tex'),'w') then
                    paperoffset = @commandline.checkedoption(&#39;paperoffset', '0cm')
                    combination = @commandline.checkedoption(&#39;combination','2*2').split(/[\*x]/o)
                    paperformat = @commandline.checkedoption(&#39;paperformat', 'A4*A4').split(/[\*x]/o)
                    bannerheight = @commandline.checkedoption(&#39;bannerheight', '')
                    pdftitle = @commandline.checkedoption(&#39;pdftitle', '')
                    nx, ny = combination[0] || &#39;2', combination[1] || combination[0] || '2'
                    from, to = paperformat[0] || &#39;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(&#39;nobanner') then
                        f << "\\setuplayout[footer=0cm]\n"
                        f << "\\setupbackgrounds[page][background=]\n"
                    end
                    f << "\\setupexternalfigures[directory=]\n"
                    if not pdftitle.empty? then
                        f << "\\setupinteraction[state=start,title={#{pdftitle}}]\n"
                    end
                    f << "\\starttext\n"
                    files.each do |filename|
                        result = @commandline.checkedoption(&#39;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(&#39;interface','english')
                    job.setvariable(&#39;simplerun',true)
                    # job.setvariable('nooptionfile',true)
                    job.setvariable(&#39;files',[job.tempfilename])
                    job.processtex
                else
                    report(&#39;no files to list')
                end
            else
                report(&#39;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(&#39;given.backend',job.getvariable('backend'))

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

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

        if (str = @commandline.option(&#39;engine')) && ! str.standard? && ! str.empty? then
            job.setvariable(&#39;mpsengine',@commandline.option('engine'))
        else
            job.setvariable(&#39;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(&#39;make',      'make formats')
commandline.registeraction(&#39;check',     'check versions')
commandline.registeraction(&#39;process',   'process file')
commandline.registeraction(&#39;mptex',     'process mp file')
commandline.registeraction(&#39;mpxtex',    'process mpx file')
commandline.registeraction(&#39;mpgraphic', 'process mp file to stand-alone graphics')
commandline.registeraction(&#39;mpstatic',  'process mp/ctx file to stand-alone graphics')

commandline.registeraction(&#39;listing',    'list of file content')
commandline.registeraction(&#39;figures',    'generate overview of figures')
commandline.registeraction(&#39;modules',    'generate module documentation')
commandline.registeraction(&#39;pdfarrange', 'impose pages (booklets)')
commandline.registeraction(&#39;pdfselect',  'select pages from file(s)')
commandline.registeraction(&#39;pdfcopy',    'copy pages from file(s)')
commandline.registeraction(&#39;pdftrim',    'trim pages from file(s)')
commandline.registeraction(&#39;pdfcombine', 'combine multiple pages')
commandline.registeraction(&#39;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 = [
    &#39;pages', 'background', 'backspace', 'topspace', 'boxtype', 9;tempdir&#39;,'bannerheight',
    &#39;printformat', 'method', 'scale', 'selection',
    &#39;combination', 'textwidth', 'addempty', 'logfile',
    &#39;startline', 'endline', 'startcolumn', 'endcolumn', 'scale'
]

extrabooleanvars = [
    &#39;centerpage', 'noduplex', 'color', 'pretty',
    &#39;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,&#39;')
    end
    job.standardvars.each do |k|
        commandline.registervalue(k,&#39;standard')
    end
    job.knownvars.each do |k|
        commandline.registervalue(k,&#39;')
    end

end

class Commands

    alias saved_help help

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

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

end

# todo: register flags -> first one true

commandline.registerflag(&#39;pdf')
commandline.registerflag(&#39;pdftex')
commandline.registerflag(&#39;pdfetex')

commandline.registerflag(&#39;dvipdfmx')
commandline.registerflag(&#39;dvipdfm')
commandline.registerflag(&#39;dpx')
commandline.registerflag(&#39;dpm')

commandline.registerflag(&#39;dvips')
commandline.registerflag(&#39;ps')

commandline.registerflag(&#39;xetex')
commandline.registerflag(&#39;xtx')
commandline.registerflag(&#39;xdv')

commandline.registerflag(&#39;aleph')

commandline.registerflag(&#39;petex')

commandline.registerflag(&#39;all')
commandline.registerflag(&#39;fast')
commandline.registerflag(&#39;sort')

# generic

commandline.registeraction(&#39;help')
commandline.registeraction(&#39;version')

commandline.registerflag(&#39;verbose')

commandline.expand

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