我正在尝试构建一个带有开关的环境,以便 - 当打开时 - 只有括号内的文本才会出现在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:NNn
和xparse
(与 类似的功能的实现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
环境,但会自动合并您的开关。输出与以前相同。