我正在考虑使用 beamer 进行我即将进行的(幻灯片)演示,其中涉及大量源代码(幻灯片之间需要展开、修改、突出显示源代码片段等)。我之前看过 beamer 教程,但还没有真正用过。
我知道我可以使用 listings 或 minted 在幻灯片上排版代码片段,但坦率地说,结果有点丑陋。我希望包含代码的框看起来更“漂亮”、“更时尚”或“更精致”,如果你愿意的话:
- 字体、线条和颜色与 beamer 主题相匹配(或许是补充);
- 关于矩形边距、圆角、阴影、透明度等设置的令人满意的组合。
- 行号看起来不再像是事后才想到的;
- 支持突出显示部分代码
- 支持代码部分灰显
...或许还有其他养眼的东西。
某些主题或软件包中是否有类似的东西?如果没有,也许某些演示模板中也有?如果甚至都没有 - 也许某些具体的演示文档中也有,我可以对其进行调整?
PS-如果使用除投影仪之外的其他工具更容易实现这一点,请在评论中说明。
答案1
经过几天的研究,我终于找到了解决您大部分问题的可行方案。所以,请做好准备,因为它涉及很多技巧,而且看起来有点(太)长。解决方案涉及以下修改:
- 重写
LatexEmbeddedLexer
inpygments
以便它支持任何地方的转义(包括字符串和注释)和我们的自定义转义序列。 - 重写
LatexFormatter
以便pygments
动态生成样式并支持突出显示,灰化。
关于列表的外观
tcolorbox
可以使用提供环境的软件包进行大量外观定制tcblisting
。如软件包手册中所示,可以自定义列表块边框、背景颜色、边距样式、阴影、透明度等。调整参数以使其符合您喜欢的beamer
主题非常容易。它还支持与 的集成minted
,使用pygments
Python 中强大的语法高亮器。总体而言,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
以便它使用我们的词法分析器和格式化程序。这可以通过以下文件实现。我们将可执行文件从 更改为pygmentize
;python3 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.py
和patch_minted.tex
都在工作目录中。python3
并pygments
安装-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}