[Tex/LaTex] Background color for fancyvrb

backgroundscolorfancyvrb

For reasons unclear to me, fancyvrb doesn't have a background option. However, the minted package, which it is based on, has one, which suggests it should not be too difficult to add.

The relevant code from minted.sty might be

\newenvironment{minted@colorbg}[1]{
  \def\minted@bgcol{#1}
  \noindent
  \begin{lrbox}{\minted@bgbox}
  \begin{minipage}{\linewidth-2\fboxsep}}
 {\end{minipage}
  \end{lrbox}%
  \colorbox{\minted@bgcol}{\usebox{\minted@bgbox}}}

I've only a sketchy idea what this code is doing, but I think it is defining the bgcolor option.

Both How to change the background color of \framebox?, and Background color in Verbatim seem relevant, but don't answer this question, at least the way I would like.

I also found http://groups.google.com/group/latexusersgroup/browse_thread/thread/c8c2e5dd1e9ff5cf, which has the following code

\documentclass{report}
\usepackage{fancybox, fancyvrb, calc}
\usepackage[svgnames]{xcolor}

\newenvironment{colframe}{%
  \begin{Sbox}
    \begin{minipage}
      {\columnwidth-\leftmargin-\rightmargin-2\fboxsep-2\fboxrule-4pt}
    }{%
    \end{minipage}
  \end{Sbox}
  \begin{center}
    \fcolorbox{black}{LightSteelBlue}{\TheSbox}
  \end{center}
}

\begin{document}  
  \begin{colframe}
    \begin{Verbatim}[frame=single]
      auto eth0
    \end{Verbatim}
  \end{colframe}
\end{document}

For some reason this produces a double line round the box, but is in the ballpark of what I want. I would prefer a bgcolor option like minted has, so one can do something like the following code. I spent some time fiddling with this, but quickly realised I had no idea what I was doing. Maybe I'll learn how to program in LaTeX someday, but it probably won't be today. Thanks.

\documentclass{article}
\usepackage{xcolor}
\definecolor{bg}{rgb}{0.95, 0.95, 0.95}
\usepackage{minted} % syntax coloring.
\newminted{c}{frame=single, bgcolor=bg}
\begin{document}
\begin{ccode*}{}
for(int i=0; i< 5; i++)
    x[i];
\end{ccode*}
\end{document}

Best Answer

\documentclass[border=2]{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{fancyvrb}


\makeatletter
\newif\ifFV@bgcolor
\newbox\FV@bgbox
\define@key{FV}{bgcolor}{\FV@bgcolortrue\def\FV@bgcolor{#1}}

\def\FV@BeginVBox{%
  \leavevmode\ifFV@bgcolor\setbox\FV@bgbox=\fi
  \hbox\ifx\FV@boxwidth\relax\else to\FV@boxwidth\fi\bgroup
  \ifcase\FV@baseline\vbox\or\vtop\or$\vcenter\fi\bgroup}
\def\FV@EndVBox{\egroup\ifmmode$\fi\hfil\egroup
  \ifFV@bgcolor\colorbox{\FV@bgcolor}{\box\FV@bgbox}\fi}
\makeatother

\begin{document}
\begin{BVerbatim}[bgcolor=LightSteelBlue]
abc
def
\end{BVerbatim}
\end{document}

Here's the result:

enter image description here

Add options to BVerbatim to have a fixed width instead of the minimum one.

Change the code into

\makeatletter
\newif\ifFV@bgcolor
\newbox\FV@bgbox
\define@key{FV}{bgcolor}{\FV@bgcolortrue\def\FV@bgcolor{#1}}
\define@key{FV}{framecolor}{\FV@bgcolortrue\def\FV@framecolor{#1}}
\def\FV@framecolor{white}

\def\FV@BeginVBox{%
  \leavevmode\ifFV@bgcolor\setbox\FV@bgbox=\fi
  \hbox\ifx\FV@boxwidth\relax\else to\FV@boxwidth\fi\bgroup
  \ifcase\FV@baseline\vbox\or\vtop\or$\vcenter\fi\bgroup}
\def\FV@EndVBox{\egroup\ifmmode$\fi\hfil\egroup
  \ifFV@bgcolor\fcolorbox{\FV@framecolor}{\FV@bgcolor}{\box\FV@bgbox}\fi}
\makeatother

to get a new key framecolor (default white, so no frame):

\begin{BVerbatim}[bgcolor=LightSteelBlue,framecolor=black]
abc
def
\end{BVerbatim}

Comments on the code

Let's look at the code for adding a background color (the extension for the frame color is very similar).

I add a conditional (\ifFV@bgcolor) and a box register (\FV@bgbox) and a key for the FV family; when the user says bgcolor=somecolor, the conditional will be set to true and somecolor is stored in \FV@bgcolor.

Then I redefine \FV@BeginVBox which is responsible for starting the box for a BVerbatim environment; its definition starts with

\leavevmode\hbox...

so what I do is to change it into

\leavevmode\ifFV@bgcolor\setbox\FV@bgbox=\fi\hbox...

In this way, when the conditional is true, the box will be stored in our new register, instead that typeset immediately.

Now the end part: \FV@EndVBox usually ends with

...\hfil\egroup}

where this \egroup closes the \hbox construction; if the conditional is true, this wouldn't typeset the box, so I make it into

...\hfil\egroup
\ifFV@bgcolor\colorbox{\FV@bgcolor}{\box\FV@bgbox}\fi}

which will typeset the box over a suitably colored background.