![是否有一種簡單的方法可以將標籤附加到“Verbatim”環境中的某些行?](https://rvso.com/image/472703/%E6%98%AF%E5%90%A6%E6%9C%89%E4%B8%80%E7%A8%AE%E7%B0%A1%E5%96%AE%E7%9A%84%E6%96%B9%E6%B3%95%E5%8F%AF%E4%BB%A5%E5%B0%87%E6%A8%99%E7%B1%A4%E9%99%84%E5%8A%A0%E5%88%B0%E2%80%9CVerbatim%E2%80%9D%E7%92%B0%E5%A2%83%E4%B8%AD%E7%9A%84%E6%9F%90%E4%BA%9B%E8%A1%8C%EF%BC%9F.png)
Verbatim
我的文件中有很多環境,其中包含內部帶有不同字元的源代碼,包括{
, (
, [
, <
。我正在嘗試找到一種將標籤附加到這些環境中的某些線路的方法。這看起來很笨拙,因為我必須將 all 替換{
為\{
和 all }
with ,\}
從而使 Java 程式碼的可讀性降低(對於我來說,文件的編輯者):
\documentclass{article}
\usepackage{fancyvrb}
\begin{document}
\begin{Verbatim}[commandchars=\\\{\}]
void main() \{
print("Hello!"); \label{foo}
\}
\end{Verbatim}
\end{document}
像這樣的事情會好得多:
\documentclass{article}
\usepackage{fancyvrb}
\begin{document}
\begin{Verbatim}
void main() {
print("Hello!"); !foo
}
\end{Verbatim}
\end{document}
是否有可能將fancyvrb
解釋!foo
為\label{foo}
? (如果fancyvrb
需要「破解」也沒關係)
答案1
您可以!
使用合適的定義將其設為活動狀態:它將查找字母數字字元並將它們作為參數傳遞給\label
.
\documentclass{article}
\usepackage{fancyvrb}
\ExplSyntaxOn
\cs_new_protected:Nn \__yegor_verbatim_label:
{
\peek_regex_replace_once:nn { [[:alnum:]]* } { \c{label}\cB\{\0\cE\} }
}
\char_set_active_eq:nN { `! } \__yegor_verbatim_label:
\ExplSyntaxOff
\begin{document}
\begin{Verbatim}[codes={\catcode`\!=\active}]
void main() {
print("Hello!"); !foo
}
\end{Verbatim}
\end{document}
您將在該文件中找到以下內容.aux
:
\newlabel{foo}{{2}{1}{}{}{}}
答案2
您可以使用代碼中未使用的不同組字符,例如
\documentclass{article}
\usepackage{fancyvrb}
\begin{document}
\begin{Verbatim}[{commandchars=\\[]}]
void main() {
print("Hello!"); \label[foo]
}
\end{Verbatim}
\end{document}
或者
\documentclass{article}
\usepackage{fancyvrb}
\begin{document}
\begin{Verbatim}[{commandchars=\\$/}]
void main() {
print("Hello!"); \label$foo/
}
\end{Verbatim}
\end{document}
注意:對於 PDFLaTeX,您不能使用 UTF8 字元作為 的值commandchars
。但對於 UTF8 引擎,例如 LuaLaTeX 也類似:
% This is a LuaLaTeX example!
\documentclass{article}
\usepackage{fancyvrb}
\begin{document}
\begin{Verbatim}[{commandchars=§«»}]
void main() {
print("Hello!"); §label«foo»
}
\end{Verbatim}
\end{document}
可以使用。
另一個選擇是使用包裹listings
代替fancyvrb
。在這種情況下,您只需要一轉義字符,例如:
\documentclass{article}
\usepackage{listings}
\begin{document}
\begin{lstlisting}[escapechar=~]
void main() {
print("Hello!"); ~\label{foo}~
}
\end{lstlisting}
\end{document}
甚至:
\documentclass{article}
\usepackage{listings}
\begin{document}
\begin{lstlisting}[escapechar=¡]
void main() {
print("Hello!"); ¡\label{foo}¡
}
\end{lstlisting}
\end{document}
或者
\documentclass{article}
\usepackage{xcolor}
\usepackage{listings}
\lstset{columns=flexible,basicstyle=\ttfamily,identifierstyle=\color{blue}}
\begin{document}
\begin{lstlisting}[language=Java,escapechar=¡]
void main() {
print("Hello!"); ¡\label{foo}¡
}
\end{lstlisting}
\end{document}
另請參閱手冊第 8 節listings
以取得更多提示和參考行號的替代方法,即使您需要所有字元在程式碼中都可用。
如果您真的堅持使用!
as\label
內部程式碼,但前提是它後面沒有"
,我建議還用foo
一個附加的 來分隔!
:
\documentclass{article}
\usepackage{fancyvrb}
\makeatletter
\let\!!
\begingroup
\catcode`\!=\active
\gdef!{\@ifnextchar"{\!}{\labeltill}}
\gdef\labeltill#1!{\label{#1}}
\endgroup
\makeatother
\begin{document}
\begin{Verbatim}[codes*={\catcode`\!\active}]
void main() {
print("Hello!"); !foo!
}
\end{Verbatim}
\end{document}
然而,使用一個從未用作程式碼一部分的字元將是一個更好的主意:
\documentclass{article}
\usepackage{fancyvrb}
\begingroup
\catcode`\^=\active
\gdef^#1^{\label{#1}}
\endgroup
\begin{document}
\begin{Verbatim}[codes*={\catcode`\^\active}}
void main() {
print("Hello!"); ^foo^
}
\end{Verbatim}
\end{document}
儘管如此,我不喜歡這個解決方案,因為我認為它很容易出錯。當最後兩個解決方案之一失敗時,程式碼的複雜性就會增加。相比之下,改變listings
範例中的字元是小事一樁。