X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=lib%2Fconfigure.py;h=ac3b15f0a70e2002853fd1d7e77762d96854aed5;hb=d6ce4abd40b2e45d5b3b4344c555cf5712135b31;hp=3e60d2041819a5d8e9016bd7602e4c19ff9225a4;hpb=df8e0ed9e0c37ab75b6979237ea0a7c7b60a17a8;p=lyx.git diff --git a/lib/configure.py b/lib/configure.py index 3e60d20418..ac3b15f0a7 100644 --- a/lib/configure.py +++ b/lib/configure.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/python # -*- coding: utf-8 -*- # # file configure.py @@ -9,7 +9,12 @@ # Full author contact details are available in file CREDITS. from __future__ import print_function -import glob, logging, os, re, shutil, subprocess, sys, stat +import glob, logging, os, errno, re, shutil, subprocess, sys, stat + +if sys.version_info[0] < 3: + import codecs + open = codecs.open + # set up logging logging.basicConfig(level = logging.DEBUG, @@ -25,6 +30,13 @@ console.setFormatter(formatter) logger = logging.getLogger('LyX') logger.addHandler(console) +def quoteIfSpace(name): + " utility function: quote name if it contains spaces " + if ' ' in name: + return '"' + name + '"' + else: + return name + def writeToFile(filename, lines, append = False): " utility function: write or append lines to filename " if append: @@ -39,7 +51,7 @@ def addToRC(lines): ''' utility function: shortcut for appending lines to outfile add newline at the end of lines. ''' - if lines.strip() != '': + if lines.strip(): writeToFile(outfile, lines + '\n', append = True) logger.debug('Add to RC:\n' + lines + '\n\n') @@ -52,15 +64,20 @@ def removeFiles(filenames): try: os.remove(file) logger.debug('Removing file %s' % file) - except: - logger.debug('Failed to remove file %s' % file) + except OSError as e: + if e.errno == errno.ENOENT: # no such file or directory + logger.debug('No need to remove file %s (it does not exists)' % file) + elif e.errno == errno.EISDIR: # is a directory + logger.debug('Failed to remove file %s (it is a directory)' % file) + else: + logger.debug('Failed to remove file %s' % file) pass -def cmdOutput(cmd, async = False): +def cmdOutput(cmd, asynchronous = False): '''utility function: run a command and get its output as a string cmd: command to run - async: if False, return whole output as a string, otherwise + asynchronous: if False, return whole output as a string, otherwise return the stdout handle from which the output can be read (the caller is then responsible for closing it) ''' @@ -72,10 +89,10 @@ def cmdOutput(cmd, async = False): cmd = 'cmd /d /c pushd ' + shortPath(os.getcwd()) + '&' + cmd else: b = True - pipe = subprocess.Popen(cmd, shell=b, close_fds=b, stdin=subprocess.PIPE, \ + pipe = subprocess.Popen(cmd, shell=b, close_fds=b, stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True) pipe.stdin.close() - if async: + if asynchronous: return pipe.stdout output = pipe.stdout.read() pipe.stdout.close() @@ -110,16 +127,16 @@ def setEnviron(): def copy_tree(src, dst, preserve_symlinks=False, level=0): ''' Copy an entire directory tree 'src' to a new location 'dst'. - + Code inspired from distutils.copy_tree. - Copying ignores non-regular files and the cache directory. + Copying ignores non-regular files and the cache directory. Pipes may be present as leftovers from LyX for lyx-server. If 'preserve_symlinks' is true, symlinks will be copied as symlinks (on platforms that support them!); otherwise (the default), the destination of the symlink will be copied. ''' - + if not os.path.isdir(src): raise FileError("cannot copy tree '%s': not a directory" % src) try: @@ -127,12 +144,12 @@ def copy_tree(src, dst, preserve_symlinks=False, level=0): except os.error as oserror: (errno, errstr) = oserror.args raise FileError("error listing files in '%s': %s" % (src, errstr)) - + if not os.path.isdir(dst): os.makedirs(dst) - + outputs = [] - + for name in names: src_name = os.path.join(src, name) dst_name = os.path.join(dst, name) @@ -150,7 +167,7 @@ def copy_tree(src, dst, preserve_symlinks=False, level=0): outputs.append(dst_name) else: logger.info("Ignore non-regular file %s", src_name) - + return outputs @@ -163,20 +180,20 @@ def checkUpgrade(): logger.info('Checking for upgrade from previous version.') parent = os.path.dirname(cwd) appname = basename[:(-len(version_suffix))] - for version in ['-2.1', '-2.0', '-1.6' ]: + for version in ['-2.3', '-2.2', '-2.1', '-2.0', '-1.6' ]: logger.debug('Checking for upgrade from previous version ' + version) previous = os.path.join(parent, appname + version) logger.debug('previous = ' + previous) if os.path.isdir( previous ): logger.info('Found directory "%s".', previous) copy_tree( previous, cwd, True ) - logger.info('Content copied to directory "%s".', cwd) + logger.info('Content copied from directory "%s".', previous) return def createDirectories(): ''' Create the build directories if necessary ''' - for dir in ['bind', 'clipart', 'doc', 'examples', 'images', 'kbd', \ + for dir in ['bind', 'clipart', 'doc', 'examples', 'images', 'kbd', 'layouts', 'scripts', 'templates', 'ui' ]: if not os.path.isdir( dir ): try: @@ -196,23 +213,22 @@ def checkTeXPaths(): from tempfile import mkstemp fd, tmpfname = mkstemp(suffix='.ltx') if os.name == 'nt': - from locale import getdefaultlocale - language, encoding = getdefaultlocale() - if encoding == None: - encoding = 'latin1' + encoding = sys.getfilesystemencoding() if sys.version_info[0] < 3: inpname = shortPath(unicode(tmpfname, encoding)).replace('\\', '/') else: - inpname = shortPath(str(tmpfname, encoding)).replace('\\', '/') + inpname = shortPath(tmpfname).replace('\\', '/') else: inpname = cmdOutput('cygpath -m ' + tmpfname) logname = os.path.basename(re.sub("(?i).ltx", ".log", inpname)) inpname = inpname.replace('~', '\\string~') - os.write(fd, r'\relax') + os.write(fd, b'\\relax') os.close(fd) - latex_out = cmdOutput(r'latex "\nonstopmode\input{%s}\makeatletter\@@end"' % inpname) + latex_out = cmdOutput(r'latex "\nonstopmode\input{%s}\makeatletter\@@end"' + % inpname) if 'Error' in latex_out: - latex_out = cmdOutput(r'latex "\nonstopmode\input{\"%s\"}\makeatletter\@@end"' % inpname) + latex_out = cmdOutput(r'latex "\nonstopmode\input{\"%s\"}\makeatletter\@@end"' + % inpname) if 'Error' in latex_out: logger.warning("configure: TeX engine needs posix-style paths in latex files") windows_style_tex_paths = 'false' @@ -252,7 +268,8 @@ def checkProg(description, progs, rc_entry = [], path = [], not_found = ''): ''' # one rc entry for each progs plus not_found entry if len(rc_entry) > 1 and len(rc_entry) != len(progs) + 1: - logger.error("rc entry should have one item or item for each prog and not_found.") + logger.error("rc entry should have one item or item " + "for each prog and not_found.") sys.exit(2) logger.info('checking for ' + description + '...') ## print '(' + ','.join(progs) + ')', @@ -262,10 +279,11 @@ def checkProg(description, progs, rc_entry = [], path = [], not_found = ''): if "PATHEXT" in os.environ: extlist = extlist + os.environ["PATHEXT"].split(os.pathsep) global java, perl + unquoted_space = re.compile(r'''((?:[^ "']|"[^"]*"|'[^']*')+)''') for idx in range(len(progs)): # ac_prog may have options, ac_word is the command name - ac_prog = progs[idx] - ac_word = ac_prog.split(' ')[0] + ac_prog = progs[idx].replace('"', '\\"') + ac_word = unquoted_space.split(progs[idx])[1::2][0].strip('"') if (ac_word.endswith('.class') or ac_word.endswith('.jar')) and java == '': continue if ac_word.endswith('.pl') and perl == '': @@ -279,13 +297,17 @@ def checkProg(description, progs, rc_entry = [], path = [], not_found = ''): logger.info(msg + ' yes') # deal with java and perl if ac_word.endswith('.class'): - ac_prog = ac_prog.replace(ac_word, r'%s \"%s\"' % (java, os.path.join(ac_dir, ac_word[:-6]))) + ac_prog = ac_prog.replace(ac_word, r'%s \"%s\"' + % (java, os.path.join(ac_dir, ac_word[:-6]))) elif ac_word.endswith('.jar'): - ac_prog = ac_prog.replace(ac_word, r'%s -jar \"%s\"' % (java, os.path.join(ac_dir, ac_word))) + ac_prog = ac_prog.replace(ac_word, r'%s -jar \"%s\"' + % (java, os.path.join(ac_dir, ac_word))) elif ac_word.endswith('.pl'): - ac_prog = ac_prog.replace(ac_word, r'%s -w \"%s\"' % (perl, os.path.join(ac_dir, ac_word))) + ac_prog = ac_prog.replace(ac_word, r'%s -w \"%s\"' + % (perl, os.path.join(ac_dir, ac_word))) elif ac_dir in additional_path: - ac_prog = ac_prog.replace(ac_word, r'\"%s\"' % (os.path.join(ac_dir, ac_word))) + ac_prog = ac_prog.replace(ac_word, r'\"%s\"' + % (os.path.join(ac_dir, ac_word))) # write rc entries for this command if len(rc_entry) == 1: addToRC(rc_entry[0].replace('%%', ac_prog)) @@ -300,7 +322,8 @@ def checkProg(description, progs, rc_entry = [], path = [], not_found = ''): return ['', not_found] -def checkProgAlternatives(description, progs, rc_entry = [], alt_rc_entry = [], path = [], not_found = ''): +def checkProgAlternatives(description, progs, rc_entry = [], + alt_rc_entry = [], path = [], not_found = ''): ''' The same as checkProg, but additionally, all found programs will be added as alt_rc_entries @@ -340,13 +363,17 @@ def checkProgAlternatives(description, progs, rc_entry = [], alt_rc_entry = [], m = None # deal with java and perl if ac_word.endswith('.class'): - ac_prog = ac_prog.replace(ac_word, r'%s \"%s\"' % (java, os.path.join(ac_dir, ac_word[:-6]))) + ac_prog = ac_prog.replace(ac_word, r'%s \"%s\"' + % (java, os.path.join(ac_dir, ac_word[:-6]))) elif ac_word.endswith('.jar'): - ac_prog = ac_prog.replace(ac_word, r'%s -jar \"%s\"' % (java, os.path.join(ac_dir, ac_word))) + ac_prog = ac_prog.replace(ac_word, r'%s -jar \"%s\"' + % (java, os.path.join(ac_dir, ac_word))) elif ac_word.endswith('.pl'): - ac_prog = ac_prog.replace(ac_word, r'%s -w \"%s\"' % (perl, os.path.join(ac_dir, ac_word))) + ac_prog = ac_prog.replace(ac_word, r'%s -w \"%s\"' + % (perl, os.path.join(ac_dir, ac_word))) elif ac_dir in additional_path: - ac_prog = ac_prog.replace(ac_word, r'\"%s\"' % (os.path.join(ac_dir, ac_word))) + ac_prog = ac_prog.replace(ac_word, r'\"%s\"' + % (os.path.join(ac_dir, ac_word))) # write rc entries for this command if found_prime == False: if len(rc_entry) == 1: @@ -438,33 +465,38 @@ def listAlternatives(progs, alt_type, rc_entry = []): def checkViewer(description, progs, rc_entry = [], path = []): ''' The same as checkProgAlternatives, but for viewers ''' alt_rc_entry = listAlternatives(progs, 'viewer', rc_entry) - return checkProgAlternatives(description, progs, rc_entry, alt_rc_entry, path, not_found = 'auto') + return checkProgAlternatives(description, progs, rc_entry, + alt_rc_entry, path, not_found = 'auto') def checkEditor(description, progs, rc_entry = [], path = []): ''' The same as checkProgAlternatives, but for editors ''' alt_rc_entry = listAlternatives(progs, 'editor', rc_entry) - return checkProgAlternatives(description, progs, rc_entry, alt_rc_entry, path, not_found = 'auto') + return checkProgAlternatives(description, progs, rc_entry, + alt_rc_entry, path, not_found = 'auto') def checkViewerNoRC(description, progs, rc_entry = [], path = []): ''' The same as checkViewer, but do not add rc entry ''' alt_rc_entry = listAlternatives(progs, 'viewer', rc_entry) rc_entry = [] - return checkProgAlternatives(description, progs, rc_entry, alt_rc_entry, path, not_found = 'auto') + return checkProgAlternatives(description, progs, rc_entry, + alt_rc_entry, path, not_found = 'auto') def checkEditorNoRC(description, progs, rc_entry = [], path = []): ''' The same as checkViewer, but do not add rc entry ''' alt_rc_entry = listAlternatives(progs, 'editor', rc_entry) rc_entry = [] - return checkProgAlternatives(description, progs, rc_entry, alt_rc_entry, path, not_found = 'auto') + return checkProgAlternatives(description, progs, rc_entry, + alt_rc_entry, path, not_found = 'auto') def checkViewerEditor(description, progs, rc_entry = [], path = []): ''' The same as checkProgAlternatives, but for viewers and editors ''' alt_rc_entry = listAlternatives(progs, ['editor', 'viewer'], rc_entry) - return checkProgAlternatives(description, progs, rc_entry, alt_rc_entry, path, not_found = 'auto') + return checkProgAlternatives(description, progs, rc_entry, + alt_rc_entry, path, not_found = 'auto') def checkDTLtools(): @@ -480,7 +512,15 @@ def checkDTLtools(): def checkInkscape(): ''' Check whether Inkscape is available and return the full path (Windows only) ''' - if os.name != 'nt': + ''' On Mac OS (darwin) a wrapper is used - therefore the version is checked ''' + ''' The answer of the real inkscape is validated and a fake binary used if this fails ''' + if sys.platform == 'darwin': + version_string = cmdOutput("inkscape --version") + if version_string.startswith('Inkscape'): + return 'inkscape' + else: + return 'inkscape-binary' + elif os.name != 'nt': return 'inkscape' if sys.version_info[0] < 3: import _winreg as winreg @@ -490,12 +530,12 @@ def checkInkscape(): try: aKey = winreg.OpenKey(aReg, r"inkscape.svg\DefaultIcon") val = winreg.QueryValueEx(aKey, "") - return str(val[0]).split('"')[1].replace('.exe', '') + return str(val[0]).split('"')[1] except EnvironmentError: try: aKey = winreg.OpenKey(aReg, r"Applications\inkscape.exe\shell\open\command") val = winreg.QueryValueEx(aKey, "") - return str(val[0]).split('"')[1].replace('.exe', '') + return str(val[0]).split('"')[1] except EnvironmentError: return 'inkscape' @@ -505,7 +545,7 @@ def checkLatex(dtl_tools): path, PPLATEX = checkProg('a DVI postprocessing program', ['pplatex $$i']) #----------------------------------------------------------------- path, PLATEX = checkProg('pLaTeX, the Japanese LaTeX', ['platex $$i']) - if PLATEX != '': + if PLATEX: # check if PLATEX is pLaTeX2e writeToFile('chklatex.ltx', r'\nonstopmode\makeatletter\@@end') # run platex on chklatex.ltx and check result @@ -521,12 +561,12 @@ def checkLatex(dtl_tools): PPLATEX = LATEX if dtl_tools: # Windows only: DraftDVI - addToRC(r'''\converter latex dvi2 "%s" "latex" + addToRC(r'''\converter latex dvi2 "%s" "latex,hyperref-driver=dvips" \converter dvi2 dvi "python -tt $$s/scripts/clean_dvi.py $$i $$o" ""''' % PPLATEX) else: - addToRC(r'\converter latex dvi "%s" "latex"' % PPLATEX) + addToRC(r'\converter latex dvi "%s" "latex,hyperref-driver=dvips"' % PPLATEX) # no latex - if LATEX != '': + if LATEX: # Check if latex is usable writeToFile('chklatex.ltx', r''' \nonstopmode @@ -551,9 +591,9 @@ def checkLuatex(): ''' Check if luatex is there ''' path, LUATEX = checkProg('LuaTeX', ['lualatex $$i']) path, DVILUATEX = checkProg('LuaTeX (DVI)', ['dvilualatex $$i']) - if LUATEX != '': + if LUATEX: addToRC(r'\converter luatex pdf5 "%s" "latex=lualatex"' % LUATEX) - if DVILUATEX != '': + if DVILUATEX: addToRC(r'\converter dviluatex dvi3 "%s" "latex=dvilualatex"' % DVILUATEX) @@ -569,6 +609,10 @@ def checkModule(module): return False +texteditors = ['xemacs', 'gvim', 'kedit', 'kwrite', 'kate', + 'nedit', 'gedit', 'geany', 'leafpad', 'mousepad', + 'xed', 'notepad', 'WinEdt', 'WinShell', 'PSPad'] + def checkFormatEntries(dtl_tools): ''' Check all formats (\Format entries) ''' checkViewerEditor('a Tgif viewer and editor', ['tgif'], @@ -589,7 +633,7 @@ def checkFormatEntries(dtl_tools): checkViewerEditor('a FEN viewer and editor', ['xboard -lpf $$i -mode EditPosition'], rc_entry = [r'\Format fen fen FEN "" "%%" "%%" "" ""']) # - checkViewerEditor('a SVG viewer and editor', [inkscape_name], + checkViewerEditor('a SVG viewer and editor', [inkscape_gui], rc_entry = [r'''\Format svg "svg" SVG "" "%%" "%%" "vector" "image/svg+xml" \Format svgz "svgz" "SVG (compressed)" "" "%%" "%%" "vector,zipped=native" ""'''], path = [inkscape_path]) @@ -604,13 +648,16 @@ def checkFormatEntries(dtl_tools): \Format tiff tif TIFF "" "%s" "%s" "" "image/tiff" \Format xbm xbm XBM "" "%s" "%s" "" "image/x-xbitmap" \Format xpm xpm XPM "" "%s" "%s" "" "image/x-xpixmap"''' - path, iv = checkViewerNoRC('a raster image viewer', ['xv', 'kview', 'gimp-remote', 'gimp'], rc_entry = [imageformats]) - path, ie = checkEditorNoRC('a raster image editor', ['gimp-remote', 'gimp'], rc_entry = [imageformats]) - addToRC(imageformats % \ - (iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie) ) - # - checkViewerEditor('a text editor', ['xemacs', 'gvim', 'kedit', 'kwrite', 'kate', \ - 'nedit', 'gedit', 'notepad', 'geany', 'leafpad', 'mousepad'], + path, iv = checkViewerNoRC('a raster image viewer', + ['xv', 'gwenview', 'kview', + 'eog', 'xviewer', 'ristretto', 'gpicview', 'lximage-qt', + 'xdg-open', 'gimp-remote', 'gimp'], + rc_entry = [imageformats]) + path, ie = checkEditorNoRC('a raster image editor', + ['gimp-remote', 'gimp'], rc_entry = [imageformats]) + addToRC(imageformats % ((iv, ie)*10)) + # + checkViewerEditor('a text editor', texteditors, rc_entry = [r'''\Format asciichess asc "Plain text (chess output)" "" "" "%%" "" "" \Format docbook sgml DocBook B "" "%%" "document,menu=export" "" \Format docbook-xml xml "DocBook (XML)" "" "" "%%" "document,menu=export" "application/docbook+xml" @@ -619,10 +666,12 @@ def checkFormatEntries(dtl_tools): \Format platex tex "LaTeX (pLaTeX)" "" "" "%%" "document,menu=export" "" \Format literate nw NoWeb N "" "%%" "document,menu=export" "" \Format sweave Rnw "Sweave" S "" "%%" "document,menu=export" "" +\Format sweave-ja Rnw "Sweave (Japanese)" S "" "%%" "document,menu=export" "" \Format r R "R/S code" "" "" "%%" "document,menu=export" "" \Format knitr Rnw "Rnw (knitr)" "" "" "%%" "document,menu=export" "" -\Format lilypond ly "LilyPond music" "" "" "%%" "vector" "text/x-lilypond" +\Format knitr-ja Rnw "Rnw (knitr, Japanese)" "" "" "%%" "document,menu=export" "" \Format lilypond-book lytex "LilyPond book (LaTeX)" "" "" "%%" "document,menu=export" "" +\Format lilypond-book-ja lytex "LilyPond book (pLaTeX)" "" "" "%%" "document,menu=export" "" \Format latex tex "LaTeX (plain)" L "" "%%" "document,menu=export" "text/x-tex" \Format luatex tex "LaTeX (LuaTeX)" "" "" "%%" "document,menu=export" "" \Format pdflatex tex "LaTeX (pdflatex)" "" "" "%%" "document,menu=export" "" @@ -634,6 +683,10 @@ def checkFormatEntries(dtl_tools): \Format text4 txt "Plain text (catdvi)" "" "" "%%" "document" "" \Format textparagraph txt "Plain Text, Join Lines" "" "" "%%" "document" "" \Format beamer.info pdf.info "Info (Beamer)" "" "" "%%" "document,menu=export" ""''' ]) + #Lilypond files have special editors, but fall back to plain text editors + checkViewerEditor('a lilypond editor', + ['frescobaldi'] + texteditors, + rc_entry = [r'''\Format lilypond ly "LilyPond music" "" "" "%%" "vector" "text/x-lilypond"''' ]) #Spreadsheets using ssconvert from gnumeric checkViewer('gnumeric spreadsheet software', ['gnumeric'], rc_entry = [r'''\Format gnumeric gnumeric "Gnumeric spreadsheet" "" "" "%%" "document" "application/x-gnumeric" @@ -645,25 +698,30 @@ def checkFormatEntries(dtl_tools): checkViewer('an HTML previewer', ['firefox', 'mozilla file://$$p$$i', 'netscape'], rc_entry = [r'\Format xhtml xhtml "LyXHTML" y "%%" "" "document,menu=export" "application/xhtml+xml"']) # - checkEditor('a BibTeX editor', ['jabref', 'JabRef', \ - 'pybliographic', 'bibdesk', 'gbib', 'kbib', \ - 'kbibtex', 'sixpack', 'bibedit', 'tkbibtex' \ - 'xemacs', 'gvim', 'kedit', 'kwrite', 'kate', \ - 'jedit', 'TeXnicCenter', 'WinEdt', 'WinShell', 'PSPad', \ - 'nedit', 'gedit', 'notepad', 'geany', 'leafpad', 'mousepad'], + checkEditor('a BibTeX editor', ['jabref', 'JabRef', + 'pybliographic', 'bibdesk', 'gbib', 'kbib', + 'kbibtex', 'sixpack', 'bibedit', 'tkbibtex', 'TeXnicCenter'] + + texteditors, rc_entry = [r'''\Format bibtex bib "BibTeX" "" "" "%%" "" "text/x-bibtex"''' ]) # #checkProg('a Postscript interpreter', ['gs'], # rc_entry = [ r'\ps_command "%%"' ]) - checkViewer('a Postscript previewer', ['kghostview', 'okular', 'qpdfview --unique', 'evince', 'gv', 'ghostview -swap', 'gsview64', 'gsview32'], + checkViewer('a Postscript previewer', + ['kghostview', 'okular', 'qpdfview --unique', + 'evince', 'xreader', + 'gv', 'ghostview -swap', 'gsview64', 'gsview32'], rc_entry = [r'''\Format eps eps EPS "" "%%" "" "vector" "image/x-eps" \Format eps2 eps "EPS (uncropped)" "" "%%" "" "vector" "" \Format eps3 eps "EPS (cropped)" "" "%%" "" "document" "" \Format ps ps Postscript t "%%" "" "document,vector,menu=export" "application/postscript"''']) # for xdg-open issues look here: http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg151818.html + # maybe use "bestApplication()" from https://github.com/jleclanche/python-mime # the MIME type is set for pdf6, because that one needs to be autodetectable by libmime - checkViewer('a PDF previewer', ['pdfview', 'kpdf', 'okular', 'qpdfview --unique', 'evince', 'kghostview', 'xpdf', 'SumatraPDF', 'acrobat', 'acroread', 'mupdf', \ - 'gv', 'ghostview', 'AcroRd32', 'gsview64', 'gsview32'], + checkViewer('a PDF previewer', + ['pdfview', 'kpdf', 'okular', 'qpdfview --unique', + 'evince', 'xreader', 'kghostview', 'xpdf', 'SumatraPDF', + 'acrobat', 'acroread', 'mupdf', + 'gv', 'ghostview', 'AcroRd32', 'gsview64', 'gsview32'], rc_entry = [r'''\Format pdf pdf "PDF (ps2pdf)" P "%%" "" "document,vector,menu=export" "" \Format pdf2 pdf "PDF (pdflatex)" F "%%" "" "document,vector,menu=export" "" \Format pdf3 pdf "PDF (dvipdfm)" m "%%" "" "document,vector,menu=export" "" @@ -673,7 +731,9 @@ def checkFormatEntries(dtl_tools): \Format pdf7 pdf "PDF (cropped)" "" "%%" "" "document,vector" "" \Format pdf8 pdf "PDF (lower resolution)" "" "%%" "" "document,vector" ""''']) # - checkViewer('a DVI previewer', ['xdvi', 'kdvi', 'okular', 'yap', 'dviout -Set=!m'], + checkViewer('a DVI previewer', ['xdvi', 'kdvi', 'okular', + 'evince', 'xreader', + 'yap', 'dviout -Set=!m'], rc_entry = [r'''\Format dvi dvi DVI D "%%" "" "document,vector,menu=export" "application/x-dvi" \Format dvi3 dvi "DVI (LuaTeX)" V "%%" "" "document,vector,menu=export" ""''']) if dtl_tools: @@ -707,14 +767,15 @@ def checkFormatEntries(dtl_tools): \Format lyx16x 16.lyx "LyX 1.6.x" "" "" "" "document" "" \Format lyx20x 20.lyx "LyX 2.0.x" "" "" "" "document" "" \Format lyx21x 21.lyx "LyX 2.1.x" "" "" "" "document" "" -\Format lyx22x 22.lyx "LyX 2.2.x" "" "" "" "document,menu=export" "" +\Format lyx22x 22.lyx "LyX 2.2.x" "" "" "" "document" "" +\Format lyx23x 23.lyx "LyX 2.3.x" "" "" "" "document,menu=export" "" \Format clyx cjklyx "CJK LyX 1.4.x (big5)" "" "" "" "document" "" \Format jlyx cjklyx "CJK LyX 1.4.x (euc-jp)" "" "" "" "document" "" \Format klyx cjklyx "CJK LyX 1.4.x (euc-kr)" "" "" "" "document" "" \Format lyxpreview lyxpreview "LyX Preview" "" "" "" "" "" -\Format pdftex pdftex_t PDFTEX "" "" "" "" "" +\Format pdftex "pdftex_t, pdf_tex" PDFTEX "" "" "" "" "" \Format program "" Program "" "" "" "" "" -\Format pstex pstex_t PSTEX "" "" "" "" "" +\Format pstex "pstex_t, ps_tex" PSTEX "" "" "" "" "" \Format wmf wmf "Windows Metafile" "" "" "" "vector" "image/x-wmf" \Format emf emf "Enhanced Metafile" "" "" "" "vector" "image/x-emf" \Format wordhtml "html, htm" "HTML (MS Word)" "" "" "" "document" "" @@ -724,10 +785,10 @@ def checkFormatEntries(dtl_tools): def checkConverterEntries(): ''' Check all converters (\converter entries) ''' checkProg('the pdflatex program', ['pdflatex $$i'], - rc_entry = [ r'\converter pdflatex pdf2 "%%" "latex=pdflatex"' ]) + rc_entry = [ r'\converter pdflatex pdf2 "%%" "latex=pdflatex,hyperref-driver=pdftex"' ]) checkProg('XeTeX', ['xelatex $$i'], - rc_entry = [ r'\converter xetex pdf4 "%%" "latex=xelatex"' ]) + rc_entry = [ r'\converter xetex pdf4 "%%" "latex=xelatex,hyperref-driver=xetex"' ]) checkLuatex() @@ -745,7 +806,7 @@ def checkConverterEntries(): in_binary_dir = os.path.join(lyx_binary_dir, 'tex2lyx') in_binary_dir = os.path.abspath(in_binary_dir).replace('\\', '/') - path, t2l = checkProg('a LaTeX/Noweb -> LyX converter', [in_binary_subdir, in_binary_subdir + version_suffix, in_binary_dir, in_binary_dir + version_suffix, 'tex2lyx' + version_suffix, 'tex2lyx'], + path, t2l = checkProg('a LaTeX/Noweb -> LyX converter', [quoteIfSpace(in_binary_subdir), quoteIfSpace(in_binary_subdir + version_suffix), quoteIfSpace(in_binary_dir), quoteIfSpace(in_binary_dir + version_suffix), 'tex2lyx' + version_suffix, 'tex2lyx'], rc_entry = [r'''\converter latex lyx "%% -f $$i $$o" "" \converter latexclipboard lyx "%% -fixedenc utf8 -f $$i $$o" "" \converter literate lyx "%% -n -m noweb -f $$i $$o" "" @@ -763,30 +824,34 @@ def checkConverterEntries(): \converter literate dviluatex "%%" ""''']) # checkProg('a Sweave -> LaTeX converter', ['Rscript --verbose --no-save --no-restore $$s/scripts/lyxsweave.R $$p$$i $$p$$o $$e $$r'], - rc_entry = [r'''\converter sweave latex "%%" "" -\converter sweave pdflatex "%%" "" -\converter sweave xetex "%%" "" -\converter sweave luatex "%%" "" -\converter sweave dviluatex "%%" ""''']) + rc_entry = [r'''\converter sweave latex "%%" "needauth" +\converter sweave pdflatex "%%" "needauth" +\converter sweave-ja platex "%%" "needauth" +\converter sweave xetex "%%" "needauth" +\converter sweave luatex "%%" "needauth" +\converter sweave dviluatex "%%" "needauth"''']) # checkProg('a knitr -> LaTeX converter', ['Rscript --verbose --no-save --no-restore $$s/scripts/lyxknitr.R $$p$$i $$p$$o $$e $$r'], - rc_entry = [r'''\converter knitr latex "%%" "" -\converter knitr pdflatex "%%" "" -\converter knitr xetex "%%" "" -\converter knitr luatex "%%" "" -\converter knitr dviluatex "%%" ""''']) + rc_entry = [r'''\converter knitr latex "%%" "needauth" +\converter knitr pdflatex "%%" "needauth" +\converter knitr-ja platex "%%" "needauth" +\converter knitr xetex "%%" "needauth" +\converter knitr luatex "%%" "needauth" +\converter knitr dviluatex "%%" "needauth"''']) # - checkProg('a Sweave -> R/S code converter', ['Rscript --verbose --no-save --no-restore $$s/scripts/lyxstangle.R $$i $$e $$r'], - rc_entry = [ r'\converter sweave r "%%" ""' ]) + checkProg('a Sweave -> R/S code converter', ['Rscript --verbose --no-save --no-restore $$s/scripts/lyxstangle.R $$i $$e $$r'], + rc_entry = [ r'\converter sweave r "%%" ""', + r'\converter sweave-ja r "%%" ""' ]) # checkProg('a knitr -> R/S code converter', ['Rscript --verbose --no-save --no-restore $$s/scripts/lyxknitr.R $$p$$i $$p$$o $$e $$r tangle'], - rc_entry = [ r'\converter knitr r "%%" ""' ]) + rc_entry = [ r'\converter knitr r "%%" ""', + r'\converter knitr-ja r "%%" ""' ]) # checkProg('an HTML -> LaTeX converter', ['html2latex $$i', 'gnuhtml2latex', 'htmltolatex -input $$i -output $$o', 'htmltolatex.jar -input $$i -output $$o'], - rc_entry = [ r'\converter html latex "%%" ""', \ - r'\converter html latex "python -tt $$s/scripts/html2latexwrapper.py %% $$i $$o" ""', \ - r'\converter html latex "%%" ""', \ + rc_entry = [ r'\converter html latex "%%" ""', + r'\converter html latex "python -tt $$s/scripts/html2latexwrapper.py %% $$i $$o" ""', + r'\converter html latex "%%" ""', r'\converter html latex "%%" ""', '' ]) # checkProg('an MS Word -> LaTeX converter', ['wvCleanLatex $$i $$o'], @@ -811,16 +876,16 @@ def checkConverterEntries(): else: # search for HTML converters other than eLyXer # On SuSE the scripts have a .sh suffix, and on debian they are in /usr/share/tex4ht/ - path, htmlconv = checkProg('a LaTeX -> HTML converter', ['htlatex $$i', 'htlatex.sh $$i', \ - '/usr/share/tex4ht/htlatex $$i', 'tth -t -e2 -L$$b < $$i > $$o', \ + path, htmlconv = checkProg('a LaTeX -> HTML converter', ['htlatex $$i', 'htlatex.sh $$i', + '/usr/share/tex4ht/htlatex $$i', 'tth -t -e2 -L$$b < $$i > $$o', 'latex2html -no_subdir -split 0 -show_section_numbers $$i', 'hevea -s $$i'], rc_entry = [ r'\converter latex html "%%" "needaux"' ]) if htmlconv.find('htlatex') >= 0 or htmlconv == 'latex2html': addToRC(r'''\copier html "python -tt $$s/scripts/ext_copy.py -e html,png,css $$i $$o"''') else: addToRC(r'''\copier html "python -tt $$s/scripts/ext_copy.py $$i $$o"''') - path, htmlconv = checkProg('a LaTeX -> HTML (MS Word) converter', ["htlatex $$i 'html,word' 'symbol/!' '-cvalidate'", \ - "htlatex.sh $$i 'html,word' 'symbol/!' '-cvalidate'", \ + path, htmlconv = checkProg('a LaTeX -> HTML (MS Word) converter', ["htlatex $$i 'html,word' 'symbol/!' '-cvalidate'", + "htlatex.sh $$i 'html,word' 'symbol/!' '-cvalidate'", "/usr/share/tex4ht/htlatex $$i 'html,word' 'symbol/!' '-cvalidate'"], rc_entry = [ r'\converter latex wordhtml "%%" "needaux"' ]) if htmlconv.find('htlatex') >= 0: @@ -873,9 +938,9 @@ def checkConverterEntries(): # checkProg('a RTF -> HTML converter', ['unrtf --html $$i > $$o'], rc_entry = [ r'\converter rtf html "%%" ""' ]) - # Do not define a converter to pdf6, ps is a pure export format + # Do not define a converter to pdf6, ps is a pure export format checkProg('a PS to PDF converter', ['ps2pdf $$i $$o'], - rc_entry = [ r'\converter ps pdf "%%" ""' ]) + rc_entry = [ r'\converter ps pdf "%%" "hyperref-driver=dvips"' ]) # checkProg('a PS to TXT converter', ['pstotext $$i > $$o'], rc_entry = [ r'\converter ps text2 "%%" ""' ]) @@ -897,6 +962,14 @@ def checkConverterEntries(): # Only define a converter from pdf6 for graphics checkProg('a PDF to EPS converter', ['pdftops -eps -f 1 -l 1 $$i $$o'], rc_entry = [ r'\converter pdf6 eps "%%" ""' ]) + # Define a converter from pdf6 to png for Macs where pdftops is missing. + # The converter utility sips allows to force the dimensions of the resulting + # png image. The value of 800 pixel for the width is arbitrary and not + # related to the current screen resolution or width. + # There is no converter parameter for this information. + checkProg('a PDF to PNG converter', + ['sips --resampleWidth 800 --setProperty format png $$i --out $$o'], + rc_entry = [ r'\converter pdf6 png "%%" ""' ]) # Create one converter for a PDF produced using TeX fonts and one for a # PDF produced using non-TeX fonts. This does not produce non-unique # conversion paths, since a given document either uses TeX fonts or not. @@ -917,13 +990,13 @@ def checkConverterEntries(): rc_entry = [ r'\converter dvi text4 "%%" ""' ]) # checkProg('a DVI to PS converter', ['dvips -o $$o $$i'], - rc_entry = [ r'\converter dvi ps "%%" ""' ]) + rc_entry = [ r'\converter dvi ps "%%" "hyperref-driver=dvips"' ]) # checkProg('a DVI to cropped EPS converter', ['dvips -E -o $$o $$i'], rc_entry = [ r'\converter dvi eps3 "%%" ""' ]) # - checkProg('a DVI to PDF converter', ['dvipdfmx -o $$o $$i', 'dvipdfm -o $$o $$i'], - rc_entry = [ r'\converter dvi pdf3 "%%" ""' ]) + checkProg('a DVI to PDF converter', ['dvipdfmx', 'dvipdfm'], + rc_entry = [ r'\converter dvi pdf3 "%% -o $$o $$i" "hyperref-driver=%%"' ]) # checkProg('a fax program', ['kdeprintfax $$i', 'ksendfax $$i', 'hylapex $$i'], rc_entry = [ r'\converter ps fax "%%" ""']) @@ -937,6 +1010,14 @@ def checkConverterEntries(): \converter fig pdftex "python -tt $$s/scripts/fig2pdftex.py $$i $$o" "" \converter fig pstex "python -tt $$s/scripts/fig2pstex.py $$i $$o" ""''') # + checkProg('a SVG -> PDFTeX converter', [inkscape_cl], + rc_entry = [ r'\converter svg pdftex "python -tt $$s/scripts/svg2pdftex.py %% $$p$$i $$p$$o" ""'], + path = [inkscape_path]) + # + checkProg('a SVG -> PSTeX converter', [inkscape_cl], + rc_entry = [ r'\converter svg pstex "python -tt $$s/scripts/svg2pstex.py %% $$p$$i $$p$$o" ""'], + path = [inkscape_path]) + # checkProg('a TIFF -> PS converter', ['tiff2ps $$i > $$o'], rc_entry = [ r'\converter tiff eps "%%" ""']) # @@ -946,16 +1027,16 @@ def checkConverterEntries(): \converter tgif png "tgif -print -color -png -o $$d $$i" "" \converter tgif pdf6 "tgif -print -color -pdf -stdout $$i > $$o" ""''']) # - checkProg('a WMF -> EPS converter', ['metafile2eps $$i $$o', 'wmf2eps -o $$o $$i', inkscape_name + ' --file=$$i --export-area-drawing --without-gui --export-eps=$$o'], + checkProg('a WMF -> EPS converter', ['metafile2eps $$i $$o', 'wmf2eps -o $$o $$i', inkscape_cl + ' --file=$$i --export-area-drawing --without-gui --export-eps=$$o'], rc_entry = [ r'\converter wmf eps "%%" ""']) # - checkProg('an EMF -> EPS converter', ['metafile2eps $$i $$o', 'wmf2eps -o $$o $$i', inkscape_name + ' --file=$$i --export-area-drawing --without-gui --export-eps=$$o'], + checkProg('an EMF -> EPS converter', ['metafile2eps $$i $$o', inkscape_cl + ' --file=$$i --export-area-drawing --without-gui --export-eps=$$o'], rc_entry = [ r'\converter emf eps "%%" ""']) # - checkProg('a WMF -> PDF converter', [inkscape_name + ' --file=$$i --export-area-drawing --without-gui --export-pdf=$$o'], + checkProg('a WMF -> PDF converter', [inkscape_cl + ' --file=$$i --export-area-drawing --without-gui --export-pdf=$$o'], rc_entry = [ r'\converter wmf pdf6 "%%" ""']) # - checkProg('an EMF -> PDF converter', [inkscape_name + ' --file=$$i --export-area-drawing --without-gui --export-pdf=$$o'], + checkProg('an EMF -> PDF converter', [inkscape_cl + ' --file=$$i --export-area-drawing --without-gui --export-pdf=$$o'], rc_entry = [ r'\converter emf pdf6 "%%" ""']) # Only define a converter to pdf6 for graphics checkProg('an EPS -> PDF converter', ['epstopdf'], @@ -991,7 +1072,7 @@ def checkConverterEntries(): # The eps2->eps converter then fixes the bounding box by cropping. # Although unoconv can convert to png and pdf as well, do not define # odg->png and odg->pdf converters, since the bb would be too large as well. - checkProg('an OpenDocument -> EPS converter', ['libreoffice -headless -nologo -convert-to eps $$i', 'unoconv -f eps --stdout $$i > $$o'], + checkProg('an OpenDocument -> EPS converter', ['libreoffice --headless --nologo --convert-to eps $$i', 'unoconv -f eps --stdout $$i > $$o'], rc_entry = [ r'\converter odg eps2 "%%" ""']) # checkProg('a SVG (compressed) -> SVG converter', ['gunzip -c $$i > $$o'], @@ -1001,21 +1082,24 @@ def checkConverterEntries(): rc_entry = [ r'\converter svg svgz "%%" ""']) # Only define a converter to pdf6 for graphics # Prefer rsvg-convert over inkscape since it is faster (see http://www.lyx.org/trac/ticket/9891) - checkProg('a SVG -> PDF converter', ['rsvg-convert -f pdf -o $$o $$i', inkscape_name + ' --file=$$i --export-area-drawing --without-gui --export-pdf=$$o'], + checkProg('a SVG -> PDF converter', ['rsvg-convert -f pdf -o $$o $$i', inkscape_cl + ' --file=$$i --export-area-drawing --without-gui --export-pdf=$$o'], rc_entry = [ r'''\converter svg pdf6 "%%" "" \converter svgz pdf6 "%%" ""'''], path = ['', inkscape_path]) # - checkProg('a SVG -> EPS converter', ['rsvg-convert -f ps -o $$o $$i', inkscape_name + ' --file=$$i --export-area-drawing --without-gui --export-eps=$$o'], + checkProg('a SVG -> EPS converter', ['rsvg-convert -f ps -o $$o $$i', inkscape_cl + ' --file=$$i --export-area-drawing --without-gui --export-eps=$$o'], rc_entry = [ r'''\converter svg eps "%%" "" \converter svgz eps "%%" ""'''], path = ['', inkscape_path]) # - checkProg('a SVG -> PNG converter', ['rsvg-convert -f png -o $$o $$i', inkscape_name + ' --without-gui --file=$$i --export-png=$$o'], + checkProg('a SVG -> PNG converter', ['rsvg-convert -f png -o $$o $$i', inkscape_cl + ' --without-gui --file=$$i --export-png=$$o'], rc_entry = [ r'''\converter svg png "%%" "", \converter svgz png "%%" ""'''], path = ['', inkscape_path]) - + # + checkProg('Gnuplot', ['gnuplot'], + rc_entry = [ r'''\Format gnuplot "gp, gnuplot" "Gnuplot" "" "" "" "vector" "text/plain" +\converter gnuplot pdf6 "python -tt $$s/scripts/gnuplot2pdf.py $$i $$o" "needauth"''' ]) # # gnumeric/xls/ods to tex checkProg('a spreadsheet -> latex converter', ['ssconvert'], @@ -1030,7 +1114,7 @@ def checkConverterEntries(): ''']) path, lilypond = checkProg('a LilyPond -> EPS/PDF/PNG converter', ['lilypond']) - if (lilypond != ''): + if (lilypond): version_string = cmdOutput("lilypond --version") match = re.match('GNU LilyPond (\S+)', version_string) if match: @@ -1053,9 +1137,9 @@ def checkConverterEntries(): logger.info('+ found LilyPond, but could not extract version number.') # path, lilypond_book = checkProg('a LilyPond book (LaTeX) -> LaTeX converter', ['lilypond-book']) - if (lilypond_book != ''): + if (lilypond_book): version_string = cmdOutput("lilypond-book --version") - match = re.match('^(\S+)$', version_string) + match = re.match('(\S+)$', version_string) if match: version_number = match.groups()[0] version = version_number.split('.') @@ -1069,6 +1153,7 @@ def checkConverterEntries(): # this, use different output folders for eps and pdf outputs. addToRC(r'\converter lilypond-book latex "lilypond-book --safe --lily-output-dir=ly-eps $$i" ""') addToRC(r'\converter lilypond-book pdflatex "lilypond-book --safe --pdf --latex-program=pdflatex --lily-output-dir=ly-pdf $$i" ""') + addToRC(r'\converter lilypond-book-ja platex "lilypond-book --safe --pdf --latex-program=platex --lily-output-dir=ly-pdf $$i" ""') addToRC(r'\converter lilypond-book xetex "lilypond-book --safe --pdf --latex-program=xelatex --lily-output-dir=ly-pdf $$i" ""') addToRC(r'\converter lilypond-book luatex "lilypond-book --safe --pdf --latex-program=lualatex --lily-output-dir=ly-pdf $$i" ""') addToRC(r'\converter lilypond-book dviluatex "lilypond-book --safe --latex-program=dvilualatex --lily-output-dir=ly-eps $$i" ""') @@ -1108,6 +1193,7 @@ def checkConverterEntries(): \converter lyx lyx20x "python -tt $$s/lyx2lyx/lyx2lyx -V 2.0 -o $$o $$i" "" \converter lyx lyx21x "python -tt $$s/lyx2lyx/lyx2lyx -V 2.1 -o $$o $$i" "" \converter lyx lyx22x "python -tt $$s/lyx2lyx/lyx2lyx -V 2.2 -o $$o $$i" "" +\converter lyx lyx23x "python -tt $$s/lyx2lyx/lyx2lyx -V 2.3 -o $$o $$i" "" \converter lyx clyx "python -tt $$s/lyx2lyx/lyx2lyx -V 1.4 -o $$o -c big5 $$i" "" \converter lyx jlyx "python -tt $$s/lyx2lyx/lyx2lyx -V 1.4 -o $$o -c euc_jp $$i" "" \converter lyx klyx "python -tt $$s/lyx2lyx/lyx2lyx -V 1.4 -o $$o -c euc_kr $$i" "" @@ -1133,7 +1219,7 @@ def checkDocBook(): r'''\converter docbook dvi "" "" \converter docbook html "" ""''']) # - if DOCBOOK != '': + if DOCBOOK: return ('yes', 'true', '\\def\\hasdocbook{yes}') else: return ('no', 'false', '') @@ -1143,20 +1229,27 @@ def checkOtherEntries(): ''' entries other than Format and Converter ''' checkProg('ChkTeX', ['chktex -n1 -n3 -n6 -n9 -n22 -n25 -n30 -n38'], rc_entry = [ r'\chktex_command "%%"' ]) - checkProgAlternatives('BibTeX or alternative programs', ['bibtex', 'bibtex8', 'biber'], - rc_entry = [ r'\bibtex_command "%%"' ], + checkProgAlternatives('BibTeX or alternative programs', + ['bibtex', 'bibtex8', 'biber'], + rc_entry = [ r'\bibtex_command "automatic"' ], alt_rc_entry = [ r'\bibtex_alternatives "%%"' ]) - checkProg('a specific Japanese BibTeX variant', ['pbibtex', 'jbibtex', 'bibtex'], - rc_entry = [ r'\jbibtex_command "%%"' ]) - checkProgAlternatives('available index processors', ['texindy', 'makeindex -c -q', 'xindy'], + checkProgAlternatives('a specific Japanese BibTeX variant', + ['pbibtex', 'upbibtex', 'jbibtex', 'bibtex', 'biber'], + rc_entry = [ r'\jbibtex_command "automatic"' ], + alt_rc_entry = [ r'\jbibtex_alternatives "%%"' ]) + checkProgAlternatives('available index processors', + ['texindy', 'makeindex -c -q', 'xindy'], rc_entry = [ r'\index_command "%%"' ], alt_rc_entry = [ r'\index_alternatives "%%"' ]) - checkProg('an index processor appropriate to Japanese', ['mendex -c -q', 'jmakeindex -c -q', 'makeindex -c -q'], + checkProg('an index processor appropriate to Japanese', + ['mendex -c -q', 'jmakeindex -c -q', 'makeindex -c -q'], rc_entry = [ r'\jindex_command "%%"' ]) checkProg('the splitindex processor', ['splitindex.pl', 'splitindex', 'splitindex.class'], rc_entry = [ r'\splitindex_command "%%"' ]) checkProg('a nomenclature processor', ['makeindex'], rc_entry = [ r'\nomencl_command "makeindex -s nomencl.ist"' ]) + checkProg('a python-pygments driver command', ['pygmentize'], + rc_entry = [ r'\pygmentize_command "%%"' ]) ## FIXME: OCTAVE is not used anywhere # path, OCTAVE = checkProg('Octave', ['octave']) ## FIXME: MAPLE is not used anywhere @@ -1168,6 +1261,13 @@ def checkOtherEntries(): \copier program "python -tt $$s/scripts/ext_copy.py $$i $$o" ''') +def _checkForClassExtension(x): + '''if the extension for a latex class is not + provided, add .cls to the classname''' + if not '.' in x: + return x.strip() + '.cls' + else: + return x.strip() def processLayoutFile(file, bool_docbook): ''' process layout file and get a line of result @@ -1175,19 +1275,19 @@ def processLayoutFile(file, bool_docbook): Declare lines look like this: \DeclareLaTeXClass[]{} - + Optionally, a \DeclareCategory line follows: - + \DeclareCategory{} - + So for example (article.layout, scrbook.layout, svjog.layout) - + \DeclareLaTeXClass{article} \DeclareCategory{Articles} - + \DeclareLaTeXClass[scrbook]{book (koma-script)} \DeclareCategory{Books} - + \DeclareLaTeXClass[svjour,svjog.clo]{article (Springer - svjour/jog)} we'd expect this output: @@ -1196,42 +1296,36 @@ def processLayoutFile(file, bool_docbook): "scrbook" "scrbook" "book (koma-script)" "false" "scrbook.cls" "Books" "svjog" "svjour" "article (Springer - svjour/jog)" "false" "svjour.cls,svjog.clo" "" ''' - def checkForClassExtension(x): - '''if the extension for a latex class is not - provided, add .cls to the classname''' - if not '.' in x: - return x.strip() + '.cls' - else: - return x.strip() classname = file.split(os.sep)[-1].split('.')[0] # return ('LaTeX', '[a,b]', 'a', ',b,c', 'article') for \DeclareLaTeXClass[a,b,c]{article} - p = re.compile(r'^\s*#\s*\\Declare(LaTeX|DocBook)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)}\s*$') - q = re.compile(r'^\s*#\s*\\DeclareCategory{(.*)}\s*$') + p = re.compile('\s*#\s*\\\\Declare(LaTeX|DocBook)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)}\s*$') + q = re.compile('\s*#\s*\\\\DeclareCategory{(.*)}\s*$') classdeclaration = "" categorydeclaration = '""' - for line in open(file).readlines(): - res = p.search(line) - qres = q.search(line) + for line in open(file, 'r', encoding='utf8').readlines(): + res = p.match(line) + qres = q.match(line) if res != None: (classtype, optAll, opt, opt1, desc) = res.groups() - avai = {'LaTeX':'false', 'DocBook':bool_docbook}[classtype] + avai = {'LaTeX': 'false', 'DocBook': bool_docbook}[classtype] if opt == None: opt = classname - prereq_latex = checkForClassExtension(classname) + prereq_latex = _checkForClassExtension(classname) else: prereq_list = optAll[1:-1].split(',') - prereq_list = list(map(checkForClassExtension, prereq_list)) + prereq_list = list(map(_checkForClassExtension, prereq_list)) prereq_latex = ','.join(prereq_list) prereq_docbook = {'true':'', 'false':'docbook'}[bool_docbook] prereq = {'LaTeX':prereq_latex, 'DocBook':prereq_docbook}[classtype] - classdeclaration = '"%s" "%s" "%s" "%s" "%s"' % (classname, opt, desc, avai, prereq) + classdeclaration = ('"%s" "%s" "%s" "%s" "%s"' + % (classname, opt, desc, avai, prereq)) if categorydeclaration != '""': return classdeclaration + " " + categorydeclaration if qres != None: categorydeclaration = '"%s"' % (qres.groups()[0]) - if classdeclaration != "": + if classdeclaration: return classdeclaration + " " + categorydeclaration - if classdeclaration != "": + if classdeclaration: return classdeclaration + " " + categorydeclaration logger.warning("Layout file " + file + " has no \DeclareXXClass line. ") return "" @@ -1252,7 +1346,7 @@ def checkLatexConfig(check_config, bool_docbook): # fails, we still have something to start lyx. logger.info(msg + ' default values') logger.info('+checking list of textclasses... ') - tx = open('textclass.lst', 'w') + tx = open('textclass.lst', 'w', encoding='utf8') tx.write(''' # This file declares layouts and their associated definition files # (include dir. relative to the place where this file is). @@ -1263,28 +1357,27 @@ def checkLatexConfig(check_config, bool_docbook): # build the list of available layout files and convert it to commands # for chkconfig.ltx foundClasses = [] - for file in glob.glob( os.path.join('layouts', '*.layout') ) + \ - glob.glob( os.path.join(srcdir, 'layouts', '*.layout' ) ) : + for file in (glob.glob(os.path.join('layouts', '*.layout')) + + glob.glob(os.path.join(srcdir, 'layouts', '*.layout'))): # valid file? if not os.path.isfile(file): continue # get stuff between /xxxx.layout . classname = file.split(os.sep)[-1].split('.')[0] # tr ' -' '__'` - cleanclass = classname.replace(' ', '_') - cleanclass = cleanclass.replace('-', '_') + cleanclass = classname.replace(' ', '_').replace('-', '_') # make sure the same class is not considered twice if foundClasses.count(cleanclass) == 0: # not found before foundClasses.append(cleanclass) retval = processLayoutFile(file, bool_docbook) - if retval != "": - tx.write(retval) + if retval: + tx.write(retval + os.linesep) tx.close() logger.info('\tdone') if not os.path.isfile('packages.lst') or not check_config: logger.info('+generating default list of packages... ') removeFiles(['packages.lst']) - tx = open('packages.lst', 'w') + tx = open('packages.lst', 'w', encoding='utf8') tx.close() logger.info('\tdone') if not check_config: @@ -1301,30 +1394,32 @@ def checkLatexConfig(check_config, bool_docbook): # Construct the list of classes to test for. # build the list of available layout files and convert it to commands # for chkconfig.ltx - declare = re.compile(r'^\s*#\s*\\Declare(LaTeX|DocBook)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)}\s*$') - category = re.compile(r'^\s*#\s*\\DeclareCategory{(.*)}\s*$') - empty = re.compile(r'^\s*$') + declare = re.compile('\\s*#\\s*\\\\Declare(LaTeX|DocBook)Class\\s*(\[([^,]*)(,.*)*\])*\\s*{(.*)}\\s*$') + category = re.compile('\\s*#\\s*\\\\DeclareCategory{(.*)}\\s*$') + empty = re.compile('\\s*$') testclasses = list() - for file in glob.glob( os.path.join('layouts', '*.layout') ) + \ - glob.glob( os.path.join(srcdir, 'layouts', '*.layout' ) ) : + for file in (glob.glob( os.path.join('layouts', '*.layout') ) + + glob.glob( os.path.join(srcdir, 'layouts', '*.layout' ) ) ): nodeclaration = False if not os.path.isfile(file): continue classname = file.split(os.sep)[-1].split('.')[0] decline = "" catline = "" - for line in open(file).readlines(): - if not empty.match(line) and line[0] != '#': + for line in open(file, 'r', encoding='utf8').readlines(): + if not empty.match(line) and line[0] != '#'[0]: if decline == "": - logger.warning("Failed to find valid \Declare line for layout file `" + file + "'.\n\t=> Skipping this file!") + logger.warning("Failed to find valid \Declare line " + "for layout file `%s'.\n\t=> Skipping this file!" % file) nodeclaration = True # A class, but no category declaration. Just break. break - if declare.search(line) != None: + if declare.match(line) != None: decline = "\\TestDocClass{%s}{%s}" % (classname, line[1:].strip()) testclasses.append(decline) - elif category.search(line) != None: - catline = "\\DeclareCategory{%s}{%s}" % (classname, category.search(line).groups()[0]) + elif category.match(line) != None: + catline = ("\\DeclareCategory{%s}{%s}" + % (classname, category.match(line).groups()[0])) testclasses.append(catline) if catline == "" or decline == "": continue @@ -1332,7 +1427,7 @@ def checkLatexConfig(check_config, bool_docbook): if nodeclaration: continue testclasses.sort() - cl = open('chklayouts.tex', 'w') + cl = open('chklayouts.tex', 'w', encoding='utf8') for line in testclasses: cl.write(line + '\n') cl.close() @@ -1343,7 +1438,7 @@ def checkLatexConfig(check_config, bool_docbook): line = latex_out.readline() if not line: break; - if re.match('^\+', line): + if line.startswith('+'): logger.info(line.strip()) # if the command succeeds, None will be returned ret = latex_out.close() @@ -1352,22 +1447,19 @@ def checkLatexConfig(check_config, bool_docbook): if rmcopy: removeFiles( [ 'chkconfig.ltx' ] ) # - # currently, values in chkconfig are only used to set - # \font_encoding - values = {} - for line in open('chkconfig.vars').readlines(): - key, val = re.sub('-', '_', line).split('=') - val = val.strip() - values[key] = val.strip("'") - # chk_fontenc may not exist - try: - addToRC(r'\font_encoding "%s"' % values["chk_fontenc"]) - except: - pass + # values in chkconfig were only used to set + # \font_encoding, which is obsolete +# values = {} +# for line in open('chkconfig.vars').readlines(): +# key, val = re.sub('-', '_', line).split('=') +# val = val.strip() +# values[key] = val.strip("'") # if configure successed, move textclass.lst.tmp to textclass.lst # and packages.lst.tmp to packages.lst - if os.path.isfile('textclass.lst.tmp') and len(open('textclass.lst.tmp').read()) > 0 \ - and os.path.isfile('packages.lst.tmp') and len(open('packages.lst.tmp').read()) > 0: + if (os.path.isfile('textclass.lst.tmp') + and len(open('textclass.lst.tmp', encoding='utf8').read()) > 0 + and os.path.isfile('packages.lst.tmp') + and len(open('packages.lst.tmp', encoding='utf8').read()) > 0): shutil.move('textclass.lst.tmp', 'textclass.lst') shutil.move('packages.lst.tmp', 'packages.lst') return ret @@ -1377,20 +1469,20 @@ def checkModulesConfig(): removeFiles(['lyxmodules.lst', 'chkmodules.tex']) logger.info('+checking list of modules... ') - tx = open('lyxmodules.lst', 'w') + tx = open('lyxmodules.lst', 'w', encoding='utf8') tx.write('''## This file declares modules and their associated definition files. ## It has been automatically generated by configure ## Use "Options/Reconfigure" if you need to update it after a ## configuration change. -## "ModuleName" "filename" "Description" "Packages" "Requires" "Excludes" "Category" +## "ModuleName" "filename" "Description" "Packages" "Requires" "Excludes" "Category" "Local" ''') # build the list of available modules seen = [] # note that this searches the local directory first, then the # system directory. that way, we pick up the user's version first. - for file in glob.glob( os.path.join('layouts', '*.module') ) + \ - glob.glob( os.path.join(srcdir, 'layouts', '*.module' ) ) : + for file in (glob.glob( os.path.join('layouts', '*.module') ) + + glob.glob( os.path.join(srcdir, 'layouts', '*.module' ) ) ): # valid file? logger.info(file) if not os.path.isfile(file): @@ -1403,7 +1495,7 @@ def checkModulesConfig(): seen.append(filename) retval = processModuleFile(file, filename, bool_docbook) - if retval != "": + if retval: tx.write(retval) tx.close() logger.info('\tdone') @@ -1424,20 +1516,20 @@ def processModuleFile(file, filename, bool_docbook): We expect output: "ModuleName" "filename" "Description" "Packages" "Requires" "Excludes" "Category" ''' - remods = re.compile(r'\DeclareLyXModule\s*(?:\[([^]]*?)\])?{(.*)}') - rereqs = re.compile(r'#+\s*Requires: (.*)') - reexcs = re.compile(r'#+\s*Excludes: (.*)') - recaty = re.compile(r'#+\s*Category: (.*)') - redbeg = re.compile(r'#+\s*DescriptionBegin\s*$') - redend = re.compile(r'#+\s*DescriptionEnd\s*$') + remods = re.compile('\s*#\s*\\\\DeclareLyXModule\s*(?:\[([^]]*?)\])?{(.*)}') + rereqs = re.compile('\s*#+\s*Requires: (.*)') + reexcs = re.compile('\s*#+\s*Excludes: (.*)') + recaty = re.compile('\\s*#\\s*\\\\DeclareCategory{(.*)}\\s*$') + redbeg = re.compile('\s*#+\s*DescriptionBegin\s*$') + redend = re.compile('\s*#+\s*DescriptionEnd\s*$') modname = desc = pkgs = req = excl = catgy = "" readingDescription = False descLines = [] - for line in open(file).readlines(): + for line in open(file, 'r', encoding='utf8').readlines(): if readingDescription: - res = redend.search(line) + res = redend.match(line) if res != None: readingDescription = False desc = " ".join(descLines) @@ -1446,11 +1538,11 @@ def processModuleFile(file, filename, bool_docbook): continue descLines.append(line[1:].strip()) continue - res = redbeg.search(line) + res = redbeg.match(line) if res != None: readingDescription = True continue - res = remods.search(line) + res = remods.match(line) if res != None: (pkgs, modname) = res.groups() if pkgs == None: @@ -1459,19 +1551,19 @@ def processModuleFile(file, filename, bool_docbook): tmp = [s.strip() for s in pkgs.split(",")] pkgs = ",".join(tmp) continue - res = rereqs.search(line) + res = rereqs.match(line) if res != None: req = res.group(1) tmp = [s.strip() for s in req.split("|")] req = "|".join(tmp) continue - res = reexcs.search(line) + res = reexcs.match(line) if res != None: excl = res.group(1) tmp = [s.strip() for s in excl.split("|")] excl = "|".join(tmp) continue - res = recaty.search(line) + res = recaty.match(line) if res != None: catgy = res.group(1) continue @@ -1480,7 +1572,7 @@ def processModuleFile(file, filename, bool_docbook): logger.warning("Module file without \DeclareLyXModule line. ") return "" - if pkgs != "": + if pkgs: # this module has some latex dependencies: # append the dependencies to chkmodules.tex, # which is \input'ed by chkconfig.ltx @@ -1491,13 +1583,170 @@ def processModuleFile(file, filename, bool_docbook): continue if pkg.endswith(".sty"): pkg = pkg[:-4] - testpackages.append("\\TestPackage{%s}" % (pkg,)) - cm = open('chkmodules.tex', 'a') + testpackages.append("\\TestPackage{%s}" % pkg) + cm = open('chkmodules.tex', 'a', encoding='utf8') for line in testpackages: cm.write(line + '\n') cm.close() - return '"%s" "%s" "%s" "%s" "%s" "%s" "%s"\n' % (modname, filename, desc, pkgs, req, excl, catgy) + local = "true" + if (file.startswith(srcdir)): + local = "false" + return ('"%s" "%s" "%s" "%s" "%s" "%s" "%s" "%s"\n' + % (modname, filename, desc, pkgs, req, excl, catgy, local)) + + +def checkCiteEnginesConfig(): + removeFiles(['lyxciteengines.lst', 'chkciteengines.tex']) + + logger.info('+checking list of cite engines... ') + tx = open('lyxciteengines.lst', 'w', encoding='utf8') + tx.write('''## This file declares cite engines and their associated definition files. +## It has been automatically generated by configure +## Use "Options/Reconfigure" if you need to update it after a +## configuration change. +## "CiteEngineName" "filename" "CiteEngineType" "CiteFramework" "DefaultBiblio" "Description" "Packages" +''') + + # build the list of available modules + seen = [] + # note that this searches the local directory first, then the + # system directory. that way, we pick up the user's version first. + for file in glob.glob( os.path.join('citeengines', '*.citeengine') ) + \ + glob.glob( os.path.join(srcdir, 'citeengines', '*.citeengine' ) ) : + # valid file? + logger.info(file) + if not os.path.isfile(file): + continue + + filename = file.split(os.sep)[-1] + filename = filename[:-11] + if seen.count(filename): + continue + + seen.append(filename) + retval = processCiteEngineFile(file, filename, bool_docbook) + if retval: + tx.write(retval) + tx.close() + logger.info('\tdone') + + +def processCiteEngineFile(file, filename, bool_docbook): + ''' process cite engines file and get a line of result + + The top of a cite engine file should look like this: + #\DeclareLyXCiteEngine[LaTeX Packages]{CiteEngineName} + #DescriptionBegin + #...body of description... + #DescriptionEnd + We expect output: + "CiteEngineName" "filename" "CiteEngineType" "CiteFramework" "DefaultBiblio" "Description" "Packages" + ''' + remods = re.compile('\s*#\s*\\\\DeclareLyXCiteEngine\s*(?:\[([^]]*?)\])?{(.*)}') + redbeg = re.compile('\s*#+\s*DescriptionBegin\s*$') + redend = re.compile('\s*#+\s*DescriptionEnd\s*$') + recet = re.compile('\s*CiteEngineType\s*(.*)') + redb = re.compile('\s*DefaultBiblio\s*(.*)') + resfm = re.compile('\s*CiteFramework\s*(.*)') + + modname = desc = pkgs = cet = db = cfm = "" + readingDescription = False + descLines = [] + + for line in open(file, 'r', encoding='utf8').readlines(): + if readingDescription: + res = redend.match(line) + if res != None: + readingDescription = False + desc = " ".join(descLines) + # Escape quotes. + desc = desc.replace('"', '\\"') + continue + descLines.append(line[1:].strip()) + continue + res = redbeg.match(line) + if res != None: + readingDescription = True + continue + res = remods.match(line) + if res != None: + (pkgs, modname) = res.groups() + if pkgs == None: + pkgs = "" + else: + tmp = [s.strip() for s in pkgs.split(",")] + pkgs = ",".join(tmp) + continue + res = recet.match(line) + if res != None: + cet = res.group(1) + continue + res = redb.match(line) + if res != None: + db = res.group(1) + continue + res = resfm.match(line) + if res != None: + cfm = res.group(1) + continue + + if modname == "": + logger.warning("Cite Engine File file without \DeclareLyXCiteEngine line. ") + return "" + + if pkgs: + # this cite engine has some latex dependencies: + # append the dependencies to chkciteengines.tex, + # which is \input'ed by chkconfig.ltx + testpackages = list() + for pkg in pkgs.split(","): + if "->" in pkg: + # this is a converter dependency: skip + continue + if pkg.endswith(".sty"): + pkg = pkg[:-4] + testpackages.append("\\TestPackage{%s}" % pkg) + cm = open('chkciteengines.tex', 'a', encoding='utf8') + for line in testpackages: + cm.write(line + '\n') + cm.close() + + return ('"%s" "%s" "%s" "%s" "%s" "%s" "%s"\n' + % (modname, filename, cet, cfm, db, desc, pkgs)) + + +def checkXTemplates(): + removeFiles(['xtemplates.lst']) + + logger.info('+checking list of external templates... ') + tx = open('xtemplates.lst', 'w', encoding='utf8') + tx.write('''## This file lists external templates. +## It has been automatically generated by configure +## Use "Options/Reconfigure" if you need to update it after a +## configuration change. +''') + + # build the list of available templates + seen = [] + # note that this searches the local directory first, then the + # system directory. that way, we pick up the user's version first. + for file in glob.glob( os.path.join('xtemplates', '*.xtemplate') ) + \ + glob.glob( os.path.join(srcdir, 'xtemplates', '*.xtemplate' ) ) : + # valid file? + logger.info(file) + if not os.path.isfile(file): + continue + + filename = file.split(os.sep)[-1] + if seen.count(filename): + continue + + seen.append(filename) + if filename: + tx.write(filename + "\n") + tx.close() + logger.info('\tdone') def checkTeXAllowSpaces(): @@ -1506,7 +1755,7 @@ def checkTeXAllowSpaces(): if lyx_check_config: msg = "Checking whether TeX allows spaces in file names... " writeToFile('a b.tex', r'\message{working^^J}' ) - if LATEX != '': + if LATEX: if os.name == 'nt' or sys.platform == 'cygwin': latex_out = cmdOutput(LATEX + r""" "\nonstopmode\input{\"a b\"}\makeatletter\@@end" """) else: @@ -1526,13 +1775,14 @@ def checkTeXAllowSpaces(): def rescanTeXFiles(): ''' Run kpsewhich to update information about TeX files ''' logger.info("+Indexing TeX files... ") - if not os.path.isfile( os.path.join(srcdir, 'scripts', 'TeXFiles.py') ): + tfscript = os.path.join(srcdir, 'scripts', 'TeXFiles.py') + if not os.path.isfile(tfscript): logger.error("configure: error: cannot find TeXFiles.py script") sys.exit(1) interpreter = sys.executable if interpreter == '': interpreter = "python" - tfp = cmdOutput(interpreter + " -tt " + '"' + os.path.join(srcdir, 'scripts', 'TeXFiles.py') + '"') + tfp = cmdOutput('"%s" -tt "%s"' % (interpreter, tfscript)) logger.info(tfp) logger.info("\tdone") @@ -1541,15 +1791,15 @@ def removeTempFiles(): # Final clean-up if not lyx_keep_temps: removeFiles(['chkconfig.vars', 'chklatex.ltx', 'chklatex.log', - 'chklayouts.tex', 'chkmodules.tex', 'missfont.log', - 'wrap_chkconfig.ltx', 'wrap_chkconfig.log']) + 'chklayouts.tex', 'chkmodules.tex', 'chkciteengines.tex', + 'missfont.log', 'wrap_chkconfig.ltx', 'wrap_chkconfig.log']) if __name__ == '__main__': lyx_check_config = True lyx_kpsewhich = True outfile = 'lyxrc.defaults' - lyxrc_fileformat = 19 + lyxrc_fileformat = 29 rc_entries = '' lyx_keep_temps = False version_suffix = '' @@ -1609,20 +1859,27 @@ Format %i # check java and perl before any checkProg that may require them java = checkProg('a java interpreter', ['java'])[1] perl = checkProg('a perl interpreter', ['perl'])[1] - (inkscape_path, inkscape_name) = os.path.split(checkInkscape()) + (inkscape_path, inkscape_gui) = os.path.split(checkInkscape()) + # On Windows, we need to call the "inkscape.com" wrapper + # for command line purposes. Other OSes do not differentiate. + inkscape_cl = inkscape_gui + if os.name == 'nt': + inkscape_cl = inkscape_gui.replace('.exe', '.com') checkFormatEntries(dtl_tools) checkConverterEntries() (chk_docbook, bool_docbook, docbook_cmd) = checkDocBook() checkTeXAllowSpaces() windows_style_tex_paths = checkTeXPaths() - if windows_style_tex_paths != '': + if windows_style_tex_paths: addToRC(r'\tex_expects_windows_paths %s' % windows_style_tex_paths) checkOtherEntries() if lyx_kpsewhich: rescanTeXFiles() checkModulesConfig() + checkCiteEnginesConfig() + checkXTemplates() # --without-latex-config can disable lyx_check_config - ret = checkLatexConfig(lyx_check_config and LATEX != '', bool_docbook) + ret = checkLatexConfig(lyx_check_config and LATEX, bool_docbook) removeTempFiles() # The return error code can be 256. Because most systems expect an error code # in the range 0-127, 256 can be interpretted as 'success'. Because we expect