# Re-Defining Description environment to only show label, not content

I'd like to re-define the description environment so that it only shows the label of each item in it.

So I'd like the following code

\begin{description}
\item [Truth] A sentence is true iff it expresses a true proposition.
\end{description}


To yield

Truth

when the document is compiled, where "Truth" is formatted in whatever the description label is.

The use case is that I've got definitions of many important terms and I'd like students in a class to generate a glossary by means of review. For that, I want to print the labels of each item, but leave the rest blank for the students to fill in.

• Will tis be part of a larger document or a document on its own? How much white space would you like to add instead of the description text itself? Please add this information as well as the documentclass you are using to your question. Probably the exam class and the \fillin command might be suitable for your case. – leandriis Oct 19 '19 at 14:15
• I think you're probably better off just defining a new environment for this; or, if both forms are in the same document, defining \description to produce the labels in one place and then the full result (labels and content) in another, to avoid duplicating the text. – dgoodmaniii Oct 19 '19 at 15:26

The following code defines the hidedescription environment that only prints the <label> associated with each \item[<label>] using the traditional description environment.

\documentclass{article}

\usepackage{environ,regexpatch}

\makeatletter
\let\olditem\item% Store regular \item macro
\NewEnviron{hidedescription}{%
% Update each \item[..]... to \itemstart[..]...\itemend
\xpatchcmd*{\BODY}{\item}{\itemend\itemstart}{}{}% All items
\xpatchcmd{\BODY}{\itemend\itemstart}{\itemstart}{}{}% First item correction
\def\itemstart[##1]##2\itemend{% Redefine \item to capture contents
\olditem[##1]% Print regular item
}%
\description\BODY\enddescription% Process environment
}
\makeatother

\begin{document}

Text before \verb|hidedescription|:
\begin{hidedescription}
\item[A] quick brown fox jumped over the lazy dog
\item[quick] brown fox jumped over the lazy dog
\item[brown] fox jumped over the lazy dog
\item[fox] jumped over the lazy dog
\item[jumped] over the lazy dog
\item[over] the lazy dog
\item[the] lazy dog
\item[lazy] dog
\item[dog]
\end{hidedescription}
Text after \verb|hidedescription|.

\end{document}


The principle mechanism is to replace the original input

\begin{hidedescription}
\item[label1] description1
\item[label2] description2
...
\item[labeln] descriptionn
\end{hidedescription}


with

\begin{hidedescription}
\itemstart[label1] description1\itemend
\itemstart[label2] description2\itemend
...
\itemstart[labeln] descriptionn\itemend
\end{hidedescription}


This way one can define a macro \itemstart that requires a specific input pattern (since all \items inside a description usually has an optional argument).

It would also be possible to define a condition that would turn on printing of the hidedescription environment's \item descriptions.

If you wish to entirely replace (redefine) the description environment, then you can use the following setup:

\makeatletter
\let\olditem\item% Store regular \item macro
\let\olddescription\description% Copy description environment start
\let\endolddescription\enddescription% Copy description environment end
\RenewEnviron{description}{%
% Update each \item[..]... to \itemstart[..]...\itemend
\xpatchcmd*{\BODY}{\item}{\itemend\itemstart}{}{}% All items
\xpatchcmd{\BODY}{\itemend\itemstart}{\itemstart}{}{}% First item correction
\def\itemstart[##1]##2\itemend{% Redefine \item to capture contents
\olditem[##1]% Print regular item
}%
\olddescription\BODY\endolddescription% Process environment
}
\makeatother


Typeset the environment's contents in a box that's discarded; in the box the \item command is redefined to add to a temporary macro. Then this macro is used in a real description environment.

Limitation: this doesn't support nested lists.

\documentclass{article}

\usepackage{environ}

\makeatletter
\NewEnviron{description*}{%
\def\hidedescriptionitems{}%
\setbox0=\vbox{
\BODY
}%
\begin{description}\hidedescriptionitems\end{description}
}
\makeatother

\begin{document}

Text before \verb|description*|:
\begin{description*}
\item[A] quick brown fox jumped over the lazy dog
\item[quick] brown fox jumped over the lazy dog
\item[brown] fox jumped over the lazy dog
\item[fox] jumped over the lazy dog
\item[jumped] over the lazy dog
\item[over] the lazy dog
\item[the] lazy dog
\item[lazy] dog
\item[dog]
\end{description*}
Text after \verb|description*|.

\end{document}


A version that also gobbles all inner environments.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentEnvironment{description*}{+b}
{
\bernhard_hidedesc:n { #1 }
}
{}

\seq_new:N \l__bernhard_hidedesc_items_seq
\tl_new:N \l__bernhard_hidedesc_body_tl
\cs_generate_variant:Nn \seq_set_split:Nnn { NnV }

\cs_new_protected:Nn \bernhard_hidedesc:n
{
\seq_clear:N \l__bernhard_hidedesc_items_seq
\tl_set:Nn \l__bernhard_hidedesc_body_tl { #1 }
% get rid of all \begin{...}...\end{...}
\regex_replace_all:nnN { \c{begin}.*?\c{end}\{.*?\} } { } \l__bernhard_hidedesc_body_tl
% split at \item
\seq_set_split:NnV \l__bernhard_hidedesc_items_seq { \item } \l__bernhard_hidedesc_body_tl
% the first item is empty, get rid of it
\seq_pop_left:NN \l__bernhard_hidedesc_items_seq \l_tmpa_tl
\begin{description}
\seq_map_function:NN \l__bernhard_hidedesc_items_seq \__bernhard_hidedesc_item:n
\end{description}
}

\cs_new:Nn \__bernhard_hidedesc_item:n
{% all items are of the form [desc] <tokens>
\__bernhard_hidedesc_item:w #1 \q_stop
}
\cs_new:Npn \__bernhard_hidedesc_item:w [ #1 ] #2 \q_stop
{
\item[#1]
}

\ExplSyntaxOff

\begin{document}

Text before \verb|description*|:
\begin{description*}
\item[A] quick brown fox jumped over the lazy dog
\item[quick] brown fox jumped over the lazy dog
\item[brown] fox jumped over the lazy dog
\item[fox] jumped over the lazy dog
\item[jumped] over the lazy dog
\item[over] the lazy dog
\item[the] lazy dog
\begin{enumerate}
\item A
\item B
\end{enumerate}
\item[lazy] dog
\item[dog]
\end{description*}
Text after \verb|description*|.

\end{document}


In both cases the output is