使用源代码“美化”投影仪演示文稿的资源?

使用源代码“美化”投影仪演示文稿的资源?

我正在考虑使用 beamer 进行我即将进行的(幻灯片)演示,其中涉及大量源代码(幻灯片之间需要展开、修改、突出显示源代码片段等)。我之前看过 beamer 教程,但还没有真正用过。

知道我可以使用 listings 或 minted 在幻灯片上排版代码片段,但坦率地说,结果有点丑陋。我希望包含代码的框看起来更“漂亮”、“更时尚”或“更精致”,如果你愿意的话:

  • 字体、线条和颜色与 beamer 主题相匹配(或许是补充);
  • 关于矩形边距、圆角、阴影、透明度等设置的令人满意的组合。
  • 行号看起来不再像是事后才想到的;
  • 支持突出显示部分代码
  • 支持代码部分灰显

...或许还有其他养眼的东西。

某些主题或软件包中是否有类似的东西?如果没有,也许某些演示模板中也有?如果甚至都没有 - 也许某些具体的演示文档中也有,我可以对其进行调整?

PS-如果使用除投影仪之外的其他工具更容易实现这一点,请在评论中说明。

答案1

经过几天的研究,我终于找到了解决您大部分问题的可行方案。所以,请做好准备,因为它涉及很多技巧,而且看起来有点(太)长。解决方案涉及以下修改:

  • 重写LatexEmbeddedLexerinpygments以便它支持任何地方的转义(包括字符串和注释)和我们的自定义转义序列。
  • 重写LatexFormatter以便pygments动态生成样式并支持突出显示,灰化。

关于列表的外观

tcolorbox可以使用提供环境的软件包进行大量外观定制tcblisting。如软件包手册中所示,可以自定义列表块边框、背景颜色、边距样式、阴影、透明度等。调整参数以使其符合您喜欢的beamer主题非常容易。它还支持与 的集成minted,使用pygmentsPython 中强大的语法高亮器。总体而言,tcblisting与软件包相比,可以生成更高质量的代码列表listings

对于一些具体问题,可以参考下面的链接:

添加高亮/灰显支持

在 的当前实现中minted,无法转义注释和字符串中的内容。转义序列也限制为一个字符长,这在实际中很不方便。可以使用以下文件 ( my_pygmentize.py) 修复此问题。它本质上与 相同pygmentize,但用LatexEmbeddedLexer我们自己的版本替换了 。在新实现 ( LatexExtendedEmbeddedLexer) 中,我们可以在函数中指定自己的转义序列__init__。在此示例中,我们使用了%* *)。该_find_safe_escape_tokens函数经过修改,以便我们可以在代码中的任何位置转义内容。

my_pygmentize.py

from pygments.token import Token
from pygments.lexer import Lexer, do_insertions
import pygments.formatters.latex as pygfmtlatex


class LatexExtendedEmbeddedLexer(pygfmtlatex.LatexEmbeddedLexer):
    def __init__(self, left, right, lang, **options):
        super().__init__('', '', lang, **options)
        
        # define left and right delimieters here
        self.left = '%*'
        self.right = '*)'

    # modified so that we can escape stuff in comments and strings
    def _find_safe_escape_tokens(self, text):
        for i, t, v in self._filter_to(
            self.lang.get_tokens_unprocessed(text),
            lambda t: False
        ):
            if t is None:
                for i2, t2, v2 in self._find_escape_tokens(v):
                    yield i + i2, t2, v2
            else:
                yield i, None, v


# replace LatexEmbeddedLexer
pygfmtlatex.LatexEmbeddedLexer = LatexExtendedEmbeddedLexer

# the rest is the same as pygmentize
import re
import sys
from pygments.cmdline import main

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
    sys.exit(main())

下一步是实现我们自己的支持高亮和灰化的格式化程序。与现有的不同LatexFormatter,我选择单独格式化每个字符,因为这样更容易实现背景颜色。但是,作为权衡,不支持边框。为了减少输出材料的空间,我决定根据样式在代码清单中的出现情况动态定义样式。

为了支持高亮/灰显,在格式化程序中添加了一个检查。我们可以使用特殊序列来切换高亮/灰显模式。例如,我曾经!!!切换高亮模式,并---切换灰显模式。可以在函数中更改每种模式的确切行为format_unencoded

myformatter.py

from io import StringIO

from pygments import highlight
from pygments.formatter import Formatter
import pygments.formatters.latex
from pygments.lexers.python import PythonLexer
from pygments.token import Token, STANDARD_TYPES
from pygments.util import get_bool_opt, get_int_opt
import copy


__all__ = ['LatexFormatter']

class Escaped:

    def __init__(self, s):
        self.s = s

def escape_tex(text, commandprefix):
    return text.replace('\\', '\x00'). \
                replace('{', '\x01'). \
                replace('}', '\x02'). \
                replace('\x00', r'\%sZbs' % commandprefix). \
                replace('\x01', r'\%sZob' % commandprefix). \
                replace('\x02', r'\%sZcb' % commandprefix). \
                replace('^', r'\%sZca' % commandprefix). \
                replace('_', r'\%sZus' % commandprefix). \
                replace('&', r'\%sZam' % commandprefix). \
                replace('<', r'\%sZlt' % commandprefix). \
                replace('>', r'\%sZgt' % commandprefix). \
                replace('#', r'\%sZsh' % commandprefix). \
                replace('%', r'\%sZpc' % commandprefix). \
                replace('$', r'\%sZdl' % commandprefix). \
                replace('-', r'\%sZhy' % commandprefix). \
                replace("'", r'\%sZsq' % commandprefix). \
                replace('"', r'\%sZdq' % commandprefix). \
                replace('~', r'\%sZti' % commandprefix). \
                replace(' ', r'\%sZsp' % commandprefix)


def escape_tex_new(text, commandprefix):
    chars = []
    for c in text:
        new_c = escape_tex(c, commandprefix)
        if c != new_c:
            chars.append(Escaped(new_c))
        else:
            chars.append(c)
    return chars


DOC_TEMPLATE = r'''
\documentclass{%(docclass)s}
\usepackage{fancyvrb}
\usepackage{color}
\usepackage[%(encoding)s]{inputenc}
%(preamble)s

%(styledefs)s

\begin{document}

\section*{%(title)s}

%(code)s
\end{document}
'''


CMD_TEMPLATE = r'''
\newcommand\%(cp)sZbs{\char`\\}
\newcommand\%(cp)sZus{\char`\_}
\newcommand\%(cp)sZob{\char`\{}
\newcommand\%(cp)sZcb{\char`\}}
\newcommand\%(cp)sZca{\char`\^}
\newcommand\%(cp)sZam{\char`\&}
\newcommand\%(cp)sZlt{\char`\<}
\newcommand\%(cp)sZgt{\char`\>}
\newcommand\%(cp)sZsh{\char`\#}
\newcommand\%(cp)sZpc{\char`\%%}
\newcommand\%(cp)sZdl{\char`\$}
\newcommand\%(cp)sZhy{\char`\-}
\newcommand\%(cp)sZsq{\char`\'}
\newcommand\%(cp)sZdq{\char`\"}
\newcommand\%(cp)sZti{\char`\~}
\newcommand\%(cp)sZsp{\phantom{\space}}
%% for compatibility with earlier versions
\newcommand\%(cp)sZat{@}
\newcommand\%(cp)sZlb{[}
\newcommand\%(cp)sZrb{]}
'''


def _get_ttype_name(ttype):
    fname = STANDARD_TYPES.get(ttype)
    if fname:
        return fname
    aname = ''
    while fname is None:
        aname = ttype[-1] + aname
        ttype = ttype.parent
        fname = STANDARD_TYPES.get(ttype)
    return fname + aname


class LaTeXStyleManager:

    def __init__(self, prefix):
        self.prefix = prefix
        self.style_to_index_d = dict()
        self.style_to_def_d = dict()
        self.style_to_cmdname_d = dict()

        self.toggle_styles = ['bold', 'italic', 'underline', 'roman', 'sans', 'mono']
        self.toggle_style_cmds = [r'\bfseries', r'\itshape', r'\underline', r'\rmfamily', r'\sffamily', r'\ttfamily']

    def number_to_base(self, n, b):
        if n == 0:
            return [0]
        digits = []
        while n:
            digits.append(int(n % b))
            n //= b
        digits.reverse()
        return digits

    def number_to_base_zero_less(self, n, b):
        digits = self.number_to_base(n, b)
        digits.reverse()
        i = 0
        carry = False
        while i < len(digits):
            if carry:
                digits[i] -= 1
                carry = False
            if digits[i] < 0:
                carry = True
                digits[i] = b + digits[i]
            if digits[i] == 0:
                if i < len(digits) - 1:
                    carry = True
                    digits[i] = b
            i += 1
        assert not carry
        if digits[-1] == 0:
            del digits[-1]
        digits.reverse()
        return digits


    def int_to_alph(self, num):
        base26 = self.number_to_base_zero_less(num + 1, 26)
        a_cc = ord('a')
        digits = [chr(a_cc + x - 1) for x in base26]
        s = ''.join(digits)
        return s

    def get_style_def(self, style_ind, style_d, comment_str=None):
        plain_defs = []
        surround_defs = []

        if style_d['cmd']:
            plain_defs.append(style_d['cmd'])

        for st in self.toggle_styles:
            if style_d[st]:
                if st == 'underline':
                    surround_defs.append(r'\underline')
                else:
                    ind = self.toggle_styles.index(st)
                    plain_defs.append(self.toggle_style_cmds[ind])

        if style_d['color']:
            plain_defs.append(r'\color[HTML]{%s}' % style_d['color'].upper())

        if style_d['bgcolor']:
            surround_defs.append(r'\colorbox[HTML]{%s}' % style_d['bgcolor'].upper())

        if style_d['bgcolor']:
            def_string = ''.join(plain_defs) + r'\strut\relax#1'
        else:
            def_string = ''.join(plain_defs) + r'\relax#1'
        for sd in surround_defs:
            def_string = sd + '{' + def_string + '}'

        if style_d['bgcolor']:
            def_string = r'\setlength{\fboxsep}{0pt}' + def_string

        def_string = r'\newcommand{\%s@%s}[1]{{%s}}' % (self.prefix, self.int_to_alph(style_ind), def_string)
        if comment_str is not None:
            def_string += '%' + comment_str
        cmd_name = r'\%s@%s' % (self.prefix, self.int_to_alph(style_ind))
        return def_string, cmd_name

    def rgb_color(self, col):
        if col:
            return [int(col[i] + col[i + 1], 16) for i in (0, 2, 4)]
        else:
            return [0,0,0]

    def get_default_style_d(self):
        ds = dict()
        for key in self.toggle_styles:
            ds[key] = None
        ds['color'] = None
        ds['bgcolor'] = None
        ds['cmd'] = ''
        return ds

    def style_to_tuple(self, style_d):
        toggle_bits = [False] * len(self.toggle_styles)
        for i in range(len(self.toggle_styles)):
            if style_d[self.toggle_styles[i]]:
                toggle_bits[i] = True
        color = self.rgb_color(style_d['color'])
        bg_color = self.rgb_color(style_d['bgcolor'])
        cmd = style_d.get('cmd', '')
        final = toggle_bits + [cmd] + color + bg_color
        return tuple(final)

    def has_style(self, style_d):
        style_tup = self.style_to_tuple(style_d)
        return style_tup in self.style_to_index_d

    def get_style_index(self, style_d, comment_str=None):
        style_tup = self.style_to_tuple(style_d)
        if style_tup in self.style_to_index_d:
            return self.style_to_index_d[style_tup]
        else:
            self.style_to_index_d[style_tup] = len(self.style_to_index_d)
            st_ind = self.style_to_index_d[style_tup]
            complete_def, cmd_name = self.get_style_def(st_ind, style_d, comment_str)
            self.style_to_def_d[st_ind] = complete_def
            self.style_to_cmdname_d[st_ind] = cmd_name
            return st_ind

    def merge_styles(self, style_ds):
        sty = self.get_default_style_d()
        for style_d in style_ds:
            for key in self.toggle_styles:
                sty[key] = sty[key] or style_d[key]
            if style_d['color']:
                sty['color'] = style_d['color']
            if style_d['bgcolor']:
                sty['bgcolor'] = style_d['bgcolor']
            if 'cmd' in style_d:
                sty['cmd'] += style_d['cmd']
        return sty

    def get_style_cmdname(self, tts, styles):
        if len(tts) == 0:
            return None
        style_ds = []
        for item in tts:
            if isinstance(item, dict):
                style_ds.append(item)
            else:
                style_ds.append(styles[item])
        merged_style = self.merge_styles(style_ds)
        comment_str = None
        if not self.has_style(merged_style):
            comment_str = '+'.join([str(x) for x in tts])
        st_ind = self.get_style_index(merged_style, comment_str=comment_str)
        return self.style_to_cmdname_d[st_ind]

class LatexFormatter(pygments.formatters.latex.LatexFormatter):
    name = 'LaTeX'
    aliases = ['latex', 'tex']
    filenames = ['*.tex']

    def __init__(self, **options):
        Formatter.__init__(self, **options)
        self.docclass = options.get('docclass', 'article')
        self.preamble = options.get('preamble', '')
        self.linenos = get_bool_opt(options, 'linenos', False)
        self.linenostart = abs(get_int_opt(options, 'linenostart', 1))
        self.linenostep = abs(get_int_opt(options, 'linenostep', 1))
        self.verboptions = options.get('verboptions', '')
        self.nobackground = get_bool_opt(options, 'nobackground', False)
        self.commandprefix = options.get('commandprefix', 'PY')
        self.texcomments = get_bool_opt(options, 'texcomments', False)
        self.mathescape = get_bool_opt(options, 'mathescape', False)
        self.escapeinside = options.get('escapeinside', '')
        if len(self.escapeinside) == 2:
            self.left = self.escapeinside[0]
            self.right = self.escapeinside[1]
        else:
            self.escapeinside = ''
        self.envname = options.get('envname', 'Verbatim')

        self.style_manager = LaTeXStyleManager(prefix=self.commandprefix)

        self._create_tt_to_style_d()
        self._create_stylesheet()

    def _create_tt_to_style_d(self):
        self.tt_to_style_d = dict()
        for ttype, ndef in self.style:
            self.tt_to_style_d[ttype] = ndef


    def format_unencoded(self, tokensource, outfile):
        t2n = self.ttype2name
        cp = self.commandprefix

        segments = []
        current_line = []

        # define custom modes
        # highlight mode
        highlight_mode_d = copy.copy(self.tt_to_style_d[Token.Text])
        highlight_mode_d['bgcolor'] = 'FFFF00'
        highlight_mode_d['cmd'] = '\\small'

        grayout_mode_d = copy.copy(self.tt_to_style_d[Token.Text])
        grayout_mode_d['color'] = '808080'
        grayout_mode_d['cmd'] = '\\tiny'

        # define the toggle strings of different modes
        mode_strings = ['!!!', '---']
        mode_styles = [highlight_mode_d, grayout_mode_d]
        mode_flags = [False] * len(mode_strings)

        def flush_line():
            nonlocal segments, current_line
            if len(current_line) > 0:
                segments.append(current_line)
            current_line = []

        toks = list(tokensource)
        for ttype, value in toks:
            new_value = []

            if ttype in Token.Comment:
                new_value.extend(escape_tex_new(value, cp))
                value = escape_tex(value, cp)
            elif ttype not in Token.Escape:
                new_value.extend(escape_tex_new(value, cp))
                value = escape_tex(value, cp)

            raw_ttype = []

            def write_content(cmdname=None, raw=False):
                nonlocal current_line, new_value
                real_cmdname = cmdname
                if raw:
                    for item in new_value:
                        if isinstance(item, Escaped):
                            current_line.append(item.s)
                        else:
                            current_line.append(item)
                else:
                    if real_cmdname is None:
                        real_cmdname = ''
                    for item in new_value:
                        if isinstance(item, Escaped):
                            current_line.append('%s{%s}' % (real_cmdname, item.s))
                        else:
                            if item == '\n':
                                flush_line()
                                continue
                            current_line.append('%s{%s}' % (real_cmdname, item))

            if ttype in Token.Escape:
                # deal with mode toggle strings
                if value in mode_strings:
                    ind = mode_strings.index(value)
                    mode_flags[ind] = not mode_flags[ind]
                else:
                    new_value.append(Escaped(value))
                    write_content(raw=True)
            else:
                while ttype is not Token:
                    raw_ttype.append(ttype)
                    ttype = ttype.parent

                for i in range(len(mode_flags)):
                    if mode_flags[i]:
                        raw_ttype.append(mode_styles[i])

                cmdname = self.style_manager.get_style_cmdname(raw_ttype, self.tt_to_style_d)
                write_content(cmdname=cmdname)

        flush_line()

        if self.full:
            realoutfile = outfile
            outfile = StringIO()

        # write the command definition
        outfile.write('\\bgroup\n')
        outfile.write('\\makeatletter\n')
        style_defs = '\n'.join(self.style_manager.style_to_def_d.values())
        outfile.write(style_defs + '\n')
        outfile.write(r'\newcommand{\PYG@COMMAND@PREFIX}{%s}' % cp + '\n')
        outfile.write(r'\newcommand{\PYG@NUM@STYLES}{%d}' % len(self.style_manager.style_to_index_d) + '\n')
        outfile.write(CMD_TEMPLATE % {'cp': cp})

        outfile.write('\\begin{' + self.envname + '}[commandchars=\\\\\\{\\}')
        if self.linenos:
            start, step = self.linenostart, self.linenostep
            outfile.write(',numbers=left' +
                          (start and ',firstnumber=%d' % start or '') +
                          (step and ',stepnumber=%d' % step or ''))
        if self.mathescape or self.texcomments or self.escapeinside:
            outfile.write(',codes={\\catcode`\\$=3\\catcode`\\^=7'
                          '\\catcode`\\_=8\\relax}')
        if self.verboptions:
            outfile.write(',' + self.verboptions)
        outfile.write(']\n')

        all_lines = '\n'.join(map(lambda x : ''.join(x), segments))
        outfile.write(all_lines + '\n')

        outfile.write('\\end{' + self.envname + '}\n')
        outfile.write('\\makeatother\n')
        outfile.write('\\egroup\n')

        if self.full:
            encoding = self.encoding or 'utf8'
            # map known existings encodings from LaTeX distribution
            encoding = {
                'utf_8': 'utf8',
                'latin_1': 'latin1',
                'iso_8859_1': 'latin1',
            }.get(encoding.replace('-', '_'), encoding)
            realoutfile.write(DOC_TEMPLATE %
                dict(docclass  = self.docclass,
                     preamble  = self.preamble,
                     title     = self.title,
                     encoding  = encoding,
                     styledefs = '',
                     code      = outfile.getvalue()))

下一步,我们需要进行修改,minted以便它使用我们的词法分析器和格式化程序。这可以通过以下文件实现。我们将可执行文件从 更改为pygmentizepython3 my_pygmentize.py我们使用-x -f myformatter.py:LatexFormatter -P commandprefix=PY以便使用我们自己的格式化程序。此代码相当长,因为我必须复制粘贴 的定义\minted@pygmentize。不知何故\patchcmd无法使用它。

patch_minted.tex

% patch \MintedPygmentize so that it uses our script
% this has to be placed after the preamble
\renewcommand{\MintedPygmentize}{python3 my_pygmentize.py}


% patch \minted@pygmentize so that it uses our own formatter
\makeatletter
\renewcommand{\minted@pygmentize}[2][\minted@outputdir\[email protected]]{%
  \minted@checkstyle{\minted@get@opt{style}{default}}%
  \stepcounter{minted@pygmentizecounter}%
  \ifthenelse{\equal{\minted@get@opt{autogobble}{false}}{true}}%
    {\def\minted@codefile{\minted@outputdir\[email protected]}}%
    {\def\minted@codefile{#1}}%
  \ifthenelse{\boolean{minted@isinline}}%
    {\def\minted@optlistcl@inlines{%
      \minted@optlistcl@g@i
      \csname minted@optlistcl@lang\minted@lang @i\endcsname}}%
    {\let\minted@optlistcl@inlines\@empty}%
  \def\minted@cmd{%
    \ifminted@kpsewhich
      \ifwindows
        \detokenize{for /f "usebackq tokens=*"}\space\@percentchar\detokenize{a in (`kpsewhich}\space\minted@codefile\detokenize{`) do}\space
      \fi
    \fi
    \MintedPygmentize\space -l #2
    -x -f myformatter.py:LatexFormatter -P commandprefix=PY -F tokenmerge % using custom formatter and prefix
    \minted@optlistcl@g \csname minted@optlistcl@lang\minted@lang\endcsname 
    \minted@optlistcl@inlines
    \minted@optlistcl@cmd -o \minted@outputdir\minted@infile\space
    \ifminted@kpsewhich
      \ifwindows
        \@percentchar\detokenize{a}%
      \else
        \detokenize{`}kpsewhich \minted@codefile\space
          \detokenize{||} \minted@codefile\detokenize{`}%
      \fi
    \else
      \minted@codefile
    \fi}%
  % For debugging, uncomment: %%%%
  % \immediate\typeout{\minted@cmd}%
  % %%%%
  \ifthenelse{\boolean{minted@cache}}%
    {%
      \ifminted@frozencache
      \else
        \ifx\XeTeXinterchartoks\minted@undefined
          \ifthenelse{\equal{\minted@get@opt{autogobble}{false}}{true}}%
            {\edef\minted@hash{\pdf@filemdfivesum{#1}%
              \pdf@mdfivesum{\minted@cmd autogobble(\ifx\FancyVerbStartNum\z@ 0\else\FancyVerbStartNum\fi-\ifx\FancyVerbStopNum\z@ 0\else\FancyVerbStopNum\fi)}}}%
            {\edef\minted@hash{\pdf@filemdfivesum{#1}%
              \pdf@mdfivesum{\minted@cmd}}}%
        \else
          \ifx\mdfivesum\minted@undefined
            \immediate\openout\minted@code\[email protected]\relax
            \immediate\write\minted@code{\minted@cmd}%
            \ifthenelse{\equal{\minted@get@opt{autogobble}{false}}{true}}%
              {\immediate\write\minted@code{autogobble(\ifx\FancyVerbStartNum\z@ 0\else\FancyVerbStartNum\fi-\ifx\FancyVerbStopNum\z@ 0\else\FancyVerbStopNum\fi)}}{}%
            \immediate\closeout\minted@code
            \edef\minted@argone@esc{#1}%
            \StrSubstitute{\minted@argone@esc}{\@backslashchar}{\@backslashchar\@backslashchar}[\minted@argone@esc]%
            \StrSubstitute{\minted@argone@esc}{"}{\@backslashchar"}[\minted@argone@esc]%
            \edef\minted@tmpfname@esc{\minted@outputdir\minted@jobname}%
            \StrSubstitute{\minted@tmpfname@esc}{\@backslashchar}{\@backslashchar\@backslashchar}[\minted@tmpfname@esc]%
            \StrSubstitute{\minted@tmpfname@esc}{"}{\@backslashchar"}[\minted@tmpfname@esc]%
            %Cheating a little here by using ASCII codes to write `{` and `}`
            %in the Python code
            \def\minted@hashcmd{%
              \detokenize{python -c "import hashlib; import os;
                hasher = hashlib.sha1();
                f = open(os.path.expanduser(os.path.expandvars(\"}\minted@[email protected]\detokenize{\")), \"rb\");
                hasher.update(f.read());
                f.close();
                f = open(os.path.expanduser(os.path.expandvars(\"}\minted@argone@esc\detokenize{\")), \"rb\");
                hasher.update(f.read());
                f.close();
                f = open(os.path.expanduser(os.path.expandvars(\"}\minted@[email protected]\detokenize{\")), \"w\");
                macro = \"\\edef\\minted@hash\" + chr(123) + hasher.hexdigest() + chr(125) + \"\";
                f.write(\"\\makeatletter\" + macro + \"\\makeatother\\endinput\n\");
                f.close();"}}%
            \ShellEscape{\minted@hashcmd}%
            \minted@input{\minted@outputdir\[email protected]}%
          \else
            \ifthenelse{\equal{\minted@get@opt{autogobble}{false}}{true}}%
             {\edef\minted@hash{\mdfivesum file {#1}%
                \mdfivesum{\minted@cmd autogobble(\ifx\FancyVerbStartNum\z@ 0\else\FancyVerbStartNum\fi-\ifx\FancyVerbStopNum\z@ 0\else\FancyVerbStopNum\fi)}}}%
             {\edef\minted@hash{\mdfivesum file {#1}%
                \mdfivesum{\minted@cmd}}}%
          \fi
        \fi
        \edef\minted@infile{\minted@cachedir/\[email protected]}%
        \IfFileExists{\minted@infile}{}{%
          \ifthenelse{\equal{\minted@get@opt{autogobble}{false}}{true}}{%
            \minted@autogobble{#1}}{}%
          \ShellEscape{\minted@cmd}}%
      \fi
      \ifthenelse{\boolean{minted@finalizecache}}%
       {%
          \edef\minted@cachefilename{listing\arabic{minted@pygmentizecounter}.pygtex}%
          \edef\minted@actualinfile{\minted@cachedir/\minted@cachefilename}%
          \ifwindows
            \StrSubstitute{\minted@infile}{/}{\@backslashchar}[\minted@infile@windows]
            \StrSubstitute{\minted@actualinfile}{/}{\@backslashchar}[\minted@actualinfile@windows]
            \ShellEscape{move /y \minted@outputdir\minted@infile@windows\space\minted@outputdir\minted@actualinfile@windows}%
          \else
            \ShellEscape{mv -f \minted@outputdir\minted@infile\space\minted@outputdir\minted@actualinfile}%
          \fi
          \let\minted@infile\minted@actualinfile
          \expandafter\minted@addcachefile\expandafter{\minted@cachefilename}%
       }%
       {\ifthenelse{\boolean{minted@frozencache}}%
         {%
            \edef\minted@cachefilename{listing\arabic{minted@pygmentizecounter}.pygtex}%
            \edef\minted@infile{\minted@cachedir/\minted@cachefilename}%
            \expandafter\minted@addcachefile\expandafter{\minted@cachefilename}}%
         {\expandafter\minted@addcachefile\expandafter{\[email protected]}}%
       }%
      \minted@inputpyg}%
    {%
      \ifthenelse{\equal{\minted@get@opt{autogobble}{false}}{true}}{%
        \minted@autogobble{#1}}{}%
      \ShellEscape{\minted@cmd}%
      \minted@inputpyg}%
}
\makeatother

一个例子

要运行此示例,请确保:

  • my_pygmentize.py、、myformatter.pypatch_minted.tex都在工作目录中。
  • python3pygments安装
  • -shell-escape已启用
\documentclass{beamer}
\usepackage[T1]{fontenc}
\usepackage[skins,listings,minted]{tcolorbox}
\usepackage{xcolor}


\begin{document}

% must not include in the prealbme
\input{patch_minted.tex}

% declare listing style
\newtcblisting{mylisting}[1]{
  listing engine=minted,
  listing only,
  minted language={#1},
  minted options={
    autogobble,
    breaklines,
    fontsize=\scriptsize,
    linenos,
    numbersep=5pt,
    escapeinside=|| % the value here doesn't matter, it just has to be present
  }
}

% redefine line number style
\renewcommand{\theFancyVerbLine}{\tiny\ttfamily\textcolor[rgb]{0.5,0.5,0.5}{\oldstylenums{\arabic{FancyVerbLine}}}}


\begin{frame}[fragile]
  
  \begin{mylisting}{python}
    # Euclidean algorithm
    def GCD(x , y):
        """This is used to calculate the GCD of the given two numbers.
        You remember the farm land problem where we need to find the 
        largest , equal size , square plots of a given plot?
        Just testing an equation here: %*$\int_a^b \frac{x}{\sin(x)} dx$*)
        """
        if y == 0:
            return x
        r = int(x % y)
        return GCD(y , r)
  \end{mylisting}
  
\end{frame}

\begin{frame}[fragile]
  
  \begin{mylisting}{python}
    # Euclidean algorithm
    def GCD(x , y):
        """This is used to calculate the GCD of the given two numbers.
        You remember the farm land problem where we need to find the 
        largest , equal size , square plots of a given plot?"""
        if y == 0:
            return x
        %*!!!*)r = int(x % y)
        return GCD(y , r)%*!!!*)
  \end{mylisting}
  
\end{frame}


\begin{frame}[fragile]
   \begin{mylisting}{python}
    # Euclidean algorithm
    def GCD(x , y):
        """This is used to calculate the GCD of the given two numbers.
        %*---*)You remember the farm land problem where we need to find the 
        largest , equal size , square plots of a given plot?"""%*---*)
        if y == 0:
            %*---*)return x%*---*)
        r = int(x % y)
        return GCD(y , r)
  \end{mylisting}
\end{frame}

\end{document}

转义字符串中的内容 在此处输入图片描述

强调 在此处输入图片描述

灰显 在此处输入图片描述

相关内容