Macro that takes any latex code as an argument

The near universal rule is that verbatim material cannot be an argument to a command. With the cprotect package, there is sometimes a workaround as shown in the MWE, but even that is not a universal fix.

EDIT: group added to prevent spillage of purple into subsequent material (thanks Ulrike).

\documentclass{article}
\usepackage{cprotect,xcolor}
\newcommand\purp[1]{{\color{purple} #1}}
\begin{document}
\cprotect\purp{
\begin{verbatim} 
asdfadf
asdf
asdf
\end{verbatim}
}
\end{document}

enter image description here


If it's just about colours, you could fake a \textcolor command, which seems to take an argument, but does support verbatim material. Note that this is no general solution, but just provides an argument taking syntax to \color which is not really an argument.

(This way one could use any formatting switches not only colours, e.g. \bfseries could be used this way, too)

EDIT: created a \switchhack that allows arbitrary formatting switches not only colours, and \colorhack calls \switchhack now.

\documentclass[]{article}

\usepackage{xcolor}

\makeatletter
\begingroup\def\:#1{\endgroup\let\switchhack@sptoken= #1}\:{ }
\newcommand\switchhack[1]
  {%
    \def\switchhack@switch{#1}%
    \switchhack@a
  }
\newcommand\switchhack@a
  {%
    \futurelet\switchhack@gobbled\switchhack@b
  }
\newcommand\switchhack@b
  {%
    \ifx\switchhack@gobbled\switchhack@sptoken
      \switchhack@eatspace
    \fi
    \@firstofone
    {%
      \ifx\bgroup\switchhack@gobbled
      \else
        \GenericWarning
          {}{Warning: Argument of \string\switchhack\space not delimited}%
        \switchhack@undelimeted
      \fi
      \switchhack@delimited
    }%
  }
\long\def\switchhack@eatspace\fi#1#2%
  {%
    \fi
    \afterassignment\switchhack@a
    \let\switchhack@gobbled=
  }
\long\def\switchhack@undelimeted\fi#1#2%
  {%
    \fi
    {\switchhack@switch#2}%
  }
\newcommand\switchhack@delimited
  {%
    \afterassignment\switchhack@do
    \let\switchhack@gobbled
  }
\newcommand\switchhack@do
  {%
    \bgroup\switchhack@switch
  }
\long\def\colorhack#1#{\colorhack@{#1}}
\newcommand\colorhack@[2]
  {%
    \switchhack{\color#1{#2}}%
  }
\makeatother

\newcommand\purp{\colorhack{purple}}
\newcommand\bfhack{\switchhack{\bfseries}}

\begin{document}
\colorhack[rgb]{.5 .4 .8}{foo}
\purp{\verb|this is blue|}
following text
\bfhack{this is bold}

\colorhack{red} Undelimeted

\purp{
  \begin{verbatim}
  This is
  verbatim
  purple (I lied up there, it never was blue)
  \end{verbatim}
}
\end{document}

enter image description here


Another possibility to get macros which take verbatim material as arguments is to grab the arguments as boxes instead. Again this is no universal solution and you can't do arbitrary stuff with it (most importantly you can't change the appearance of the boxed material after it is boxed, that's what the optional arguments of grabbox are for, to make some formatting possible).

The following defines \purp to take its argument inside of a \hbox and \purp* to take it inside of a \vbox (of course the macro name in both cases is \purp, the second one is just followed by a star).

\documentclass[]{article}

\usepackage{grabbox}
\usepackage{xcolor}

\makeatletter
\newsavebox\purp@box
\newcommand\purp
  {%
    \begingroup
    \@ifstar
      {%
        \grabbox\purp@box[\color{purple}]\vbox{\unvbox\purp@box\endgroup}%
      }
      {%
        \grabbox\purp@box[\color{purple}]\hbox{\unhbox\purp@box\endgroup}%
      }%
  }
\makeatother

\begin{document}
\purp{\verb|this is blue|}

other text

\purp*{
  \begin{verbatim}
  This is
  verbatim
  purple (I lied up there, it never was blue)
  \end{verbatim}
}
\end{document}

enter image description here