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