2 # -*- coding: utf-8 -*-
5 # This file is part of LyX, the document processor.
6 # Licence details can be found in the file COPYING.
9 # Full author contact details are available in file CREDITS.
11 import sys, os, re, shutil, glob, logging
14 logging.basicConfig(level = logging.DEBUG,
15 format = '%(levelname)s: %(message)s', # ignore application name
16 filename = 'configure.log',
19 # Add a handler to log to console
20 console = logging.StreamHandler()
21 console.setLevel(logging.INFO) # the console only print out general information
22 formatter = logging.Formatter('%(message)s') # only print out the message itself
23 console.setFormatter(formatter)
24 logger = logging.getLogger('LyX')
25 logger.addHandler(console)
27 def writeToFile(filename, lines, append = False):
28 " utility function: write or append lines to filename "
30 file = open(filename, 'a')
32 file = open(filename, 'w')
38 ''' utility function: shortcut for appending lines to outfile
39 add newline at the end of lines.
41 if lines.strip() != '':
42 writeToFile(outfile, lines + '\n', append = True)
43 logger.debug('Add to RC:\n' + lines + '\n\n')
46 def removeFiles(filenames):
47 '''utility function: 'rm -f'
48 ignore errors when file does not exist, or is a directory.
50 for file in filenames:
53 logger.debug('Removing file %s' % file)
55 logger.debug('Failed to remove file %s' % file)
60 '''utility function: run a command and get its output as a string
70 ''' I do not really know why this is useful, but we might as well keep it.
72 Only set these to C if already set. These must not be set unconditionally
73 because not all systems understand e.g. LANG=C (notably SCO).
74 Fixing LC_MESSAGES prevents Solaris sh from translating var values in set!
75 Non-C LC_CTYPE values break the ctype check.
77 os.environ['LANG'] = os.getenv('LANG', 'C')
78 os.environ['LC'] = os.getenv('LC_ALL', 'C')
79 os.environ['LC_MESSAGE'] = os.getenv('LC_MESSAGE', 'C')
80 os.environ['LC_CTYPE'] = os.getenv('LC_CTYPE', 'C')
83 def createDirectories():
84 ''' Create the build directories if necessary '''
85 for dir in ['bind', 'clipart', 'doc', 'examples', 'images', 'kbd', \
86 'layouts', 'scripts', 'templates', 'ui' ]:
87 if not os.path.isdir( dir ):
90 logger.debug('Create directory %s.' % dir)
92 logger.error('Failed to create directory %s.' % dir)
97 ''' Determine the path-style needed by the TeX engine on Win32 (Cygwin) '''
98 windows_style_tex_paths = ''
100 return windows_style_tex_paths
101 if os.name == 'nt' or sys.platform == 'cygwin':
102 from tempfile import mkstemp
103 fd, tmpfname = mkstemp(suffix='.ltx')
105 from ctypes import windll, create_unicode_buffer
106 GetShortPathName = windll.kernel32.GetShortPathNameW
107 longname = unicode(tmpfname)
108 shortlen = GetShortPathName(longname, 0, 0)
109 shortname = create_unicode_buffer(shortlen)
110 if GetShortPathName(longname, shortname, shortlen):
111 inpname = shortname.value.replace('\\', '/')
113 inpname = tmpfname.replace('\\', '/')
115 inpname = cmdOutput('cygpath -m ' + tmpfname)
116 logname = os.path.basename(inpname.replace('.ltx', '.log'))
117 inpname = inpname.replace('~', '\\string~')
118 os.write(fd, r'\relax')
120 latex_out = cmdOutput(r'latex "\nonstopmode\input{%s}"' % inpname)
121 if 'Error' in latex_out:
122 latex_out = cmdOutput(r'latex "\nonstopmode\input{\"%s\"}"' % inpname)
123 if 'Error' in latex_out:
124 logger.warning("configure: TeX engine needs posix-style paths in latex files")
125 windows_style_tex_paths = 'false'
127 logger.info("configure: TeX engine needs windows-style paths in latex files")
128 windows_style_tex_paths = 'true'
129 removeFiles([tmpfname, logname, 'texput.log'])
130 return windows_style_tex_paths
133 ## Searching some useful programs
134 def checkProg(description, progs, rc_entry = [], path = [], not_found = ''):
136 This function will search a program in $PATH plus given path
137 If found, return directory and program name (not the options).
139 description: description of the program
141 progs: check programs, for each prog, the first word is used
142 for searching but the whole string is used to replace
143 %% for a rc_entry. So, feel free to add '$$i' etc for programs.
145 path: additional pathes
147 rc_entry: entry to outfile, can be
148 1. emtpy: no rc entry will be added
149 2. one pattern: %% will be replaced by the first found program,
150 or '' if no program is found.
151 3. several patterns for each prog and not_found. This is used
152 when different programs have different usages. If you do not
153 want not_found entry to be added to the RC file, you can specify
154 an entry for each prog and use '' for the not_found entry.
156 not_found: the value that should be used instead of '' if no program
160 # one rc entry for each progs plus not_found entry
161 if len(rc_entry) > 1 and len(rc_entry) != len(progs) + 1:
162 logger.error("rc entry should have one item or item for each prog and not_found.")
164 logger.info('checking for ' + description + '...')
165 ## print '(' + ','.join(progs) + ')',
166 for idx in range(len(progs)):
167 # ac_prog may have options, ac_word is the command name
169 ac_word = ac_prog.split(' ')[0]
170 msg = '+checking for "' + ac_word + '"... '
171 path = os.environ["PATH"].split(os.pathsep) + path
173 if "PATHEXT" in os.environ:
174 extlist = extlist + os.environ["PATHEXT"].split(os.pathsep)
177 if os.path.isfile( os.path.join(ac_dir, ac_word + ext) ):
178 logger.info(msg + ' yes')
179 # write rc entries for this command
180 if len(rc_entry) == 1:
181 addToRC(rc_entry[0].replace('%%', ac_prog))
182 elif len(rc_entry) > 1:
183 addToRC(rc_entry[idx].replace('%%', ac_prog))
184 return [ac_dir, ac_word]
186 logger.info(msg + ' no')
187 # write rc entries for 'not found'
188 if len(rc_entry) > 0: # the last one.
189 addToRC(rc_entry[-1].replace('%%', not_found))
190 return ['', not_found]
193 def checkProgAlternatives(description, progs, rc_entry = [], alt_rc_entry = [], path = [], not_found = ''):
195 The same as checkProg, but additionally, all found programs will be added
198 # one rc entry for each progs plus not_found entry
199 if len(rc_entry) > 1 and len(rc_entry) != len(progs) + 1:
200 logger.error("rc entry should have one item or item for each prog and not_found.")
202 logger.info('checking for ' + description + '...')
203 ## print '(' + ','.join(progs) + ')',
206 real_ac_word = not_found
207 for idx in range(len(progs)):
208 # ac_prog may have options, ac_word is the command name
210 ac_word = ac_prog.split(' ')[0]
211 msg = '+checking for "' + ac_word + '"... '
212 path = os.environ["PATH"].split(os.pathsep) + path
214 if "PATHEXT" in os.environ:
215 extlist = extlist + os.environ["PATHEXT"].split(os.pathsep)
219 if os.path.isfile( os.path.join(ac_dir, ac_word + ext) ):
220 logger.info(msg + ' yes')
221 pr = re.compile(r'(\\\S+)(.*)$')
223 # write rc entries for this command
224 if found_prime == False:
225 if len(rc_entry) == 1:
226 addToRC(rc_entry[0].replace('%%', ac_prog))
227 elif len(rc_entry) > 1:
228 addToRC(rc_entry[idx].replace('%%', ac_prog))
230 real_ac_word = ac_word
232 if len(alt_rc_entry) == 1:
233 alt_rc = alt_rc_entry[0]
235 # if no explicit alt_rc is given, construct one
236 m = pr.match(rc_entry[0])
238 alt_rc = m.group(1) + "_alternatives" + m.group(2)
239 addToRC(alt_rc.replace('%%', ac_prog))
240 elif len(alt_rc_entry) > 1:
241 alt_rc = alt_rc_entry[idx]
243 # if no explicit alt_rc is given, construct one
244 m = pr.match(rc_entry[idx])
246 alt_rc = m.group(1) + "_alternatives" + m.group(2)
247 addToRC(alt_rc.replace('%%', ac_prog))
252 if found_alt == False:
254 logger.info(msg + ' no')
256 return [real_ac_dir, real_ac_word]
257 # write rc entries for 'not found'
258 if len(rc_entry) > 0: # the last one.
259 addToRC(rc_entry[-1].replace('%%', not_found))
260 return ['', not_found]
263 def addViewerAlternatives(rcs):
264 r = re.compile(r'\\Format (\S+).*$')
267 for idxx in range(len(rcs)):
271 alt = r'\viewer_alternatives ' + m.group(1) + " %%"
273 m = r.match(rcs[idxx])
277 alt += r'\viewer_alternatives ' + m.group(1) + " %%"
281 def addEditorAlternatives(rcs):
282 r = re.compile(r'\\Format (\S+).*$')
285 for idxx in range(len(rcs)):
289 alt = r'\editor_alternatives ' + m.group(1) + " %%"
291 m = r.match(rcs[idxx])
295 alt += r'\editor_alternatives ' + m.group(1) + " %%"
299 def checkViewer(description, progs, rc_entry = [], path = []):
300 ''' The same as checkProgAlternatives, but for viewers '''
301 if len(rc_entry) > 1 and len(rc_entry) != len(progs) + 1:
302 logger.error("rc entry should have one item or item for each prog and not_found.")
305 for idx in range(len(progs)):
306 if len(rc_entry) == 1:
307 rcs = rc_entry[0].split('\n')
308 alt = addViewerAlternatives(rcs)
309 alt_rc_entry.insert(0, alt)
310 elif len(rc_entry) > 1:
311 rcs = rc_entry[idx].split('\n')
312 alt = addViewerAlternatives(rcs)
313 alt_rc_entry.insert(idx, alt)
314 return checkProgAlternatives(description, progs, rc_entry, alt_rc_entry, path, not_found = 'auto')
317 def checkEditor(description, progs, rc_entry = [], path = []):
318 ''' The same as checkProgAlternatives, but for editors '''
319 if len(rc_entry) > 1 and len(rc_entry) != len(progs) + 1:
320 logger.error("rc entry should have one item or item for each prog and not_found.")
323 for idx in range(len(progs)):
324 if len(rc_entry) == 1:
325 rcs = rc_entry[0].split('\n')
326 alt = addEditorAlternatives(rcs)
327 alt_rc_entry.insert(0, alt)
328 elif len(rc_entry) > 1:
329 rcs = rc_entry[idx].split('\n')
330 alt = addEditorAlternatives(rcs)
331 alt_rc_entry.insert(idx, alt)
332 return checkProgAlternatives(description, progs, rc_entry, alt_rc_entry, path, not_found = 'auto')
335 def checkViewerNoRC(description, progs, rc_entry = [], path = []):
336 ''' The same as checkViewer, but do not add rc entry '''
337 if len(rc_entry) > 1 and len(rc_entry) != len(progs) + 1:
338 logger.error("rc entry should have one item or item for each prog and not_found.")
341 for idx in range(len(progs)):
342 if len(rc_entry) == 1:
343 rcs = rc_entry[0].split('\n')
344 alt = addViewerAlternatives(rcs)
345 alt_rc_entry.insert(0, alt)
346 elif len(rc_entry) > 1:
347 rcs = rc_entry[idx].split('\n')
348 alt = addViewerAlternatives(rcs)
349 alt_rc_entry.insert(idx, alt)
351 return checkProgAlternatives(description, progs, rc_entry, alt_rc_entry, path, not_found = 'auto')
354 def checkEditorNoRC(description, progs, rc_entry = [], path = []):
355 ''' The same as checkViewer, but do not add rc entry '''
356 if len(rc_entry) > 1 and len(rc_entry) != len(progs) + 1:
357 logger.error("rc entry should have one item or item for each prog and not_found.")
360 for idx in range(len(progs)):
361 if len(rc_entry) == 1:
362 rcs = rc_entry[0].split('\n')
363 alt = addEditorAlternatives(rcs)
364 alt_rc_entry.insert(0, alt)
365 elif len(rc_entry) > 1:
366 rcs = rc_entry[idx].split('\n')
367 alt = addEditorAlternatives(rcs)
368 alt_rc_entry.insert(idx, alt)
370 return checkProgAlternatives(description, progs, rc_entry, alt_rc_entry, path, not_found = 'auto')
373 def checkViewerEditor(description, progs, rc_entry = [], path = []):
374 ''' The same as checkProgAlternatives, but for viewers and editors '''
375 checkEditorNoRC(description, progs, rc_entry, path)
376 return checkViewer(description, progs, rc_entry, path)
380 ''' Check whether DTL tools are available (Windows only) '''
381 # Find programs! Returned path is not used now
382 if ((os.name == 'nt' or sys.platform == 'cygwin') and
383 checkProg('DVI to DTL converter', ['dv2dt']) != ['', ''] and
384 checkProg('DTL to DVI converter', ['dt2dv']) != ['', '']):
391 def checkLatex(dtl_tools):
392 ''' Check latex, return lyx_check_config '''
393 path, LATEX = checkProg('a Latex2e program', ['latex $$i', 'latex2e $$i'])
394 path, PPLATEX = checkProg('a DVI postprocessing program', ['pplatex $$i'])
395 #-----------------------------------------------------------------
396 path, PLATEX = checkProg('pLaTeX, the Japanese LaTeX', ['platex $$i'])
398 # check if PLATEX is pLaTeX2e
399 writeToFile('chklatex.ltx', '''
403 # run platex on chklatex.ltx and check result
404 if cmdOutput(PLATEX + ' chklatex.ltx').find('pLaTeX2e') != -1:
405 # We have the Japanese pLaTeX2e
406 addToRC(r'\converter platex dvi "%s" "latex=platex"' % PLATEX)
409 removeFiles(['chklatex.ltx', 'chklatex.log'])
410 #-----------------------------------------------------------------
411 # use LATEX to convert from latex to dvi if PPLATEX is not available
415 # Windows only: DraftDVI
416 addToRC(r'''\converter latex dvi2 "%s" "latex"
417 \converter dvi2 dvi "python -tt $$s/scripts/clean_dvi.py $$i $$o" ""''' % PPLATEX)
419 addToRC(r'\converter latex dvi "%s" "latex"' % PPLATEX)
422 # Check if latex is usable
423 writeToFile('chklatex.ltx', '''
424 \\nonstopmode\\makeatletter
425 \\ifx\\undefined\\documentclass\\else
426 \\message{ThisIsLaTeX2e}
430 # run latex on chklatex.ltx and check result
431 if cmdOutput(LATEX + ' chklatex.ltx').find('ThisIsLaTeX2e') != -1:
435 logger.warning("Latex not usable (not LaTeX2e) ")
436 # remove temporary files
437 removeFiles(['chklatex.ltx', 'chklatex.log'])
442 ''' Check if luatex is there and usable '''
443 path, LUATEX = checkProg('LuaTeX', ['lualatex $$i'])
444 path, DVILUATEX = checkProg('LuaTeX (DVI)', ['dvilualatex $$i'])
446 # luatex binary is there
447 msg = "checking if LuaTeX is usable ..."
448 # Check if luatex is usable
449 writeToFile('luatest.tex', '''
450 \\nonstopmode\\documentclass{minimal}
451 \\usepackage{fontspec}
456 # run lualatex on luatest.tex and check result
457 luatest = cmdOutput(LUATEX + ' luatest.tex')
458 if luatest.find('XeTeX is required to compile this document') != -1:
459 # fontspec/luatex too old! We do not support this version.
460 logger.info(msg + ' no (probably not recent enough)')
461 elif luatest.find('! LaTeX Error: File `fontspec.sty\' not found') != -1:
463 logger.info(msg + ' no (missing fontspec)')
466 logger.info(msg + ' yes')
467 addToRC(r'\converter luatex pdf5 "%s" "latex=lualatex"' % LUATEX)
469 addToRC(r'\converter luatex dvi3 "%s" "latex=lualatex"' % DVILUATEX)
470 # remove temporary files
471 removeFiles(['luatest.tex', 'luatest.log', 'luatest.aux', 'luatest.pdf'])
474 def checkModule(module):
475 ''' Check for a Python module, return the status '''
476 msg = 'checking for "' + module + ' module"... '
479 logger.info(msg + ' yes')
482 logger.info(msg + ' no')
486 def checkFormatEntries(dtl_tools):
487 ''' Check all formats (\Format entries) '''
488 checkViewerEditor('a Tgif viewer and editor', ['tgif'],
489 rc_entry = [r'\Format tgif obj Tgif "" "%%" "%%" "vector"'])
491 checkViewerEditor('a FIG viewer and editor', ['xfig', 'jfig3-itext.jar', 'jfig3.jar'],
492 rc_entry = [r'\Format fig fig FIG "" "%%" "%%" "vector"'])
494 checkViewerEditor('a Dia viewer and editor', ['dia'],
495 rc_entry = [r'\Format dia dia DIA "" "%%" "%%" "vector"'])
497 checkViewerEditor('a Grace viewer and editor', ['xmgrace'],
498 rc_entry = [r'\Format agr agr Grace "" "%%" "%%" "vector"'])
500 checkViewerEditor('a FEN viewer and editor', ['xboard -lpf $$i -mode EditPosition'],
501 rc_entry = [r'\Format fen fen FEN "" "%%" "%%" ""'])
503 checkViewerEditor('a SVG viewer and editor', ['inkscape'],
504 rc_entry = [r'\Format svg svg SVG "" "%%" "%%" "vector"'])
506 path, iv = checkViewerNoRC('a raster image viewer', ['xv', 'kview', 'gimp-remote', 'gimp'],
507 rc_entry = [r'''\Format bmp bmp BMP "" "%s" "%s" ""
508 \Format gif gif GIF "" "%s" "%s" ""
509 \Format jpg jpg JPEG "" "%s" "%s" ""
510 \Format pbm pbm PBM "" "%s" "%s" ""
511 \Format pgm pgm PGM "" "%s" "%s" ""
512 \Format png png PNG "" "%s" "%s" ""
513 \Format ppm ppm PPM "" "%s" "%s" ""
514 \Format tiff tif TIFF "" "%s" "%s" ""
515 \Format xbm xbm XBM "" "%s" "%s" ""
516 \Format xpm xpm XPM "" "%s" "%s" ""'''])
517 path, ie = checkEditorNoRC('a raster image editor', ['gimp-remote', 'gimp'],
518 rc_entry = [r'''\Format bmp bmp BMP "" "%s" "%s" ""
519 \Format gif gif GIF "" "%s" "%s" ""
520 \Format jpg jpg JPEG "" "%s" "%s" ""
521 \Format pbm pbm PBM "" "%s" "%s" ""
522 \Format pgm pgm PGM "" "%s" "%s" ""
523 \Format png png PNG "" "%s" "%s" ""
524 \Format ppm ppm PPM "" "%s" "%s" ""
525 \Format tiff tif TIFF "" "%s" "%s" ""
526 \Format xbm xbm XBM "" "%s" "%s" ""
527 \Format xpm xpm XPM "" "%s" "%s" ""'''])
528 addToRC(r'''\Format bmp bmp BMP "" "%s" "%s" ""
529 \Format gif gif GIF "" "%s" "%s" ""
530 \Format jpg jpg JPEG "" "%s" "%s" ""
531 \Format pbm pbm PBM "" "%s" "%s" ""
532 \Format pgm pgm PGM "" "%s" "%s" ""
533 \Format png png PNG "" "%s" "%s" ""
534 \Format ppm ppm PPM "" "%s" "%s" ""
535 \Format tiff tif TIFF "" "%s" "%s" ""
536 \Format xbm xbm XBM "" "%s" "%s" ""
537 \Format xpm xpm XPM "" "%s" "%s" ""''' % \
538 (iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie) )
540 checkViewerEditor('a text editor', ['xemacs', 'gvim', 'kedit', 'kwrite', 'kate', \
541 'nedit', 'gedit', 'notepad'],
542 rc_entry = [r'''\Format asciichess asc "Plain text (chess output)" "" "" "%%" ""
543 \Format asciiimage asc "Plain text (image)" "" "" "%%" ""
544 \Format asciixfig asc "Plain text (Xfig output)" "" "" "%%" ""
545 \Format dateout tmp "date (output)" "" "" "%%" ""
546 \Format docbook sgml DocBook B "" "%%" "document,menu=export"
547 \Format docbook-xml xml "Docbook (XML)" "" "" "%%" "document,menu=export"
548 \Format dot dot "Graphviz Dot" "" "" "%%" "vector"
549 \Format platex tex "LaTeX (pLaTeX)" "" "" "%%" "document,menu=export"
550 \Format literate nw NoWeb N "" "%%" "document,menu=export"
551 \Format sweave Rnw "Sweave" S "" "%%" "document,menu=export"
552 \Format lilypond ly "LilyPond music" "" "" "%%" "vector"
553 \Format lilypond-book lytex "LilyPond book (LaTeX)" "" "" "%%" "document,menu=export"
554 \Format latex tex "LaTeX (plain)" L "" "%%" "document,menu=export"
555 \Format luatex tex "LaTeX (LuaTeX)" "" "" "%%" "document,menu=export"
556 \Format pdflatex tex "LaTeX (pdflatex)" "" "" "%%" "document,menu=export"
557 \Format xetex tex "LaTeX (XeTeX)" "" "" "%%" "document,menu=export"
558 \Format text txt "Plain text" a "" "%%" "document,menu=export"
559 \Format text2 txt "Plain text (pstotext)" "" "" "%%" "document"
560 \Format text3 txt "Plain text (ps2ascii)" "" "" "%%" "document"
561 \Format text4 txt "Plain text (catdvi)" "" "" "%%" "document"
562 \Format textparagraph txt "Plain Text, Join Lines" "" "" "%%" "document"''' ])
563 #Spreadsheets using ssconvert from gnumeric
564 checkViewer('gnumeric spreadsheet software', ['gnumeric'],
565 rc_entry = [r'''\Format gnumeric gnumeric "Gnumeric spreadsheet" "" "" "%%" "document"
566 \Format excel xls "Excel spreadsheet" "" "" "%%" "document"
567 \Format oocalc ods "OpenOffice spreadsheet" "" "" "%%" "document"'''])
569 path, xhtmlview = checkViewer('an HTML previewer', ['firefox', 'mozilla file://$$p$$i', 'netscape'],
570 rc_entry = [r'\Format xhtml xhtml "LyXHTML" y "%%" "" "document,menu=export"'])
572 addToRC(r'\Format xhtml xhtml "LyXHTML" y "" "" "document,menu=export"')
574 checkEditor('a BibTeX editor', ['jabref', 'JabRef', \
575 'pybliographic', 'bibdesk', 'gbib', 'kbib', \
576 'kbibtex', 'sixpack', 'bibedit', 'tkbibtex' \
577 'xemacs', 'gvim', 'kedit', 'kwrite', 'kate', \
578 'nedit', 'gedit', 'notepad'],
579 rc_entry = [r'''\Format bibtex bib "BibTeX" "" "" "%%" ""''' ])
581 #checkProg('a Postscript interpreter', ['gs'],
582 # rc_entry = [ r'\ps_command "%%"' ])
583 checkViewer('a Postscript previewer', ['kghostview', 'okular', 'evince', 'gv', 'ghostview -swap'],
584 rc_entry = [r'''\Format eps eps EPS "" "%%" "" "vector"
585 \Format ps ps Postscript t "%%" "" "document,vector"'''])
586 # for xdg-open issues look here: http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg151818.html
587 checkViewer('a PDF previewer', ['kpdf', 'okular', 'evince', 'kghostview', 'xpdf', 'acrobat', 'acroread', \
589 rc_entry = [r'''\Format pdf pdf "PDF (ps2pdf)" P "%%" "" "document,vector,menu=export"
590 \Format pdf2 pdf "PDF (pdflatex)" F "%%" "" "document,vector,menu=export"
591 \Format pdf3 pdf "PDF (dvipdfm)" m "%%" "" "document,vector,menu=export"
592 \Format pdf4 pdf "PDF (XeTeX)" X "%%" "" "document,vector,menu=export"
593 \Format pdf5 pdf "PDF (LuaTeX)" u "%%" "" "document,vector,menu=export"'''])
595 checkViewer('a DVI previewer', ['xdvi', 'kdvi', 'okular', 'yap', 'dviout -Set=!m'],
596 rc_entry = [r'''\Format dvi dvi DVI D "%%" "" "document,vector,menu=export"
597 \Format dvi3 dvi "DVI (LuaTeX)" V "%%" "" "document,vector,menu=export"'''])
599 # Windows only: DraftDVI
600 addToRC(r'\Format dvi2 dvi DraftDVI "" "" "" "vector"')
602 checkViewer('an HTML previewer', ['firefox', 'mozilla file://$$p$$i', 'netscape'],
603 rc_entry = [r'\Format html html HTML H "%%" "" "document,menu=export"'])
605 checkViewerEditor('Noteedit', ['noteedit'],
606 rc_entry = [r'\Format noteedit not Noteedit "" "%%" "%%" "vector"'])
608 checkViewerEditor('an OpenDocument/OpenOffice viewer', ['swriter', 'oowriter', 'abiword'],
609 rc_entry = [r'''\Format odt odt OpenDocument "" "%%" "%%" "document,vector,menu=export"
610 \Format sxw sxw "OpenOffice.Org (sxw)" "" "" "" "document,vector"'''])
612 checkViewerEditor('a Rich Text and Word viewer', ['swriter', 'oowriter', 'abiword'],
613 rc_entry = [r'''\Format rtf rtf "Rich Text Format" "" "%%" "%%" "document,vector,menu=export"
614 \Format word doc "MS Word" W "%%" "%%" "document,vector,menu=export"'''])
616 # entries that do not need checkProg
617 addToRC(r'''\Format date "" "date command" "" "" "" ""
618 \Format csv csv "Table (CSV)" "" "" "" "document"
619 \Format fax "" Fax "" "" "" "document"
620 \Format lyx lyx LyX "" "" "" ""
621 \Format lyx13x 13.lyx "LyX 1.3.x" "" "" "" "document"
622 \Format lyx14x 14.lyx "LyX 1.4.x" "" "" "" "document"
623 \Format lyx15x 15.lyx "LyX 1.5.x" "" "" "" "document"
624 \Format lyx16x 16.lyx "LyX 1.6.x" "" "" "" "document,menu=export"
625 \Format clyx cjklyx "CJK LyX 1.4.x (big5)" "" "" "" "document"
626 \Format jlyx cjklyx "CJK LyX 1.4.x (euc-jp)" "" "" "" "document"
627 \Format klyx cjklyx "CJK LyX 1.4.x (euc-kr)" "" "" "" "document"
628 \Format lyxpreview lyxpreview "LyX Preview" "" "" "" ""
629 \Format lyxpreview-lytex lyxpreview-lytex "LyX Preview (LilyPond book)" "" "" "" ""
630 \Format lyxpreview-platex lyxpreview-platex "LyX Preview (pLaTeX)" "" "" "" ""
631 \Format pdftex pdftex_t PDFTEX "" "" "" ""
632 \Format program "" Program "" "" "" ""
633 \Format pstex pstex_t PSTEX "" "" "" ""
634 \Format wmf wmf "Windows Metafile" "" "" "" "vector"
635 \Format emf emf "Enhanced Metafile" "" "" "" "vector"
636 \Format wordhtml html "HTML (MS Word)" "" "" "" "document"
640 def checkConverterEntries():
641 ''' Check all converters (\converter entries) '''
642 checkProg('the pdflatex program', ['pdflatex $$i'],
643 rc_entry = [ r'\converter pdflatex pdf2 "%%" "latex=pdflatex"' ])
645 checkProg('XeTeX', ['xelatex $$i'],
646 rc_entry = [ r'\converter xetex pdf4 "%%" "latex=xelatex"' ])
650 ''' If we're running LyX in-place then tex2lyx will be found in
651 ../src/tex2lyx. Add this directory to the PATH temporarily and
653 Use PATH to avoid any problems with paths-with-spaces.
655 path_orig = os.environ["PATH"]
656 os.environ["PATH"] = os.path.join('..', 'src', 'tex2lyx') + \
657 os.pathsep + path_orig
659 # First search for tex2lyx with version suffix (bug 6986)
660 checkProg('a LaTeX/Noweb -> LyX converter', ['tex2lyx' + version_suffix, 'tex2lyx'],
661 rc_entry = [r'''\converter latex lyx "%% -f $$i $$o" ""
662 \converter literate lyx "%% -n -f $$i $$o" ""'''])
664 os.environ["PATH"] = path_orig
667 checkProg('a Noweb -> LaTeX converter', ['noweave -delay -index $$i > $$o'],
668 rc_entry = [r'''\converter literate latex "%%" ""
669 \converter literate pdflatex "%%" ""'''])
671 checkProg('a Sweave -> LaTeX converter', ['Rscript --verbose --no-save --no-restore $$s/scripts/lyxsweave.R $$p$$i $$p$$o $$e $$r'],
672 rc_entry = [r'''\converter sweave latex "%%" ""
673 \converter sweave pdflatex "%%" ""
674 \converter sweave xetex "%%" ""
675 \converter sweave luatex "%%" ""'''])
677 checkProg('an HTML -> LaTeX converter', ['html2latex $$i', 'gnuhtml2latex $$i', \
678 'htmltolatex -input $$i -output $$o', 'java -jar htmltolatex.jar -input $$i -output $$o'],
679 rc_entry = [ r'\converter html latex "%%" ""' ])
681 checkProg('an MS Word -> LaTeX converter', ['wvCleanLatex $$i $$o'],
682 rc_entry = [ r'\converter word latex "%%" ""' ])
684 # eLyXer: search as an executable (elyxer.py, elyxer)
685 path, elyxer = checkProg('a LyX -> HTML converter',
686 ['elyxer.py --directory $$r $$i $$o', 'elyxer --directory $$r $$i $$o'],
687 rc_entry = [ r'\converter lyx html "%%" ""' ])
688 path, elyxer = checkProg('a LyX -> HTML (MS Word) converter',
689 ['elyxer.py --html --directory $$r $$i $$o', 'elyxer --html --directory $$r $$i $$o'],
690 rc_entry = [ r'\converter lyx wordhtml "%%" ""' ])
691 if elyxer.find('elyxer') >= 0:
692 addToRC(r'''\copier html "python -tt $$s/scripts/ext_copy.py -e html,png,jpg,jpeg,css $$i $$o"''')
693 addToRC(r'''\copier wordhtml "python -tt $$s/scripts/ext_copy.py -e html,png,jpg,jpeg,css $$i $$o"''')
695 # search for HTML converters other than eLyXer
696 # On SuSE the scripts have a .sh suffix, and on debian they are in /usr/share/tex4ht/
697 path, htmlconv = checkProg('a LaTeX -> HTML converter', ['htlatex $$i', 'htlatex.sh $$i', \
698 '/usr/share/tex4ht/htlatex $$i', 'tth -t -e2 -L$$b < $$i > $$o', \
699 'latex2html -no_subdir -split 0 -show_section_numbers $$i', 'hevea -s $$i'],
700 rc_entry = [ r'\converter latex html "%%" "needaux"' ])
701 if htmlconv.find('htlatex') >= 0 or htmlconv == 'latex2html':
702 addToRC(r'''\copier html "python -tt $$s/scripts/ext_copy.py -e html,png,css $$i $$o"''')
704 addToRC(r'''\copier html "python -tt $$s/scripts/ext_copy.py $$i $$o"''')
705 path, htmlconv = checkProg('a LaTeX -> HTML (MS Word) converter', ["htlatex $$i 'html,word' 'symbol/!' '-cvalidate'", \
706 "htlatex.sh $$i 'html,word' 'symbol/!' '-cvalidate'", \
707 "/usr/share/tex4ht/htlatex $$i 'html,word' 'symbol/!' '-cvalidate'"],
708 rc_entry = [ r'\converter latex wordhtml "%%" "needaux"' ])
709 if htmlconv.find('htlatex') >= 0:
710 addToRC(r'''\copier wordhtml "python -tt $$s/scripts/ext_copy.py -e html,png,css $$i $$o"''')
712 addToRC(r'''\copier wordhtml "python -tt $$s/scripts/ext_copy.py $$i $$o"''')
715 # Check if LyXBlogger is installed
716 lyxblogger_found = checkModule('lyxblogger')
718 addToRC(r'\Format blog blog "LyXBlogger" "" "" "" "document"')
719 addToRC(r'\converter xhtml blog "python -m lyxblogger $$i" ""')
722 checkProg('an OpenOffice.org -> LaTeX converter', ['w2l -clean $$i'],
723 rc_entry = [ r'\converter sxw latex "%%" ""' ])
725 checkProg('an OpenDocument -> LaTeX converter', ['w2l -clean $$i'],
726 rc_entry = [ r'\converter odt latex "%%" ""' ])
727 # According to http://www.tug.org/applications/tex4ht/mn-commands.html
728 # the command mk4ht oolatex $$i has to be used as default,
729 # but as this would require to have Perl installed, in MiKTeX oolatex is
730 # directly available as application.
731 # On SuSE the scripts have a .sh suffix, and on debian they are in /usr/share/tex4ht/
732 # Both SuSE and debian have oolatex
733 checkProg('a LaTeX -> Open Document converter', [
734 'oolatex $$i', 'mk4ht oolatex $$i', 'oolatex.sh $$i', '/usr/share/tex4ht/oolatex $$i',
735 'htlatex $$i \'xhtml,ooffice\' \'ooffice/! -cmozhtf\' \'-coo\' \'-cvalidate\''],
736 rc_entry = [ r'\converter latex odt "%%" "needaux"' ])
737 # On windows it is called latex2rt.exe
738 checkProg('a LaTeX -> RTF converter', ['latex2rtf -p -S -o $$o $$i', 'latex2rt -p -S -o $$o $$i'],
739 rc_entry = [ r'\converter latex rtf "%%" "needaux"' ])
741 checkProg('a RTF -> HTML converter', ['unrtf --html $$i > $$o'],
742 rc_entry = [ r'\converter rtf html "%%" ""' ])
744 checkProg('a PS to PDF converter', ['ps2pdf13 $$i $$o'],
745 rc_entry = [ r'\converter ps pdf "%%" ""' ])
747 checkProg('a PS to TXT converter', ['pstotext $$i > $$o'],
748 rc_entry = [ r'\converter ps text2 "%%" ""' ])
750 checkProg('a PS to TXT converter', ['ps2ascii $$i $$o'],
751 rc_entry = [ r'\converter ps text3 "%%" ""' ])
753 checkProg('a PS to EPS converter', ['ps2eps $$i'],
754 rc_entry = [ r'\converter ps eps "%%" ""' ])
756 checkProg('a PDF to PS converter', ['pdf2ps $$i $$o', 'pdftops $$i $$o'],
757 rc_entry = [ r'\converter pdf ps "%%" ""' ])
759 checkProg('a PDF to EPS converter', ['pdftops -eps -f 1 -l 1 $$i $$o'],
760 rc_entry = [ r'\converter pdf eps "%%" ""' ])
762 checkProg('a DVI to TXT converter', ['catdvi $$i > $$o'],
763 rc_entry = [ r'\converter dvi text4 "%%" ""' ])
765 checkProg('a DVI to PS converter', ['dvips -o $$o $$i'],
766 rc_entry = [ r'\converter dvi ps "%%" ""' ])
768 checkProg('a DVI to PDF converter', ['dvipdfmx -o $$o $$i', 'dvipdfm -o $$o $$i'],
769 rc_entry = [ r'\converter dvi pdf3 "%%" ""' ])
771 path, dvipng = checkProg('dvipng', ['dvipng'])
772 path, dv2dt = checkProg('DVI to DTL converter', ['dv2dt'])
773 if dvipng == "dvipng" and dv2dt == 'dv2dt':
774 addToRC(r'\converter lyxpreview png "python -tt $$s/scripts/lyxpreview2bitmap.py" ""')
776 # set empty converter to override the default imagemagick
777 addToRC(r'\converter lyxpreview png "" ""')
779 addToRC(r'\converter lyxpreview ppm "python -tt $$s/scripts/lyxpreview2bitmap.py" ""')
781 # set empty converter to override the default imagemagick
782 addToRC(r'\converter lyxpreview ppm "" ""')
784 checkProg('a fax program', ['kdeprintfax $$i', 'ksendfax $$i', 'hylapex $$i'],
785 rc_entry = [ r'\converter ps fax "%%" ""'])
787 path, fig2dev = checkProg('a FIG -> Image converter', ['fig2dev'])
788 if fig2dev == "fig2dev":
789 addToRC(r'''\converter fig eps "fig2dev -L eps $$i $$o" ""
790 \converter fig ppm "fig2dev -L ppm $$i $$o" ""
791 \converter fig png "fig2dev -L png $$i $$o" ""
792 \converter fig pdftex "python -tt $$s/scripts/fig2pdftex.py $$i $$o" ""
793 \converter fig pstex "python -tt $$s/scripts/fig2pstex.py $$i $$o" ""''')
795 checkProg('a TIFF -> PS converter', ['tiff2ps $$i > $$o'],
796 rc_entry = [ r'\converter tiff eps "%%" ""', ''])
798 checkProg('a TGIF -> EPS/PPM converter', ['tgif'],
800 r'''\converter tgif eps "tgif -print -color -eps -stdout $$i > $$o" ""
801 \converter tgif png "tgif -print -color -png -o $$d $$i" ""
802 \converter tgif pdf "tgif -print -color -pdf -stdout $$i > $$o" ""''',
805 checkProg('a WMF -> EPS converter', ['metafile2eps $$i $$o', 'wmf2eps -o $$o $$i'],
806 rc_entry = [ r'\converter wmf eps "%%" ""'])
808 checkProg('an EMF -> EPS converter', ['metafile2eps $$i $$o', 'wmf2eps -o $$o $$i'],
809 rc_entry = [ r'\converter emf eps "%%" ""'])
811 checkProg('an EPS -> PDF converter', ['epstopdf'],
812 rc_entry = [ r'\converter eps pdf "epstopdf --outfile=$$o $$i" ""', ''])
814 # no agr -> pdf converter, since the pdf library used by gracebat is not
815 # free software and therefore not compiled in in many installations.
816 # Fortunately, this is not a big problem, because we will use epstopdf to
817 # convert from agr to pdf via eps without loss of quality.
818 checkProg('a Grace -> Image converter', ['gracebat'],
820 r'''\converter agr eps "gracebat -hardcopy -printfile $$o -hdevice EPS $$i 2>/dev/null" ""
821 \converter agr png "gracebat -hardcopy -printfile $$o -hdevice PNG $$i 2>/dev/null" ""
822 \converter agr jpg "gracebat -hardcopy -printfile $$o -hdevice JPEG $$i 2>/dev/null" ""
823 \converter agr ppm "gracebat -hardcopy -printfile $$o -hdevice PNM $$i 2>/dev/null" ""''',
826 checkProg('a Dot -> Image converter', ['dot'],
828 r'''\converter dot eps "dot -Teps $$i -o $$o" ""
829 \converter dot png "dot -Tpng $$i -o $$o" ""''',
832 checkProg('a Dia -> PNG converter', ['dia -e $$o -t png $$i'],
833 rc_entry = [ r'\converter dia png "%%" ""'])
835 checkProg('a Dia -> EPS converter', ['dia -e $$o -t eps $$i'],
836 rc_entry = [ r'\converter dia eps "%%" ""'])
838 checkProg('a SVG -> PDF converter', ['rsvg-convert -f pdf -o $$o $$i', 'inkscape --file=$$i --export-area-drawing --without-gui --export-pdf=$$o'],
839 rc_entry = [ r'\converter svg pdf "%%" ""'])
841 checkProg('a SVG -> EPS converter', ['rsvg-convert -f ps -o $$o $$i', 'inkscape --file=$$i --export-area-drawing --without-gui --export-eps=$$o'],
842 rc_entry = [ r'\converter svg eps "%%" ""'])
844 checkProg('a SVG -> PNG converter', ['rsvg-convert -f png -o $$o $$i', 'inkscape --without-gui --file=$$i --export-png=$$o'],
845 rc_entry = [ r'\converter svg png "%%" ""'])
848 # gnumeric/xls/ods to tex
849 checkProg('a spreadsheet -> latex converter', ['ssconvert'],
850 rc_entry = [ r'''\converter gnumeric latex "ssconvert --export-type=Gnumeric_html:latex $$i $$o" ""
851 \converter ods latex "ssconvert --export-type=Gnumeric_html:latex $$i $$o" ""
852 \converter xls latex "ssconvert --export-type=Gnumeric_html:latex $$i $$o" ""''',
855 path, lilypond = checkProg('a LilyPond -> EPS/PDF/PNG converter', ['lilypond'])
857 version_string = cmdOutput("lilypond --version")
858 match = re.match('GNU LilyPond (\S+)', version_string)
860 version_number = match.groups()[0]
861 version = version_number.split('.')
862 if int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 11):
863 addToRC(r'''\converter lilypond eps "lilypond -dbackend=eps -dsafe --ps $$i" ""
864 \converter lilypond png "lilypond -dbackend=eps -dsafe --png $$i" ""''')
865 addToRC(r'\converter lilypond pdf "lilypond -dbackend=eps -dsafe --pdf $$i" ""')
866 logger.info('+ found LilyPond version %s.' % version_number)
867 elif int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 6):
868 addToRC(r'''\converter lilypond eps "lilypond -b eps --ps --safe $$i" ""
869 \converter lilypond png "lilypond -b eps --png $$i" ""''')
870 if int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 9):
871 addToRC(r'\converter lilypond pdf "lilypond -b eps --pdf --safe $$i" ""')
872 logger.info('+ found LilyPond version %s.' % version_number)
874 logger.info('+ found LilyPond, but version %s is too old.' % version_number)
876 logger.info('+ found LilyPond, but could not extract version number.')
878 path, lilypond_book = checkProg('a LilyPond book (LaTeX) -> LaTeX converter', ['lilypond-book'])
879 if (lilypond_book != ''):
880 version_string = cmdOutput("lilypond-book --version")
881 match = re.match('^(\S+)$', version_string)
883 version_number = match.groups()[0]
884 version = version_number.split('.')
885 if int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 13):
887 addToRC(r'\converter lyxpreview-lytex ppm "python -tt $$s/scripts/lyxpreview-lytex2bitmap.py" ""')
889 # set empty converter to override the default imagemagick
890 addToRC(r'\converter lyxpreview-lytex ppm "" ""')
891 if dvipng == "dvipng" and dv2dt == 'dv2dt':
892 addToRC(r'\converter lyxpreview-lytex png "python -tt $$s/scripts/lyxpreview-lytex2bitmap.py" ""')
894 # set empty converter to override the default imagemagick
895 addToRC(r'\converter lyxpreview-lytex png "" ""')
896 # Note: The --lily-output-dir flag is required because lilypond-book
897 # does not process input again unless the input has changed,
898 # even if the output format being requested is different. So
899 # once a .eps file exists, lilypond-book won't create a .pdf
900 # even when requested with --pdf. This is a problem if a user
901 # clicks View PDF after having done a View DVI. To circumvent
902 # this, use different output folders for eps and pdf outputs.
903 addToRC(r'\converter lilypond-book latex "lilypond-book --safe --lily-output-dir=ly-eps $$i" ""')
904 addToRC(r'\converter lilypond-book pdflatex "lilypond-book --safe --pdf --latex-program=pdflatex --lily-output-dir=ly-pdf $$i" ""')
905 addToRC(r'\converter lilypond-book xetex "lilypond-book --safe --pdf --latex-program=xelatex --lily-output-dir=ly-pdf $$i" ""')
906 addToRC(r'\converter lilypond-book luatex "lilypond-book --safe --pdf --latex-program=lualatex --lily-output-dir=ly-pdf $$i" ""')
907 logger.info('+ found LilyPond-book version %s.' % version_number)
909 logger.info('+ found LilyPond-book, but version %s is too old.' % version_number)
911 logger.info('+ found LilyPond-book, but could not extract version number.')
913 checkProg('a Noteedit -> LilyPond converter', ['noteedit --export-lilypond $$i'],
914 rc_entry = [ r'\converter noteedit lilypond "%%" ""', ''])
916 # Currently, lyxpak outputs a gzip compressed tar archive on *nix
917 # and a zip archive on Windows.
918 # So, we configure the appropriate version according to the platform.
919 cmd = r'\converter lyx %s "python -tt $$s/scripts/lyxpak.py $$r/$$i" ""'
921 addToRC(r'\Format lyxzip zip "LyX Archive (zip)" "" "" "" "document,menu=export"')
922 addToRC(cmd % "lyxzip")
924 addToRC(r'\Format lyxgz gz "LyX Archive (tar.gz)" "" "" "" "document,menu=export"')
925 addToRC(cmd % "lyxgz")
928 # FIXME: no rc_entry? comment it out
929 # checkProg('Image converter', ['convert $$i $$o'])
931 # Entries that do not need checkProg
932 addToRC(r'''\converter lyxpreview-platex ppm "python -tt $$s/scripts/lyxpreview-platex2bitmap.py" ""
933 \converter csv lyx "python -tt $$s/scripts/csv2lyx.py $$i $$o" ""
934 \converter date dateout "python -tt $$s/scripts/date.py %d-%m-%Y > $$o" ""
935 \converter docbook docbook-xml "cp $$i $$o" "xml"
936 \converter fen asciichess "python -tt $$s/scripts/fen2ascii.py $$i $$o" ""
937 \converter lyx lyx13x "python -tt $$s/lyx2lyx/lyx2lyx -t 221 $$i > $$o" ""
938 \converter lyx lyx14x "python -tt $$s/lyx2lyx/lyx2lyx -t 245 $$i > $$o" ""
939 \converter lyx lyx15x "python -tt $$s/lyx2lyx/lyx2lyx -t 276 $$i > $$o" ""
940 \converter lyx lyx16x "python -tt $$s/lyx2lyx/lyx2lyx -t 345 $$i > $$o" ""
941 \converter lyx clyx "python -tt $$s/lyx2lyx/lyx2lyx -c big5 -t 245 $$i > $$o" ""
942 \converter lyx jlyx "python -tt $$s/lyx2lyx/lyx2lyx -c euc_jp -t 245 $$i > $$o" ""
943 \converter lyx klyx "python -tt $$s/lyx2lyx/lyx2lyx -c euc_kr -t 245 $$i > $$o" ""
944 \converter clyx lyx "python -tt $$s/lyx2lyx/lyx2lyx -c big5 $$i > $$o" ""
945 \converter jlyx lyx "python -tt $$s/lyx2lyx/lyx2lyx -c euc_jp $$i > $$o" ""
946 \converter klyx lyx "python -tt $$s/lyx2lyx/lyx2lyx -c euc_kr $$i > $$o" ""
951 ''' Check docbook '''
952 path, DOCBOOK = checkProg('SGML-tools 2.x (DocBook), db2x scripts or xsltproc', ['sgmltools', 'db2dvi', 'xsltproc'],
954 r'''\converter docbook dvi "sgmltools -b dvi $$i" ""
955 \converter docbook html "sgmltools -b html $$i" ""''',
956 r'''\converter docbook dvi "db2dvi $$i" ""
957 \converter docbook html "db2html $$i" ""''',
958 r'''\converter docbook dvi "" ""
959 \converter docbook html "" ""''',
960 r'''\converter docbook dvi "" ""
961 \converter docbook html "" ""'''])
964 return ('yes', 'true', '\\def\\hasdocbook{yes}')
966 return ('no', 'false', '')
969 def checkOtherEntries():
970 ''' entries other than Format and Converter '''
971 checkProg('ChkTeX', ['chktex -n1 -n3 -n6 -n9 -n22 -n25 -n30 -n38'],
972 rc_entry = [ r'\chktex_command "%%"' ])
973 checkProgAlternatives('BibTeX or alternative programs', ['bibtex', 'bibtex8', 'biber'],
974 rc_entry = [ r'\bibtex_command "%%"' ],
975 alt_rc_entry = [ r'\bibtex_alternatives "%%"' ])
976 checkProg('a specific Japanese BibTeX variant', ['pbibtex', 'jbibtex', 'bibtex'],
977 rc_entry = [ r'\jbibtex_command "%%"' ])
978 checkProgAlternatives('available index processors', ['texindy', 'makeindex -c -q', 'xindy'],
979 rc_entry = [ r'\index_command "%%"' ],
980 alt_rc_entry = [ r'\index_alternatives "%%"' ])
981 checkProg('an index processor appropriate to Japanese', ['mendex -c -q', 'jmakeindex -c -q', 'makeindex -c -q'],
982 rc_entry = [ r'\jindex_command "%%"' ])
983 path, splitindex = checkProg('the splitindex processor', ['splitindex.pl', 'splitindex'],
984 rc_entry = [ r'\splitindex_command "%%"' ])
986 checkProg('the splitindex processor (java version)', ['splitindex.class'],
987 rc_entry = [ r'\splitindex_command "java splitindex"' ])
988 checkProg('a nomenclature processor', ['makeindex'],
989 rc_entry = [ r'\nomencl_command "makeindex -s nomencl.ist"' ])
990 ## FIXME: OCTAVE is not used anywhere
991 # path, OCTAVE = checkProg('Octave', ['octave'])
992 ## FIXME: MAPLE is not used anywhere
993 # path, MAPLE = checkProg('Maple', ['maple'])
994 checkProg('a spool command', ['lp', 'lpr'],
996 r'''\print_spool_printerprefix "-d "
997 \print_spool_command "lp"''',
998 r'''\print_spool_printerprefix "-P",
999 \print_spool_command "lpr"''',
1001 # Add the rest of the entries (no checkProg is required)
1002 addToRC(r'''\copier fig "python -tt $$s/scripts/fig_copy.py $$i $$o"
1003 \copier pstex "python -tt $$s/scripts/tex_copy.py $$i $$o $$l"
1004 \copier pdftex "python -tt $$s/scripts/tex_copy.py $$i $$o $$l"
1005 \copier program "python -tt $$s/scripts/ext_copy.py $$i $$o"
1009 def processLayoutFile(file, bool_docbook):
1010 ''' process layout file and get a line of result
1012 Declare lines look like this: (article.layout, scrbook.layout, svjog.layout)
1014 \DeclareLaTeXClass{article}
1015 \DeclareLaTeXClass[scrbook]{book (koma-script)}
1016 \DeclareLaTeXClass[svjour,svjog.clo]{article (Springer - svjour/jog)}
1020 "article" "article" "article" "false" "article.cls"
1021 "scrbook" "scrbook" "book (koma-script)" "false" "scrbook.cls"
1022 "svjog" "svjour" "article (Springer - svjour/jog)" "false" "svjour.cls,svjog.clo"
1024 def checkForClassExtension(x):
1025 '''if the extension for a latex class is not
1026 provided, add .cls to the classname'''
1028 return x.strip() + '.cls'
1031 classname = file.split(os.sep)[-1].split('.')[0]
1032 # return ('LaTeX', '[a,b]', 'a', ',b,c', 'article') for \DeclareLaTeXClass[a,b,c]{article}
1033 p = re.compile(r'\Declare(LaTeX|DocBook)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)}')
1034 for line in open(file).readlines():
1035 res = p.search(line)
1037 (classtype, optAll, opt, opt1, desc) = res.groups()
1038 avai = {'LaTeX':'false', 'DocBook':bool_docbook}[classtype]
1041 prereq_latex = checkForClassExtension(classname)
1043 prereq_list = optAll[1:-1].split(',')
1044 prereq_list = map(checkForClassExtension, prereq_list)
1045 prereq_latex = ','.join(prereq_list)
1046 prereq_docbook = {'true':'', 'false':'docbook'}[bool_docbook]
1047 prereq = {'LaTeX':prereq_latex, 'DocBook':prereq_docbook}[classtype]
1048 return '"%s" "%s" "%s" "%s" "%s"\n' % (classname, opt, desc, avai, prereq)
1049 logger.warning("Layout file " + file + " has no \DeclareXXClass line. ")
1053 def checkLatexConfig(check_config, bool_docbook):
1054 ''' Explore the LaTeX configuration
1055 Return None (will be passed to sys.exit()) for success.
1057 msg = 'checking LaTeX configuration... '
1058 # if --without-latex-config is forced, or if there is no previous
1059 # version of textclass.lst, re-generate a default file.
1060 if not os.path.isfile('textclass.lst') or not check_config:
1061 # remove the files only if we want to regenerate
1062 removeFiles(['textclass.lst', 'packages.lst'])
1064 # Then, generate a default textclass.lst. In case configure.py
1065 # fails, we still have something to start lyx.
1066 logger.info(msg + ' default values')
1067 logger.info('+checking list of textclasses... ')
1068 tx = open('textclass.lst', 'w')
1070 # This file declares layouts and their associated definition files
1071 # (include dir. relative to the place where this file is).
1072 # It contains only default values, since chkconfig.ltx could not be run
1073 # for some reason. Run ./configure.py if you need to update it after a
1074 # configuration change.
1076 # build the list of available layout files and convert it to commands
1079 for file in glob.glob( os.path.join('layouts', '*.layout') ) + \
1080 glob.glob( os.path.join(srcdir, 'layouts', '*.layout' ) ) :
1082 if not os.path.isfile(file):
1084 # get stuff between /xxxx.layout .
1085 classname = file.split(os.sep)[-1].split('.')[0]
1087 cleanclass = classname.replace(' ', '_')
1088 cleanclass = cleanclass.replace('-', '_')
1089 # make sure the same class is not considered twice
1090 if foundClasses.count(cleanclass) == 0: # not found before
1091 foundClasses.append(cleanclass)
1092 retval = processLayoutFile(file, bool_docbook)
1096 logger.info('\tdone')
1097 if not check_config:
1099 # the following will generate textclass.lst.tmp, and packages.lst.tmp
1100 logger.info(msg + '\tauto')
1101 removeFiles(['chkconfig.classes', 'chkconfig.vars', 'chklayouts.tex',
1102 'wrap_chkconfig.ltx'])
1104 if not os.path.isfile( 'chkconfig.ltx' ):
1105 shutil.copyfile( os.path.join(srcdir, 'chkconfig.ltx'), 'chkconfig.ltx' )
1107 writeToFile('wrap_chkconfig.ltx', '%s\n\\input{chkconfig.ltx}\n' % docbook_cmd)
1108 # Construct the list of classes to test for.
1109 # build the list of available layout files and convert it to commands
1111 declare = re.compile(r'\Declare(LaTeX|DocBook)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)}')
1112 empty = re.compile(r'^\s*$')
1113 testclasses = list()
1114 for file in glob.glob( os.path.join('layouts', '*.layout') ) + \
1115 glob.glob( os.path.join(srcdir, 'layouts', '*.layout' ) ) :
1116 nodeclaration = False
1117 if not os.path.isfile(file):
1119 classname = file.split(os.sep)[-1].split('.')[0]
1120 for line in open(file).readlines():
1121 if not empty.match(line) and line[0] != '#':
1122 logger.warning("Failed to find valid \Declare line for layout file `" + file + "'.\n\t=> Skipping this file!")
1123 nodeclaration = True
1125 if declare.search(line) == None:
1127 testclasses.append("\\TestDocClass{%s}{%s}" % (classname, line[1:].strip()))
1132 cl = open('chklayouts.tex', 'w')
1133 for line in testclasses:
1134 cl.write(line + '\n')
1137 # we have chklayouts.tex, then process it
1138 fout = os.popen(LATEX + ' wrap_chkconfig.ltx')
1140 line = fout.readline()
1143 if re.match('^\+', line):
1144 logger.info(line.strip())
1145 # if the command succeeds, None will be returned
1148 # currently, values in chhkconfig are only used to set
1151 for line in open('chkconfig.vars').readlines():
1152 key, val = re.sub('-', '_', line).split('=')
1154 values[key] = val.strip("'")
1155 # chk_fontenc may not exist
1157 addToRC(r'\font_encoding "%s"' % values["chk_fontenc"])
1160 if rmcopy: # remove the copied file
1161 removeFiles( [ 'chkconfig.ltx' ] )
1162 # if configure successed, move textclass.lst.tmp to textclass.lst
1163 # and packages.lst.tmp to packages.lst
1164 if os.path.isfile('textclass.lst.tmp') and len(open('textclass.lst.tmp').read()) > 0 \
1165 and os.path.isfile('packages.lst.tmp') and len(open('packages.lst.tmp').read()) > 0:
1166 shutil.move('textclass.lst.tmp', 'textclass.lst')
1167 shutil.move('packages.lst.tmp', 'packages.lst')
1171 def checkModulesConfig():
1172 removeFiles(['lyxmodules.lst', 'chkmodules.tex'])
1174 logger.info('+checking list of modules... ')
1175 tx = open('lyxmodules.lst', 'w')
1176 tx.write('''## This file declares modules and their associated definition files.
1177 ## It has been automatically generated by configure
1178 ## Use "Options/Reconfigure" if you need to update it after a
1179 ## configuration change.
1180 ## "ModuleName" "filename" "Description" "Packages" "Requires" "Excludes" "Category"
1183 # build the list of available modules
1185 # note that this searches the local directory first, then the
1186 # system directory. that way, we pick up the user's version first.
1187 for file in glob.glob( os.path.join('layouts', '*.module') ) + \
1188 glob.glob( os.path.join(srcdir, 'layouts', '*.module' ) ) :
1191 if not os.path.isfile(file):
1194 filename = file.split(os.sep)[-1]
1195 filename = filename[:-7]
1196 if seen.count(filename):
1199 seen.append(filename)
1200 retval = processModuleFile(file, filename, bool_docbook)
1204 logger.info('\tdone')
1207 def processModuleFile(file, filename, bool_docbook):
1208 ''' process module file and get a line of result
1210 The top of a module file should look like this:
1211 #\DeclareLyXModule[LaTeX Packages]{ModuleName}
1213 #...body of description...
1215 #Requires: [list of required modules]
1216 #Excludes: [list of excluded modules]
1217 #Category: [category name]
1218 The last three lines are optional (though do give a category).
1220 "ModuleName" "filename" "Description" "Packages" "Requires" "Excludes" "Category"
1222 remods = re.compile(r'\DeclareLyXModule\s*(?:\[([^]]*?)\])?{(.*)}')
1223 rereqs = re.compile(r'#+\s*Requires: (.*)')
1224 reexcs = re.compile(r'#+\s*Excludes: (.*)')
1225 recaty = re.compile(r'#+\s*Category: (.*)')
1226 redbeg = re.compile(r'#+\s*DescriptionBegin\s*$')
1227 redend = re.compile(r'#+\s*DescriptionEnd\s*$')
1229 modname = desc = pkgs = req = excl = catgy = ""
1230 readingDescription = False
1233 for line in open(file).readlines():
1234 if readingDescription:
1235 res = redend.search(line)
1237 readingDescription = False
1238 desc = " ".join(descLines)
1240 desc = desc.replace('"', '\\"')
1242 descLines.append(line[1:].strip())
1244 res = redbeg.search(line)
1246 readingDescription = True
1248 res = remods.search(line)
1250 (pkgs, modname) = res.groups()
1254 tmp = [s.strip() for s in pkgs.split(",")]
1255 pkgs = ",".join(tmp)
1257 res = rereqs.search(line)
1260 tmp = [s.strip() for s in req.split("|")]
1263 res = reexcs.search(line)
1266 tmp = [s.strip() for s in excl.split("|")]
1267 excl = "|".join(tmp)
1269 res = recaty.search(line)
1271 catgy = res.group(1)
1275 logger.warning("Module file without \DeclareLyXModule line. ")
1279 # this module has some latex dependencies:
1280 # append the dependencies to chkmodules.tex,
1281 # which is \input'ed by chkconfig.ltx
1282 testpackages = list()
1283 for pkg in pkgs.split(","):
1285 # this is a converter dependency: skip
1287 if pkg.endswith(".sty"):
1289 testpackages.append("\\TestPackage{%s}" % (pkg,))
1290 cm = open('chkmodules.tex', 'a')
1291 for line in testpackages:
1292 cm.write(line + '\n')
1295 return '"%s" "%s" "%s" "%s" "%s" "%s" "%s"\n' % (modname, filename, desc, pkgs, req, excl, catgy)
1298 def checkTeXAllowSpaces():
1299 ''' Let's check whether spaces are allowed in TeX file names '''
1300 tex_allows_spaces = 'false'
1301 if lyx_check_config:
1302 msg = "Checking whether TeX allows spaces in file names... "
1303 writeToFile('a b.tex', r'\message{working^^J}' )
1305 if os.name == 'nt' or sys.platform == 'cygwin':
1306 latex_out = cmdOutput(LATEX + r""" "\nonstopmode\input{\"a b\"}" """)
1308 latex_out = cmdOutput(LATEX + r""" '\nonstopmode\input{"a b"}' """)
1311 if 'working' in latex_out:
1312 logger.info(msg + 'yes')
1313 tex_allows_spaces = 'true'
1315 logger.info(msg + 'no')
1316 tex_allows_spaces = 'false'
1317 addToRC(r'\tex_allows_spaces ' + tex_allows_spaces)
1318 removeFiles( [ 'a b.tex', 'a b.log', 'texput.log' ])
1321 def removeTempFiles():
1323 if not lyx_keep_temps:
1324 removeFiles(['chkconfig.vars', 'chklatex.ltx', 'chklatex.log',
1325 'chklayouts.tex', 'chkmodules.tex', 'missfont.log',
1326 'wrap_chkconfig.ltx', 'wrap_chkconfig.log'])
1329 if __name__ == '__main__':
1330 lyx_check_config = True
1331 outfile = 'lyxrc.defaults'
1332 lyxrc_fileformat = 1
1334 lyx_keep_temps = False
1336 ## Parse the command line
1337 for op in sys.argv[1:]: # default shell/for list is $*, the options
1338 if op in [ '-help', '--help', '-h' ]:
1339 print '''Usage: configure [options]
1341 --help show this help lines
1342 --keep-temps keep temporary files (for debug. purposes)
1343 --without-latex-config do not run LaTeX to determine configuration
1344 --with-version-suffix=suffix suffix of binary installed files
1347 elif op == '--without-latex-config':
1348 lyx_check_config = False
1349 elif op == '--keep-temps':
1350 lyx_keep_temps = True
1351 elif op[0:22] == '--with-version-suffix=': # never mind if op is not long enough
1352 version_suffix = op[22:]
1354 print "Unknown option", op
1357 # check if we run from the right directory
1358 srcdir = os.path.dirname(sys.argv[0])
1361 if not os.path.isfile( os.path.join(srcdir, 'chkconfig.ltx') ):
1362 logger.error("configure: error: cannot find chkconfig.ltx script")
1366 dtl_tools = checkDTLtools()
1367 ## Write the first part of outfile
1368 writeToFile(outfile, '''# This file has been automatically generated by LyX' lib/configure.py
1369 # script. It contains default settings that have been determined by
1370 # examining your system. PLEASE DO NOT MODIFY ANYTHING HERE! If you
1371 # want to customize LyX, use LyX' Preferences dialog or modify directly
1372 # the "preferences" file instead. Any setting in that file will
1373 # override the values given here.
1377 ''' % lyxrc_fileformat)
1379 LATEX = checkLatex(dtl_tools)
1380 checkFormatEntries(dtl_tools)
1381 checkConverterEntries()
1382 (chk_docbook, bool_docbook, docbook_cmd) = checkDocBook()
1383 checkTeXAllowSpaces()
1384 windows_style_tex_paths = checkTeXPaths()
1385 if windows_style_tex_paths != '':
1386 addToRC(r'\tex_expects_windows_paths %s' % windows_style_tex_paths)
1388 checkModulesConfig()
1389 # --without-latex-config can disable lyx_check_config
1390 ret = checkLatexConfig(lyx_check_config and LATEX != '', bool_docbook)
1392 # The return error code can be 256. Because most systems expect an error code
1393 # in the range 0-127, 256 can be interpretted as 'success'. Because we expect
1394 # a None for success, 'ret is not None' is used to exit.
1395 sys.exit(ret is not None)