Module Gnumed.pycommon.gmTex

GNUmed LaTeX definitions and helpers.

Functions

def compile_latex_to_pdf(latex_filename: str = None, verbose: bool = False, is_sandboxed: bool = False) ‑> str
Expand source code
def compile_latex_to_pdf(latex_filename:str=None, verbose:bool=False, is_sandboxed:bool=False) -> str:
        """Compile LaTeX code to PDF using xelatex or pdflatex.

        Args:
                is_sandboxed: whether or not already sandboxed (no need to create a sandbox for compiling)

        Returns:
                Name of resulting PDF, or None on failure.
        """
        xelatex_avail = __detect_xelatex()
        __detect_pdflatex()
        if not (xelatex_avail or __pdflatex_executable):
                _log.error('neither xelatex nor pdflatex found, LaTeX not usable')
                return None

        if is_sandboxed:
                sandbox_dir = os.path.split(latex_filename)[0]
        else:
                sandbox_dir = mk_sandbox_dir(prefix = fname_stem(latex_filename) + '_')
                shutil.copy(latex_filename, sandbox_dir)
                latex_filename = os.path.join(sandbox_dir, os.path.split(latex_filename)[1])
        _log.debug('LaTeX sandbox directory: [%s]', sandbox_dir)
        if xelatex_avail:
                pdf_name = __compile_with_xelatex(sandbox_dir = sandbox_dir, latex_filename = latex_filename)
                if pdf_name is not None:
                        return pdf_name

                _log.error('issue compiling with xelatex, trying with pdflatex')
        pdf_name = __compile_with_pdflatex(sandbox_dir = sandbox_dir, latex_filename = latex_filename)
        if pdf_name is not None:
                return pdf_name

        _log.error('issue compiling with pdflatex, too')
        return None

Compile LaTeX code to PDF using xelatex or pdflatex.

Args
-----=
is_sandboxed
whether or not already sandboxed (no need to create a sandbox for compiling)

Returns -----= Name of resulting PDF, or None on failure.

def require_package(package: str = None) ‑> str
Expand source code
def require_package(package:str=None) -> str:
        return _LATEX__require_pkg_code % {'pkg': package}
def rst2latex_snippet(rst_text)
Expand source code
def rst2latex_snippet(rst_text):
        global du_core
        if du_core is None:
                try:
                        from docutils import core as du_core
                except ImportError:
                        _log.warning('cannot turn ReST into LaTeX: docutils not installed')
                        return tex_escape_string(text = rst_text)

        parts = du_core.publish_parts (
                source = rst_text.replace('\\', '\\\\'),
                source_path = '<internal>',
                writer_name = 'latex',
                #destination_path = '/path/to/LaTeX-template/for/calculating/relative/links/template.tex',
                settings_overrides = {
                        'input_encoding': 'unicode'             # un-encoded unicode
                },
                enable_exit_status = True                       # how to use ?
        )
        return parts['body']
def tex_escape_string(text: str = None,
replace_known_unicode: bool = True,
replace_eol: bool = False,
keep_visual_eol: bool = False,
strip_whitespace: bool = True) ‑> str
Expand source code
def tex_escape_string(text:str=None, replace_known_unicode:bool=True, replace_eol:bool=False, keep_visual_eol:bool=False, strip_whitespace:bool=True) -> str:
        r"""Check for special TeX characters and transform them.

        Args:
                text: plain (unicode) text to escape for LaTeX processing,
                        note that any valid LaTeX code contained within will be
                        escaped, too
                replace_eol: replaces "\n" with "\newline{}", careful with that, does not do what it seems
                keep_visual_eol: replaces "\n" with "\newline{}%\n" such that
                        both LaTeX will know to place a line break
                        at this point as well as the visual formatting
                        is preserved in the LaTeX source (think multi-
                        row table cells)
                strip_whitespace: whether to remove surrounding whitespace

        Returns:
                A hopefully properly escaped string palatable to LaTeX.
        """
        # must happen first
        text = text.replace('{', '-----{{{{{-----')
        text = text.replace('}', '-----}}}}}-----')

        text = text.replace('\\', r'\textbackslash{}')                  # requires \usepackage{textcomp} in LaTeX source

        text = text.replace('-----{{{{{-----', r'\{{}')
        text = text.replace('-----}}}}}-----', r'\}{}')

        text = text.replace('^', r'\textasciicircum{}')
        text = text.replace('~', r'\textasciitilde{}')

        text = text.replace('%', r'\%{}')
        text = text.replace('&', r'\&{}')
        text = text.replace('#', r'\#{}')
        text = text.replace('$', r'\${}')
        text = text.replace('_', r'\_{}')
        if replace_eol:
                if keep_visual_eol:
                        text = text.replace('\n', '\\newline{}%\n')
                else:
                        text = text.replace('\n', '\\newline{}')

        if replace_known_unicode:
                # this should NOT be replaced for Xe(La)Tex
                text = text.replace(u_euro, r'\euro{}')         # requires \usepackage[official]{eurosym} in LaTeX source
                text = text.replace(u_sum, r'$\Sigma$')

        if strip_whitespace:
                return text.strip()

        return text

Check for special TeX characters and transform them.

Args
-----=
text
plain (unicode) text to escape for LaTeX processing, note that any valid LaTeX code contained within will be escaped, too
replace_eol
replaces "\n" with "\newline{}", careful with that, does not do what it seems
keep_visual_eol
replaces "\n" with "\newline{}%\n" such that both LaTeX will know to place a line break at this point as well as the visual formatting is preserved in the LaTeX source (think multi- row table cells)
strip_whitespace
whether to remove surrounding whitespace

Returns -----= A hopefully properly escaped string palatable to LaTeX.

def wrap_usepackage_cmd(filename: str = None) ‑> str
Expand source code
def wrap_usepackage_cmd(filename:str=None) -> str:
        r"""Replaces \usepackage with \gmcheckandloadpkg in <latex_file>.

        Only one \usepackage per line and only at start of lines.

        Args:
                filename: name of file to process

        Returns:
                Name of processed file.
        """
        output_filename = '%s.safe-usepkg.tex' % fname_stem_with_path(filename)
        _log.debug(' [%s] -> [%s]', filename, output_filename)
        input_file = open(filename, mode = 'rt', encoding = 'utf-8-sig')
        output_file = open(output_filename, mode = 'wt', encoding = 'utf8')
        gmcheckandloadpkg_defined = False
        for line in input_file:
                if not line.lstrip().startswith(r'\usepackage'):
                        output_file.write(line)
                        continue
                if not gmcheckandloadpkg_defined:
                        output_file.write(_LATEX__define_gmcheckandloadpkg_cmd)
                        gmcheckandloadpkg_defined = True
                pkg_name = _REGEX_LaTeX__usepackage__name.findall(line)[0]
                pkg_name = pkg_name.strip('{}')
                parts = line.split('%', 1)
                usepackage_cmd = parts[0].strip()
                comment = '\n'
                if len(parts) > 1:
                        comment = '\t\t%%%s' % parts[1]
                _log.debug(r'wrapping [%s] found', usepackage_cmd)
                output_file.write(r'\gmcheckandloadpkg{%s.sty}{%s}%s' % (pkg_name, usepackage_cmd, comment))
        output_file.close()
        input_file.close()
        return output_filename

Replaces \usepackage with \gmcheckandloadpkg in .

Only one \usepackage per line and only at start of lines.

Args
-----=
filename
name of file to process

Returns -----= Name of processed file.

def xetex_escape_string(text=None)
Expand source code
def xetex_escape_string(text=None):
        # a web search did not reveal anything else for Xe(La)Tex
        # as opposed to LaTeX, except true unicode chars
        return tex_escape_string(text = text, replace_known_unicode = False)