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 addAlternatives(rcs, alt_type):
265 Returns a \\prog_alternatives string to be used as an alternative
268 r = re.compile(r'\\Format (\S+).*$')
271 alt_token = '\\%s_alternatives ' % alt_type
272 for idxx in range(len(rcs)):
276 alt = alt_token + m.group(1) + " %%"
278 m = r.match(rcs[idxx])
282 alt += alt_token + m.group(1) + " %%"
286 def listAlternatives(progs, alt_type, rc_entry = []):
288 Returns a list of \\prog_alternatives strings to be used as alternative
291 if len(rc_entry) > 1 and len(rc_entry) != len(progs) + 1:
292 logger.error("rc entry should have one item or item for each prog and not_found.")
295 for idx in range(len(progs)):
296 if len(rc_entry) == 1:
297 rcs = rc_entry[0].split('\n')
298 alt = addAlternatives(rcs, alt_type)
299 alt_rc_entry.insert(0, alt)
300 elif len(rc_entry) > 1:
301 rcs = rc_entry[idx].split('\n')
302 alt = addAlternatives(rcs, alt_type)
303 alt_rc_entry.insert(idx, alt)
307 def checkViewer(description, progs, rc_entry = [], path = []):
308 ''' The same as checkProgAlternatives, but for viewers '''
309 alt_rc_entry = listAlternatives(progs, 'viewer', rc_entry)
310 return checkProgAlternatives(description, progs, rc_entry, alt_rc_entry, path, not_found = 'auto')
313 def checkEditor(description, progs, rc_entry = [], path = []):
314 ''' The same as checkProgAlternatives, but for editors '''
315 alt_rc_entry = listAlternatives(progs, 'editor', rc_entry)
316 return checkProgAlternatives(description, progs, rc_entry, alt_rc_entry, path, not_found = 'auto')
319 def checkViewerNoRC(description, progs, rc_entry = [], path = []):
320 ''' The same as checkViewer, but do not add rc entry '''
321 alt_rc_entry = listAlternatives(progs, 'viewer', rc_entry)
323 return checkProgAlternatives(description, progs, rc_entry, alt_rc_entry, path, not_found = 'auto')
326 def checkEditorNoRC(description, progs, rc_entry = [], path = []):
327 ''' The same as checkViewer, but do not add rc entry '''
328 alt_rc_entry = listAlternatives(progs, 'editor', rc_entry)
330 return checkProgAlternatives(description, progs, rc_entry, alt_rc_entry, path, not_found = 'auto')
333 def checkViewerEditor(description, progs, rc_entry = [], path = []):
334 ''' The same as checkProgAlternatives, but for viewers and editors '''
335 checkEditorNoRC(description, progs, rc_entry, path)
336 return checkViewer(description, progs, rc_entry, path)
340 ''' Check whether DTL tools are available (Windows only) '''
341 # Find programs! Returned path is not used now
342 if ((os.name == 'nt' or sys.platform == 'cygwin') and
343 checkProg('DVI to DTL converter', ['dv2dt']) != ['', ''] and
344 checkProg('DTL to DVI converter', ['dt2dv']) != ['', '']):
351 def checkLatex(dtl_tools):
352 ''' Check latex, return lyx_check_config '''
353 path, LATEX = checkProg('a Latex2e program', ['latex $$i', 'latex2e $$i'])
354 path, PPLATEX = checkProg('a DVI postprocessing program', ['pplatex $$i'])
355 #-----------------------------------------------------------------
356 path, PLATEX = checkProg('pLaTeX, the Japanese LaTeX', ['platex $$i'])
358 # check if PLATEX is pLaTeX2e
359 writeToFile('chklatex.ltx', '''
363 # run platex on chklatex.ltx and check result
364 if cmdOutput(PLATEX + ' chklatex.ltx').find('pLaTeX2e') != -1:
365 # We have the Japanese pLaTeX2e
366 addToRC(r'\converter platex dvi "%s" "latex=platex"' % PLATEX)
369 removeFiles(['chklatex.ltx', 'chklatex.log'])
370 #-----------------------------------------------------------------
371 # use LATEX to convert from latex to dvi if PPLATEX is not available
375 # Windows only: DraftDVI
376 addToRC(r'''\converter latex dvi2 "%s" "latex"
377 \converter dvi2 dvi "python -tt $$s/scripts/clean_dvi.py $$i $$o" ""''' % PPLATEX)
379 addToRC(r'\converter latex dvi "%s" "latex"' % PPLATEX)
382 # Check if latex is usable
383 writeToFile('chklatex.ltx', '''
384 \\nonstopmode\\makeatletter
385 \\ifx\\undefined\\documentclass\\else
386 \\message{ThisIsLaTeX2e}
390 # run latex on chklatex.ltx and check result
391 if cmdOutput(LATEX + ' chklatex.ltx').find('ThisIsLaTeX2e') != -1:
395 logger.warning("Latex not usable (not LaTeX2e) ")
396 # remove temporary files
397 removeFiles(['chklatex.ltx', 'chklatex.log'])
402 ''' Check if luatex is there and usable '''
403 path, LUATEX = checkProg('LuaTeX', ['lualatex $$i'])
404 path, DVILUATEX = checkProg('LuaTeX (DVI)', ['dvilualatex $$i'])
406 # luatex binary is there
407 msg = "checking if LuaTeX is usable ..."
408 # Check if luatex is usable
409 writeToFile('luatest.tex', '''
410 \\nonstopmode\\documentclass{minimal}
411 \\usepackage{fontspec}
416 # run lualatex on luatest.tex and check result
417 luatest = cmdOutput(LUATEX + ' luatest.tex')
418 if luatest.find('XeTeX is required to compile this document') != -1:
419 # fontspec/luatex too old! We do not support this version.
420 logger.info(msg + ' no (probably not recent enough)')
421 elif luatest.find('! LaTeX Error: File `fontspec.sty\' not found') != -1:
423 logger.info(msg + ' no (missing fontspec)')
426 logger.info(msg + ' yes')
427 addToRC(r'\converter luatex pdf5 "%s" "latex=lualatex"' % LUATEX)
429 addToRC(r'\converter luatex dvi3 "%s" "latex=lualatex"' % DVILUATEX)
430 # remove temporary files
431 removeFiles(['luatest.tex', 'luatest.log', 'luatest.aux', 'luatest.pdf'])
434 def checkModule(module):
435 ''' Check for a Python module, return the status '''
436 msg = 'checking for "' + module + ' module"... '
439 logger.info(msg + ' yes')
442 logger.info(msg + ' no')
446 def checkFormatEntries(dtl_tools):
447 ''' Check all formats (\Format entries) '''
448 checkViewerEditor('a Tgif viewer and editor', ['tgif'],
449 rc_entry = [r'\Format tgif obj Tgif "" "%%" "%%" "vector"'])
451 checkViewerEditor('a FIG viewer and editor', ['xfig', 'jfig3-itext.jar', 'jfig3.jar'],
452 rc_entry = [r'\Format fig fig FIG "" "%%" "%%" "vector"'])
454 checkViewerEditor('a Dia viewer and editor', ['dia'],
455 rc_entry = [r'\Format dia dia DIA "" "%%" "%%" "vector"'])
457 checkViewerEditor('a Grace viewer and editor', ['xmgrace'],
458 rc_entry = [r'\Format agr agr Grace "" "%%" "%%" "vector"'])
460 checkViewerEditor('a FEN viewer and editor', ['xboard -lpf $$i -mode EditPosition'],
461 rc_entry = [r'\Format fen fen FEN "" "%%" "%%" ""'])
463 checkViewerEditor('a SVG viewer and editor', ['inkscape'],
464 rc_entry = [r'\Format svg svg SVG "" "%%" "%%" "vector"'])
466 path, iv = checkViewerNoRC('a raster image viewer', ['xv', 'kview', 'gimp-remote', 'gimp'],
467 rc_entry = [r'''\Format bmp bmp BMP "" "%s" "%s" ""
468 \Format gif gif GIF "" "%s" "%s" ""
469 \Format jpg jpg JPEG "" "%s" "%s" ""
470 \Format pbm pbm PBM "" "%s" "%s" ""
471 \Format pgm pgm PGM "" "%s" "%s" ""
472 \Format png png PNG "" "%s" "%s" ""
473 \Format ppm ppm PPM "" "%s" "%s" ""
474 \Format tiff tif TIFF "" "%s" "%s" ""
475 \Format xbm xbm XBM "" "%s" "%s" ""
476 \Format xpm xpm XPM "" "%s" "%s" ""'''])
477 path, ie = checkEditorNoRC('a raster image editor', ['gimp-remote', 'gimp'],
478 rc_entry = [r'''\Format bmp bmp BMP "" "%s" "%s" ""
479 \Format gif gif GIF "" "%s" "%s" ""
480 \Format jpg jpg JPEG "" "%s" "%s" ""
481 \Format pbm pbm PBM "" "%s" "%s" ""
482 \Format pgm pgm PGM "" "%s" "%s" ""
483 \Format png png PNG "" "%s" "%s" ""
484 \Format ppm ppm PPM "" "%s" "%s" ""
485 \Format tiff tif TIFF "" "%s" "%s" ""
486 \Format xbm xbm XBM "" "%s" "%s" ""
487 \Format xpm xpm XPM "" "%s" "%s" ""'''])
488 addToRC(r'''\Format bmp bmp BMP "" "%s" "%s" ""
489 \Format gif gif GIF "" "%s" "%s" ""
490 \Format jpg jpg JPEG "" "%s" "%s" ""
491 \Format pbm pbm PBM "" "%s" "%s" ""
492 \Format pgm pgm PGM "" "%s" "%s" ""
493 \Format png png PNG "" "%s" "%s" ""
494 \Format ppm ppm PPM "" "%s" "%s" ""
495 \Format tiff tif TIFF "" "%s" "%s" ""
496 \Format xbm xbm XBM "" "%s" "%s" ""
497 \Format xpm xpm XPM "" "%s" "%s" ""''' % \
498 (iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie) )
500 checkViewerEditor('a text editor', ['xemacs', 'gvim', 'kedit', 'kwrite', 'kate', \
501 'nedit', 'gedit', 'notepad'],
502 rc_entry = [r'''\Format asciichess asc "Plain text (chess output)" "" "" "%%" ""
503 \Format asciiimage asc "Plain text (image)" "" "" "%%" ""
504 \Format asciixfig asc "Plain text (Xfig output)" "" "" "%%" ""
505 \Format dateout tmp "date (output)" "" "" "%%" ""
506 \Format docbook sgml DocBook B "" "%%" "document,menu=export"
507 \Format docbook-xml xml "Docbook (XML)" "" "" "%%" "document,menu=export"
508 \Format dot dot "Graphviz Dot" "" "" "%%" "vector"
509 \Format platex tex "LaTeX (pLaTeX)" "" "" "%%" "document,menu=export"
510 \Format literate nw NoWeb N "" "%%" "document,menu=export"
511 \Format sweave Rnw "Sweave" S "" "%%" "document,menu=export"
512 \Format lilypond ly "LilyPond music" "" "" "%%" "vector"
513 \Format lilypond-book lytex "LilyPond book (LaTeX)" "" "" "%%" "document,menu=export"
514 \Format latex tex "LaTeX (plain)" L "" "%%" "document,menu=export"
515 \Format luatex tex "LaTeX (LuaTeX)" "" "" "%%" "document,menu=export"
516 \Format pdflatex tex "LaTeX (pdflatex)" "" "" "%%" "document,menu=export"
517 \Format xetex tex "LaTeX (XeTeX)" "" "" "%%" "document,menu=export"
518 \Format text txt "Plain text" a "" "%%" "document,menu=export"
519 \Format text2 txt "Plain text (pstotext)" "" "" "%%" "document"
520 \Format text3 txt "Plain text (ps2ascii)" "" "" "%%" "document"
521 \Format text4 txt "Plain text (catdvi)" "" "" "%%" "document"
522 \Format textparagraph txt "Plain Text, Join Lines" "" "" "%%" "document"''' ])
523 #Spreadsheets using ssconvert from gnumeric
524 checkViewer('gnumeric spreadsheet software', ['gnumeric'],
525 rc_entry = [r'''\Format gnumeric gnumeric "Gnumeric spreadsheet" "" "" "%%" "document"
526 \Format excel xls "Excel spreadsheet" "" "" "%%" "document"
527 \Format oocalc ods "OpenOffice spreadsheet" "" "" "%%" "document"'''])
529 path, xhtmlview = checkViewer('an HTML previewer', ['firefox', 'mozilla file://$$p$$i', 'netscape'],
530 rc_entry = [r'\Format xhtml xhtml "LyXHTML" y "%%" "" "document,menu=export"'])
532 addToRC(r'\Format xhtml xhtml "LyXHTML" y "" "" "document,menu=export"')
534 checkEditor('a BibTeX editor', ['jabref', 'JabRef', \
535 'pybliographic', 'bibdesk', 'gbib', 'kbib', \
536 'kbibtex', 'sixpack', 'bibedit', 'tkbibtex' \
537 'xemacs', 'gvim', 'kedit', 'kwrite', 'kate', \
538 'nedit', 'gedit', 'notepad'],
539 rc_entry = [r'''\Format bibtex bib "BibTeX" "" "" "%%" ""''' ])
541 #checkProg('a Postscript interpreter', ['gs'],
542 # rc_entry = [ r'\ps_command "%%"' ])
543 checkViewer('a Postscript previewer', ['kghostview', 'okular', 'evince', 'gv', 'ghostview -swap'],
544 rc_entry = [r'''\Format eps eps EPS "" "%%" "" "vector"
545 \Format ps ps Postscript t "%%" "" "document,vector"'''])
546 # for xdg-open issues look here: http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg151818.html
547 checkViewer('a PDF previewer', ['kpdf', 'okular', 'evince', 'kghostview', 'xpdf', 'acrobat', 'acroread', \
549 rc_entry = [r'''\Format pdf pdf "PDF (ps2pdf)" P "%%" "" "document,vector,menu=export"
550 \Format pdf2 pdf "PDF (pdflatex)" F "%%" "" "document,vector,menu=export"
551 \Format pdf3 pdf "PDF (dvipdfm)" m "%%" "" "document,vector,menu=export"
552 \Format pdf4 pdf "PDF (XeTeX)" X "%%" "" "document,vector,menu=export"
553 \Format pdf5 pdf "PDF (LuaTeX)" u "%%" "" "document,vector,menu=export"'''])
555 checkViewer('a DVI previewer', ['xdvi', 'kdvi', 'okular', 'yap', 'dviout -Set=!m'],
556 rc_entry = [r'''\Format dvi dvi DVI D "%%" "" "document,vector,menu=export"
557 \Format dvi3 dvi "DVI (LuaTeX)" V "%%" "" "document,vector,menu=export"'''])
559 # Windows only: DraftDVI
560 addToRC(r'\Format dvi2 dvi DraftDVI "" "" "" "vector"')
562 checkViewer('an HTML previewer', ['firefox', 'mozilla file://$$p$$i', 'netscape'],
563 rc_entry = [r'\Format html html HTML H "%%" "" "document,menu=export"'])
565 checkViewerEditor('Noteedit', ['noteedit'],
566 rc_entry = [r'\Format noteedit not Noteedit "" "%%" "%%" "vector"'])
568 checkViewerEditor('an OpenDocument/OpenOffice viewer', ['swriter', 'oowriter', 'abiword'],
569 rc_entry = [r'''\Format odt odt OpenDocument "" "%%" "%%" "document,vector,menu=export"
570 \Format sxw sxw "OpenOffice.Org (sxw)" "" "" "" "document,vector"'''])
572 checkViewerEditor('a Rich Text and Word viewer', ['swriter', 'oowriter', 'abiword'],
573 rc_entry = [r'''\Format rtf rtf "Rich Text Format" "" "%%" "%%" "document,vector,menu=export"
574 \Format word doc "MS Word" W "%%" "%%" "document,vector,menu=export"'''])
576 # entries that do not need checkProg
577 addToRC(r'''\Format date "" "date command" "" "" "" ""
578 \Format csv csv "Table (CSV)" "" "" "" "document"
579 \Format fax "" Fax "" "" "" "document"
580 \Format lyx lyx LyX "" "" "" ""
581 \Format lyx13x 13.lyx "LyX 1.3.x" "" "" "" "document"
582 \Format lyx14x 14.lyx "LyX 1.4.x" "" "" "" "document"
583 \Format lyx15x 15.lyx "LyX 1.5.x" "" "" "" "document"
584 \Format lyx16x 16.lyx "LyX 1.6.x" "" "" "" "document,menu=export"
585 \Format clyx cjklyx "CJK LyX 1.4.x (big5)" "" "" "" "document"
586 \Format jlyx cjklyx "CJK LyX 1.4.x (euc-jp)" "" "" "" "document"
587 \Format klyx cjklyx "CJK LyX 1.4.x (euc-kr)" "" "" "" "document"
588 \Format lyxpreview lyxpreview "LyX Preview" "" "" "" ""
589 \Format lyxpreview-lytex lyxpreview-lytex "LyX Preview (LilyPond book)" "" "" "" ""
590 \Format lyxpreview-platex lyxpreview-platex "LyX Preview (pLaTeX)" "" "" "" ""
591 \Format pdftex pdftex_t PDFTEX "" "" "" ""
592 \Format program "" Program "" "" "" ""
593 \Format pstex pstex_t PSTEX "" "" "" ""
594 \Format wmf wmf "Windows Metafile" "" "" "" "vector"
595 \Format emf emf "Enhanced Metafile" "" "" "" "vector"
596 \Format wordhtml html "HTML (MS Word)" "" "" "" "document"
600 def checkConverterEntries():
601 ''' Check all converters (\converter entries) '''
602 checkProg('the pdflatex program', ['pdflatex $$i'],
603 rc_entry = [ r'\converter pdflatex pdf2 "%%" "latex=pdflatex"' ])
605 checkProg('XeTeX', ['xelatex $$i'],
606 rc_entry = [ r'\converter xetex pdf4 "%%" "latex=xelatex"' ])
610 ''' If we're running LyX in-place then tex2lyx will be found in
611 ../src/tex2lyx. Add this directory to the PATH temporarily and
613 Use PATH to avoid any problems with paths-with-spaces.
615 path_orig = os.environ["PATH"]
616 os.environ["PATH"] = os.path.join('..', 'src', 'tex2lyx') + \
617 os.pathsep + path_orig
619 # First search for tex2lyx with version suffix (bug 6986)
620 checkProg('a LaTeX/Noweb -> LyX converter', ['tex2lyx' + version_suffix, 'tex2lyx'],
621 rc_entry = [r'''\converter latex lyx "%% -f $$i $$o" ""
622 \converter literate lyx "%% -n -f $$i $$o" ""'''])
624 os.environ["PATH"] = path_orig
627 checkProg('a Noweb -> LaTeX converter', ['noweave -delay -index $$i > $$o'],
628 rc_entry = [r'''\converter literate latex "%%" ""
629 \converter literate pdflatex "%%" ""'''])
631 checkProg('a Sweave -> LaTeX converter', ['Rscript --verbose --no-save --no-restore $$s/scripts/lyxsweave.R $$p$$i $$p$$o $$e $$r'],
632 rc_entry = [r'''\converter sweave latex "%%" ""
633 \converter sweave pdflatex "%%" ""
634 \converter sweave xetex "%%" ""
635 \converter sweave luatex "%%" ""'''])
637 checkProg('an HTML -> LaTeX converter', ['html2latex $$i', 'gnuhtml2latex $$i', \
638 'htmltolatex -input $$i -output $$o', 'java -jar htmltolatex.jar -input $$i -output $$o'],
639 rc_entry = [ r'\converter html latex "%%" ""' ])
641 checkProg('an MS Word -> LaTeX converter', ['wvCleanLatex $$i $$o'],
642 rc_entry = [ r'\converter word latex "%%" ""' ])
644 # eLyXer: search as an executable (elyxer.py, elyxer)
645 path, elyxer = checkProg('a LyX -> HTML converter',
646 ['elyxer.py --directory $$r $$i $$o', 'elyxer --directory $$r $$i $$o'],
647 rc_entry = [ r'\converter lyx html "%%" ""' ])
648 path, elyxer = checkProg('a LyX -> HTML (MS Word) converter',
649 ['elyxer.py --html --directory $$r $$i $$o', 'elyxer --html --directory $$r $$i $$o'],
650 rc_entry = [ r'\converter lyx wordhtml "%%" ""' ])
651 if elyxer.find('elyxer') >= 0:
652 addToRC(r'''\copier html "python -tt $$s/scripts/ext_copy.py -e html,png,jpg,jpeg,css $$i $$o"''')
653 addToRC(r'''\copier wordhtml "python -tt $$s/scripts/ext_copy.py -e html,png,jpg,jpeg,css $$i $$o"''')
655 # search for HTML converters other than eLyXer
656 # On SuSE the scripts have a .sh suffix, and on debian they are in /usr/share/tex4ht/
657 path, htmlconv = checkProg('a LaTeX -> HTML converter', ['htlatex $$i', 'htlatex.sh $$i', \
658 '/usr/share/tex4ht/htlatex $$i', 'tth -t -e2 -L$$b < $$i > $$o', \
659 'latex2html -no_subdir -split 0 -show_section_numbers $$i', 'hevea -s $$i'],
660 rc_entry = [ r'\converter latex html "%%" "needaux"' ])
661 if htmlconv.find('htlatex') >= 0 or htmlconv == 'latex2html':
662 addToRC(r'''\copier html "python -tt $$s/scripts/ext_copy.py -e html,png,css $$i $$o"''')
664 addToRC(r'''\copier html "python -tt $$s/scripts/ext_copy.py $$i $$o"''')
665 path, htmlconv = checkProg('a LaTeX -> HTML (MS Word) converter', ["htlatex $$i 'html,word' 'symbol/!' '-cvalidate'", \
666 "htlatex.sh $$i 'html,word' 'symbol/!' '-cvalidate'", \
667 "/usr/share/tex4ht/htlatex $$i 'html,word' 'symbol/!' '-cvalidate'"],
668 rc_entry = [ r'\converter latex wordhtml "%%" "needaux"' ])
669 if htmlconv.find('htlatex') >= 0:
670 addToRC(r'''\copier wordhtml "python -tt $$s/scripts/ext_copy.py -e html,png,css $$i $$o"''')
672 addToRC(r'''\copier wordhtml "python -tt $$s/scripts/ext_copy.py $$i $$o"''')
675 # Check if LyXBlogger is installed
676 lyxblogger_found = checkModule('lyxblogger')
678 addToRC(r'\Format blog blog "LyXBlogger" "" "" "" "document"')
679 addToRC(r'\converter xhtml blog "python -m lyxblogger $$i" ""')
682 checkProg('an OpenOffice.org -> LaTeX converter', ['w2l -clean $$i'],
683 rc_entry = [ r'\converter sxw latex "%%" ""' ])
685 checkProg('an OpenDocument -> LaTeX converter', ['w2l -clean $$i'],
686 rc_entry = [ r'\converter odt latex "%%" ""' ])
687 # According to http://www.tug.org/applications/tex4ht/mn-commands.html
688 # the command mk4ht oolatex $$i has to be used as default,
689 # but as this would require to have Perl installed, in MiKTeX oolatex is
690 # directly available as application.
691 # On SuSE the scripts have a .sh suffix, and on debian they are in /usr/share/tex4ht/
692 # Both SuSE and debian have oolatex
693 checkProg('a LaTeX -> Open Document converter', [
694 'oolatex $$i', 'mk4ht oolatex $$i', 'oolatex.sh $$i', '/usr/share/tex4ht/oolatex $$i',
695 'htlatex $$i \'xhtml,ooffice\' \'ooffice/! -cmozhtf\' \'-coo\' \'-cvalidate\''],
696 rc_entry = [ r'\converter latex odt "%%" "needaux"' ])
697 # On windows it is called latex2rt.exe
698 checkProg('a LaTeX -> RTF converter', ['latex2rtf -p -S -o $$o $$i', 'latex2rt -p -S -o $$o $$i'],
699 rc_entry = [ r'\converter latex rtf "%%" "needaux"' ])
701 checkProg('a RTF -> HTML converter', ['unrtf --html $$i > $$o'],
702 rc_entry = [ r'\converter rtf html "%%" ""' ])
704 checkProg('a PS to PDF converter', ['ps2pdf13 $$i $$o'],
705 rc_entry = [ r'\converter ps pdf "%%" ""' ])
707 checkProg('a PS to TXT converter', ['pstotext $$i > $$o'],
708 rc_entry = [ r'\converter ps text2 "%%" ""' ])
710 checkProg('a PS to TXT converter', ['ps2ascii $$i $$o'],
711 rc_entry = [ r'\converter ps text3 "%%" ""' ])
713 checkProg('a PS to EPS converter', ['ps2eps $$i'],
714 rc_entry = [ r'\converter ps eps "%%" ""' ])
716 checkProg('a PDF to PS converter', ['pdf2ps $$i $$o', 'pdftops $$i $$o'],
717 rc_entry = [ r'\converter pdf ps "%%" ""' ])
719 checkProg('a PDF to EPS converter', ['pdftops -eps -f 1 -l 1 $$i $$o'],
720 rc_entry = [ r'\converter pdf eps "%%" ""' ])
722 checkProg('a DVI to TXT converter', ['catdvi $$i > $$o'],
723 rc_entry = [ r'\converter dvi text4 "%%" ""' ])
725 checkProg('a DVI to PS converter', ['dvips -o $$o $$i'],
726 rc_entry = [ r'\converter dvi ps "%%" ""' ])
728 checkProg('a DVI to PDF converter', ['dvipdfmx -o $$o $$i', 'dvipdfm -o $$o $$i'],
729 rc_entry = [ r'\converter dvi pdf3 "%%" ""' ])
731 path, dvipng = checkProg('dvipng', ['dvipng'])
732 path, dv2dt = checkProg('DVI to DTL converter', ['dv2dt'])
733 if dvipng == "dvipng" and dv2dt == 'dv2dt':
734 addToRC(r'\converter lyxpreview png "python -tt $$s/scripts/lyxpreview2bitmap.py" ""')
736 # set empty converter to override the default imagemagick
737 addToRC(r'\converter lyxpreview png "" ""')
739 addToRC(r'\converter lyxpreview ppm "python -tt $$s/scripts/lyxpreview2bitmap.py" ""')
741 # set empty converter to override the default imagemagick
742 addToRC(r'\converter lyxpreview ppm "" ""')
744 checkProg('a fax program', ['kdeprintfax $$i', 'ksendfax $$i', 'hylapex $$i'],
745 rc_entry = [ r'\converter ps fax "%%" ""'])
747 path, fig2dev = checkProg('a FIG -> Image converter', ['fig2dev'])
748 if fig2dev == "fig2dev":
749 addToRC(r'''\converter fig eps "fig2dev -L eps $$i $$o" ""
750 \converter fig ppm "fig2dev -L ppm $$i $$o" ""
751 \converter fig png "fig2dev -L png $$i $$o" ""
752 \converter fig pdftex "python -tt $$s/scripts/fig2pdftex.py $$i $$o" ""
753 \converter fig pstex "python -tt $$s/scripts/fig2pstex.py $$i $$o" ""''')
755 checkProg('a TIFF -> PS converter', ['tiff2ps $$i > $$o'],
756 rc_entry = [ r'\converter tiff eps "%%" ""', ''])
758 checkProg('a TGIF -> EPS/PPM converter', ['tgif'],
760 r'''\converter tgif eps "tgif -print -color -eps -stdout $$i > $$o" ""
761 \converter tgif png "tgif -print -color -png -o $$d $$i" ""
762 \converter tgif pdf "tgif -print -color -pdf -stdout $$i > $$o" ""''',
765 checkProg('a WMF -> EPS converter', ['metafile2eps $$i $$o', 'wmf2eps -o $$o $$i'],
766 rc_entry = [ r'\converter wmf eps "%%" ""'])
768 checkProg('an EMF -> EPS converter', ['metafile2eps $$i $$o', 'wmf2eps -o $$o $$i'],
769 rc_entry = [ r'\converter emf eps "%%" ""'])
771 checkProg('an EPS -> PDF converter', ['epstopdf'],
772 rc_entry = [ r'\converter eps pdf "epstopdf --outfile=$$o $$i" ""', ''])
774 # no agr -> pdf converter, since the pdf library used by gracebat is not
775 # free software and therefore not compiled in in many installations.
776 # Fortunately, this is not a big problem, because we will use epstopdf to
777 # convert from agr to pdf via eps without loss of quality.
778 checkProg('a Grace -> Image converter', ['gracebat'],
780 r'''\converter agr eps "gracebat -hardcopy -printfile $$o -hdevice EPS $$i 2>/dev/null" ""
781 \converter agr png "gracebat -hardcopy -printfile $$o -hdevice PNG $$i 2>/dev/null" ""
782 \converter agr jpg "gracebat -hardcopy -printfile $$o -hdevice JPEG $$i 2>/dev/null" ""
783 \converter agr ppm "gracebat -hardcopy -printfile $$o -hdevice PNM $$i 2>/dev/null" ""''',
786 checkProg('a Dot -> Image converter', ['dot'],
788 r'''\converter dot eps "dot -Teps $$i -o $$o" ""
789 \converter dot png "dot -Tpng $$i -o $$o" ""''',
792 checkProg('a Dia -> PNG converter', ['dia -e $$o -t png $$i'],
793 rc_entry = [ r'\converter dia png "%%" ""'])
795 checkProg('a Dia -> EPS converter', ['dia -e $$o -t eps $$i'],
796 rc_entry = [ r'\converter dia eps "%%" ""'])
798 checkProg('a SVG -> PDF converter', ['rsvg-convert -f pdf -o $$o $$i', 'inkscape --file=$$i --export-area-drawing --without-gui --export-pdf=$$o'],
799 rc_entry = [ r'\converter svg pdf "%%" ""'])
801 checkProg('a SVG -> EPS converter', ['rsvg-convert -f ps -o $$o $$i', 'inkscape --file=$$i --export-area-drawing --without-gui --export-eps=$$o'],
802 rc_entry = [ r'\converter svg eps "%%" ""'])
804 checkProg('a SVG -> PNG converter', ['rsvg-convert -f png -o $$o $$i', 'inkscape --without-gui --file=$$i --export-png=$$o'],
805 rc_entry = [ r'\converter svg png "%%" ""'])
808 # gnumeric/xls/ods to tex
809 checkProg('a spreadsheet -> latex converter', ['ssconvert'],
810 rc_entry = [ r'''\converter gnumeric latex "ssconvert --export-type=Gnumeric_html:latex $$i $$o" ""
811 \converter ods latex "ssconvert --export-type=Gnumeric_html:latex $$i $$o" ""
812 \converter xls latex "ssconvert --export-type=Gnumeric_html:latex $$i $$o" ""''',
815 path, lilypond = checkProg('a LilyPond -> EPS/PDF/PNG converter', ['lilypond'])
817 version_string = cmdOutput("lilypond --version")
818 match = re.match('GNU LilyPond (\S+)', version_string)
820 version_number = match.groups()[0]
821 version = version_number.split('.')
822 if int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 11):
823 addToRC(r'''\converter lilypond eps "lilypond -dbackend=eps -dsafe --ps $$i" ""
824 \converter lilypond png "lilypond -dbackend=eps -dsafe --png $$i" ""''')
825 addToRC(r'\converter lilypond pdf "lilypond -dbackend=eps -dsafe --pdf $$i" ""')
826 logger.info('+ found LilyPond version %s.' % version_number)
827 elif int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 6):
828 addToRC(r'''\converter lilypond eps "lilypond -b eps --ps --safe $$i" ""
829 \converter lilypond png "lilypond -b eps --png $$i" ""''')
830 if int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 9):
831 addToRC(r'\converter lilypond pdf "lilypond -b eps --pdf --safe $$i" ""')
832 logger.info('+ found LilyPond version %s.' % version_number)
834 logger.info('+ found LilyPond, but version %s is too old.' % version_number)
836 logger.info('+ found LilyPond, but could not extract version number.')
838 path, lilypond_book = checkProg('a LilyPond book (LaTeX) -> LaTeX converter', ['lilypond-book'])
839 if (lilypond_book != ''):
840 version_string = cmdOutput("lilypond-book --version")
841 match = re.match('^(\S+)$', version_string)
843 version_number = match.groups()[0]
844 version = version_number.split('.')
845 if int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 13):
847 addToRC(r'\converter lyxpreview-lytex ppm "python -tt $$s/scripts/lyxpreview-lytex2bitmap.py" ""')
849 # set empty converter to override the default imagemagick
850 addToRC(r'\converter lyxpreview-lytex ppm "" ""')
851 if dvipng == "dvipng" and dv2dt == 'dv2dt':
852 addToRC(r'\converter lyxpreview-lytex png "python -tt $$s/scripts/lyxpreview-lytex2bitmap.py" ""')
854 # set empty converter to override the default imagemagick
855 addToRC(r'\converter lyxpreview-lytex png "" ""')
856 # Note: The --lily-output-dir flag is required because lilypond-book
857 # does not process input again unless the input has changed,
858 # even if the output format being requested is different. So
859 # once a .eps file exists, lilypond-book won't create a .pdf
860 # even when requested with --pdf. This is a problem if a user
861 # clicks View PDF after having done a View DVI. To circumvent
862 # this, use different output folders for eps and pdf outputs.
863 addToRC(r'\converter lilypond-book latex "lilypond-book --safe --lily-output-dir=ly-eps $$i" ""')
864 addToRC(r'\converter lilypond-book pdflatex "lilypond-book --safe --pdf --latex-program=pdflatex --lily-output-dir=ly-pdf $$i" ""')
865 addToRC(r'\converter lilypond-book xetex "lilypond-book --safe --pdf --latex-program=xelatex --lily-output-dir=ly-pdf $$i" ""')
866 addToRC(r'\converter lilypond-book luatex "lilypond-book --safe --pdf --latex-program=lualatex --lily-output-dir=ly-pdf $$i" ""')
867 logger.info('+ found LilyPond-book version %s.' % version_number)
869 logger.info('+ found LilyPond-book, but version %s is too old.' % version_number)
871 logger.info('+ found LilyPond-book, but could not extract version number.')
873 checkProg('a Noteedit -> LilyPond converter', ['noteedit --export-lilypond $$i'],
874 rc_entry = [ r'\converter noteedit lilypond "%%" ""', ''])
876 # Currently, lyxpak outputs a gzip compressed tar archive on *nix
877 # and a zip archive on Windows.
878 # So, we configure the appropriate version according to the platform.
879 cmd = r'\converter lyx %s "python -tt $$s/scripts/lyxpak.py $$r/$$i" ""'
881 addToRC(r'\Format lyxzip zip "LyX Archive (zip)" "" "" "" "document,menu=export"')
882 addToRC(cmd % "lyxzip")
884 addToRC(r'\Format lyxgz gz "LyX Archive (tar.gz)" "" "" "" "document,menu=export"')
885 addToRC(cmd % "lyxgz")
888 # FIXME: no rc_entry? comment it out
889 # checkProg('Image converter', ['convert $$i $$o'])
891 # Entries that do not need checkProg
892 addToRC(r'''\converter lyxpreview-platex ppm "python -tt $$s/scripts/lyxpreview-platex2bitmap.py" ""
893 \converter csv lyx "python -tt $$s/scripts/csv2lyx.py $$i $$o" ""
894 \converter date dateout "python -tt $$s/scripts/date.py %d-%m-%Y > $$o" ""
895 \converter docbook docbook-xml "cp $$i $$o" "xml"
896 \converter fen asciichess "python -tt $$s/scripts/fen2ascii.py $$i $$o" ""
897 \converter lyx lyx13x "python -tt $$s/lyx2lyx/lyx2lyx -t 221 $$i > $$o" ""
898 \converter lyx lyx14x "python -tt $$s/lyx2lyx/lyx2lyx -t 245 $$i > $$o" ""
899 \converter lyx lyx15x "python -tt $$s/lyx2lyx/lyx2lyx -t 276 $$i > $$o" ""
900 \converter lyx lyx16x "python -tt $$s/lyx2lyx/lyx2lyx -t 345 $$i > $$o" ""
901 \converter lyx clyx "python -tt $$s/lyx2lyx/lyx2lyx -c big5 -t 245 $$i > $$o" ""
902 \converter lyx jlyx "python -tt $$s/lyx2lyx/lyx2lyx -c euc_jp -t 245 $$i > $$o" ""
903 \converter lyx klyx "python -tt $$s/lyx2lyx/lyx2lyx -c euc_kr -t 245 $$i > $$o" ""
904 \converter clyx lyx "python -tt $$s/lyx2lyx/lyx2lyx -c big5 $$i > $$o" ""
905 \converter jlyx lyx "python -tt $$s/lyx2lyx/lyx2lyx -c euc_jp $$i > $$o" ""
906 \converter klyx lyx "python -tt $$s/lyx2lyx/lyx2lyx -c euc_kr $$i > $$o" ""
911 ''' Check docbook '''
912 path, DOCBOOK = checkProg('SGML-tools 2.x (DocBook), db2x scripts or xsltproc', ['sgmltools', 'db2dvi', 'xsltproc'],
914 r'''\converter docbook dvi "sgmltools -b dvi $$i" ""
915 \converter docbook html "sgmltools -b html $$i" ""''',
916 r'''\converter docbook dvi "db2dvi $$i" ""
917 \converter docbook html "db2html $$i" ""''',
918 r'''\converter docbook dvi "" ""
919 \converter docbook html "" ""''',
920 r'''\converter docbook dvi "" ""
921 \converter docbook html "" ""'''])
924 return ('yes', 'true', '\\def\\hasdocbook{yes}')
926 return ('no', 'false', '')
929 def checkOtherEntries():
930 ''' entries other than Format and Converter '''
931 checkProg('ChkTeX', ['chktex -n1 -n3 -n6 -n9 -n22 -n25 -n30 -n38'],
932 rc_entry = [ r'\chktex_command "%%"' ])
933 checkProgAlternatives('BibTeX or alternative programs', ['bibtex', 'bibtex8', 'biber'],
934 rc_entry = [ r'\bibtex_command "%%"' ],
935 alt_rc_entry = [ r'\bibtex_alternatives "%%"' ])
936 checkProg('a specific Japanese BibTeX variant', ['pbibtex', 'jbibtex', 'bibtex'],
937 rc_entry = [ r'\jbibtex_command "%%"' ])
938 checkProgAlternatives('available index processors', ['texindy', 'makeindex -c -q', 'xindy'],
939 rc_entry = [ r'\index_command "%%"' ],
940 alt_rc_entry = [ r'\index_alternatives "%%"' ])
941 checkProg('an index processor appropriate to Japanese', ['mendex -c -q', 'jmakeindex -c -q', 'makeindex -c -q'],
942 rc_entry = [ r'\jindex_command "%%"' ])
943 path, splitindex = checkProg('the splitindex processor', ['splitindex.pl', 'splitindex'],
944 rc_entry = [ r'\splitindex_command "%%"' ])
946 checkProg('the splitindex processor (java version)', ['splitindex.class'],
947 rc_entry = [ r'\splitindex_command "java splitindex"' ])
948 checkProg('a nomenclature processor', ['makeindex'],
949 rc_entry = [ r'\nomencl_command "makeindex -s nomencl.ist"' ])
950 ## FIXME: OCTAVE is not used anywhere
951 # path, OCTAVE = checkProg('Octave', ['octave'])
952 ## FIXME: MAPLE is not used anywhere
953 # path, MAPLE = checkProg('Maple', ['maple'])
954 checkProg('a spool command', ['lp', 'lpr'],
956 r'''\print_spool_printerprefix "-d "
957 \print_spool_command "lp"''',
958 r'''\print_spool_printerprefix "-P",
959 \print_spool_command "lpr"''',
961 # Add the rest of the entries (no checkProg is required)
962 addToRC(r'''\copier fig "python -tt $$s/scripts/fig_copy.py $$i $$o"
963 \copier pstex "python -tt $$s/scripts/tex_copy.py $$i $$o $$l"
964 \copier pdftex "python -tt $$s/scripts/tex_copy.py $$i $$o $$l"
965 \copier program "python -tt $$s/scripts/ext_copy.py $$i $$o"
969 def processLayoutFile(file, bool_docbook):
970 ''' process layout file and get a line of result
972 Declare lines look like this: (article.layout, scrbook.layout, svjog.layout)
974 \DeclareLaTeXClass{article}
975 \DeclareLaTeXClass[scrbook]{book (koma-script)}
976 \DeclareLaTeXClass[svjour,svjog.clo]{article (Springer - svjour/jog)}
980 "article" "article" "article" "false" "article.cls"
981 "scrbook" "scrbook" "book (koma-script)" "false" "scrbook.cls"
982 "svjog" "svjour" "article (Springer - svjour/jog)" "false" "svjour.cls,svjog.clo"
984 def checkForClassExtension(x):
985 '''if the extension for a latex class is not
986 provided, add .cls to the classname'''
988 return x.strip() + '.cls'
991 classname = file.split(os.sep)[-1].split('.')[0]
992 # return ('LaTeX', '[a,b]', 'a', ',b,c', 'article') for \DeclareLaTeXClass[a,b,c]{article}
993 p = re.compile(r'\Declare(LaTeX|DocBook)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)}')
994 for line in open(file).readlines():
997 (classtype, optAll, opt, opt1, desc) = res.groups()
998 avai = {'LaTeX':'false', 'DocBook':bool_docbook}[classtype]
1001 prereq_latex = checkForClassExtension(classname)
1003 prereq_list = optAll[1:-1].split(',')
1004 prereq_list = map(checkForClassExtension, prereq_list)
1005 prereq_latex = ','.join(prereq_list)
1006 prereq_docbook = {'true':'', 'false':'docbook'}[bool_docbook]
1007 prereq = {'LaTeX':prereq_latex, 'DocBook':prereq_docbook}[classtype]
1008 return '"%s" "%s" "%s" "%s" "%s"\n' % (classname, opt, desc, avai, prereq)
1009 logger.warning("Layout file " + file + " has no \DeclareXXClass line. ")
1013 def checkLatexConfig(check_config, bool_docbook):
1014 ''' Explore the LaTeX configuration
1015 Return None (will be passed to sys.exit()) for success.
1017 msg = 'checking LaTeX configuration... '
1018 # if --without-latex-config is forced, or if there is no previous
1019 # version of textclass.lst, re-generate a default file.
1020 if not os.path.isfile('textclass.lst') or not check_config:
1021 # remove the files only if we want to regenerate
1022 removeFiles(['textclass.lst', 'packages.lst'])
1024 # Then, generate a default textclass.lst. In case configure.py
1025 # fails, we still have something to start lyx.
1026 logger.info(msg + ' default values')
1027 logger.info('+checking list of textclasses... ')
1028 tx = open('textclass.lst', 'w')
1030 # This file declares layouts and their associated definition files
1031 # (include dir. relative to the place where this file is).
1032 # It contains only default values, since chkconfig.ltx could not be run
1033 # for some reason. Run ./configure.py if you need to update it after a
1034 # configuration change.
1036 # build the list of available layout files and convert it to commands
1039 for file in glob.glob( os.path.join('layouts', '*.layout') ) + \
1040 glob.glob( os.path.join(srcdir, 'layouts', '*.layout' ) ) :
1042 if not os.path.isfile(file):
1044 # get stuff between /xxxx.layout .
1045 classname = file.split(os.sep)[-1].split('.')[0]
1047 cleanclass = classname.replace(' ', '_')
1048 cleanclass = cleanclass.replace('-', '_')
1049 # make sure the same class is not considered twice
1050 if foundClasses.count(cleanclass) == 0: # not found before
1051 foundClasses.append(cleanclass)
1052 retval = processLayoutFile(file, bool_docbook)
1056 logger.info('\tdone')
1057 if not check_config:
1059 # the following will generate textclass.lst.tmp, and packages.lst.tmp
1060 logger.info(msg + '\tauto')
1061 removeFiles(['chkconfig.classes', 'chkconfig.vars', 'chklayouts.tex',
1062 'wrap_chkconfig.ltx'])
1064 if not os.path.isfile( 'chkconfig.ltx' ):
1065 shutil.copyfile( os.path.join(srcdir, 'chkconfig.ltx'), 'chkconfig.ltx' )
1067 writeToFile('wrap_chkconfig.ltx', '%s\n\\input{chkconfig.ltx}\n' % docbook_cmd)
1068 # Construct the list of classes to test for.
1069 # build the list of available layout files and convert it to commands
1071 declare = re.compile(r'\Declare(LaTeX|DocBook)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)}')
1072 empty = re.compile(r'^\s*$')
1073 testclasses = list()
1074 for file in glob.glob( os.path.join('layouts', '*.layout') ) + \
1075 glob.glob( os.path.join(srcdir, 'layouts', '*.layout' ) ) :
1076 nodeclaration = False
1077 if not os.path.isfile(file):
1079 classname = file.split(os.sep)[-1].split('.')[0]
1080 for line in open(file).readlines():
1081 if not empty.match(line) and line[0] != '#':
1082 logger.warning("Failed to find valid \Declare line for layout file `" + file + "'.\n\t=> Skipping this file!")
1083 nodeclaration = True
1085 if declare.search(line) == None:
1087 testclasses.append("\\TestDocClass{%s}{%s}" % (classname, line[1:].strip()))
1092 cl = open('chklayouts.tex', 'w')
1093 for line in testclasses:
1094 cl.write(line + '\n')
1097 # we have chklayouts.tex, then process it
1098 fout = os.popen(LATEX + ' wrap_chkconfig.ltx')
1100 line = fout.readline()
1103 if re.match('^\+', line):
1104 logger.info(line.strip())
1105 # if the command succeeds, None will be returned
1108 # currently, values in chhkconfig are only used to set
1111 for line in open('chkconfig.vars').readlines():
1112 key, val = re.sub('-', '_', line).split('=')
1114 values[key] = val.strip("'")
1115 # chk_fontenc may not exist
1117 addToRC(r'\font_encoding "%s"' % values["chk_fontenc"])
1120 if rmcopy: # remove the copied file
1121 removeFiles( [ 'chkconfig.ltx' ] )
1122 # if configure successed, move textclass.lst.tmp to textclass.lst
1123 # and packages.lst.tmp to packages.lst
1124 if os.path.isfile('textclass.lst.tmp') and len(open('textclass.lst.tmp').read()) > 0 \
1125 and os.path.isfile('packages.lst.tmp') and len(open('packages.lst.tmp').read()) > 0:
1126 shutil.move('textclass.lst.tmp', 'textclass.lst')
1127 shutil.move('packages.lst.tmp', 'packages.lst')
1131 def checkModulesConfig():
1132 removeFiles(['lyxmodules.lst', 'chkmodules.tex'])
1134 logger.info('+checking list of modules... ')
1135 tx = open('lyxmodules.lst', 'w')
1136 tx.write('''## This file declares modules and their associated definition files.
1137 ## It has been automatically generated by configure
1138 ## Use "Options/Reconfigure" if you need to update it after a
1139 ## configuration change.
1140 ## "ModuleName" "filename" "Description" "Packages" "Requires" "Excludes" "Category"
1143 # build the list of available modules
1145 # note that this searches the local directory first, then the
1146 # system directory. that way, we pick up the user's version first.
1147 for file in glob.glob( os.path.join('layouts', '*.module') ) + \
1148 glob.glob( os.path.join(srcdir, 'layouts', '*.module' ) ) :
1151 if not os.path.isfile(file):
1154 filename = file.split(os.sep)[-1]
1155 filename = filename[:-7]
1156 if seen.count(filename):
1159 seen.append(filename)
1160 retval = processModuleFile(file, filename, bool_docbook)
1164 logger.info('\tdone')
1167 def processModuleFile(file, filename, bool_docbook):
1168 ''' process module file and get a line of result
1170 The top of a module file should look like this:
1171 #\DeclareLyXModule[LaTeX Packages]{ModuleName}
1173 #...body of description...
1175 #Requires: [list of required modules]
1176 #Excludes: [list of excluded modules]
1177 #Category: [category name]
1178 The last three lines are optional (though do give a category).
1180 "ModuleName" "filename" "Description" "Packages" "Requires" "Excludes" "Category"
1182 remods = re.compile(r'\DeclareLyXModule\s*(?:\[([^]]*?)\])?{(.*)}')
1183 rereqs = re.compile(r'#+\s*Requires: (.*)')
1184 reexcs = re.compile(r'#+\s*Excludes: (.*)')
1185 recaty = re.compile(r'#+\s*Category: (.*)')
1186 redbeg = re.compile(r'#+\s*DescriptionBegin\s*$')
1187 redend = re.compile(r'#+\s*DescriptionEnd\s*$')
1189 modname = desc = pkgs = req = excl = catgy = ""
1190 readingDescription = False
1193 for line in open(file).readlines():
1194 if readingDescription:
1195 res = redend.search(line)
1197 readingDescription = False
1198 desc = " ".join(descLines)
1200 desc = desc.replace('"', '\\"')
1202 descLines.append(line[1:].strip())
1204 res = redbeg.search(line)
1206 readingDescription = True
1208 res = remods.search(line)
1210 (pkgs, modname) = res.groups()
1214 tmp = [s.strip() for s in pkgs.split(",")]
1215 pkgs = ",".join(tmp)
1217 res = rereqs.search(line)
1220 tmp = [s.strip() for s in req.split("|")]
1223 res = reexcs.search(line)
1226 tmp = [s.strip() for s in excl.split("|")]
1227 excl = "|".join(tmp)
1229 res = recaty.search(line)
1231 catgy = res.group(1)
1235 logger.warning("Module file without \DeclareLyXModule line. ")
1239 # this module has some latex dependencies:
1240 # append the dependencies to chkmodules.tex,
1241 # which is \input'ed by chkconfig.ltx
1242 testpackages = list()
1243 for pkg in pkgs.split(","):
1245 # this is a converter dependency: skip
1247 if pkg.endswith(".sty"):
1249 testpackages.append("\\TestPackage{%s}" % (pkg,))
1250 cm = open('chkmodules.tex', 'a')
1251 for line in testpackages:
1252 cm.write(line + '\n')
1255 return '"%s" "%s" "%s" "%s" "%s" "%s" "%s"\n' % (modname, filename, desc, pkgs, req, excl, catgy)
1258 def checkTeXAllowSpaces():
1259 ''' Let's check whether spaces are allowed in TeX file names '''
1260 tex_allows_spaces = 'false'
1261 if lyx_check_config:
1262 msg = "Checking whether TeX allows spaces in file names... "
1263 writeToFile('a b.tex', r'\message{working^^J}' )
1265 if os.name == 'nt' or sys.platform == 'cygwin':
1266 latex_out = cmdOutput(LATEX + r""" "\nonstopmode\input{\"a b\"}" """)
1268 latex_out = cmdOutput(LATEX + r""" '\nonstopmode\input{"a b"}' """)
1271 if 'working' in latex_out:
1272 logger.info(msg + 'yes')
1273 tex_allows_spaces = 'true'
1275 logger.info(msg + 'no')
1276 tex_allows_spaces = 'false'
1277 addToRC(r'\tex_allows_spaces ' + tex_allows_spaces)
1278 removeFiles( [ 'a b.tex', 'a b.log', 'texput.log' ])
1281 def removeTempFiles():
1283 if not lyx_keep_temps:
1284 removeFiles(['chkconfig.vars', 'chklatex.ltx', 'chklatex.log',
1285 'chklayouts.tex', 'chkmodules.tex', 'missfont.log',
1286 'wrap_chkconfig.ltx', 'wrap_chkconfig.log'])
1289 if __name__ == '__main__':
1290 lyx_check_config = True
1291 outfile = 'lyxrc.defaults'
1292 lyxrc_fileformat = 1
1294 lyx_keep_temps = False
1296 ## Parse the command line
1297 for op in sys.argv[1:]: # default shell/for list is $*, the options
1298 if op in [ '-help', '--help', '-h' ]:
1299 print '''Usage: configure [options]
1301 --help show this help lines
1302 --keep-temps keep temporary files (for debug. purposes)
1303 --without-latex-config do not run LaTeX to determine configuration
1304 --with-version-suffix=suffix suffix of binary installed files
1307 elif op == '--without-latex-config':
1308 lyx_check_config = False
1309 elif op == '--keep-temps':
1310 lyx_keep_temps = True
1311 elif op[0:22] == '--with-version-suffix=': # never mind if op is not long enough
1312 version_suffix = op[22:]
1314 print "Unknown option", op
1317 # check if we run from the right directory
1318 srcdir = os.path.dirname(sys.argv[0])
1321 if not os.path.isfile( os.path.join(srcdir, 'chkconfig.ltx') ):
1322 logger.error("configure: error: cannot find chkconfig.ltx script")
1326 dtl_tools = checkDTLtools()
1327 ## Write the first part of outfile
1328 writeToFile(outfile, '''# This file has been automatically generated by LyX' lib/configure.py
1329 # script. It contains default settings that have been determined by
1330 # examining your system. PLEASE DO NOT MODIFY ANYTHING HERE! If you
1331 # want to customize LyX, use LyX' Preferences dialog or modify directly
1332 # the "preferences" file instead. Any setting in that file will
1333 # override the values given here.
1337 ''' % lyxrc_fileformat)
1339 LATEX = checkLatex(dtl_tools)
1340 checkFormatEntries(dtl_tools)
1341 checkConverterEntries()
1342 (chk_docbook, bool_docbook, docbook_cmd) = checkDocBook()
1343 checkTeXAllowSpaces()
1344 windows_style_tex_paths = checkTeXPaths()
1345 if windows_style_tex_paths != '':
1346 addToRC(r'\tex_expects_windows_paths %s' % windows_style_tex_paths)
1348 checkModulesConfig()
1349 # --without-latex-config can disable lyx_check_config
1350 ret = checkLatexConfig(lyx_check_config and LATEX != '', bool_docbook)
1352 # The return error code can be 256. Because most systems expect an error code
1353 # in the range 0-127, 256 can be interpretted as 'success'. Because we expect
1354 # a None for success, 'ret is not None' is used to exit.
1355 sys.exit(ret is not None)