![逃离地狱](https://linux22.com/image/253041/%E9%80%83%E7%A6%BB%E5%9C%B0%E7%8B%B1.png)
给定以下 MWE,其中code
函数的参数包含下划线:
\documentclass [11pt,oneside,onecolumn]{article}
\usepackage{listings}
\usepackage{filecontents}
\begin{filecontents*}{hello_world.c}
#include <stdio.h>
int main(void) {
printf("Hello World!\n");
// return 0;
}
\end{filecontents*}
\makeatletter
\def\code{\@ifnextchar[{\@with}{\@without}}
\def\@with[#1]#2{
}
\def\@without#1{
\section{#1}
\lstinputlisting[]{#1}
}
\makeatother
\begin{document}
\code{hello_world.c}
\end{document}
#1
两个不同的函数使用了相同的参数: section
,需要对下划线进行转义;lstinputlisting
,需要对下划线进行转义。不是逃脱。
如果用户对文件名进行转义,编译会因为 而失败section
。如果用户不对文件名进行转义,listings
则无法找到文件名。
如何解决这个问题?
答案1
请尝试使您的 MWE 独立存在(如在此答案中一样),这在回答时确实有帮助。
您可以使用 eTeX 原语\detokenize
来进行_
安全T1
字体编码,以便_
将字符打印为下划线:
\documentclass [11pt,oneside,onecolumn]{article}
\usepackage[T1]{fontenc}
\makeatletter
\usepackage{listings}
\def\code{\@ifnextchar[{\@with}{\@without}}%
\def\@with[#1]#2{%
}
\def\@without#1{%
\section{\protect\detokenize{#1}}%
\lstinputlisting[]{#1}%
}
\makeatother
\begin{document}
\tableofcontents
\code{hello_world.c}
\end{document}
答案2
有多个包负责排版文件名,例如 url、path。以下示例使用包 url。我假设的可选参数的\code
目的是将选项传递给 lstinputlisting 命令。在这种情况下,使用 进行黑客攻击\@ifnextchar
是没有必要的。
\documentclass [11pt,oneside,onecolumn]{article}
\usepackage[T1]{fontenc}
\usepackage{listings}
\usepackage{url}
\usepackage{makerobust}
% Define \file that typeset a file name using the url package
% that also takes care of hyphenation issues, ...
\newcommand*{\file}{}% to get an error if \file is already defined
\DeclareUrlCommand{\file}{\urlstyle{sf}}
% Different styles are available, e.g.:
% sf: sans serif font (\sffamily)
% rm: roman font (\rmfamily)
% tt: typewriter font (\ttfamily)
\MakeRobustCommand{\file}
% as robust command \file do not need \protect
\newcommand*{\code}[2][]{%
\section{\file{#2}}%
\lstinputlisting[{#1}]{#2}%
}
\begin{document}
\tableofcontents
\code{hello_world.c}
\end{document}