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