![Существует ли простой способ прикрепления меток к некоторым строкам внутри среды «Verbatim»?](https://rvso.com/image/472703/%D0%A1%D1%83%D1%89%D0%B5%D1%81%D1%82%D0%B2%D1%83%D0%B5%D1%82%20%D0%BB%D0%B8%20%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%BE%D0%B9%20%D1%81%D0%BF%D0%BE%D1%81%D0%BE%D0%B1%20%D0%BF%D1%80%D0%B8%D0%BA%D1%80%D0%B5%D0%BF%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BC%D0%B5%D1%82%D0%BE%D0%BA%20%D0%BA%20%D0%BD%D0%B5%D0%BA%D0%BE%D1%82%D0%BE%D1%80%D1%8B%D0%BC%20%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B0%D0%BC%20%D0%B2%D0%BD%D1%83%D1%82%D1%80%D0%B8%20%D1%81%D1%80%D0%B5%D0%B4%D1%8B%20%C2%ABVerbatim%C2%BB%3F.png)
У меня Verbatim
в документе много окружений, содержащих исходный код с различными символами внутри, включая {
, (
, [
, <
. Я пытаюсь найти способ прикрепить метки к некоторым строкам внутри этих окружений. Это выглядит неуклюже, так как мне приходится заменять все {
на \{
и все }
на \}
, что делает код 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
для получения дополнительных подсказок и альтернативы ссылкам на номера строк, даже если вам нужно, чтобы все символы можно было использовать в коде.
Если вы действительно настаиваете на использовании !
внутреннего \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
— это пустяк.