声明的文档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}