使用 lstlisting 环境漂亮地打印 LaTeX 语法

使用 lstlisting 环境漂亮地打印 LaTeX 语法

我想要这个:

\begin{lstlisting}
  \mymacro[<optional argument>]{<mandatory argument>}
\end{lstlisting}

生成如下输出:

期望输出

我已尝试过几次,但尚未成功。

部分解决方案

下面是一个完整的测试文档,展示了我迄今为止所尝试的内容:

\documentclass{article}

% Macros for the syntax environment
\newcommand*{\cs}[1]{{\ttfamily\char`\\#1}}
\newcommand*{\meta}[1]{{\ensuremath{\langle}\rmfamily\itshape#1\/\ensuremath{\rangle}}}
\newcommand*{\oarg}[1]{{\ttfamily[\meta{#1}]}}
\newcommand*{\marg}[1]{{\ttfamily\char`\{\meta{#1}\char`\}}}
\newenvironment{syntax}{\par\medskip\bgroup\obeyspaces\strut}{\egroup\medskip}

\usepackage{listings}

% Shortcut for verbatim code
\lstMakeShortInline[basicstyle=\ttfamily]|

% First attempt to pretty-print the syntax
\lstdefinestyle{first}{%
  columns=fullflexible,
  basicstyle=\ttfamily,
  moredelim={[is][\meta]{<}{>}},
}

\lstdefinestyle{second}{%
  columns=fullflexible,
  basicstyle=\ttfamily,
  literate=*{<}{{$\langle$\itshape}}{1}{>}{{\/$\rangle$}}{1},
}

\begin{document}

\parindent0pt

\section{The problem}

I would like this:

\begin{lstlisting}
  \mymacro[<optional argument>]{<mandatory argument>}
\end{lstlisting}%

to generate output like this:

\begin{syntax}
  \cs{mymacro}\oarg{optional argument}\marg{mandatory argument}
\end{syntax}

\section{Partial solutions}

The first attempt uses the |moredelim| key:

\begin{lstlisting}[style=first]
  \mymacro[<optional argument>]{<mandatory argument>}
\end{lstlisting}

It looks like the |\meta| macro is applied to each ``word'' instead of the entire text delimited by |<| and |>|.

\medskip

The second attempt uses the \texttt{literate} key:
\begin{lstlisting}[style=second]
  \mymacro[<optional argument>]{<mandatory argument>}
\end{lstlisting}

This successfully replaces the |<| and |>| characters, but doesn't apply the |\itshape| formatting.

Any suggestions? Thanks!

\end{document}

答案1

moredelim如果您使用选项,它可以与分隔符一起使用**。在这种情况下,分隔符宏不是在每个单词周围调用,而是在由分隔文本组成的组的开头调用。您只需将组的内容抓取到 a 中lrbox以排版它周围的<内容>

\documentclass{article}

% Macros for the syntax environment
\newenvironment{syntax}{\par\medskip\bgroup\obeyspaces\strut}{\egroup\medskip}

\makeatletter
\newenvironment{hl@env}
{\begin{lrbox}{\@tempboxa}\rmfamily\itshape}
{\end{lrbox}\ensuremath{\langle}\usebox{\@tempboxa}\kern.3ex\ensuremath{\rangle}}

\newcommand\boxmeta{%
  \begin{hl@env}\bgroup\aftergroup\hl@endenv%
}
\def\hl@endenv{%
  \end{hl@env}%   
  \egroup
}
\makeatother

\usepackage{listings}

% Shortcut for verbatim code
\lstMakeShortInline[basicstyle=\ttfamily]|

% First attempt to pretty-print the syntax
\lstdefinestyle{first}{%
  columns=fullflexible,
  basicstyle=\ttfamily,
  moredelim=**[is][\boxmeta]{<}{>},
}


\begin{document}

\parindent0pt

\section{The problem}

I would like this:

\begin{lstlisting}
  \mymacro[<optional argument>]{<mandatory argument>}
\end{lstlisting}%

to generate output like this:

\begin{syntax}
  \cs{mymacro}\oarg{optional argument}\marg{mandatory argument}
\end{syntax}

\section{Working solution}

The first attempt uses the |moredelim=**| key:

\begin{lstlisting}[style=first]
  \mymacro[<optional argument>]{<mandatory argument>}
\end{lstlisting}

This works :-)


\end{document}

在此处输入图片描述

答案2

您可以尝试以下方法,但我有点怀疑它是否非常可靠。我担心字体更改会泄露到您不想要的地方。

\documentclass{article}
\usepackage[formats]{listings}

\lstdefinestyle{first}{%
  columns=fullflexible,
  basicstyle=\ttfamily,
}

\makeatletter
\lstdefineformat{argument}{%
<=$\langle$\aftergroup\rmfamily\aftergroup\itshape,%
>=$\rangle$\aftergroup\normalfont\aftergroup\lst@basicstyle}%
\makeatother

\begin{document}
\begin{lstlisting}[style=first,format=argument]
  \mymacro[<optional argument>]{<mandatory argument>}
\end{lstlisting}

\end{document}

答案3

如果您愿意将命令列为morekeywords,那么您可以使用:

\lstdefinelanguage{MyLanguage}{
    showstringspaces=false,
    identifierstyle=\color{black}\rmfamily\itshape,
    keywordstyle=\color{black}\bfseries,
    morekeywords={mymacro}% list your commands here,
}

\lstdefinestyle{third}{%
    language=MyLanguage,
    columns=fullflexible,
    basicstyle=\ttfamily,
    literate=*{<}{{$\langle$}}{1}{>}{{\/$\rangle$}}{1},
}

得出的结果是:

在此处输入图片描述

代码:

\documentclass{article}
\usepackage{xcolor}

% Macros for the syntax environment
\newcommand*{\cs}[1]{{\ttfamily\char`\\#1}}
\newcommand*{\meta}[1]{{\ensuremath{\langle}\rmfamily\itshape#1\/\ensuremath{\rangle}}}
\newcommand*{\oarg}[1]{{\ttfamily[\meta{#1}]}}
\newcommand*{\marg}[1]{{\ttfamily\char`\{\meta{#1}\char`\}}}
\newenvironment{syntax}{\par\medskip\bgroup\obeyspaces\strut}{\egroup\medskip}

\usepackage{listings}

% Shortcut for verbatim code
\lstMakeShortInline[basicstyle=\ttfamily]|

\lstdefinelanguage{MyLanguage}{
    showstringspaces=false,
    identifierstyle=\color{black}\rmfamily\itshape,
    keywordstyle=\color{black}\bfseries,
    morekeywords={mymacro}% list your commands here,
}

\lstdefinestyle{third}{%
    language=MyLanguage,
    columns=fullflexible,
    basicstyle=\ttfamily,
    literate=*{<}{{$\langle$}}{1}{>}{{\/$\rangle$}}{1},
}


\begin{document}

\parindent0pt

\section{The problem}

I would like this:

\begin{lstlisting}
  \mymacro[<optional argument>]{<mandatory argument>}
\end{lstlisting}%

to generate output like this:

\begin{syntax}
  \cs{mymacro}\oarg{optional argument}\marg{mandatory argument}
\end{syntax}

\section{The Solution}

\begin{lstlisting}[style=third]
  \mymacro[<optional argument>]{<mandatory argument>}
\end{lstlisting}
\end{document}

答案4

显然,该literate键不能强制listings以斜体打印参数——但我们可以使用包来确定控制序列、注释和特殊字符是什么。因此,我建议将整个内容设置为斜体,然后将所有内容设置为不是一个正直的论点。

操作方法如下:

\documentclass{article}

\usepackage{xcolor,listings}

\newcommand{\macrocolor}[1]{\textcolor{violet}{#1}}
\newcommand{\commentcolor}[1]{\textcolor{purple}{#1}}
\newcommand{\literatecolori}[1]{\textcolor{cyan}{#1}}
\newcommand{\literatecolorii}[1]{\textcolor{blue}{#1}}
\newcommand{\literatecoloriii}[1]{\textcolor{orange}{#1}}

\lstset{
    basicstyle=\ttfamily\upshape,
    identifierstyle=\rmfamily\itshape,
    language=[LaTex]TeX,
    texcsstyle=*\macrocolor,
    commentstyle=\commentcolor,
    literate=   {\{}{{\literatecolori{\{}$\langle$}}{2}
            {\}}{{$\rangle$\literatecolori{\}}}}{2}
            {[}{{\literatecolorii{[}$\langle$}}{2}
            {]}{{$\rangle$\literatecolorii{]}}}{2}
            {\$}{{\literatecoloriii{\$}}}{1},
}

\lstnewenvironment{macro}[1][]
    {\lstset{texcs=[1]{#1},}}
    {}  

\begin{document}

\begin{macro}[mymacro]
\mymacro[opt. arg.]{mand. arg.}% Some comment
\end{macro}

\end{document}

在此处输入图片描述

我使用颜色是为了清晰起见,也因为我预计有些人可能会想要它们——但它们根本没有必要。

只需确保在环境的可选参数中写出您正在使用的命令。

编辑:看了 Peter Grill 的回答,我才意识到使用identifierstyle会更明智,因为它允许删除所有当时无用的字体命令。我相应地编辑了我的答案——它不会以任何方式修改输出——但我想承认这最初是他的想法。

相关内容