[Tex/LaTex] Redefine existing command

macrosmulticolumnxparse

My question is whether I can redefine an existing command for example \multicolumn and make the required arguments optional, without loosing the content of multicolumn? Another option would be to get the content of multicolumn and pass it to some custom command. Is it possible? I already read about xparse but i cant figure out how I could use it in my case. I would be greatful for some help or some tips, thanks.

I have the following code:

\documentclass[a4paper,12pt,oneside]{scrbook}
\usepackage[dutch]{babel}  %Quotes won't work without babel
\usepackage[utf8]{inputenc}   %This is very important!
\usepackage[T1]{fontenc}

\usepackage{graphicx}
\usepackage[pdfborder={0 0 0}, breaklinks=true, pdftex=true, raiselinks=true]{hyperref}
\usepackage{tabularx}
\newcolumntype{Y}{>{\raggedright}X}

\begin{document}
\section{Description}
\begin{tabularx}{\linewidth}{|Y|Y|}\hline
\multicolumn{2}{c}{some text}\\
\hline
\begin{itemize}
\item  Fixing
\item  Remastering
\item  Converting
\item  Control
\end{itemize}
 & \begin{center} \resizebox{10cm}{!}{\includegraphics{picture.png}}\\ \textit{picturedescription}\end{center}
\tabularnewline \hline
\end{tabularx}
\end{document}
\end{comment}

The code is autogenerated so I have no influence on this and my idea was to change the tabularx environment and edit \multicolumn in my own package. I need to place the picture wrapped by the text on the right side and all the text on the left side, is it possible or am I on the wrong path?

Best Answer

Here is a way to use the xparse package to make the first two parameters optional:

enter image description here

Explanation:

Unless we are totally replacing the existing definition, command redefinitions are usually tweaks of existing commands. So, we still need access to the original functionality. Hence, command redefinitions are usually done in two stages: The first is to save the existing definition under a new name, and the second is to use this older definition when required.

  • First save the original definition of \multicolumn as \OldMulticolumn. You can do this with:

    \let\OldMulticolumn\multicolumn
    

    In this case \let is fine, but if you wish to redefine a macro that has optional parameters, you have to use \LetLtxMacro from the letltxmacro package . A detailed description of \LetLtxMacro can be found at this question at closed square root symbol. So in this case it is not necessary to use \LetLtxMacro, but is fine to do so.

  • Then, we redefine \multicolumn as desired and use \OldMulticolumn when we need to invoke the original multicolumn functionality:

    \DeclareExpandableDocumentCommand{\multicolumn}{O{2} O{c |} m}{%
        \OldMulticolumn{#1}{#2}{#3}%
    }%
    

    From the link in the References section the command has to be expandable since it is used within a tabular environment, so \DeclareExpandableDocumentCommand works.

  • The next part {O{2} O{c |} m} provides the specification of the three parameters.

    The first O{2} says that the first parameter, #1, is an optional parameter (specified in square brackets) and if it not provided it defaults to 2. In this particular case this is the number of columns that the \multicolumn is to span.

    The next O{c |} says that the second parameter, #2, is also optional and if not provided it defaults to c |. This is the alignment specification that would be the second parameter of the original \multicolumn.

    The last parameter is of type m which means that this is a mandatory parameter that needs to be provided with the usual {}.

    So, based in the arg spec of ...{\MultiColumn}{O{2} O{c |} m} (using a different name here to hopefully avoid confustion with the existing \multicolumn) the following three would equivalent:

    \\MultiColumn{xyz}%         
    \\MultiColumn[2]{xyz}%
    \\MultiColumn[2][c |]{xyz}%
    

    all three have the parameters #1=2, #2=c |, #3=xyz.

For more details please refer to the xparse package documentation.

References:

Code:

\documentclass{article}
\usepackage{xparse}
\usepackage{letltxmacro}

\LetLtxMacro{\OldMulticolumn}{\multicolumn}

\DeclareExpandableDocumentCommand{\multicolumn}{O{2} O{c |} m}{%
    \OldMulticolumn{#1}{#2}{#3}%
}%


\begin{document}
\begin{tabular}{|l | l |l |}\hline
    a & \multicolumn{some long centered content}\\\hline
    b & c & d\\\hline
    a & \multicolumn[2][l|]{left content}\\ \hline
\end{tabular}
\end{document}

The above is the normal usage of \multicolumn. Note that in order to specify the alignment, the number of columns needs to be specified. One could certainly enhance the macro to test for an empty parameter and replace it with the default value -- that is using it as \multicolumn}[][r |]{x} would be equivalent to \multicolumn}[2][r |]{x}.

However, in my cases the number of columns to span in a table is usually fixed so I prefer to swap the order of the options and so that I can just provide the alignment. Now using \multicolumn[r |]{right content} I get right aligned content spanning the 2 columns:

enter image description here

Code:

\documentclass{article}
\usepackage{xparse}
\usepackage{letltxmacro}

\LetLtxMacro{\OldMulticolumn}{\multicolumn}

\DeclareExpandableDocumentCommand{\multicolumn}{O{c |} O{2} m}{%
    \OldMulticolumn{#2}{#1}{#3}%
}%


\begin{document}
\begin{tabular}{|l | l |l |}\hline
    a & \multicolumn{some long centered content}\\\hline
    b & c & d\\\hline
    a & \multicolumn[r |]{right content}\\ \hline
\end{tabular}
\end{document}
Related Question