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