]> git.lyx.org Git - lyx.git/blob - lib/configure.py
* lyx_1_4.py
[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')
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')
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    "TeX (latex)"           l  "" "%%"
227 \Format linuxdoc   sgml    LinuxDoc               x  "" "%%"
228 \Format pdflatex   tex    "TeX (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   checkProg('a LaTeX -> LyX converter', [os.path.join('..','src','tex2lyx','tex2lyx') + ' -f $$i $$o', \
271     'tex2lyx' +  version_suffix + ' -f $$i $$o' ],
272     rc_entry = [ r'\converter latex      lyx        "%%"        ""' ])
273   #
274   checkProg('a Noweb -> LyX converter', ['noweb2lyx' + version_suffix + ' $$i $$o'], path = ['./reLyX'],
275     rc_entry = [ r'\converter literate   lyx        "%%"        ""' ])
276   #
277   checkProg('a Noweb -> LaTeX converter', ['noweave -delay -index $$i > $$o'],
278     rc_entry = [ r'\converter literate   latex      "%%"        ""' ])
279   #
280   checkProg('a HTML -> LaTeX converter', ['html2latex $$i'],
281     rc_entry = [ r'\converter html       latex      "%%"        ""' ])
282   #
283   checkProg('a MSWord -> LaTeX converter', ['wvCleanLatex $$i $$o'],
284     rc_entry = [ r'\converter word       latex      "%%"        ""' ])
285   #
286   checkProg('a LaTeX -> MS Word converter', ["htlatex $$i 'html,word' 'symbol/!' '-cvalidate'"],
287     rc_entry = [ r'\converter latex      wordhtml   "%%"        ""' ])
288   #
289   checkProg('an OpenOffice.org -> LaTeX converter', ['w2l -clean $$i'],
290     rc_entry = [ r'\converter sxw        latex      "%%"        ""' ])
291   #
292   checkProg('an LaTeX -> OpenOffice.org LaTeX converter', ['oolatex $$i', 'oolatex.sh $$i'],
293     rc_entry = [ r'\converter latex      sxw        "%%"        "latex"' ])
294   #
295   checkProg('a PS to PDF converter', ['ps2pdf13 $$i'],
296     rc_entry = [ r'\converter ps         pdf        "%%"        ""' ])
297   #
298   checkProg('a DVI to PS converter', ['dvips -o $$o $$i'],
299     rc_entry = [ r'\converter dvi        ps         "%%"        ""' ])
300   #
301   checkProg('a DVI to PDF converter', ['dvipdfm $$i'],
302     rc_entry = [ r'\converter dvi        pdf3       "%%"        ""' ])
303   #
304   path, dvipng = checkProg('dvipng', ['dvipng'])
305   if dvipng == "dvipng":
306     addToRC(r'\converter lyxpreview png        "python $$s/scripts/lyxpreview2bitmap.py"        ""')
307   else:
308     addToRC(r'\converter lyxpreview png        ""       ""')
309   #  
310   checkProg('a fax program', ['kdeprintfax $$i', 'ksendfax $$i'],
311     rc_entry = [ r'\converter ps         fax        "%%"        ""'])
312   #
313   checkProg('a FIG -> EPS/PPM converter', ['fig2dev'],
314     rc_entry = [
315       r'''\converter fig        eps        "fig2dev -L eps $$i $$o"     ""
316 \converter fig        ppm        "fig2dev -L ppm $$i $$o"       ""
317 \converter fig        png        "fig2dev -L png $$i $$o"       ""''',
318       ''])
319   #
320   checkProg('a TIFF -> PS converter', ['tiff2ps $$i > $$o'],
321     rc_entry = [ r'\converter tiff       eps        "%%"        ""', ''])
322   #
323   checkProg('a TGIF -> EPS/PPM converter', ['tgif'],
324     rc_entry = [
325       r'''\converter tgif       eps        "tgif -stdout -print -color -eps $$i > $$o"  ""
326 \converter tgif       pdf        "tgif -stdout -print -color -pdf $$i > $$o"    ""''',
327       ''])
328   #
329   checkProg('a EPS -> PDF converter', ['epstopdf'],
330     rc_entry = [ r'\converter eps        pdf        "epstopdf --outfile=$$o $$i"        ""', ''])
331   #
332   checkProg('a Grace -> Image converter', ['gracebat'],
333     rc_entry = [
334       r'''\converter agr        eps        "gracebat -hardcopy -printfile $$o -hdevice EPS $$i 2>/dev/null"     ""
335 \converter agr        png        "gracebat -hardcopy -printfile $$o -hdevice PNG $$i 2>/dev/null"       ""
336 \converter agr        jpg        "gracebat -hardcopy -printfile $$o -hdevice JPEG $$i 2>/dev/null"      ""
337 \converter agr        ppm        "gracebat -hardcopy -printfile $$o -hdevice PNM $$i 2>/dev/null"       ""''',
338       ''])
339   #
340   checkProg('a LaTeX -> HTML converter', ['htlatex $$i', 'tth  -t -e2 -L$$b < $$i > $$o', \
341     'latex2html -no_subdir -split 0 -show_section_numbers $$i', 'hevea -s $$i'],
342     rc_entry = [ r'\converter latex      html       "%%"        "originaldir,needaux"' ])
343   #
344   # FIXME: no rc_entry? comment it out
345   # checkProg('Image converter', ['convert $$i $$o'])
346   #
347   # Entried that do not need checkProg
348   addToRC(r'''\converter lyxpreview ppm        "python $$s/scripts/lyxpreview2bitmap.py"        ""
349 \converter date       dateout    "date +%d-%m-%Y > $$o" ""
350 \converter docbook    docbook-xml "cp $$i $$o"  "xml"
351 \converter fen        asciichess "python $$s/scripts/fen2ascii.py $$i $$o"      ""
352 \converter fig        pdftex     "sh $$s/scripts/fig2pdftex.sh $$i $$o" ""
353 \converter fig        pstex      "sh $$s/scripts/fig2pstex.sh $$i $$o"  ""
354 \converter lyx        lyx13x     "python $$s/lyx2lyx/lyx2lyx -t 221 $$i > $$o"  ""
355 ''')
356
357
358 def checkLinuxDoc():
359   ''' Check linuxdoc '''
360   #
361   path, LINUXDOC = checkProg('SGML-tools 1.x (LinuxDoc)', ['sgml2lyx'],
362     rc_entry = [
363     r'''\converter linuxdoc   lyx        "sgml2lyx $$i" ""
364 \converter linuxdoc   latex      "sgml2latex $$i"       ""
365 \converter linuxdoc   dvi        "sgml2latex -o dvi $$i"        ""
366 \converter linuxdoc   html       "sgml2html $$i"        ""''',
367     r'''\converter linuxdoc   lyx        "none" ""
368 \converter linuxdoc   latex      "none" ""
369 \converter linuxdoc   dvi        "none" ""
370 \converter linuxdoc   html       "none" ""''' ])
371   if LINUXDOC != 'none':
372     return ('yes', 'true', '\\def\\haslinuxdoc{yes}')
373   else:
374     return ('no', 'false', '')
375
376
377 def checkDocBook():
378   ''' Check docbook '''
379   path, DOCBOOK = checkProg('SGML-tools 2.x (DocBook) or db2x scripts', ['sgmltools', 'db2dvi'],
380     rc_entry = [
381       r'''\converter docbook    dvi        "sgmltools -b dvi $$i"       ""
382 \converter docbook    html       "sgmltools -b html $$i"        ""''',
383       r'''\converter docbook    dvi        "db2dvi $$i" ""
384 \converter docbook    html       "db2html $$i"  ""''',
385       r'''\converter docbook    dvi        "none"       ""
386 \converter docbook    html       "none" ""'''])
387   #
388   if DOCBOOK != 'none':
389     return ('yes', 'true', '\\def\\hasdocbook{yes}')
390   else:
391     return ('no', 'false', '')
392
393
394 def checkOtherEntries():
395   ''' entries other than Format and Converter '''
396   checkProg('a *roff formatter', ['groff', 'nroff'],
397     rc_entry = [
398       r'\ascii_roff_command "groff -t -Tlatin1 $$FName"',
399       r'\ascii_roff_command "tbl $$FName | nroff"',
400       r'\ascii_roff_command "none"' ])
401   checkProg('ChkTeX', ['chktex -n1 -n3 -n6 -n9 -n22 -n25 -n30 -n38'],
402     rc_entry = [ r'\chktex_command "%%"' ])
403   checkProg('a spellchecker', ['ispell'],
404     rc_entry = [ r'\spell_command "%%"' ])
405   ## FIXME: OCTAVE is not used anywhere
406   # path, OCTAVE = checkProg('Octave', ['octave'])
407   ## FIXME: MAPLE is not used anywhere
408   # path, MAPLE = checkProg('Maple', ['maple'])
409   checkProg('a spool command', ['lp', 'lpr'],
410     rc_entry = [
411       r'''\print_spool_printerprefix "-d "
412 \print_spool_command "lp"''',
413       r'''\print_spool_printerprefix "-P",
414 \print_spool_command "lpr"''',
415       ''])
416   # Add the rest of the entries (no checkProg is required)
417   addToRC(r'''\copier    fig        "sh $$s/scripts/fig_copy.sh $$i $$o"
418 \copier    pstex      "python $$s/scripts/tex_copy.py $$i $$o $$l"
419 \copier    pdftex     "python $$s/scripts/tex_copy.py $$i $$o $$l"
420 ''')
421
422
423 def processLayoutFile(file, bool_docbook, bool_linuxdoc):
424   ''' process layout file and get a line of result
425     
426     Declear line are like this: (article.layout, scrbook.layout, svjog.layout)
427     
428     \DeclareLaTeXClass{article}
429     \DeclareLaTeXClass[scrbook]{book (koma-script)}
430     \DeclareLaTeXClass[svjour,svjog.clo]{article (Springer - svjour/jog)}
431
432     we expect output:
433     
434     "article" "article" "article" "false"
435     "scrbook" "scrbook" "book (koma-script)" "false"
436     "svjog" "svjour" "article (Springer - svjour/jog)" "false"
437   '''
438   classname = file.split(os.sep)[-1].split('.')[0]
439   # return ('LaTeX', '[a,b]', 'a', ',b,c', 'article') for \DeclearLaTeXClass[a,b,c]{article}
440   p = re.compile(r'\Declare(LaTeX|DocBook|LinuxDoc)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)}')
441   for line in open(file).readlines():
442     res = p.search(line)
443     if res != None:
444       (classtype, optAll, opt, opt1, desc) = res.groups()
445       avai = {'LaTeX':'false', 'DocBook':bool_docbook, 'LinuxDoc':bool_linuxdoc}[classtype]
446       if opt == None:
447         opt = classname
448       return '"%s" "%s" "%s" "%s"\n' % (classname, opt, desc, avai)
449   print "Layout file without \DeclearXXClass line. "
450   sys.exit(2)
451
452   
453 def checkLatexConfig(check_config, bool_docbook, bool_linuxdoc):
454   ''' Explore the LaTeX configuration '''
455   print 'checking LaTeX configuration... ',
456   # First, remove the files that we want to re-create
457   removeFiles(['textclass.lst', 'packages.lst', 'chkconfig.sed'])
458   #
459   if not check_config:
460     print ' default values'
461     print '+checking list of textclasses... '
462     tx = open('textclass.lst', 'w')
463     tx.write('''
464 # This file declares layouts and their associated definition files
465 # (include dir. relative to the place where this file is).
466 # It contains only default values, since chkconfig.ltx could not be run
467 # for some reason. Run ./configure if you need to update it after a
468 # configuration change.
469 ''')
470     # build the list of available layout files and convert it to commands
471     # for chkconfig.ltx
472     foundClasses = []
473     for file in glob.glob( os.path.join('layouts', '*.layout') ) + \
474       glob.glob( os.path.join(srcdir, 'layouts', '*.layout' ) ) :
475       # valid file?
476       if not os.path.isfile(file): 
477         continue
478       # get stuff between /xxxx.layout .
479       classname = file.split(os.sep)[-1].split('.')[0]
480       #  tr ' -' '__'`
481       cleanclass = classname.replace(' ', '_')
482       cleanclass = cleanclass.replace('-', '_')
483       # make sure the same class is not considered twice
484       if foundClasses.count(cleanclass) == 0: # not found before
485         foundClasses.append(cleanclass)
486         tx.write(processLayoutFile(file, bool_docbook, bool_linuxdoc))
487     tx.close()
488     print '\tdone'
489   else:
490     print '\tauto'
491     removeFiles(['wrap_chkconfig.ltx', 'chkconfig.vars', \
492       'chkconfig.classes', 'chklayouts.tex'])
493     rmcopy = False
494     if not os.path.isfile( 'chkconfig.ltx' ):
495       shutil.copy( os.path.join(srcdir, 'chkconfig.ltx'),  'chkconfig.ltx' )
496       rmcopy = True
497     writeToFile('wrap_chkconfig.ltx', '%s\n%s\n\\input{chkconfig.ltx}\n' \
498       % (linuxdoc_cmd, docbook_cmd) )
499     # Construct the list of classes to test for.
500     # build the list of available layout files and convert it to commands
501     # for chkconfig.ltx
502     p1 = re.compile(r'\Declare(LaTeX|DocBook|LinuxDoc)Class')
503     testclasses = list()
504     for file in glob.glob( os.path.join('layouts', '*.layout') ) + \
505       glob.glob( os.path.join(srcdir, 'layouts', '*.layout' ) ) :
506       if not os.path.isfile(file):
507         continue
508       classname = file.split(os.sep)[-1].split('.')[0]
509       for line in open(file).readlines():
510         if p1.search(line) == None:
511           continue
512         if line[0] != '#':
513           print "Wrong input layout file with line '" + line
514           sys.exit(3)
515         testclasses.append("\\TestDocClass{%s}{%s}" % (classname, line[1:].strip()))
516         break
517     testclasses.sort()
518     cl = open('chklayouts.tex', 'w')
519     for line in testclasses:
520       cl.write(line + '\n')
521     cl.close()
522     #
523     # we have chklayouts.tex, then process it
524     for line in cmdOutput(LATEX + ' wrap_chkconfig.ltx').splitlines():
525       if re.match('^\+', line):
526         print line
527     #
528     # currently, values in chhkconfig are only used to set
529     # \font_encoding
530     values = {}
531     for line in open('chkconfig.vars').readlines():
532       key, val = re.sub('-', '_', line).split('=')
533       values[key] = val.strip("'\n")
534     # chk_fontenc may not exist 
535     try:
536       addToRC(r'\font_encoding "%s"' % values["chk_fontenc"])
537     except:
538       pass
539     if rmcopy:   # remove the copied file
540       removeFiles( [ 'chkconfig.ltx' ] )
541
542
543 def createLaTeXConfig():
544   ''' create LaTeXConfig.lyx '''
545   # if chkconfig.sed does not exist (because LaTeX did not run),
546   # then provide a standard version.
547   if not os.path.isfile('chkconfig.sed'):
548     writeToFile('chkconfig.sed', 's!@.*@!???!g\n')
549   print "creating packages.lst"
550   # if packages.lst does not exist (because LaTeX did not run),
551   # then provide a standard version.
552   if not os.path.isfile('packages.lst'):
553     writeToFile('packages.lst', '''
554 ### This file should contain the list of LaTeX packages that have been
555 ### recognized by LyX. Unfortunately, since configure could not find
556 ### your LaTeX2e program, the tests have not been run. Run ./configure
557 ### if you need to update it after a configuration change.
558 ''')
559   print 'creating doc/LaTeXConfig.lyx'
560   #
561   # This is originally done by sed, using a
562   # tex-generated file chkconfig.sed
563   ##sed -f chkconfig.sed ${srcdir}/doc/LaTeXConfig.lyx.in
564   ##  >doc/LaTeXConfig.lyx
565   # Now, we have to do it by hand (python).
566   #
567   # add to chekconfig.sed
568   writeToFile('chkconfig.sed', '''s!@chk_linuxdoc@!%s!g
569 s!@chk_docbook@!%s!g
570   ''' % (chk_linuxdoc, chk_docbook) , append=True)
571   # process this sed file!!!!
572   lyxin = open( os.path.join(srcdir, 'doc', 'LaTeXConfig.lyx.in')).readlines()
573   # get the rules
574   p = re.compile(r's!(.*)!(.*)!g')
575   # process each sed replace.
576   for sed in open('chkconfig.sed').readlines():
577     if sed.strip() == '':
578       continue
579     try:
580       fr, to = p.match(sed).groups()
581       # if latex did not run, change all @name@ to '???'
582       if fr == '@.*@':
583         for line in range(len(lyxin)):
584           lyxin[line] = re.sub('@.*@', to, lyxin[line])
585       else:
586         for line in range(len(lyxin)):
587           lyxin[line] = lyxin[line].replace(fr, to)
588     except:  # wrong sed entry?
589       print "Wrong sed entry in chkconfig.sed: '" + sed + "'"
590       sys.exit(4)
591   # 
592   writeToFile( os.path.join('doc', 'LaTeXConfig.lyx'),
593     ''.join(lyxin))
594
595
596 def checkTeXAllowSpaces():
597   ''' Let's check whether spaces are allowed in TeX file names '''
598   tex_allows_spaces = 'false'
599   if lyx_check_config:
600     print "Checking whether TeX allows spaces in file names... ",
601     writeToFile('a b.tex', r'\message{working^^J}' )
602     # FIXME: the bsh version uses < /dev/null which is not portable.
603     # Can anyone confirm if this option (-interaction) is available
604     # at other flavor of latex as well? (MikTex/win, Web2C/linux are fine.) 
605     if ''.join(cmdOutput(LATEX + ' -interaction=nonstopmode "a b"')).find('working') != -1:
606       print 'yes'
607       tex_allows_spaces = 'true'
608     else:
609       print 'no'
610       tex_allows_spaces = 'false'
611     addToRC(r'\tex_allows_spaces ' + tex_allows_spaces)
612     removeFiles( [ 'a b.tex', 'a b.log', 'texput.log' ])
613
614
615 def removeExtraFiles():
616   # Remove superfluous files if we are not writing in the main lib
617   # directory
618   for file in [outfile, 'textclass.lst', 'packages.lst', \
619     'doc/LaTeXConfig.lyx']:
620     try:
621       # we rename the file first, so that we avoid comparing a file with itself
622       os.rename(file, file + '.new')
623       syscfg = open( os.path.join(srcdir, file) ).read()
624       mycfg = open( file + '.new').read()
625       if mycfg == syscfg:
626         print "removing ", file, " which is identical to the system global version"
627         removeFiles( [file + '.new'] )
628       else:
629         os.rename( file + '.new', file )
630     except:  # use local version if anthing goes wrong.
631       os.rename( file + '.new', file )
632       pass
633   # Final clean-up
634   if not lyx_keep_temps:
635     removeFiles(['chkconfig.sed', 'chkconfig.vars',  \
636       'wrap_chkconfig.ltx', 'wrap_chkconfig.log', \
637       'chklayouts.tex', 'missfont.log'])
638
639
640 if __name__ == '__main__':
641   lyx_check_config = True
642   outfile = 'lyxrc.defaults'
643   rc_entries = ''
644   lyx_keep_temps = False
645   version_suffix = ''
646   ## Parse the command line
647   for op in sys.argv[1:]:   # default shell/for list is $*, the options
648     if op in [ '-help', '--help', '-h' ]:
649       print '''Usage: configure [options]
650 Options:
651   --help                   show this help lines
652   --keep-temps             keep temporary files (for debug. purposes)
653   --without-latex-config   do not run LaTeX to determine configuration
654   --with-version-suffix=suffix suffix of binary installed files
655 '''
656       sys.exit(0)
657     elif op == '--without-latex-config':
658       lyx_check_config = False
659     elif op == '--keep-temps':
660       lyx_keep_temps = True
661     elif op[0:22] == '--with-version-suffix=':  # never mind if op is not long enough
662       version_suffix = op[22:]
663     else:
664       print "Unknown option", op
665       sys.exit(1)
666   #    
667   # check if we run from the right directory
668   srcdir = os.path.dirname(sys.argv[0])
669   if srcdir == '':
670     srcdir = '.'
671   if not os.path.isfile( os.path.join(srcdir, 'chkconfig.ltx') ):
672     print "configure: error: cannot find chkconfig.ltx script"
673     sys.exit(1)
674   setEnviron()
675   createDirectories()
676   checkCygwinPath(srcdir)
677   ## Write the first part of outfile
678   writeToFile(outfile, '''# This file has been automatically generated by LyX' lib/configure.py
679 # script. It contains default settings that have been determined by
680 # examining your system. PLEASE DO NOT MODIFY ANYTHING HERE! If you
681 # want to customize LyX, make a copy of the file LYXDIR/lyxrc as
682 # ~/.lyx/lyxrc and edit this file instead. Any setting in lyxrc will
683 # override the values given here.
684 ''')
685   # check latex
686   LATEX = checkLatex()
687   checkFormatEntries()
688   checkConverterEntries()
689   (chk_linuxdoc, bool_linuxdoc, linuxdoc_cmd) = checkLinuxDoc()
690   (chk_docbook, bool_docbook, docbook_cmd) = checkDocBook()
691   checkTeXAllowSpaces()
692   checkOtherEntries()
693   # --without-latex-config can disable lyx_check_config
694   checkLatexConfig( lyx_check_config and LATEX != '', bool_docbook, bool_linuxdoc)
695   createLaTeXConfig()
696   removeExtraFiles()