]> git.lyx.org Git - lyx.git/blob - lib/configure.py
add another typename, see r20470
[lyx.git] / lib / configure.py
1 #! /usr/bin/env python
2 # -*- coding: utf-8 -*-
3 #
4 # file configure.py
5 # This file is part of LyX, the document processor.
6 # Licence details can be found in the file COPYING.
7
8 # \author Bo Peng
9 # Full author contact details are available in file CREDITS.
10
11 import sys, os, re, shutil, glob
12
13
14 class Tee:
15     ''' Writing to a Tee object will write to all file objects it keeps.
16         That is to say, writing to Tee(sys.stdout, open(logfile, 'w')) will
17         write to sys.stdout as well as a log file.
18     '''
19     def __init__(self, *args):
20         self.files = args
21
22     def write(self, data):
23         for f in self.files:
24             result = f.write(data)
25         return result
26
27     def writelines(self, seq):
28         for i in seq:
29             self.write(i)
30
31
32 def writeToFile(filename, lines, append = False):
33     " utility function: write or append lines to filename "
34     if append:
35         file = open(filename, 'a')
36     else:
37         file = open(filename, 'w')
38     file.write(lines)
39     file.close()
40
41
42 def addToRC(lines):
43     ''' utility function: shortcut for appending lines to outfile
44         add newline at the end of lines.
45     '''
46     if lines.strip() != '':
47         writeToFile(outfile, lines + '\n', append = True)
48
49
50 def removeFiles(filenames):
51     '''utility function: 'rm -f'
52         ignore errors when file does not exist, or is a directory.
53     '''
54     for file in filenames:
55         try:
56             os.remove(file)
57         except:
58             pass
59
60
61 def cmdOutput(cmd):
62     '''utility function: run a command and get its output as a string
63         cmd: command to run
64     '''
65     fout = os.popen(cmd)
66     output = fout.read()
67     fout.close()
68     return output.strip()
69
70
71 def setEnviron():
72     ''' I do not really know why this is useful, but we might as well keep it.
73         NLS nuisances.
74         Only set these to C if already set.  These must not be set unconditionally
75         because not all systems understand e.g. LANG=C (notably SCO).
76         Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
77         Non-C LC_CTYPE values break the ctype check.
78     '''
79     os.environ['LANG'] = os.getenv('LANG', 'C')
80     os.environ['LC'] = os.getenv('LC_ALL', 'C')
81     os.environ['LC_MESSAGE'] = os.getenv('LC_MESSAGE', 'C')
82     os.environ['LC_CTYPE'] = os.getenv('LC_CTYPE', 'C')
83
84
85 def createDirectories():
86     ''' Create the build directories if necessary '''
87     for dir in ['bind', 'clipart', 'doc', 'examples', 'images', 'kbd', \
88         'layouts', 'scripts', 'templates', 'ui' ]:
89         if not os.path.isdir( dir ):
90             try:
91                 os.mkdir( dir)
92             except:
93                 print "Failed to create directory ", dir
94                 sys.exit(1)
95
96
97 def checkTeXPaths():
98     ''' Determine the path-style needed by the TeX engine on Win32 (Cygwin) '''
99     windows_style_tex_paths = ''
100     if os.name == 'nt' or sys.platform == 'cygwin':
101         from tempfile import mkstemp
102         fd, tmpfname = mkstemp(suffix='.ltx')
103         if os.name == 'nt':
104             inpname = tmpfname.replace('\\', '/')
105         else:
106             inpname = cmdOutput('cygpath -m ' + tmpfname)
107         logname = os.path.basename(inpname.replace('.ltx', '.log'))
108         inpname = inpname.replace('~', '\\string~')
109         os.write(fd, r'\relax')
110         os.close(fd)
111         latex_out = cmdOutput(r'latex "\nonstopmode\input{%s}"' % inpname)
112         if 'Error' in latex_out:
113             print "configure: TeX engine needs posix-style paths in latex files"
114             windows_style_tex_paths = 'false'
115         else:
116             print "configure: TeX engine needs windows-style paths in latex files"
117             windows_style_tex_paths = 'true'
118         removeFiles([tmpfname, logname, 'texput.log'])
119     return windows_style_tex_paths
120
121
122 ## Searching some useful programs
123 def checkProg(description, progs, rc_entry = [], path = [], not_found = ''):
124     '''
125         This function will search a program in $PATH plus given path
126         If found, return directory and program name (not the options).
127
128         description: description of the program
129
130         progs: check programs, for each prog, the first word is used
131             for searching but the whole string is used to replace
132             %% for a rc_entry. So, feel free to add '$$i' etc for programs.
133
134         path: additional pathes
135
136         rc_entry: entry to outfile, can be
137             1. emtpy: no rc entry will be added
138             2. one pattern: %% will be replaced by the first found program,
139                 or '' if no program is found.
140             3. several patterns for each prog and not_found. This is used 
141                 when different programs have different usages. If you do not 
142                 want not_found entry to be added to the RC file, you can specify 
143                 an entry for each prog and use '' for the not_found entry.
144
145         not_found: the value that should be used instead of '' if no program
146             was found
147
148     '''
149     # one rc entry for each progs plus not_found entry
150     if len(rc_entry) > 1 and len(rc_entry) != len(progs) + 1:
151         print "rc entry should have one item or item for each prog and not_found."
152         sys.exit(2)
153     print 'checking for ' + description + '...'
154     ## print '(' + ','.join(progs) + ')',
155     for idx in range(len(progs)):
156         # ac_prog may have options, ac_word is the command name
157         ac_prog = progs[idx]
158         ac_word = ac_prog.split(' ')[0]
159         print '+checking for "' + ac_word + '"... ',
160         path = os.environ["PATH"].split(os.pathsep) + path
161         for ac_dir in path:
162             # check both ac_word and ac_word.exe (for windows system)
163             if os.path.isfile( os.path.join(ac_dir, ac_word) ) or \
164                 os.path.isfile( os.path.join(ac_dir, ac_word + ".exe") ):
165                 print ' yes'
166                 # write rc entries for this command
167                 if len(rc_entry) == 1:
168                     addToRC(rc_entry[0].replace('%%', ac_prog))
169                 elif len(rc_entry) > 1:
170                     addToRC(rc_entry[idx].replace('%%', ac_prog))
171                 return [ac_dir, ac_word]
172         # if not successful
173         print ' no'
174     # write rc entries for 'not found'
175     if len(rc_entry) > 0:  # the last one.
176         addToRC(rc_entry[-1].replace('%%', not_found))
177     return ['', not_found]
178
179
180 def checkViewer(description, progs, rc_entry = [], path = []):
181     ''' The same as checkProg, but for viewers and editors '''
182     return checkProg(description, progs, rc_entry, path, not_found = 'auto')
183
184
185 def checkDTLtools():
186     ''' Check whether DTL tools are available (Windows only) '''
187     # Find programs! Returned path is not used now
188     if ((os.name == 'nt' or sys.platform == 'cygwin') and
189             checkProg('DVI to DTL converter', ['dv2dt']) != ['', ''] and
190             checkProg('DTL to DVI converter', ['dt2dv']) != ['', '']):
191         dtl_tools = True
192     else:
193         dtl_tools = False
194     return dtl_tools
195
196
197 def checkLatex(dtl_tools):
198     ''' Check latex, return lyx_check_config '''
199     if dtl_tools:
200         # Windows only: DraftDVI
201         converter_entry = r'''\converter latex      dvi2       "%%"     "latex"
202 \converter dvi2       dvi        "python -tt $$s/scripts/clean_dvi.py $$i $$o"  ""'''
203     else:
204         converter_entry = r'\converter latex      dvi        "%%"       "latex"'
205     path, LATEX = checkProg('a Latex2e program', ['pplatex $$i', 'latex $$i', 'latex2e $$i'],
206         rc_entry = [converter_entry])
207     # no latex
208     if LATEX != '':
209         # Check if latex is usable
210         writeToFile('chklatex.ltx', '''
211 \\nonstopmode\\makeatletter
212 \\ifx\\undefined\\documentclass\\else
213   \\message{ThisIsLaTeX2e}
214 \\fi
215 \\@@end
216 ''')
217         # run latex on chklatex.ltx and check result
218         if cmdOutput(LATEX + ' chklatex.ltx').find('ThisIsLaTeX2e') != -1:
219             # valid latex2e
220             return LATEX
221         else:
222             print "Latex not usable (not LaTeX2e) "
223         # remove temporary files
224         removeFiles(['chklatex.ltx', 'chklatex.log'])
225     return ''
226
227
228 def checkFormatEntries(dtl_tools):  
229     ''' Check all formats (\Format entries) '''
230     checkViewer('a Tgif viewer and editor', ['tgif'],
231         rc_entry = [r'\Format tgif       obj     Tgif                   "" "%%" "%%"    "vector"'])
232     #
233     checkViewer('a FIG viewer and editor', ['xfig'],
234         rc_entry = [r'\Format fig        fig     FIG                    "" "%%" "%%"    "vector"'])
235     #
236     checkViewer('a Grace viewer and editor', ['xmgrace'],
237         rc_entry = [r'\Format agr        agr     Grace                  "" "%%" "%%"    "vector"'])
238     #
239     checkViewer('a FEN viewer and editor', ['xboard -lpf $$i -mode EditPosition'],
240         rc_entry = [r'\Format fen        fen     FEN                    "" "%%" "%%"    ""'])
241     #
242     path, iv = checkViewer('a raster image viewer', ['xv', 'kview', 'gimp-remote', 'gimp'])
243     path, ie = checkViewer('a raster image editor', ['gimp-remote', 'gimp'])
244     addToRC(r'''\Format bmp        bmp     BMP                    "" "%s"       "%s"    ""
245 \Format gif        gif     GIF                    "" "%s"       "%s"    ""
246 \Format jpg        jpg     JPEG                   "" "%s"       "%s"    ""
247 \Format pbm        pbm     PBM                    "" "%s"       "%s"    ""
248 \Format pgm        pgm     PGM                    "" "%s"       "%s"    ""
249 \Format png        png     PNG                    "" "%s"       "%s"    ""
250 \Format ppm        ppm     PPM                    "" "%s"       "%s"    ""
251 \Format tiff       tif     TIFF                   "" "%s"       "%s"    ""
252 \Format xbm        xbm     XBM                    "" "%s"       "%s"    ""
253 \Format xpm        xpm     XPM                    "" "%s"       "%s"    ""''' % \
254         (iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie) )
255     #
256     checkViewer('a text editor', ['xemacs', 'gvim', 'kedit', 'kwrite', 'kate', \
257         'nedit', 'gedit', 'notepad'],
258         rc_entry = [r'''\Format asciichess asc    "Plain text (chess output)"  "" ""    "%%"    ""
259 \Format asciiimage asc    "Plain text (image)"         "" ""    "%%"    ""
260 \Format asciixfig  asc    "Plain text (Xfig output)"   "" ""    "%%"    ""
261 \Format dateout    tmp    "date (output)"         "" "" "%%"    ""
262 \Format docbook    sgml    DocBook                B  "" "%%"    "document"
263 \Format docbook-xml xml   "Docbook (XML)"         "" "" "%%"    "document"
264 \Format literate   nw      NoWeb                  N  "" "%%"    "document"
265 \Format lilypond   ly     "LilyPond music"        "" "" "%%"    "vector"
266 \Format latex      tex    "LaTeX (plain)"         L  "" "%%"    "document"
267 \Format linuxdoc   sgml    LinuxDoc               x  "" "%%"    "document"
268 \Format pdflatex   tex    "LaTeX (pdflatex)"      "" "" "%%"    "document"
269 \Format text       txt    "Plain text"            a  "" "%%"    "document"
270 \Format text2      txt    "Plain text (pstotext)" "" "" "%%"    "document"
271 \Format text3      txt    "Plain text (ps2ascii)" "" "" "%%"    "document"
272 \Format text4      txt    "Plain text (catdvi)"   "" "" "%%"    "document"
273 \Format textparagraph txt "Plain Text, Join Lines" "" ""        "%%"    "document"''' ])
274     #
275     #checkProg('a Postscript interpreter', ['gs'],
276     #  rc_entry = [ r'\ps_command "%%"' ])
277     checkViewer('a Postscript previewer', ['kghostview', 'evince', 'gv', 'ghostview -swap'],
278         rc_entry = [r'''\Format eps        eps     EPS                    "" "%%"       ""      "vector"
279 \Format ps         ps      Postscript             t  "%%"       ""      "document,vector"'''])
280     #
281     checkViewer('a PDF previewer', ['kpdf', 'evince', 'kghostview', 'xpdf', 'acrobat', 'acroread', \
282                     'gv', 'ghostview'],
283         rc_entry = [r'''\Format pdf        pdf    "PDF (ps2pdf)"          P  "%%"       ""      "document,vector"
284 \Format pdf2       pdf    "PDF (pdflatex)"        F  "%%"       ""      "document,vector"
285 \Format pdf3       pdf    "PDF (dvipdfm)"         m  "%%"       ""      "document,vector"'''])
286     #
287     checkViewer('a DVI previewer', ['xdvi', 'kdvi'],
288         rc_entry = [r'\Format dvi        dvi     DVI                    D  "%%" ""      "document,vector"'])
289     if dtl_tools:
290         # Windows only: DraftDVI
291         addToRC(r'\Format dvi2       dvi     DraftDVI               ""  ""      "document,vector"')
292     #
293     checkViewer('an HTML previewer', ['firefox', 'mozilla file://$$p$$i', 'netscape'],
294         rc_entry = [r'\Format html       html    HTML                   H  "%%" ""      "document"'])
295     #
296     checkViewer('Noteedit', ['noteedit'],
297         rc_entry = [r'\Format noteedit   not     Noteedit               "" "%%" "%%"    "vector"'])
298     #
299     checkViewer('an OpenDocument viewer', ['oowriter'],
300         rc_entry = [r'\Format odt        odt     OpenDocument           "" "%%" "%%"    "document,vector"'])
301     #
302     # entried that do not need checkProg
303     addToRC(r'''\Format date       ""     "date command"          "" "" ""      ""
304 \Format fax        ""      Fax                    "" "" ""      "document"
305 \Format lyx        lyx     LyX                    "" "" ""      ""
306 \Format lyx13x     lyx13  "LyX 1.3.x"             "" "" ""      "document"
307 \Format lyx14x     lyx14  "LyX 1.4.x"             "" "" ""      "document"
308 \Format lyx15x     lyx15  "LyX 1.5.x"             "" "" ""      "document"
309 \Format clyx       cjklyx "CJK LyX 1.4.x (big5)"  "" "" ""      "document"
310 \Format jlyx       cjklyx "CJK LyX 1.4.x (euc-jp)" "" ""        ""      "document"
311 \Format klyx       cjklyx "CJK LyX 1.4.x (euc-kr)" "" ""        ""      "document"
312 \Format lyxpreview lyxpreview "LyX Preview"       "" "" ""      ""
313 \Format pdftex     pdftex_t PDFTEX                "" "" ""      ""
314 \Format program    ""      Program                "" "" ""      ""
315 \Format pstex      pstex_t PSTEX                  "" "" ""      ""
316 \Format rtf        rtf    "Rich Text Format"      "" "" ""      "document,vector"
317 \Format sxw        sxw    "OpenOffice.Org (sxw)"  ""  ""        ""      "document,vector"
318 \Format wmf        wmf    "Windows Metafile"      "" "" ""      "vector"
319 \Format emf        emf    "Enhanced Metafile"     "" "" ""      "vector"
320 \Format word       doc    "MS Word"               W  "" ""      "document,vector"
321 \Format wordhtml   html   "HTML (MS Word)"        "" ""        ""       "document"
322 ''')
323
324
325 def checkConverterEntries():
326     ''' Check all converters (\converter entries) '''
327     checkProg('the pdflatex program', ['pdflatex $$i'],
328         rc_entry = [ r'\converter pdflatex   pdf2       "%%"    "latex"' ])
329     
330     ''' If we're running LyX in-place then tex2lyx will be found in
331             ../src/tex2lyx. Add this directory to the PATH temporarily and
332             search for tex2lyx.
333             Use PATH to avoid any problems with paths-with-spaces.
334     '''
335     path_orig = os.environ["PATH"]
336     os.environ["PATH"] = os.path.join('..', 'src', 'tex2lyx') + \
337         os.pathsep + path_orig
338
339     checkProg('a LaTeX/Noweb -> LyX converter', ['tex2lyx', 'tex2lyx' + version_suffix],
340         rc_entry = [r'''\converter latex      lyx        "%% -f $$i $$o"        ""
341 \converter literate   lyx        "%% -n -f $$i $$o"     ""'''])
342
343     os.environ["PATH"] = path_orig
344
345     #
346     checkProg('a Noweb -> LaTeX converter', ['noweave -delay -index $$i > $$o'],
347         rc_entry = [ r'\converter literate   latex      "%%"    ""' ])
348     #
349     checkProg('an HTML -> LaTeX converter', ['html2latex $$i'],
350         rc_entry = [ r'\converter html       latex      "%%"    ""' ])
351     #
352     checkProg('an MS Word -> LaTeX converter', ['wvCleanLatex $$i $$o'],
353         rc_entry = [ r'\converter word       latex      "%%"    ""' ])
354     # On SuSE the scripts have a .sh suffix, and on debian they are in /usr/share/tex4ht/
355     path, htmlconv = checkProg('a LaTeX -> HTML converter', ['htlatex $$i', 'htlatex.sh $$i', \
356         '/usr/share/tex4ht/htlatex $$i', 'tth  -t -e2 -L$$b < $$i > $$o', \
357         'latex2html -no_subdir -split 0 -show_section_numbers $$i', 'hevea -s $$i'],
358         rc_entry = [ r'\converter latex      html       "%%"    "needaux"' ])
359     if htmlconv.find('htlatex') >= 0 or htmlconv == 'latex2html':
360       addToRC(r'''\copier    html       "python -tt $$s/scripts/ext_copy.py -e html,png,css $$i $$o"''')
361     else:
362       addToRC(r'''\copier    html       "python -tt $$s/scripts/ext_copy.py $$i $$o"''')
363
364     # On SuSE the scripts have a .sh suffix, and on debian they are in /usr/share/tex4ht/
365     path, htmlconv = checkProg('a LaTeX -> MS Word converter', ["htlatex $$i 'html,word' 'symbol/!' '-cvalidate'", \
366         "htlatex.sh $$i 'html,word' 'symbol/!' '-cvalidate'", \
367         "/usr/share/tex4ht/htlatex $$i 'html,word' 'symbol/!' '-cvalidate'"],
368         rc_entry = [ r'\converter latex      wordhtml   "%%"    "needaux"' ])
369     if htmlconv.find('htlatex') >= 0:
370       addToRC(r'''\copier    wordhtml       "python -tt $$s/scripts/ext_copy.py -e html,png,css $$i $$o"''')
371     #
372     checkProg('an OpenOffice.org -> LaTeX converter', ['w2l -clean $$i'],
373         rc_entry = [ r'\converter sxw        latex      "%%"    ""' ])
374     #
375     checkProg('an OpenDocument -> LaTeX converter', ['w2l -clean $$i'],
376         rc_entry = [ r'\converter odt        latex      "%%"    ""' ])
377     # On SuSE the scripts have a .sh suffix, and on debian they are in /usr/share/tex4ht/
378     # Both SuSE and debian have oolatex
379     checkProg('a LaTeX -> Open Document converter', ['oolatex $$i', 'oolatex.sh $$i', \
380         '/usr/share/tex4ht/oolatex $$i', \
381         'htlatex $$i \'xhtml,ooffice\' \'ooffice/! -cmozhtf\' \'-coo\' \'-cvalidate\''],
382         rc_entry = [ r'\converter latex      odt        "%%"    "needaux"' ])
383     # On windows it is called latex2rt.exe
384     checkProg('a LaTeX -> RTF converter', ['latex2rtf -p -S -o $$o $$i', 'latex2rt -p -S -o $$o $$i'],
385         rc_entry = [ r'\converter latex      rtf        "%%"    "needaux"' ])
386     #
387     checkProg('a PS to PDF converter', ['ps2pdf13 $$i $$o'],
388         rc_entry = [ r'\converter ps         pdf        "%%"    ""' ])
389     #
390     checkProg('a PS to TXT converter', ['pstotext $$i > $$o'],
391         rc_entry = [ r'\converter ps         text2      "%%"    ""' ])
392     #
393     checkProg('a PS to TXT converter', ['ps2ascii $$i $$o'],
394         rc_entry = [ r'\converter ps         text3      "%%"    ""' ])
395     #
396     checkProg('a DVI to TXT converter', ['catdvi $$i > $$o'],
397         rc_entry = [ r'\converter dvi        text4      "%%"    ""' ])
398     #
399     checkProg('a DVI to PS converter', ['dvips -o $$o $$i'],
400         rc_entry = [ r'\converter dvi        ps         "%%"    ""' ])
401     #
402     checkProg('a DVI to PDF converter', ['dvipdfmx -o $$o $$i', 'dvipdfm -o $$o $$i'],
403         rc_entry = [ r'\converter dvi        pdf3       "%%"    ""' ])
404     #
405     path, dvipng = checkProg('dvipng', ['dvipng'])
406     if dvipng == "dvipng":
407         addToRC(r'\converter lyxpreview png        "python -tt $$s/scripts/lyxpreview2bitmap.py"        ""')
408     else:
409         addToRC(r'\converter lyxpreview png        ""   ""')
410     #  
411     checkProg('a fax program', ['kdeprintfax $$i', 'ksendfax $$i'],
412         rc_entry = [ r'\converter ps         fax        "%%"    ""'])
413     #
414     checkProg('a FIG -> EPS/PPM converter', ['fig2dev'],
415         rc_entry = [
416             r'''\converter fig        eps        "fig2dev -L eps $$i $$o"       ""
417 \converter fig        ppm        "fig2dev -L ppm $$i $$o"       ""
418 \converter fig        png        "fig2dev -L png $$i $$o"       ""''',
419             ''])
420     #
421     checkProg('a TIFF -> PS converter', ['tiff2ps $$i > $$o'],
422         rc_entry = [ r'\converter tiff       eps        "%%"    ""', ''])
423     #
424     checkProg('a TGIF -> EPS/PPM converter', ['tgif'],
425         rc_entry = [
426             r'''\converter tgif       eps        "tgif -stdout -print -color -eps $$i > $$o"    ""
427 \converter tgif       ppm        "tgif -stdout -print -color -ppm $$i > $$o"    ""
428 \converter tgif       png        "tgif -stdout -print -color -png $$i > $$o"    ""
429 \converter tgif       pdf        "tgif -stdout -print -color -pdf $$i > $$o"    ""''',
430             ''])
431     #
432     checkProg('a WMF -> EPS converter', ['metafile2eps $$i $$o', 'wmf2eps -o $$o $$i'],
433         rc_entry = [ r'\converter wmf        eps        "%%"    ""'])
434     #
435     checkProg('an EMF -> EPS converter', ['metafile2eps $$i $$o', 'wmf2eps -o $$o $$i'],
436         rc_entry = [ r'\converter emf        eps        "%%"    ""'])
437     #
438     checkProg('an EPS -> PDF converter', ['epstopdf'],
439         rc_entry = [ r'\converter eps        pdf        "epstopdf --outfile=$$o $$i"    ""', ''])
440     #
441     # no agr -> pdf converter, since the pdf library used by gracebat is not
442     # free software and therefore not compiled in in many installations.
443     # Fortunately, this is not a big problem, because we will use epstopdf to
444     # convert from agr to pdf via eps without loss of quality.
445     checkProg('a Grace -> Image converter', ['gracebat'],
446         rc_entry = [
447             r'''\converter agr        eps        "gracebat -hardcopy -printfile $$o -hdevice EPS $$i 2>/dev/null"       ""
448 \converter agr        png        "gracebat -hardcopy -printfile $$o -hdevice PNG $$i 2>/dev/null"       ""
449 \converter agr        jpg        "gracebat -hardcopy -printfile $$o -hdevice JPEG $$i 2>/dev/null"      ""
450 \converter agr        ppm        "gracebat -hardcopy -printfile $$o -hdevice PNM $$i 2>/dev/null"       ""''',
451             ''])
452     #
453     #
454     path, lilypond = checkProg('a LilyPond -> EPS/PDF/PNG converter', ['lilypond'])
455     if (lilypond != ''):
456         version_string = cmdOutput("lilypond --version")
457         match = re.match('GNU LilyPond (\S+)', version_string)
458         if match:
459             version_number = match.groups()[0]
460             version = version_number.split('.')
461             if int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 6):
462                 addToRC(r'''\converter lilypond   eps        "lilypond -b eps --ps $$i" ""
463 \converter lilypond   png        "lilypond -b eps --png $$i"    ""''')
464                 if int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 9):
465                     addToRC(r'\converter lilypond   pdf        "lilypond -b eps --pdf $$i"      ""')
466                 print '+  found LilyPond version %s.' % version_number
467             else:
468                 print '+  found LilyPond, but version %s is too old.' % version_number
469         else:
470             print '+  found LilyPond, but could not extract version number.'
471     #
472     checkProg('a Noteedit -> LilyPond converter', ['noteedit --export-lilypond $$i'],
473         rc_entry = [ r'\converter noteedit   lilypond   "%%"    ""', ''])
474     #
475     # FIXME: no rc_entry? comment it out
476     # checkProg('Image converter', ['convert $$i $$o'])
477     #
478     # Entries that do not need checkProg
479     addToRC(r'''\converter lyxpreview ppm        "python -tt $$s/scripts/lyxpreview2bitmap.py"  ""
480 \converter date       dateout    "python -tt $$s/scripts/date.py %d-%m-%Y > $$o"        ""
481 \converter docbook    docbook-xml "cp $$i $$o"  "xml"
482 \converter fen        asciichess "python -tt $$s/scripts/fen2ascii.py $$i $$o"  ""
483 \converter fig        pdftex     "python -tt $$s/scripts/fig2pdftex.py $$i $$o" ""
484 \converter fig        pstex      "python -tt $$s/scripts/fig2pstex.py $$i $$o"  ""
485 \converter lyx        lyx13x     "python -tt $$s/lyx2lyx/lyx2lyx -t 221 $$i > $$o"      ""
486 \converter lyx        lyx14x     "python -tt $$s/lyx2lyx/lyx2lyx -t 245 $$i > $$o"      ""
487 \converter lyx        lyx15x     "python -tt $$s/lyx2lyx/lyx2lyx -t 276 $$i > $$o"      ""
488 \converter lyx        clyx       "python -tt $$s/lyx2lyx/lyx2lyx -c big5 -t 245 $$i > $$o"      ""
489 \converter lyx        jlyx       "python -tt $$s/lyx2lyx/lyx2lyx -c euc_jp -t 245 $$i > $$o"    ""
490 \converter lyx        klyx       "python -tt $$s/lyx2lyx/lyx2lyx -c euc_kr -t 245 $$i > $$o"    ""
491 \converter clyx       lyx        "python -tt $$s/lyx2lyx/lyx2lyx -c big5 $$i > $$o"     ""
492 \converter jlyx       lyx        "python -tt $$s/lyx2lyx/lyx2lyx -c euc_jp $$i > $$o"   ""
493 \converter klyx       lyx        "python -tt $$s/lyx2lyx/lyx2lyx -c euc_kr $$i > $$o"   ""
494 ''')
495
496
497 def checkLinuxDoc():
498     ''' Check linuxdoc '''
499     #
500     path, LINUXDOC = checkProg('SGML-tools 1.x (LinuxDoc)', ['sgml2lyx'],
501         rc_entry = [
502         r'''\converter linuxdoc   lyx        "sgml2lyx $$i"     ""
503 \converter linuxdoc   latex      "sgml2latex $$i"       ""
504 \converter linuxdoc   dvi        "sgml2latex -o dvi $$i"        ""
505 \converter linuxdoc   html       "sgml2html $$i"        ""''',
506         r'''\converter linuxdoc   lyx        "" ""
507 \converter linuxdoc   latex      ""     ""
508 \converter linuxdoc   dvi        ""     ""
509 \converter linuxdoc   html       ""     ""''' ])
510     if LINUXDOC != '':
511         return ('yes', 'true', '\\def\\haslinuxdoc{yes}')
512     else:
513         return ('no', 'false', '')
514
515
516 def checkDocBook():
517     ''' Check docbook '''
518     path, DOCBOOK = checkProg('SGML-tools 2.x (DocBook) or db2x scripts', ['sgmltools', 'db2dvi'],
519         rc_entry = [
520             r'''\converter docbook    dvi        "sgmltools -b dvi $$i" ""
521 \converter docbook    html       "sgmltools -b html $$i"        ""''',
522             r'''\converter docbook    dvi        "db2dvi $$i"   ""
523 \converter docbook    html       "db2html $$i"  ""''',
524             r'''\converter docbook    dvi        ""     ""
525 \converter docbook    html       ""     ""'''])
526     #
527     if DOCBOOK != '':
528         return ('yes', 'true', '\\def\\hasdocbook{yes}')
529     else:
530         return ('no', 'false', '')
531
532
533 def checkOtherEntries():
534     ''' entries other than Format and Converter '''
535     checkProg('a *roff formatter', ['groff', 'nroff'],
536         rc_entry = [
537             r'\plaintext_roff_command "groff -t -Tlatin1 $$FName"',
538             r'\plaintext_roff_command "tbl $$FName | nroff"',
539             r'\plaintext_roff_command ""' ])
540     checkProg('ChkTeX', ['chktex -n1 -n3 -n6 -n9 -n22 -n25 -n30 -n38'],
541         rc_entry = [ r'\chktex_command "%%"' ])
542     checkProg('a spellchecker', ['ispell'],
543         rc_entry = [ r'\spell_command "%%"' ])
544     ## FIXME: OCTAVE is not used anywhere
545     # path, OCTAVE = checkProg('Octave', ['octave'])
546     ## FIXME: MAPLE is not used anywhere
547     # path, MAPLE = checkProg('Maple', ['maple'])
548     checkProg('a spool command', ['lp', 'lpr'],
549         rc_entry = [
550             r'''\print_spool_printerprefix "-d "
551 \print_spool_command "lp"''',
552             r'''\print_spool_printerprefix "-P",
553 \print_spool_command "lpr"''',
554             ''])
555     # Add the rest of the entries (no checkProg is required)
556     addToRC(r'''\copier    fig        "python -tt $$s/scripts/fig_copy.py $$i $$o"
557 \copier    pstex      "python -tt $$s/scripts/tex_copy.py $$i $$o $$l"
558 \copier    pdftex     "python -tt $$s/scripts/tex_copy.py $$i $$o $$l"
559 \copier    program    "python -tt $$s/scripts/ext_copy.py $$i $$o"
560 ''')
561
562
563 def processLayoutFile(file, bool_docbook, bool_linuxdoc):
564     ''' process layout file and get a line of result
565         
566         Declare lines look like this: (article.layout, scrbook.layout, svjog.layout)
567         
568         \DeclareLaTeXClass{article}
569         \DeclareLaTeXClass[scrbook]{book (koma-script)}
570         \DeclareLaTeXClass[svjour,svjog.clo]{article (Springer - svjour/jog)}
571
572         we expect output:
573         
574         "article" "article" "article" "false"
575         "scrbook" "scrbook" "book (koma-script)" "false"
576         "svjog" "svjour" "article (Springer - svjour/jog)" "false"
577     '''
578     classname = file.split(os.sep)[-1].split('.')[0]
579     # return ('LaTeX', '[a,b]', 'a', ',b,c', 'article') for \DeclareLaTeXClass[a,b,c]{article}
580     p = re.compile(r'\Declare(LaTeX|DocBook|LinuxDoc)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)}')
581     for line in open(file).readlines():
582         res = p.search(line)
583         if res != None:
584             (classtype, optAll, opt, opt1, desc) = res.groups()
585             avai = {'LaTeX':'false', 'DocBook':bool_docbook, 'LinuxDoc':bool_linuxdoc}[classtype]
586             if opt == None:
587                 opt = classname
588             return '"%s" "%s" "%s" "%s"\n' % (classname, opt, desc, avai)
589     print "Layout file without \DeclareXXClass line. "
590     sys.exit(2)
591
592     
593 def checkLatexConfig(check_config, bool_docbook, bool_linuxdoc):
594     ''' Explore the LaTeX configuration '''
595     print 'checking LaTeX configuration... ',
596     # First, remove the files that we want to re-create
597     removeFiles(['textclass.lst', 'packages.lst', 'chkconfig.sed'])
598     #
599     if not check_config:
600         print ' default values'
601         print '+checking list of textclasses... '
602         tx = open('textclass.lst', 'w')
603         tx.write('''
604 # This file declares layouts and their associated definition files
605 # (include dir. relative to the place where this file is).
606 # It contains only default values, since chkconfig.ltx could not be run
607 # for some reason. Run ./configure.py if you need to update it after a
608 # configuration change.
609 ''')
610         # build the list of available layout files and convert it to commands
611         # for chkconfig.ltx
612         foundClasses = []
613         for file in glob.glob( os.path.join('layouts', '*.layout') ) + \
614             glob.glob( os.path.join(srcdir, 'layouts', '*.layout' ) ) :
615             # valid file?
616             if not os.path.isfile(file): 
617                 continue
618             # get stuff between /xxxx.layout .
619             classname = file.split(os.sep)[-1].split('.')[0]
620             #  tr ' -' '__'`
621             cleanclass = classname.replace(' ', '_')
622             cleanclass = cleanclass.replace('-', '_')
623             # make sure the same class is not considered twice
624             if foundClasses.count(cleanclass) == 0: # not found before
625                 foundClasses.append(cleanclass)
626                 tx.write(processLayoutFile(file, bool_docbook, bool_linuxdoc))
627         tx.close()
628         print '\tdone'
629     else:
630         print '\tauto'
631         removeFiles(['wrap_chkconfig.ltx', 'chkconfig.vars', \
632             'chkconfig.classes', 'chklayouts.tex'])
633         rmcopy = False
634         if not os.path.isfile( 'chkconfig.ltx' ):
635             shutil.copyfile( os.path.join(srcdir, 'chkconfig.ltx'), 'chkconfig.ltx' )
636             rmcopy = True
637         writeToFile('wrap_chkconfig.ltx', '%s\n%s\n\\input{chkconfig.ltx}\n' \
638             % (linuxdoc_cmd, docbook_cmd) )
639         # Construct the list of classes to test for.
640         # build the list of available layout files and convert it to commands
641         # for chkconfig.ltx
642         p1 = re.compile(r'\Declare(LaTeX|DocBook)Class')
643         testclasses = list()
644         for file in glob.glob( os.path.join('layouts', '*.layout') ) + \
645             glob.glob( os.path.join(srcdir, 'layouts', '*.layout' ) ) :
646             if not os.path.isfile(file):
647                 continue
648             classname = file.split(os.sep)[-1].split('.')[0]
649             for line in open(file).readlines():
650                 if p1.search(line) == None:
651                     continue
652                 if line[0] != '#':
653                     print "Wrong input layout file with line '" + line
654                     sys.exit(3)
655                 testclasses.append("\\TestDocClass{%s}{%s}" % (classname, line[1:].strip()))
656                 break
657         testclasses.sort()
658         cl = open('chklayouts.tex', 'w')
659         for line in testclasses:
660             cl.write(line + '\n')
661         cl.close()
662         #
663         # we have chklayouts.tex, then process it
664         fout = os.popen(LATEX + ' wrap_chkconfig.ltx')
665         while True:
666             line = fout.readline()
667             if not line:
668                 break;
669             if re.match('^\+', line):
670                 print line,
671         fout.close()
672         #
673         # currently, values in chhkconfig are only used to set
674         # \font_encoding
675         values = {}
676         for line in open('chkconfig.vars').readlines():
677             key, val = re.sub('-', '_', line).split('=')
678             val = val.strip()
679             values[key] = val.strip("'")
680         # chk_fontenc may not exist 
681         try:
682             addToRC(r'\font_encoding "%s"' % values["chk_fontenc"])
683         except:
684             pass
685         if rmcopy:   # remove the copied file
686             removeFiles( [ 'chkconfig.ltx' ] )
687
688
689 def createLaTeXConfig():
690     ''' create LaTeXConfig.lyx '''
691     # if chkconfig.sed does not exist (because LaTeX did not run),
692     # then provide a standard version.
693     if not os.path.isfile('chkconfig.sed'):
694         writeToFile('chkconfig.sed', 's!@.*@!???!g\n')
695     print "creating packages.lst"
696     # if packages.lst does not exist (because LaTeX did not run),
697     # then provide a standard version.
698     if not os.path.isfile('packages.lst'):
699         writeToFile('packages.lst', '''
700 ### This file should contain the list of LaTeX packages that have been
701 ### recognized by LyX. Unfortunately, since configure could not find
702 ### your LaTeX2e program, the tests have not been run. Run ./configure.py
703 ### if you need to update it after a configuration change.
704 ''')
705     print 'creating doc/LaTeXConfig.lyx'
706     #
707     # This is originally done by sed, using a
708     # tex-generated file chkconfig.sed
709     ##sed -f chkconfig.sed ${srcdir}/doc/LaTeXConfig.lyx.in
710     ##  >doc/LaTeXConfig.lyx
711     # Now, we have to do it by hand (python).
712     #
713     # add to chekconfig.sed
714     writeToFile('chkconfig.sed', '''s!@chk_linuxdoc@!%s!g
715 s!@chk_docbook@!%s!g
716     ''' % (chk_linuxdoc, chk_docbook) , append=True)
717     # process this sed file!!!!
718     lyxin = open( os.path.join(srcdir, 'doc', 'LaTeXConfig.lyx.in')).readlines()
719     # get the rules
720     p = re.compile(r's!(.*)!(.*)!g')
721     # process each sed replace.
722     for sed in open('chkconfig.sed').readlines():
723         if sed.strip() == '':
724             continue
725         try:
726             fr, to = p.match(sed).groups()
727             # if latex did not run, change all @name@ to '???'
728             if fr == '@.*@':
729                 for line in range(len(lyxin)):
730                     lyxin[line] = re.sub('@.*@', to, lyxin[line])
731             else:
732                 for line in range(len(lyxin)):
733                     lyxin[line] = lyxin[line].replace(fr, to)
734         except:  # wrong sed entry?
735             print "Wrong sed entry in chkconfig.sed: '" + sed + "'"
736             sys.exit(4)
737     # 
738     writeToFile( os.path.join('doc', 'LaTeXConfig.lyx'),
739         ''.join(lyxin))
740
741
742 def checkModulesConfig():
743   removeFiles(['lyxmodules.lst'])
744
745   print '+checking list of modules... '
746   tx = open('lyxmodules.lst', 'w')
747   tx.write('''## This file declares modules and their associated definition files.
748 ## It has been automatically generated by configure
749 ## Use "Options/Reconfigure" if you need to update it after a
750 ## configuration change. 
751 ''')
752   # build the list of available modules
753   foundClasses = []
754   for file in glob.glob( os.path.join('layouts', '*.module') ) + \
755       glob.glob( os.path.join(srcdir, 'layouts', '*.module' ) ) :
756       # valid file?
757       print file
758       if not os.path.isfile(file): 
759           continue
760       tx.write(processModuleFile(file, bool_docbook, bool_linuxdoc))
761   tx.close()
762   print '\tdone'
763
764 def processModuleFile(file, bool_docbook, bool_linuxdoc):
765     ''' process module file and get a line of result
766
767         Declare lines look like this:
768           \DeclareLyXModule[LaTeX Packages]{Description}{ModuleName}...
769         We expect output:
770           "ModuleName" "filename" "Description" "Packages"
771         "
772     '''
773     p = re.compile(r'\DeclareLyXModule\s*(?:\[([^]]*)\])?{(.*)}{(.*)}')
774     for line in open(file).readlines():
775         res = p.search(line)
776         if res != None:
777             (packages, desc, modname) = res.groups()
778             #check availability...need to add that
779             if packages == None:
780               packages = ""
781             else:
782               pkgs = [s.strip() for s in packages.split(",")]
783               packages = ",".join(pkgs)
784
785             filename = file.split(os.sep)[-1]
786             return '"%s" "%s" "%s" "%s"\n' % (modname, filename, desc, packages)
787     print "Module file without \DeclareLyXModule line. "
788     sys.exit(2)
789
790
791
792
793 def checkTeXAllowSpaces():
794     ''' Let's check whether spaces are allowed in TeX file names '''
795     tex_allows_spaces = 'false'
796     if lyx_check_config:
797         print "Checking whether TeX allows spaces in file names... ",
798         writeToFile('a b.tex', r'\message{working^^J}' )
799         if os.name == 'nt':
800             latex_out = cmdOutput(LATEX + r""" "\nonstopmode\input{\"a b\"}" """)
801         else:
802             latex_out = cmdOutput(LATEX + r""" '\nonstopmode\input{"a b"}' """)
803         if 'working' in latex_out:
804             print 'yes'
805             tex_allows_spaces = 'true'
806         else:
807             print 'no'
808             tex_allows_spaces = 'false'
809         addToRC(r'\tex_allows_spaces ' + tex_allows_spaces)
810         removeFiles( [ 'a b.tex', 'a b.log', 'texput.log' ])
811
812
813 def removeTempFiles():
814     # Final clean-up
815     if not lyx_keep_temps:
816         removeFiles(['chkconfig.sed', 'chkconfig.vars',  \
817             'wrap_chkconfig.ltx', 'wrap_chkconfig.log', \
818             'chklayouts.tex', 'missfont.log', 
819             'chklatex.ltx', 'chklatex.log'])
820
821
822 if __name__ == '__main__':
823     lyx_check_config = True
824     outfile = 'lyxrc.defaults'
825     rc_entries = ''
826     lyx_keep_temps = False
827     version_suffix = ''
828     logfile = 'configure.log'
829     ## Parse the command line
830     for op in sys.argv[1:]:   # default shell/for list is $*, the options
831         if op in [ '-help', '--help', '-h' ]:
832             print '''Usage: configure [options]
833 Options:
834     --help                   show this help lines
835     --keep-temps             keep temporary files (for debug. purposes)
836     --without-latex-config   do not run LaTeX to determine configuration
837     --with-version-suffix=suffix suffix of binary installed files
838 '''
839             sys.exit(0)
840         elif op == '--without-latex-config':
841             lyx_check_config = False
842         elif op == '--keep-temps':
843             lyx_keep_temps = True
844         elif op[0:22] == '--with-version-suffix=':  # never mind if op is not long enough
845             version_suffix = op[22:]
846         else:
847             print "Unknown option", op
848             sys.exit(1)
849     #
850     # set up log file for stdout and stderr
851     log = open(logfile, 'w')
852     sys.stdout = Tee(sys.stdout, log)
853     sys.stderr = Tee(sys.stderr, log)
854     # check if we run from the right directory
855     srcdir = os.path.dirname(sys.argv[0])
856     if srcdir == '':
857         srcdir = '.'
858     if not os.path.isfile( os.path.join(srcdir, 'chkconfig.ltx') ):
859         print "configure: error: cannot find chkconfig.ltx script"
860         sys.exit(1)
861     setEnviron()
862     createDirectories()
863     windows_style_tex_paths = checkTeXPaths()
864     dtl_tools = checkDTLtools()
865     ## Write the first part of outfile
866     writeToFile(outfile, '''# This file has been automatically generated by LyX' lib/configure.py
867 # script. It contains default settings that have been determined by
868 # examining your system. PLEASE DO NOT MODIFY ANYTHING HERE! If you
869 # want to customize LyX, use LyX' Preferences dialog or modify directly 
870 # the "preferences" file instead. Any setting in that file will
871 # override the values given here.
872 ''')
873     # check latex
874     LATEX = checkLatex(dtl_tools)
875     checkFormatEntries(dtl_tools)
876     checkConverterEntries()
877     (chk_linuxdoc, bool_linuxdoc, linuxdoc_cmd) = checkLinuxDoc()
878     (chk_docbook, bool_docbook, docbook_cmd) = checkDocBook()
879     checkTeXAllowSpaces()
880     if windows_style_tex_paths != '':
881         addToRC(r'\tex_expects_windows_paths %s' % windows_style_tex_paths)
882     checkOtherEntries()
883     # --without-latex-config can disable lyx_check_config
884     checkLatexConfig( lyx_check_config and LATEX != '', bool_docbook, bool_linuxdoc)
885     createLaTeXConfig()
886     checkModulesConfig() #lyx_check_config and LATEX != '')
887     removeTempFiles()