3

Is it possible to do a string comparison with a list/array of variables?

Here is my example code, ticking the defined \currentbox:

\documentclass{standalone}
\usepackage[most]{tcolorbox}

\makeatletter
% DEFINE BOX WITH GIVEN NAME
\newcommand\mybox[1]{%
    \ifnum\pdf@strcmp{\unexpanded{#1}}{\currentbox}=0 %
    \expandafter\@firstoftwo
    \else
    \expandafter\@secondoftwo
    \fi
    {\setlength\fboxsep{0pt}\colorbox{teal}{\framebox(18,10){\textbf{\color{white}#1}}}}
    {\framebox(18,10){\textbf{#1}}}%
}
\makeatother

% define current box
\def\currentbox{B}

\begin{document}
    \begin{tcbitemize}[size=fbox,
                       colframe=white,
                       colback=white,
                       raster equal height,
                       raster force size=false,
                       raster equal skip=0pt,
                       raster columns=4]
        \tcbitem[width=0.20\linewidth]
            \mybox{A}
        \tcbitem[width=0.20\linewidth]
            \mybox{B}
        \tcbitem[width=0.20\linewidth]
            \mybox{C}
        \tcbitem[width=0.20\linewidth]
            \mybox{D}
    \end{tcbitemize}%
\end{document}

So if \currentbox is a list/array containing 'A' and 'B' and it is possible to strcmp if it is in a list/array, this would generate:

enter image description here

6

You can use expl3/xparse:

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

\ExplSyntaxOn
% DEFINE BOX WITH GIVEN NAME
\NewDocumentCommand\mybox{m}
 {
  \clist_if_in:NnTF \g_api_mybox_labels_clist { #1 }
   {
    \group_begin:
    \setlength\fboxsep{0pt}
    \colorbox{teal}{\framebox(18,10){\bfseries\color{white}#1}}
    \group_end:
   }
   {
    \framebox(18,10){\bfseries#1}
   }
 }
\clist_new:N \g_api_mybox_labels_clist
\clist_gset:Nn \g_api_mybox_labels_clist { A , C }
\ExplSyntaxOff

\begin{document}

\begin{tcbitemize}[
  size=fbox,
  colframe=white,
  colback=white,
  raster equal height,
  raster force size=false,
  raster equal skip=0pt,
  raster columns=4
]
\tcbitem[width=0.20\linewidth] \mybox{A}

\tcbitem[width=0.20\linewidth] \mybox{B}

\tcbitem[width=0.20\linewidth] \mybox{C}

\tcbitem[width=0.20\linewidth] \mybox{D}
\end{tcbitemize}

\end{document}

enter image description here

Adding an interface for setting the keys is easy:

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

\ExplSyntaxOn
% DEFINE BOX WITH GIVEN NAME
\NewDocumentCommand\mybox{m}
 {
  \clist_if_in:NnTF \g_api_mybox_labels_clist { #1 }
   {
    \group_begin:
    \setlength\fboxsep{0pt}
    \colorbox{teal}{\framebox(18,10){\bfseries\color{white}#1}}
    \group_end:
   }
   {
    \framebox(18,10){\bfseries#1}
   }
 }
\clist_new:N \g_api_mybox_labels_clist
\NewDocumentCommand{\setmyboxkeys}{m}
 {
  \clist_gset:Nn \g_api_mybox_labels_clist { #1 }
 }
\ExplSyntaxOff

\begin{document}

\section{The list is not set}

\begin{tcbitemize}[
  size=fbox,
  colframe=white,
  colback=white,
  raster equal height,
  raster force size=false,
  raster equal skip=0pt,
  raster columns=4
]
\tcbitem[width=0.20\linewidth] \mybox{A}

\tcbitem[width=0.20\linewidth] \mybox{B}

\tcbitem[width=0.20\linewidth] \mybox{C}

\tcbitem[width=0.20\linewidth] \mybox{D}
\end{tcbitemize}

\section{The list is set}

\setmyboxkeys{A,C}

\begin{tcbitemize}[
  size=fbox,
  colframe=white,
  colback=white,
  raster equal height,
  raster force size=false,
  raster equal skip=0pt,
  raster columns=4
]
\tcbitem[width=0.20\linewidth] \mybox{A}

\tcbitem[width=0.20\linewidth] \mybox{B}

\tcbitem[width=0.20\linewidth] \mybox{C}

\tcbitem[width=0.20\linewidth] \mybox{D}
\end{tcbitemize}

\end{document}

enter image description here

You might want to add the selection of the keys to the options for tcbitemize:

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

\ExplSyntaxOn
% DEFINE BOX WITH GIVEN NAME
\NewDocumentCommand\mybox{m}
 {
  \clist_if_in:NnTF \l_api_mybox_labels_clist { #1 }
   {
    \group_begin:
    \setlength\fboxsep{0pt}
    \colorbox{teal}{\framebox(18,10){\bfseries\color{white}#1}}
    \group_end:
   }
   {
    \framebox(18,10){\bfseries#1}
   }
 }
\clist_new:N \l_api_mybox_labels_clist

\tcbset{mybox~keys/.code=\clist_set:Nn \l_api_mybox_labels_clist { #1 }}
\ExplSyntaxOff

\begin{document}

\section{The list is not set}

\begin{tcbitemize}[
  size=fbox,
  colframe=white,
  colback=white,
  raster equal height,
  raster force size=false,
  raster equal skip=0pt,
  raster columns=4
]
\tcbitem[width=0.20\linewidth] \mybox{A}

\tcbitem[width=0.20\linewidth] \mybox{B}

\tcbitem[width=0.20\linewidth] \mybox{C}

\tcbitem[width=0.20\linewidth] \mybox{D}
\end{tcbitemize}

\section{The list is set}

\begin{tcbitemize}[
  mybox keys={A,C},% <---- set the keys
  size=fbox,
  colframe=white,
  colback=white,
  raster equal height,
  raster force size=false,
  raster equal skip=0pt,
  raster columns=4
]
\tcbitem[width=0.20\linewidth] \mybox{A}

\tcbitem[width=0.20\linewidth] \mybox{B}

\tcbitem[width=0.20\linewidth] \mybox{C}

\tcbitem[width=0.20\linewidth] \mybox{D}
\end{tcbitemize}

\end{document}
  • Excelent! Is it also possible to renew the variables in \g_api_mybox_labels_clist in the document? – API Jul 2 '16 at 7:56
  • @API I'll add an interface later; doing my tour, now. 😀 – egreg Jul 2 '16 at 12:22
  • @API I added two ways for setting the keys. – egreg Jul 3 '16 at 10:10
5

You can use four lines from opmac.tex where \isinlist macro is defined:

\documentclass{standalone}
\usepackage[most]{tcolorbox}

% from opmac.tex:
\long\def\isinlist#1#2#3{\long\def\tmp##1#2##2\end{\def\tmp{##2}%
   \ifx\tmp\empty \csname iffalse\expandafter\endcsname \else
                  \csname iftrue\expandafter\endcsname \fi}% end of \def\tmp
   \expandafter\tmp#1\endlistsep#2\end
}

% DEFINE BOX WITH GIVEN NAME
\def\mybox#1{%
   \isinlist\currentbox{#1}\iftrue
      \setlength\fboxsep{0pt}\colorbox{teal}{\framebox(18,10)
                                             {\textbf{\color{white}#1}}}%
   \else 
      \framebox(18,10){\textbf{#1}}%
   \fi
}

% define current box
\def\currentbox{AC}
\begin{document}
    \begin{tcbitemize}[size=fbox,
                       colframe=white,
                       colback=white,
                       raster equal height,
                       raster force size=false,
                       raster equal skip=0pt,
                       raster columns=4]
        \tcbitem[width=0.20\linewidth]
            \mybox{A}
        \tcbitem[width=0.20\linewidth]
            \mybox{B}
        \tcbitem[width=0.20\linewidth]
            \mybox{C}
        \tcbitem[width=0.20\linewidth]
            \mybox{D}
    \end{tcbitemize}%
\end{document}

Note that you need not any more macro package.

  • Thanks. I will use \isinlist\currentbox{"#1"}\iftrue with \def\currentbox{"A","C"} to make it a little bit more robust – API Jul 2 '16 at 8:08
  • A doubt, since you use \isinlist\foo{baz}\iftrue so that it works in nested \if .. \fi constructions, why didn't you choose a more readable syntax like \if\isinlist\foo{baz}YES\else NO\fi? Is there anything more to that syntax you decided to use? – Manuel Jul 2 '16 at 9:22
  • @Manuel I don't see any important difference between \if\ismacro... and \ismacro...\iftrue. The second solution is mine and I use this many years. And I don't mix more approaches in my code. The first solution is (IMHO) more tricky because \ismacro needs to be expanded to something like xx\fi first. And there is more tricky solution: expand \ismacro with ) separator to (\fi first and use: \if(\ismacro...). – wipet Jul 3 '16 at 4:26

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.