2

Problem description

I am trying to create an environment that produces boxed paragraphs with different styles.

So I tried to implement some "if"-"elif"-"else" blocks, that will compare the arguments passed to the environment to some given keywords to decide which style will be applied to a paragraph.

Unfortunately, implementing such an idea was far from being as simple as it sounds, since all the methods I tried (here), in order to compare an argument with a string did not give correct results.

MWE

Here is what I have tried (I got my inspiration from here):

\documentclass{article}
\usepackage{xcolor}
\usepackage[most]{tcolorbox}
\usepackage{ifthen}
%#################################
\newtcolorbox{mybox}[2][]{colback=black!5!white,colframe=black!45!white,fonttitle=\bfseries,enhanced,breakable,attach boxed title to top left={yshift*=-\tcboxedtitleheight/2},title={#2}}
%#################################
\makeatletter
\newcommand*\BEGININGcommands{}
\newcommand*\ENDINGcommands{}

\newenvironment{myENV}[1][]
{%
    \ifthenelse{\equal{#1}{keyword}}
    {
      % if '#1' == 'keyword' then apply the 'mybox' style to the selected paragraph
      \textcolor{green!35!white}{
      \textbf{Seeing this means that:} \fbox{\#1} and \fbox{keyword} represent the same string, which means that the content will be formatted by surrounding it with \textbf{mybox}.}\par\vspace{1em}
      \def\BEGININGcommands{\begin{mybox}[#1]}
      \def\ENDINGcommands{\end{mybox}}
    }
    {
      % else dont apply anything
      \textcolor{red!35!white}{\textbf{Seeing this means that:} \fbox{\#1} is not the same as \fbox{keyword}, which means that no formating will be applied.}\par\vspace{1em}
      \def\BEGININGcommands{}
      \def\ENDINGcommands{}
    }
    \BEGININGcommands
}
{%
    \ENDINGcommands%
}
\makeatother
%#################################
\begin{document}
\begin{myENV}{keywordA}
  This paragraph \textbf{should be formatted} as the \textbf{keywordA} is \textbf{specified}.
\end{myENV}
\par\vspace{2em}\noindent\rule{\textwidth}{1pt}\vspace{2em}
\begin{myENV}{keywordB}
  This paragraph \textbf{should not be formatted} as the \textbf{keywordA} is \textbf{not specified}.
\end{myENV}
\end{document}

Output

enter image description here

Desired output

enter image description here

8
  • \newenvironment{myENV}[1][] defined myENV with an optional argument so \begin{myENV}[keyword]` not \begin{myENV}{keyword} Nov 10, 2022 at 0:55
  • \def\BEGININGcommands{\begin{myENV}[#1]} is programming an infinite loop if #1 is keyword Nov 10, 2022 at 0:58
  • 1
    What is the main aim here? Have an environment myENV format its contents depending on what you supply as the first argument? That doesn't seem to be the case in the example code, since the argument (keyword) is not used really.
    – Werner
    Nov 10, 2022 at 1:22
  • @Werner yeah that's exactly what I'm aiming for, (i.e. create an environment that formats its content according to the argument supplied to it) I modified the code to make the idea clearer.
    – Mycroft_47
    Nov 10, 2022 at 13:14
  • @DavidCarlisle you are right, \def\BEGININGcommands{\begin{myENV}[#1]} will produce an infinite loop of tests, I rather intended to write \def\BEGININGcommands{\begin{mybox}[#1]}
    – Mycroft_47
    Nov 10, 2022 at 13:23

2 Answers 2

2

You're using the wrong type and number of arguments.

For more than one choice, \ifthenelse becomes very cumbersome. I propose an expl3 solution with which it's easy to accommodate any number of choices for the keywords.


\documentclass{article}
\usepackage{xcolor}
\usepackage[most]{tcolorbox}

\newtcolorbox{myboxA}[1]{
  colback=black!5!white,
  colframe=black!45!white,
  fonttitle=\bfseries,
  enhanced,
  breakable,
  attach boxed title to top left={yshift*=-\tcboxedtitleheight/2},
  title={#1}
}
\newtcolorbox{myboxB}[1]{
  colback=red!5!white,
  colframe=red!45!white,
  fonttitle=\bfseries,
  enhanced,
  breakable,
  attach boxed title to top left={yshift*=-\tcboxedtitleheight/2},
  title={#1}
}

\ExplSyntaxOn

\NewDocumentEnvironment{myENV}{O{}}
 {
  \str_case:nn { #1 }
   {
    {keywordA}{\begin{myboxA}{#1}}
    {keywordB}{\begin{myboxB}{#1}}
   }
 }
 {
  \str_case:nn { #1 }
   {
    {keywordA}{\end{myboxA}}
    {keywordB}{\end{myboxB}}
   }
 }

\ExplSyntaxOff

\begin{document}

\begin{myENV}[keywordA]
  This paragraph \textbf{should be formatted} as the \textbf{keywordA} is \textbf{specified}.
\end{myENV}

\begin{myENV}[keywordB]
  This paragraph \textbf{should be formatted} as the \textbf{keywordB} is \textbf{specified}.
\end{myENV}

\begin{myENV}[foo]
  No formatting here.
\end{myENV}

\end{document}

enter image description here

1
  • Straight to the point, this is exactly what I wanted to do, thank you very much @egreg.
    – Mycroft_47
    Nov 10, 2022 at 13:45
1

Instead of creating separate tcolorbox environments for each possibility, create a style. Each style holds the key-value options associated with the formatting, that you can then pass via environment options.

enter image description here

\documentclass{article}

\usepackage{xcolor}
\usepackage[most]{tcolorbox}

\tcbset{
  % Define base style common to all boxes
  base/.style = {
    fonttitle = \bfseries,
    enhanced,
    breakable,
    attach boxed title to top left={yshift*=-\tcboxedtitleheight/2}
  },
  % Define keywordA-specific box style additions/overrides
  keywordA/.style = {
    colback = black!5!white,
    colframe = black!45!white,
  },
  % Define keywordB-specific box style additions/overrides
  keywordB/.style = {
    colback = red!5!white,
    colframe = red!45!white
  }
}

\NewDocumentEnvironment{myENV}{ O{} m }{%
  \begin{tcolorbox}[
    base, % load base style
    #1, % load additional style based on optional argument
    title = {#2} % Title in second (mandatory) argument
  ]
}{%
  \end{tcolorbox}
}

\begin{document}

\begin{myENV}[keywordA]{Something A}
  This paragraph \textbf{should be formatted} as the \textbf{keywordA} is \textbf{specified}.
\end{myENV}

\begin{myENV}[keywordB]{Something B}
  This paragraph \textbf{should be formatted} as the \textbf{keywordB} is \textbf{specified}.
\end{myENV}

\end{document}
1
  • Great idea, it will really help to better organize my preamble, thank you very much @Werner
    – Mycroft_47
    Nov 10, 2022 at 18:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .