[Tex/LaTex] Wrap a few lines of Algorithmic in a box

adjustboxalgorithmicboxes

I have some pseudocode where I want to reveal an algorithm little-by-little. Currently I highlight the code that is revealed by coloring it red and this looks good onscreen. However, on print, this coloring is difficult to see so I additionally want to highlight the lines that are revealed by wrapping them inside a box. I want this to also include the line numbers. How can I do this?

I've provided a picture of what I want to achieve below, and added the MWE at the bottom (btw, is there a simple way of copying and pasting code snippets onto this page? I had to manually adjust the indentation of the code in order for it to be recognized as such, which was very annoying).

enter image description here

\documentclass{article}

\usepackage{xcolor}
\usepackage{adjustbox}
\usepackage[noend]{algpseudocode}

\begin{document}

\scriptsize
\setlength{\tabcolsep}{2pt}
\renewcommand{\arraystretch}{2}

\begin{adjustbox}{tabular={ll},center}

    \begin{adjustbox}{minipage=[t]{.62\linewidth},fbox}
        \begin{algorithmic}[1]  
            \Statex         
            \If{code}
                \State code
            \color{lightgray!20}
            \ElsIf{code}
                \State code 
            \Else
                \State code
            \EndIf
        \end{algorithmic}
    \end{adjustbox}     
    &
    \begin{adjustbox}{minipage=[t][]{.62\linewidth},fbox}
        \begin{algorithmic}[1]  
            \Statex         
            \If{code}
                \State code
            \color{red}
            \ElsIf{code}
                \State code 
            \color{lightgray!20}
            \Else
                \State code
            \EndIf      
        \end{algorithmic}       
    \end{adjustbox}
    \\
    \begin{adjustbox}{minipage=[t][]{.62\linewidth},fbox}
        \begin{algorithmic}[1]  
            \Statex         
            \If{code}
                \State code
            \ElsIf{code}
                \State code 
            \color{red}
            \Else
                \State code
            \EndIf      
        \end{algorithmic}
    \end{adjustbox}

\end{adjustbox}

\end{document}

Best Answer

A very unelegant solution, but it works. Note that you have to compile twice.

Result

  1. Using tikz define a macro \tikzmark which uses a "invisible" picture with remember picture and overlay options. This allows you to give a name to the coordinates of that point, which can be used later to draw things on top of the page. There is a package named tikzmark, which has a much more versatile and robust implementation, but for this particular case the "simple" version is enough.

  2. Just before each listing, put \tikzmark{left} to give a name to the coordinate of the top left corner of that listing. This will be used as reference for the left border of the box.

  3. Put \tikzmark{begin} before the first red line. This will be used as reference for the top border of the box.

  4. Put \tikzmark{end} after the last red line. This will be used as reference for the bottom border of the box.

  5. Use a tikzpicture with remember picture and overlay options, and use the before named coordinates and some calc to draw the red box as desired.

The following code implements this idea. For easier repetition, the code which draws the red box was extracted to a macro. You simply have to put \drawredbox after the listing which defined (left), (begin) and (end) coordinates.

\documentclass{article}

\usepackage{xcolor}
\usepackage{adjustbox}
\usepackage[noend]{algpseudocode}
\usepackage{tikz}
\usetikzlibrary{calc}

\newcommand{\tikzmark}[1]{\tikz[overlay,remember picture,baseline] \node [anchor=base] (#1) {};}%

\def\drawredbox{%
\begin{tikzpicture}[remember picture, overlay]
\draw[thick, red] ($(left|-begin)+(2pt,-2pt)$) rectangle ($(left|-end)+(4cm,-2pt)$);
\end{tikzpicture}%
}



\begin{document}

\scriptsize
\setlength{\tabcolsep}{2pt}
\renewcommand{\arraystretch}{2}

\begin{adjustbox}{tabular={ll},center}

    \begin{adjustbox}{minipage=[t]{.62\linewidth},fbox}
        \begin{algorithmic}[1]  
            \Statex         
            \If{code}
                \State code
            \color{lightgray!20}
            \ElsIf{code}
                \State code 
            \Else
                \State code
            \EndIf
        \end{algorithmic}
    \end{adjustbox}     
    &
    \tikzmark{left}% <-------------------------------------- left
    \begin{adjustbox}{minipage=[t][]{.62\linewidth},fbox}
        \begin{algorithmic}[1]
            \Statex         
            \If{code}
                \State code
            \color{red}\tikzmark{begin} % <------------------ begin
            \ElsIf{code}
                \State code 
            \color{lightgray!20}\tikzmark{end} % <----------- end
            \Else
                \State code
            \EndIf
        \end{algorithmic}
    \end{adjustbox}\drawredbox % <-------- Drawing of the red box
    \\
    \tikzmark{left}% <-------------------------------------- left
    \begin{adjustbox}{minipage=[t][]{.62\linewidth},fbox}
        \begin{algorithmic}[1]  
            \Statex         
            \If{code}
                \State code
            \ElsIf{code}
                \State code 
            \color{red}\tikzmark{begin}% <------------------ begin
            \Else
                \State code
            \EndIf\tikzmark{end} % <------------------------ end      
        \end{algorithmic}
    \end{adjustbox}\drawredbox % <------- Drawing of the red box
\end{adjustbox}
\end{document}

You can tweak the fixed dimensions used for the width of the red box and the distance to the baselines.