2

Say I want to define an environment like "color description" which would be the same as "description" except that one could add an optional color background to the label: \begin{colordescription}[red] ...

My question is inspired by the following: description (at least with enumitem) also has "normal" optional arguments (e.g. [style=...]) so, to ensure the new "colordescription" environment works the same way, I'd need to place the new optional arguments before (or after) the known ones, like \begin{colordescription}[red][style=...].

I'd like to visually separate the "new" optionals, which is why I thought of syntax like \begin{colordescription}<red>[style=...]: I think there are few occasions where the body of an environment would start with <, so the angle brackets wouldn't be confused with regular text. Maybe there's a way to consume the character after \begin{...} and do a special parse if this character is a <?

  • See the documentation of xparse: it enables you to defines commands or environments with various types of arguments, among which the d type (argument with delimiters). – Bernard Mar 12 at 14:25
6

xparse allows (almost) arbitrary delimiters to commands using the d/D argument type. You can define the environment with:

\NewDocumentEnvironment{colordescription}{ D<>{white} O{} }
  {\begin{description}[format=\colorbox{#1},#2]}
  {\end{description}}

then the argument #1 will be optional, delimited by <...>, default white, and the argument #2 will be optional, delimited by [...], default empty.

\documentclass{article}
\usepackage{enumitem}
\usepackage{xcolor}
\usepackage{xparse}
\NewDocumentEnvironment{colordescription}{ D<>{white} O{} }
  {\begin{description}[format=\colorbox{#1},#2]}
  {\end{description}}
\begin{document}

\begin{colordescription}
  \item[foo] bar
\end{colordescription}

\begin{colordescription}[style=nextline]
  \item[foo] bar
\end{colordescription}

\begin{colordescription}<red>
  \item[foo] bar
\end{colordescription}

\begin{colordescription}<red>[style=nextline]
  \item[foo] bar
\end{colordescription}

\end{document}

enter image description here

| improve this answer | |
2

EDITED to hand all 3 arguments directly to final macro, so no expansion is necessary on OP's part.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\makeatletter
\newenvironment{z}[1]{\@ifnextchar<{\zz{#1}}{\zz{#1}<Opt2 default>}}{}
\makeatother
\def\zz#1<#2>{%
  \def\argi{#1}
  \def\argii{#2}
  \zzz
}
\newcommand\zzz[1][Opt 3 default]{
  \expandafter\expandafter\expandafter\zzzz\expandafter\expandafter
  \expandafter{\expandafter\argi\expandafter}\expandafter{\argii}{#1}
}
\newcommand\zzzz[3]{
  First arg is \detokenize{#1}\\
  Bracket option is \detokenize{#2}\\
  Option argument is \detokenize{#3}  
}
\begin{document}
\begin{z}{ABC} \end{z}

\begin{z}{ABC}[\def] \end{z}

\begin{z}{ABC}<hi \mom> \end{z}

\begin{z}{ABC}<hi \mom>[\def] \end{z}
\end{document}

enter image description here

| improve this answer | |
  • 2
    Oh, no, you have \zz-itis :-) – Phelype Oleinik Mar 12 at 14:32
  • 3
    @PhelypeOleinik I'm just trolling for David's vote. – Steven B. Segletes Mar 12 at 14:33
  • 1
    Hehe, had a coworker at one time who named all his files zzz, what ever it was was then determined by the folder name it sat in – daleif Mar 13 at 7:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.