如何使用 fancyvrb 同时显示结果和逐字文本?

如何使用 fancyvrb 同时显示结果和逐字文本?

声明的文档fancyvrb:“您可以构建示例环境(显示结果和逐字文本)......”

如何?

例如,应如何fancyvrb使用来自的命令来构造诸如\showboth下面“玩具示例”中所示的命令,以便输出显示的“期望”输出而不是我得到的“实际”输出?

玩具示例

\documentclass{article}
\usepackage{fancyvrb}

\newcommand{\showboth}[1]{{#1} --- \protect\Verb!#1!}

\newcommand{\doit}[1]{also {#1}}

\begin{document}

Actual output: \quad \showboth{\doit{this}}

\bigskip

Desired output: \quad \doit{this} --- \verb!\doit{this}!

\end{document}

如何显示命令结果及其逐字文本

实际应用

在实际应用中,我需要这样一个命令 \showboth,它可以与来自周围命令传递的参数一起使用。

这样做的目的是让我能够系统地尝试文档设计中的各种样式。例如,我希望能够轻松地看到我喜欢哪种样式来交叉引用定理和章节,如以下来源所示。

在该源中,加载的包showboth仅由@Ulrich Diez 的答案中的代码组成。

我想要的是一个 1 参数宏,其参数是一个标签(thm:big,例如),它产生itemize所示的完整环境(其各个项目依次调用\showboth各种引用命令,而那些引用命令依次将该标签作为它们自己的参数。

\documentclass{article}

\usepackage{amsthm}
\usepackage{thmtools}
\usepackage{enumitem}
\usepackage{suffix}

\usepackage{showboth} % code from Ulrich Diez's answer

\usepackage[colorlinks=true,linkcolor=red]{hyperref}
\usepackage{cleveref}

% Tefererencing macros:

\newcommand{\thmref}[1]{\nameref*{#1} (\cref{#1})}

\newcommand{\thmnameref}[1]{\hyperref[{#1}]{\nameref{#1}}}
\WithSuffix\newcommand\thmnameref*[1]{\nameref*{#1}}

\newcommand*{\fullref}[1]{\hyperref[{#1}]{\cref{#1}} \nameref*{#1}}

\newcommand*{\unitref}[1]{\cref{#1} (\nameref*{#1})}
\newcommand*{\unitnameref}[1]{\hyperref[{#1}]{\cref{#1}} (\nameref*{#1})}

% Thorerem styles

\swapnumbers

\declaretheoremstyle[
headfont=\bfseries,
notefont=\bfseries, 
headformat=\NAME\NUMBER\let\thmt@space\@empty\NOTE,
bodyfont=\mdseries\itshape,
]{thmstyle}

\makeatletter
\declaretheoremstyle[
headfont=\bfseries,
notefont=\bfseries, notebraces={}{},
headformat=\NUMBER\let\thmt@space\@empty\NOTE,
bodyfont=\mdseries\itshape,
]{namedthmstyle}
\makeatother

\theoremstyle{thmstyle}% default
\declaretheorem[name=Theorem,numberwithin=section]{theorem}

\theoremstyle{namedthmstyle}
\declaretheorem[style=namedthmstyle, name=Theorem,title = {},numberlike=theorem]{namedtheorem}

\begin{document}

\section{Stuff}\label{sec:stuff}

\begin{theorem}[refname=Theorem,name=Preliminary Result]\label{thm:prelim}
Notice this!
\end{theorem}

\begin{namedtheorem}[name=The Big Theorem]\label{thm:big}
Very important!
\end{namedtheorem}

\begin{theorem}\label{thm:another}
Another big result.
\end{theorem}

\begin{itemize}
\item  \showboth!\thmref{thm:big}! 
\item \showboth!\thmnameref{thm:big}! 
\item \showboth!\thmnameref*{thm:big}!
\item \showboth!\fullref{thm:big}! % LITTLE USE!
\item \showboth!\nameref{thm:big} \cref{thm:big}!
\item \showboth!\nameref*{thm:big} \cref{thm:big}! 
\item \showboth!\cref{thm:big}! 
\item \showboth!\cref*{thm:big}!
\end{itemize}

\smallskip

\begin{itemize}
\item  \showboth!\thmref{thm:prelim}! 
\item \showboth!\thmnameref{thm:prelim}! 
\item \showboth!\thmnameref*{thm:prelim}!
\item \showboth!\fullref{thm:prelim}! % LITTLE USE!
\item \showboth!\nameref{thm:prelim} \cref{thm:prelim}!
\item \showboth!\nameref*{thm:prelim} \cref{thm:prelim}! 
\item \showboth!\cref{thm:prelim}! 
\item \showboth!\cref*{thm:prelim}!
\end{itemize}

\smallskip

\begin{itemize}
\item  \showboth!\thmref{thm:another}! 
\item \showboth!\thmnameref{thm:another}! 
\item \showboth!\thmnameref*{thm:another}!
\item \showboth!\fullref{thm:another}! % LITTLE USE!
\item \showboth!\nameref{thm:another} \cref{thm:another}!
\item \showboth!\nameref*{thm:another} \cref{thm:another}! 
\item \showboth!\cref{thm:another}! 
\item \showboth!\cref*{thm:another}!
\end{itemize}

\smallskip

\begin{itemize}
\item \showboth!\unitnameref{sec:stuff}!
\item \showboth!\unitref{sec:stuff}!
\item  \showboth!\thmref{sec:stuff}! 
\item \showboth!\thmnameref{sec:stuff}! 
\item \showboth!\thmnameref*{sec:stuff}!
\item \showboth!\fullref{sec:stuff}! % LITTLE USE!
\item \showboth!\nameref{sec:stuff} \cref{sec:stuff}!
\item \showboth!\nameref*{sec:stuff} \cref{sec:stuff}! 
\item \showboth!\cref{sec:stuff}! 
\item \showboth!\cref*{sec:stuff}!
\end{itemize}

\end{document}

答案1

让我提前说一下,我对 fancyvrb 包一点也不熟悉,因为到现在我从未使用过它。

因此,我不知道该软件包是否已经提供了一些基础设施来实现您的愿望。

我即兴地建议\showboth在“verbatim catcode régime”下阅读它的参数,然后\showboth将该参数传递给另一个宏,\innershowboth该宏反过来将该参数\scantokens按原样传递给—once,并将其与用于调用\Verb—command 的标记一起传递给—once。

我刚刚编写了一个宏\UDcollectOneVerbArg,它确实在“逐字 catcode 规则”下读取参数,然后将这些参数和逐字分隔符传递给其他宏。
我很乐意在下面的示例中使用它来实现\showboth

与命令\verb(来自 LaTeX 内核)和\Verb(来自 fancyvrb 包)一样,该命令\showboth需要在“逐字 catcode 机制”下读取其参数。因此,\verb与命令一样,\Verb该命令\showboth不适用于由其他宏传递的参数/来自宏定义的参数,这些参数在正常 catcode 机制下被标记化。对于没有经验的人来说,最佳做法是\showboth<verbatim-Arg>在宏定义和宏参数中使用 not。

在此处输入图片描述

\documentclass{article}
\usepackage{fancyvrb}
\makeatletter
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
%% (\romannumeral expansion was introduced in order to overcome the 
%% concerns and worries about improperly balanced \if..\else..\fi constructs.)
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
  \UD@secondoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@firstoftwo}%
}%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% // Snippet written by Ulrich Diez on November 30, 2016
%
% Implement generic stuff for reading arguments "verbatim":
%
% Syntax of \UDcollectOneVerbArg
%
%   \UDcollectOneVerbArg{<^^M-replacement>}{<mandatory>}<delimiter of verbatim arg><verbatim arg><delimiter of verbatim arg>
%   yields:
%   <mandatory>{<delimiter of verbatim arg>}{<verbatim arg>}
%
%   \UDcollectOneVerbArg{<^^M-replacement>}{<mandatory>}{<verbatim arg>}
%   yields:
%   <mandatory>{}{<verbatim arg>}
%
% with each character ^^M (usually=\endline-char) in <verbatim arg>
% replaced by token-sequence <^^M-replacement>.
%
% If reading <^^M-replacement> and <mandatory> from input is necessary,
% they will be read under unchanged catcode regime.
%
% The <verbatim arg> is also mandatory.
% It will be read under verbatim-catcode-conditions.
% There must be a leading character in front of it.
% If that leading character is an opening brace, it will be
% "assumed" that the <verbatim arg> is nested into braces.
% Otherwise it will be "assumed" that the <verbatim arg> is
% delimited by that leading character---which implies a
% syntax like with the argument of \verb.
%
% Empty-lines will not be ignored.
%
% <delimiter of verbatim arg> will be read under verbatim-catcode-conditions
% if present.
%
\begingroup
\catcode`\^^M=12 %
\UD@firstoftwo{%
  \endgroup%
  \newcommand\UDEndlreplace[2]{\romannumeral0\@UDEndlreplace{#2}#1^^M\relax{}}%
  \newcommand*\@UDEndlreplace{}%
  \long\def\@UDEndlreplace#1#2^^M#3\relax#4#5{%
    \UD@CheckWhetherNull{#3}%
    { #5{#4#2}}{\@UDEndlreplace{#1}#3\relax{#4#2#1}{#5}}%
  }%
}{}%
\newcommand\UDcollectOneVerbArg{\@UDOneVerbArg{\@UDcollectOneVerbArg}}%
\newcommand\@UDOneVerbArg[3]{%
  \@bsphack
  \begingroup
  \let\do\@makeother\dospecials
  \catcode`\{=1 %
  \catcode`\ =10 %
  \@ifnextchar\bgroup
  {\catcode`\}=2 \@@UDOneVerbArg{#1}{#2}{#3}{}}%
  {\do\{\@@UDOneVerbArg{#1}{#2}{#3}}%
}%
\newcommand\@@UDOneVerbArg[4]{%
  \do\ %
  \catcode`\^^M=12 %
  \long\def\@tempb##1#4{%
    \edef\@tempb{##1}%
    \@onelevel@sanitize\@tempb
    \expandafter\UDEndlreplace\expandafter{\@tempb}{#2}{\def\@tempb}%
    \expandafter#1\expandafter{\@tempb}{#3}{#4}%
  }%
  \@tempb
}%
\newcommand\@UDcollectOneVerbArg[3]{%
  \endgroup
  \@esphack
  #2{#3}{#1}%
}%
% Implementation of generic stuff for reading arguments "verbatim" done.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newcommand\showboth{\UDcollectOneVerbArg{^^J}{\innershowboth}}%
\newcommand\innershowboth[2]{%
  \UD@CheckWhetherNull{#1}%
  {\scantokens{{#2} --- \Verb{#2}\begingroup\catcode`\X=14 X}}%<-This will raise an error as \Verb does not accept opening braces as delimiter.
  {\scantokens{{#2} --- \Verb#1#2#1\begingroup\catcode`\X=14 X}}%
  \endgroup
}

\makeatother

\newcommand{\doit}[1]{also {#1}}

\begin{document}

\noindent\Verb|\doit{this  and that} --- \Verb!\doit{this  and that}!| yields:\medskip\\
\null\quad \doit{this  and that} --- \Verb!\doit{this  and that}!
\bigskip

\noindent\Verb|\showboth!\doit{this  and that}!| yields:\medskip\\    
\null\quad \showboth!\doit{this  and that}!
\bigskip    

\end{document}

相关内容