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