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