Overleaf 中 minted 的自定义样式

Overleaf 中 minted 的自定义样式

所以我刚刚从 转到listingsminted因为listings当背景颜色设置为深色时,线条会显示出来,这非常烦人。另一方面,Minted 很烦人,因为似乎没有一种简单的方法来定义我自己的风格,除了 Python,但是我如何在 Overleaf 中实现这一点?

答案1

更新:我错了,这似乎是可能的。参见Alex Reinking 的回答了解详情。

如果我的回答最终未被接受,我将删除它。抱歉提供错误信息!


恐怕这在 Overleaf 中是不可能的。你可以从.py文件中加载自定义词法分析器而无需安装它,但不幸的是,没有办法从本地.py文件加载 Pygments 样式,而无需在系统级别安装或将其注册为插件——这在 Overleaf 的编译服务器上是不可能的。

如果您需要在 Pygments 中使用自定义样式,则需要安装您自己的 TeX 发行版以在您自己的系统上进行编译。

答案2

当然,你只需要愿意稍微(滥用)使用 minted 的内部功能。minted 的工作方式是要求创建一个充满 TeX 宏的文件,这些宏决定了样式。如果该文件已经存在,它只会将其加载到名为您想要加载的样式的pygmentize宏中。作为优化,如果该宏已经存在,它会跳过运行!\minted@PYGdef@<style><style>pygmentize

因此,您可以按照以下方法将自己的样式文件插入系统minted

\makeatletter
\CatchFileDef{\minted@PYGdef@thesis}{thesis-style}{\catcode`@=11\catcode`\%=14\catcode``=12\endlinechar=-1}
\makeatother

\usemintedstyle{thesis}

thesis将从项目根目录中名为 的文件创建一个名为 的样式thesis-style.tex(而不是.pygstyle,以便云编辑可以正常工作)。 catcode 的任务是确保正确解释 pygstyle 文件中的字符。实际上可能只@需要 ,但为了安全起见,我从 复制了 catcode 设置minted

至于pygstyle首先创作文件,您可以尝试编辑现有文件(使用足够接近的样式构建一次并进行调整)或者通过在本地使用 Python 执行所有操作然后冻结文件pygstyle(在我看来,开销更高)从头开始创建自己的样式。

最后,这是在最新版本的 Minted 上完成的,因此您应该在 Overleaf 上使用 TexLive 2022。

答案3

可以做到。例如,我有一个针对一种名为 Portugol 的语言的自定义词法分析器,因此我上传了该词法分析器,并命名为该名称PortugolStudioLexer.py(名称任意)。然后,您可以使用以下方式启动 minted 环境

\begin{minted}{PortugolStudioLexer.py:PortugolStudioLexer -x}

\end{minted}

您还可以使用minted界面创建自己的命令:

\setminted[PortugolStudioLexer.py:PortugolStudioLexer -x]{linenos}
\newmint[portugol]{PortugolStudioLexer.py:PortugolStudioLexer -x}{}
\newminted[portugolcode]{PortugolStudioLexer.py:PortugolStudioLexer -x}{
    tabsize=2, obeytabs}
\newmintinline[portugolinline]{PortugolStudioLexer.py:PortugolStudioLexer -x}{}
\newmintedfile[portugolfile]{PortugolStudioLexer.py:PortugolStudioLexer -x}{tabsize=2, obeytabs}
\newcommand{\portugolitem}{\portugolfile[linenos = false, xleftmargin = 2em]}

因此您获得了命令\portugol\portugolinline\portugolcode环境portugolcode

答案4

除了Alex 的回答,也可以修补 Overleaf 的 pygmentize 安装,以便从 python 源中查找和编译你的样式(这样你不必在本地预编译它们)。

这个脚本可以达到这个目的:https://gist.github.com/dn0sar/d67672d3793271a2985e4ec20f425174(脚本也粘贴在下面)

只需将脚本放在项目根目录中,然后修改脚本LOCAL_STYLE_MAP以添加规范来导入您的样式(无论它在您的项目中的什么位置)。

最后,在你的 latex 前言中添加以下两行以使用修补后的 pygmentize 版本:

\immediate\write18{bash ./pygmentize_patcher.sh}
\renewcommand{\MintedPygmentize}{./pygmentize}

请注意,这pygmentize_patcher.sh是脚本的名称。现在,您可以将在中指定的键名用作样式,LOCAL_STYLE_MAPpygmentize 将找到并加载您的样式。


如果你好奇这是如何运作的,是 pygmentize 如何查找和加载内置样式。

注意,每个导入都强制以 开头pygments.styles.。该补丁替换了 python 内置命令__import__,以便pygments.styles.删除 中指定的样式的前缀LOCAL_STYLE_MAP

由于 Overleaf 目前不允许覆盖已安装的 python 文件,修补后的 pygmentize 将保存在项目根目录中。\renewcommand{\MintedPygmentize}{./pygmentize}然后将默认调用替换pygmentize为修补后的调用。

这是上面要点中的 bash 脚本:

## Tested with Pygments 2.11.0 and 2.13.0

## Add your own styles in the python map defined in the local_style_map variable
## The format specification is given in the comments inside the variable
local_style_map=$(cat <<EOF
LOCAL_STYLE_MAP = {
    ## this key is the alias name of your style, add more if you have more styles
    'customcc' : {
        ## file from where to import the custom style class
        ## this is relative to the project root
        ## e.g,. if you have your custom style in custom_style/c_styles.py
        ## you should have the import below
        
        "file_import": "custom_style.c_styles", 
        
        ## Class name defined in the "file_import" above
        
        "class_name":  "CustomC", 
    },
}
EOF
)

##### DO NOT MODIFY BELOW HERE

pygmentize_path=$(which pygmentize)

# Take shebang from the current pygmentize installation
shebang=$(head -n 1 $pygmentize_path)
if [[ "${shebang:0:2}" != '#!' ]]; then
    shebang=""
fi

preamble=$(cat <<EOF

import builtins
from pygments.styles import STYLE_MAP

for k in LOCAL_STYLE_MAP:
    STYLE_MAP[k] = LOCAL_STYLE_MAP[k]["file_import"] + '::' + LOCAL_STYLE_MAP[k]["class_name"]

default_import = builtins.__import__

def custom_import(name, *args):
    for k in LOCAL_STYLE_MAP:
        if name == 'pygments.styles.' + LOCAL_STYLE_MAP[k]["file_import"]:
            # print(f'Patching search path to find "{k}"')
            name = LOCAL_STYLE_MAP[k]["file_import"]
    return default_import(name, *args)

builtins.__import__ = custom_import

EOF
)

echo "$shebang" > pygmentize
echo "" >> pygmentize
echo "$local_style_map" >> pygmentize
echo "$preamble" >> pygmentize
echo "" >> pygmentize
cat $pygmentize_path >> pygmentize

chmod u+x pygmentize

相关内容