带有交换机的环境

带有交换机的环境

我正在尝试构建一个带有开关的环境,以便 - 当打开时 - 只有括号内的文本才会出现在pdf文件中。

如果有例外,并且可以打印标有*的项目的整个文本,那就太好了。

有类似的东西存在吗?我找不到例子。

\documentclass{scrreprt}
\usepackage{enumerate}
\begin{document}
\begin{description}
\item[ABC] 12345
\item[CDEF] 098765
\item*[xxxx] yyyyy
\end{description}
\end{document}

答案1

您可以environ更轻松地使用它来操纵环境的内容。

\documentclass{article}
\usepackage{xparse,environ}

\ExplSyntaxOn
\NewEnviron{xdesc}
 {
  \begin{description}
  \cp_xdesc_main:NV \xdescitemshow \BODY
  \end{description}
 }

\NewEnviron{xdesc*}
 {
  \begin{description}
  \cp_xdesc_main:NV \xdescitemhide \BODY
  \end{description}
 }

\cs_new_protected:Nn \cp_xdesc_main:Nn
 {
  \seq_set_split:Nnn \l_cp_xdesc_items_in_seq { \item } { #2 }
  \seq_pop_left:NN \l_cp_xdesc_items_in_seq \l_tmpa_tl
  \seq_clear:N \l_cp_xdesc_items_out_seq
  \seq_map_inline:Nn \l_cp_xdesc_items_in_seq
   {
    \seq_put_right:Nn \l_cp_xdesc_items_out_seq { #1 ##1 \endxdescitem }
   }
  \seq_use:Nn \l_cp_xdesc_items_out_seq { }
 }
\cs_generate_variant:Nn \cp_xdesc_main:Nn { NV }

\NewDocumentCommand{\xdescitemshow}{sO{}+u{\endxdescitem}}
 {
  \item[#2] #3
 }
\NewDocumentCommand{\xdescitemhide}{sO{}+u{\endxdescitem}}
 {
  \item[#2] \IfBooleanT{#1}{#3}
 }
\ExplSyntaxOff

\begin{document}

\section{Show}

\begin{xdesc}
\item[ABC] 12345

\item[CDEF] 098765

\item*[xxxx] yyyyy
\end{xdesc}

\section{Hide}

\begin{xdesc*}
\item[ABC] 12345
\item[CDEF] 098765
\item*[xxxx] yyyyy
\end{xdesc*}

\end{document}

在此处输入图片描述

这个想法是收集内容并在 处拆分\item;第一个项目将为空,我们将其丢弃。然后我们通过在它前面添加 或\xdescitemshow\xdescitemhide以标记 结尾来处理每个项目\endxdescitem;这两个命令处理它们的参数,插入\item,收集可选参数(可能还有*),然后打印或丢弃以下文本,直到\endxdescitem

2019 年 3 月更新

expl3利用( )的新功能\seq_map_variable:NNnxparse(与 类似的功能的实现environ),可以简化代码。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentEnvironment{xdesc}{+b}
 {
  \begin{description}
  \cp_xdesc_main:Nn \xdescitemshow { #1 }
  \end{description}
 }{}

\NewDocumentEnvironment{xdesc*}{+b}
 {
  \begin{description}
  \cp_xdesc_main:Nn \xdescitemhide { #1 }
  \end{description}
 }{}

\seq_new:N \l_cp_xdesc_items_seq
\tl_new:N \l__cp_xdesc_temp_tl

\cs_new_protected:Nn \cp_xdesc_main:Nn
 {
  % split the input at \item
  \seq_set_split:Nnn \l_cp_xdesc_items_seq { \item } { #2 }
  % throw away the first element, that's empty
  \seq_pop_left:NN \l_cp_xdesc_items_seq \l_tmpa_tl
  %
  \seq_map_variable:NNn \l_cp_xdesc_items_seq \l__cp_xdesc_temp_tl
   {
    \exp_last_unbraced:NV #1 \l__cp_xdesc_temp_tl \stopxdescitem
   }
 }

\NewDocumentCommand{\xdescitemshow}{sO{}+u{\stopxdescitem}}
 {
  \item[#2] #3
 }
\NewDocumentCommand{\xdescitemhide}{sO{}+u{\stopxdescitem}}
 {
  \item[#2] \IfBooleanT{#1}{#3}
 }
\NewDocumentCommand{\stopxdescitem}{}{} % for safety

\ExplSyntaxOff

\begin{document}

\section{Show}

\begin{xdesc}
\item[ABC] 12345

\item[CDEF] 098765

\item*[xxxx] yyyyy
\end{xdesc}

\section{Hide}

\begin{xdesc*}
\item[ABC] 12345
\item[CDEF] 098765
\item*[xxxx] yyyyy
\end{xdesc*}

\end{document}

答案2

我不知道有哪个包可以做到这一点。如果您准备将“项目文本”括在括号中,以便为每个项目输入类似以下内容:

\Item[ABC]{12345}

那么这相对简单,使用解析包。您需要做的就是定义一个\Item带有三个参数的命令:

  • 可选*
  • 该命令的可选标签\item,以及
  • “项目文本”

然后,该\Item命令使用(参见 xparser](https://www.ctan.org/pkg/xparse) 手册,然后做适当的事情。

例如,你得到输出

在此处输入图片描述

使用代码:

\documentclass{scrreprt}
\usepackage{enumerate}
\usepackage{xparse}
\newif\ifMySwitch% a "switch" for turning othe item text on/off

\NewDocumentCommand\Item{ som }{% *[label]{text}
\IfBooleanTF{#1}{ \IfNoValueTF{#2}{\item #3}{\item[#2]#3} }
  {\IfNoValueTF{#2}{\item}{\item[#2]}\ifMySwitch #3\fi}
}

\begin{document}

  Switched on: \MySwitchtrue
  \begin{description}
    \Item[ABC]{12345}
    \Item[CDEF]{098765}
    \Item*[xxxx]{yyyyy}
  \end{description}

  Switched off \MySwitchfalse
  \begin{description}
    \Item[ABC]{12345}
    \Item[CDEF]{098765}
    \Item*[xxxx]{yyyyy}
  \end{description}

\end{document}

如果你不喜欢将“项目文本”括在括号中,那么这有点棘手。我认为最简单的解决方法是假设“项目文本”最多包含一个段落,这对我来说似乎很合理,然后要求每项都以空行结尾。特别是,最后一项在 之前需要一个空行\end{Description}

如果您假设这一点,那么您实际上可以重复上面的代码,但现在 item 命令将所有内容委托给一个\greedyItem命令,该命令将所有内容读入到下一段的末尾作为项目文本。对于 LaTeX,“下一段的末尾”意味着下一个\par,这就是为什么\par出现#3在 的定义之后的原因\greedyItem。以下代码实现了这一点:

\documentclass{scrreprt}
\usepackage{enumitem}

\newlist{Description}{description}{3}% a new description environment
\setlist[Description]{before=\let\item\Item}% in which the switch is automatic
\let\realItem=\item% save the "real" item for future use
\usepackage{xparse}
\newif\ifMySwitch% switch on/switch off

\def\greedyItem[#1][#2]#3\par{% #3 = until end of paragraph
  \IfBooleanTF{#1}{ \IfNoValueTF{#2}{\realItem #3}{\realItem[#2]#3} }%
    {\IfNoValueTF{#2}{\realItem}{\realItem[#2]}\ifMySwitch #3\fi}%
}
\NewDocumentCommand\Item{ so }{\greedyItem[#1][#2]}

\begin{document}

  Switched on: \MySwitchtrue
  \begin{Description}
    \item[ABC]12345

    \item[CDEF]098765

    \item*[xxxx]yyyyy

  \end{Description}

  Switched off \MySwitchfalse
  \begin{Description}
    \item[ABC]12345

    \item[CDEF]098765

    \item*[xxxx]yyyyy

  \end{Description}

\end{document}

顺便说一句,我已经改用枚举项我更喜欢这个包,并添加了一些花哨的功能来隐藏新Description环境中的代码,这个新环境就是通常的description环境,但会自动合并您的开关。输出与以前相同。

相关内容