A rough draft of ly2dvi32.py is enclosed.

Disclaimer,

The present state relies on the proposed Windows-NT binary
distribution directory structure.  Therefore mileage will vary.
Actually it will most likely catch an exception attempting to locate
titledefs.  But I think it is best just to get it out there so we can
rip it apart.

Please be candid with your comments, for I am new to Python.

Take care my friends,
Jeffrey B. Reed

-- 
Jeffrey B. Reed
[EMAIL PROTECTED]
#!/bin/python

name = 'ly2dvi'
version = '0.0.1'

import sys
import os
import getopt
import re
import string
import time
import glob

class Input:

    def __init__(this):
       this.__fd = None 

    def open(this,file):
        for i in [''] + Props.get('include')[0:]:
            ifile = os.path.join(i,file)
            for j in ['','.ly','.fly']:
                jfile = ifile+j
                try:
                    this.__fd = open( jfile, 'r' )
                    return
                except:
                    pass
        sys.exit('ExitNotFound', file)

    def close(this):
        this.__fd.close()

    def type(this):
        firstline = this.__fd.readline()
        this.__fd.seek(0)
        if ( re.match('% Creator: GNU LilyPond [0-9]+[.0-9]+',firstline ) ):
            return 'output'
        else:
            return 'source'
#
# Scan file for variable settings
#
    def setVars(this):  
        """Scan source file for variable settings"""
        varTable = [
            #   regexp              set method
            #   ------              ----------
            ( 'language',        Props.setLanguage ),
            ( 'latexheaders',    Props.setHeader ),
            ( 'orientation',     Props.setOrientation ),
            ( 'paperpapersize',  Props.setPaperZize ),
            ( 'papertextheight', Props.setTextHeight ),
            ( 'paperlinewidth',  Props.setLineWidth ),
            ( 'filename',        Props.setFilename ),
            ]

        titles={}
        line='prime the pump' # ugh
        while line:
            line=this.__fd.readline()
            m=re.match('\\\\def\\\\mudela([\w]+){(.*)}',line)
            if( m ):
                for var in varTable:
                    if ( m.group(1) == var[0] ):
                        var[1](m.group(2),'file')
                        break
                for var in Props.get('titledefs'):
                    if ( m.group(1) == var ):
                        titles[var]=m.group(2)
                        break
        Props.setTitles(titles,'file')
        this.__fd.seek(0)

class TeXOutput:

    def __init__(this):
       this.__fd = None 
       this.__base = ''
       this.__outfile = ''

    def write(this,str):
        this.__fd.write(str)

    def start(this,file):
        """Start the latex file"""
        now=time.asctime(time.localtime(time.time()))
        linewidth = Props.get('linewidth')
        textheight = Props.get('textheight')

        if ( Props.get('orientation') == 'landscape' ):
            pagewidth = Props.get('pageheight')
            pageheight = Props.get('pagewidth')
        else:
            pageheight = Props.get('pageheight')
            pagewidth = Props.get('pagewidth')
                             
        horizontalMarginArg =  ( (pagewidth - linewidth)/2 )   
        verticalMarginArg =  ( (pageheight - textheight)/2  )

        top="""\
%% Creator: %s
%% Automatically generated from  %s, %s

\\documentclass[%s]{article}

%s 
\\usepackage{geometry}
\\usepackage[latin1]{inputenc} 
%%\\usepackage[T1]{fontenc} 
%s 
%%\\addtolength{\\oddsidemargin}{-1cm} 
%%\\addtolength{\\topmargin}{-1cm} 
%%\\setlength{\\textwidth}{%s} 
%%\\setlength{\\textheight}{%s} 
\\geometry{width=%spt, left=%spt, height=%spt, top=%spt} 
\\input lilyponddefs 
\\input titledefs 
%s 
\\begin{document}
""" % ( program_id(), Props.get('filename'), now, Props.get('papersize'),
        Props.get('language'), Props.get('pagenumber'), linewidth, textheight,
        linewidth, horizontalMarginArg, textheight, verticalMarginArg,
        Props.get('header') )
        
        pathcomp = os.path.splitext(file)
        this.__base = pathcomp[0]
        this.__outfile = '%s.%d%s' % (pathcomp[0], os.getpid(), pathcomp[1])
        try:
            this.__fd = open(this.__outfile,"w")
        except:
            sys.exit('ExitNoWrite', this.__outfile)
        this.write(top)
        this.__mudelaDefs('')
        this.write("""\
\\cmrtwenty% ugh
\\makelilytitle
""") 

    def next(this):
        this.write("""\
\\def\\theopus{}%
\\def\\thepiece{}%
\\def\\mudelaopus{}%
\\def\\mudelapiece{}%
""")
        this.__mudelaDefs("\\def")
        this.write("""\
\\def\\theopus{\\mudelaopus}% ugh
\\def\\thepiece{\\mudelapiece}%
\\makelilypiecetitle
""")

    def __mudelaDefs(this,opt):
        titles = Props.get('titles')
        for key in titles.keys():
            this.write('%s\\mudela%s{%s}%%\n' % (opt,key,titles[key]))

    def end(this):
        outfile=this.__base + '.dvi'
        if ( Props.get('output') != '' ):
            outfile = os.path.join(Props.get('output'), outfile )
            
        this.write("""\
\\vfill\\hfill{\\LilyIdString}
\\end{document}
""")
        this.__fd.close()
        stat = os.system('latex \\nonstopmode \\input %s' %
                         (this.__outfile))
        if ( stat ):
            sys.exit('ExitBadLatex')
        if ( os.path.isfile(outfile) ):
            os.remove(outfile)
        os.rename(this.__base + '.' + str(os.getpid()) + '.dvi', outfile)

class Properties:

    def __set(this,var,value,requester):
        if ( this.__overrideTable[requester] < this.__data[var][1] ):
            return 0
        else:
            this.__data[var] = [value, this.__overrideTable[requester]]

    def get(this,var):
        if ( var == 'include' or var == 'lilyOutputFiles' ):
            return this.__data[var][0][0:]  # return a copy not a ref
        else:
            return this.__data[var][0]
            
    def __init__(this):
        this.__overrideTable = {
            'init'        : 0,
            'environment' : 1,
            'rcfile'      : 2,
            'file'        : 3,
            'commandline' : 4,
            'program'     : 5
            }

        this.__roverrideTable = {} # reverse lookup
        for i in this.__overrideTable.items():
            this.__roverrideTable[i[1]]=i[0]
        
        this.__data = {
            'pagewidth'    :  [597, this.__overrideTable['init']],
            'pageheight'   :  [845, this.__overrideTable['init']],
            'papersize'    :  ['a4paper', this.__overrideTable['init']],
            'textheight'   :  [0, this.__overrideTable['init']],
            'linewidth'    :  [0, this.__overrideTable['init']],
            'orientation'  :  ['portrait', this.__overrideTable['init']],
            'language'     :  ['%', this.__overrideTable['init']],
            'include'      :  [[], this.__overrideTable['init']],
            'debug'        :  [0, this.__overrideTable['init']],
            'keeplilypond' :  [0, this.__overrideTable['init']],
            'keeply2dvi'   :  [0, this.__overrideTable['init']],
            'pagenumber'   :  ['%', this.__overrideTable['init']],
            'separate'     :  [0, this.__overrideTable['init']],
            'output'       :  ['', this.__overrideTable['init']],
            'header'       :  ['%', this.__overrideTable['init']],
            'dependencies' :  [0, this.__overrideTable['init']],
            'root'         :  ['', this.__overrideTable['init']],
            'tmp'          :  ['d:\tmp', this.__overrideTable['init']],
            'filename'     :  ['', this.__overrideTable['init']],
            'titledefs'    :  [[], this.__overrideTable['init']],
            'titles'       :  [{}, this.__overrideTable['init']],
            'lilyOutputFiles' :  [[], this.__overrideTable['init']],
            }

        if( os.environ.has_key('LILYINCLUDE') ):
            tmp=this.get('include')
            for s in string.split(os.environ['LILYINCLUDE'],os.pathsep):
                tmp.append(s)
            this.__set('include', tmp, 'environment')    

        if( os.environ.has_key('LILYPOND')):
            this.__set('root',os.environ['LILYPOND'], 'environment')
        else:
            p=os.path.split(sys.argv[0])
            p=os.path.split(p[0])
            this.__set('root',p[0],'init')

        os.environ['TEXINPUTS']= os.path.join(this.get('root'), 'texmf',
                                                  'tex', 'lilypond' )

        if( os.environ.has_key('TMP') ):
            this.__set('tmp',os.environ['TMP'],'environment')

        if( not os.environ.has_key('HOME') ):
            if ( os.environ.has_key('HOMEDRIVE') and \
                 os.environ.has_key('HOMEPATH')):
                os.environ['HOME'] = os.environ['HOMEDRIVE'] + \
                                     os.environ['HOMEPATH']
            else:
                os.environ['HOME'] = os.curdir
        

        file = os.path.join(this.get('root'), 'texmf', 'tex', 'lilypond',
                            'titledefs.tex' )
        try:
            fd=open( file, "r" )
        except:
            sys.exit('ExitNotFound',file)
            
        mudefs=[]    
        line='prime the pump' # ugh
        while line:
            line=fd.readline()
            m=re.match('\\\\newcommand\*{\\\\mudela([\w]+)}',line)
            if( m ):
                mudefs.append(m.group(1))
        fd.close
        this.__set('titledefs', mudefs, 'init')

#
# Read rc file
#
    def rcfile(this):
        """Read RCfile"""
        varTable = [
            #   name              set method
            #   ----              ----------
            ( 'LILYPOND',       this.setInclude ),
            ( 'LANGUAGE',       this.setLanguage ),
            ( 'LATEXHF',        this.setHeader ),
            ( 'ORIENTATION',    this.setOrientation ),
            ( 'OUTPUTDIR',      this.setOutput ),
            ( 'PAPERSIZE',      this.setPaperZize ),
            ( 'PHEIGHT',        this.setTextHeight ),
            ( 'TMP',            this.setTmp ),
            ( 'PWIDTH',         this.setLineWidth ),
            ]

        for d in [os.path.join(this.get('root'),'share','lilypond'), \
                  os.environ['HOME'], os.curdir ]:
            file=os.path.join(d,'.lilyrc')
            try:
                fd = open( file, 'r' )
            except:
                continue
            
            line='prime the pump' # ugh
            while line:
                line=fd.readline()
                if( re.match('#.*',line) ):
                    continue
                m=re.search('([\w]+)=(.*)',line)
                if( m ):
                    for var in varTable:
                        if ( m.group(1) == var[0] ):
                            var[1](m.group(2),'rcfile')
                            break
            fd.close

#
# Set paper size
#
    def setPaperZize(this,size,requester):
        paperTable = [
            # regex          width    height      name
            # -----          -----    ------      ----
            ( 'a0.*',        2389,    3381,    'a0paper' ),
            ( 'a1$|a1p.*',   1690,    2389,    'a1paper' ),
            ( 'a2.*',        1194,    1690,    'a2paper' ),
            ( 'a3.*',        845,     1194,    'a3paper' ),
            ( 'a4.*',        597,     845,     'a4paper' ),
            ( 'a5.*',        423,     597,     'a5paper' ),
            ( 'a6.*',        298,     423,     'a6paper' ),
            ( 'a7.*',        211,     298,     'a7paper' ),
            ( 'a8.*',        305,     211,     'a8paper' ),
            ( 'a9.*',        105,     305,     'a9paper' ),
            ( 'a10.*',       74,      105,     'a10paper' ),
            ( 'b0.*',        2847,    4023,    'b0paper' ),
            ( 'b1.*',        2012,    2847,    'b1paper' ),
            ( 'b2.*',        1423,    2012,    'b2paper' ),
            ( 'b3.*',        1006,    1423,    'b3paper' ),
            ( 'b4.*',        712,     1006,    'b4paper' ),
            ( 'b5.*',        503,     712,     'b5paper' ),
            ( 'archA$',      650,     867,     'archApaper' ),
            ( 'archB$',      867,     1301,    'archBpaper' ),
            ( 'archC$',      1301,    1734,    'archCpaper' ),
            ( 'archD$',      1734,    2602,    'archDpaper' ),
            ( 'archE$',      2602,    3469,    'archEpaper' ),
            ( 'flsa$|flse$', 614,     940,     'flsapaper' ),
            ( 'halfletter$', 397,     614,     'halfletterpaper' ),
            ( 'ledger$',     1229,    795,     'ledgerpaper' ),
            ( 'legal$',      614,     1012,    'legalpaper' ),
            ( 'letter$',     614,     795,     'letterpaper' ),
            ( 'note$',       542,     723,     'notepaper' )
            ]

        found=0
        for paper in paperTable:
            if ( re.match(paper[0],size) ):
                found=1
                this.__set('pagewidth',paper[1],requester)
                this.__set('pageheight',paper[2],requester)
                this.__set('papersize',paper[3],requester)
                break

        if ( not found ):
            sys.exit('ExitBadPaper',size)

#
# set Text Height
#
    def setTextHeight(this,size,requester):
        m=re.match('([0-9][.0-9]*)(cm|mm|pt|$)',size)
        if( m ):
            if ( m.group(2) == 'cm' ):
                this.__set('textheight',\
                           float(m.group(1)) * 72.27/2.54, requester )
            elif ( m.group(2) == 'mm' ):
                this.__set('textheight',\
                           float(m.group(1)) * 72.27/25.4, requester )
            elif ( m.group(2) == 'pt' ):
                this.__set('textheight', float(m.group(1)), requester )
            elif ( m.group(2) == '' ):
                this.__set('textheight', float(m.group(1)), requester )
            else:
                sys.exit('ExitBadHeight', m.group(2))
        else:           
            sys.exit('ExitBadHeight', size)
#
# set Text Width
#
    def setLineWidth(this,size,requester):
        m=re.match('([0-9][.0-9]*)(cm|mm|pt|$)',size)
        if( m ):
            if ( m.group(2) == 'cm' ):
                this.__set('linewidth', \
                float(m.group(1)) * 72.27/2.54, requester )
            elif ( m.group(2) == 'mm' ):
                this.__set('linewidth', \
                float(m.group(1)) * 72.27/25.4, requester )
            elif ( m.group(2) == 'pt' ):
                this.__set('linewidth', float(m.group(1)), requester )
            elif ( m.group(2) == '' ):
                this.__set('linewidth', float(m.group(1)), requester )
            else:
                sys.exit('ExitBadWidth', m.group(2))
        else:           
            sys.exit('ExitBadWidth', size)
#
# Set Orientation
#
    def setOrientation(this,orient,requester):
        if ( orient == 'landscape' or orient == 'portrait' ):
            this.__set('orientation', orient, requester )
        else:
            sys.exit('ExitBadOrient', orient)
#
# Set Language
#
    def setLanguage(this,lang,requester):
        this.__set('language', '\\usepackage[%s]{babel}' % (lang), requester )
#
# Append Include
#
    def setInclude(this,inc, requester):
        tmp = this.get('include')
        tmp.append(inc)
        this.__set('include', tmp, requester )
#
# Set debug flag
#
    def setDebug(this,requester):
        this.__set('debug',1,requester)

#
# Clear debug flag
#
    def clearDebug(this, requester):
        this.__set('debug',0,requester)
#
# Set Keeplilypond flag
#
    def setKeeplilypond(this, requester):       
        this.__set('keeplilypond',1,requester)

#
# Clear Keeplilypond flag
#
    def clearKeeplilypond(this, requester):     
        this.__set('keeplilypond',0,requester)

#
# Set Keeply2dvi flag
#
    def setKeeply2dvi(this, requester): 
        this.__set('keeply2dvi',1,requester)
#
# Clear Keeply2dvi flag
#
    def clearKeeply2dvi(this, requester):       
        this.__set('keeply2dvi',0,requester)
#
# Set No page number flag
#
    def setNonumber(this, requester):   
        this.__set('pagenumber','\\pagestyle{empty}',requester)

#
# Clear No page number flag
#
    def clearNonumber(this, requester): 
        this.__set('pagenumber','%',requester)
#
# Set separate flag
#
    def setSeparate(this, requester):   
        this.__set('separate',1,requester)

#
# Clear separate flag
#
    def clearSeparate(this, requester): 
        this.__set('separate',0,requester)

#
# Set output directory name
#
    def setOutput(this,out,requester):
        this.__set('output',out,requester)

#
# Set latex header name
#
    def setHeader(this,head, requester):
        this.__set('header',head,requester)
#
# Set Dependencies flag to generate makefile dependencies
#
    def setDependencies(this, requester):       
        this.__set('dependencies',1,requester)

#
# Clear Dependencies flag
#
    def clearDependencies(this, requester):     
        this.__set('dependencies',0,requester)
#
# Set tmp directory
#
    def setTmp(this,dir, requester):    
        this.__set('tmp',dir,requester)
#
# Set mudela source file name
#
    def setFilename(this,file, requester):      
        this.__set('filename',file,requester)
#
# Set title commands
#
    def setTitles(this,titles, requester):      
        this.__set('titles',titles,requester)

    def addLilyOutputFiles(this,file,requester):
        tmp = this.get('lilyOutputFiles')
        tmp.append(file)
        this.__set('lilyOutputFiles',tmp,requester)

    def printProps(this):
        for key in this.__data.keys():
            print "%s <%s>:<%s>" % (key,this.get(key),
                                    this.__roverrideTable[this.__data[key][1]])

def getLilyopts():
    if( len(Props.get('include')) > 0 ):
        inc = '-I ' + string.join(Props.get('include'),os.pathsep)
    else:
        inc = ''
        if ( Props.get('dependencies') ):
            dep=' -d'
        else:
            dep=''
        return inc + dep

def writeLilylog(contents):
    if ( Props.get('keeplilypond') ):
        file='lilylog.' + str(os.getpid())
        output = Props.get('output')
        if ( output != '' ):
            file = os.path.join( output, file )
        try:
            fd = open( file, 'w' )
        except:
            sys.exit('ExitNoWrite', file)
        fd.write(contents)
        fd.close()

def getTeXFile(contents):
    m = re.search('^TeX output to (.+)\.tex', contents,re.M)
    if ( m ):
        return ( m.group(1)+'.tex' )
    else:
        sys.exit('ExitNoTeXName')

def program_id ():
    return name + ' ' + version;


def mailaddress():
    try:
        return os.environ['MAILADDRESS']
    except KeyError:
        return '(address unknown)'


def identify ():
    sys.stderr.write (program_id () + '\n')

def help ():
    sys.stderr.write (
        'Generate dvi file from mudela or lilypond output\n'
        'Usage: ' + name + ' [OPTION]... [FILE]...\n'
        '\n'
        'Options:\n'
        '  -D,--debug           increase verbosity\n'
        '  -F,--headers=        name of additional LaTeX headers file\n'
        '  -H,--Height=         set paper height (points) (see manual page)\n'
        '  -I,--include=DIR     add DIR to LilyPond\'s search path\n'
        '  -K,--keeplilypond    keep lilypond output files\n'
        '  -L,--landscape       set landscape orientation\n'
        '  -N,--nonumber        switch off page numbering\n'
        '  -O,--orientation=    set orientation (obsolete - use -L instead)\n'
        '  -W,--Width=          set paper width (points) (see manual page)\n'
        '  -d,--dependencies    tell lilypond make a dependencies file\n'
        '  -h,--help            this help text\n'
        '  -k,--keeply2dvi      keep ly2dvi output files\n'
        '  -l,--language=       give LaTeX language (babel)\n'
        '  -o,--output=         set output directory\n'
        '  -p,--papersize=      give LaTeX papersize (eg. a4)\n'
        '  -s,--separate        run all files separately through LaTeX\n'
        '\n'
        'files may be (a mix of) input to or output from lilypond(1)\n'
        )


def main():
    """Generate dvi files from lilypond source/output"""

    infile = Input()
    outfile = TeXOutput()
    texInputFiles=[]

    Props.rcfile()
    (options, files) = getopt.getopt (sys.argv[1:],
                                      'DF:H:I:KLNW:dhkl:o:p:s',
                                      ['debug', 'headers=', 'Height=',
                                       'include=', 'keeplilypond', 'landscape',
                                       'nonumber', 'Width=', 'dependencies',
                                       'help', 'keeply2dvi', 'language=',
                                       'output=', 'papersize=', 'separate'])
    for opt in options:
        o = opt[0]
        a = opt[1]
        if o == '--debug' or o == '-D':
            Props.setDebug('commandline')
        elif o == '--headers' or o == '-F':
            Props.setHeader(a,'commandline')
        elif o == '--include' or o == '-I':
            Props.setInclude(a,'commandline')
        elif o == '--Height' or o == '-H':
            Props.setTextHeight(a,'commandline')
        elif o == '--keeplilypond' or o == '-K':
            Props.setKeeplilypond('commandline')
        elif o == '--landscape' or o == '-L':
            Props.setOrientation('landscape','commandline')
        elif o == '--nonumber' or o == '-N':
            Props.setNonumber('commandline')
        elif o == '--Width' or o == '-W':
            Props.setLineWidth(a,'commandline')
        elif o == '--dependencies' or o == '-d':
            Props.setDependencies('commandline')
        elif o == '--help' or o == '-h':
            help()
            return 0
        elif o == '--keeply2dvi' or o == '-k':
            Props.setKeeply2dvi('commandline')
        elif o == '--language' or o == '-l':
            Props.setLanguage(a,'commandline')
        elif o == '--output' or o == '-o':
            Props.setOutput(a,'commandline')
        elif o == '--papersize' or o == '-p':
            Props.setPaperZize(a,'commandline')
        elif o == '--separate' or o == '-s':
            Props.setSeparate('commandline')

    if( len(files) ):    
        for file in files:
            infile.open(file)
            type = infile.type()
            infile.close()
            if ( type == 'source' ):
                cmd = 'lilypond %s %s 2>&1' % (getLilyopts(), file)
                fd = os.popen( cmd , 'r' )
                log = fd.read()
                stat = fd.close()
                print log
                if( stat ):
                    sys.exit('ExitBadLily', cmd )
                texFile=getTeXFile(log)
                writeLilylog(log)
                Props.addLilyOutputFiles(texFile,'program')
                texInputFiles.append(texFile)
            else:
                texInputFiles.append(file)

        firstfile=1
        for file in texInputFiles:
            infile.open(file)
            infile.setVars() # first pass set variables
            infile.close()
            Props.printProps()
            if ( firstfile ):
                outfile.start(file)
            else:
                outfile.next()
            outfile.write("""\
\\input{%s}
""" % (file))
            if( Props.get('separate') ):
                outfile.end()
            else:
                firstfile=0
        if( not Props.get('separate') ):
            outfile.end()
    else:
        help()
        sys.exit('ExitBadArgs','No files specified')

#
# Exit values
#
ExitTable = {
    'ExitInterupt'         : ['Ouch!', 1 ],
    'ExitBadArgs'          : ['Wrong number of arguments', 2 ],
    'ExitNotFound'         : ['File not found', 3 ],
    'ExitBadPaper'         : ['Unknown papersize', 4 ],
    'ExitBadHeight'        : ['Invalid Height specification', 5 ],
    'ExitBadWidth'         : ['Invalid Width specification', 6 ],
    'ExitBadOrient'        : ['Invalid Orientation specification', 7 ],
    'ExitNoWrite'          : ['Permission denied', 8 ],
    'ExitNoTeXName'        : ['hmm, I could not find an output file name', 9 ],
    'ExitBadLily'          : ['Lilypond failed', 10 ],
    'ExitBadLatex'         : ['Latex failed', 11 ],
    'ExitUnknown'          : ['Unknown Exit Code', 20 ],
    }

def cleanup():
    lilyfiles = []
    tmpfiles = []
    if ( not Props.get('keeplilypond') ):
        lilyfiles = Props.get('lilyOutputFiles')
    if ( not Props.get('keeply2dvi') ):
        tmpfiles = glob.glob('*.' + str(os.getpid()) + '.*' )
    for file in lilyfiles + tmpfiles:
        if ( os.path.isfile(file) ):
            os.remove(file)
try:
    identify()
    Props = Properties()
    main()

except KeyboardInterrupt:
    print ExitTable['ExitInterupt'][0]
    cleanup()
    sys.exit(ExitTable['ExitInterupt'][1])

except SystemExit, errno:
    if ( ExitTable.has_key(errno.args[0]) ):
        msg = ExitTable[errno.args[0]]
    else:
        msg = ExitTable['ExitUnknown']
    if ( len(errno.args) > 1 ):    
        sys.stderr.write( '%s: %s: %s\n' % (name, msg[0], errno.args[1]))
    else:
        sys.stderr.write( '%s %s\n' % (name, msg[0]))
    cleanup()
    sys.exit(msg[1])
else:
    cleanup()

    

                                   

Reply via email to