Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I have a code listing to write in a report, but I'd like to blur or hide some code parts with a colored box (of same length as the hidden text), so that readers cannot see the hidden parts. (Another requirement is that readers should not be able to copy & paste the hidden text from the PDF.)

As an example, I would like b=c; in the listing below to be hidden by a black box (or blurred).

For that, I define a \confidentiel for hiding text in a black box. It works fine on normal text ouside a listing block. However, it doesn't work inside an mcode listing block: instead of producing a black box, \confidentiel{code to hide or blur} gets printed verbatim.

I'm using the mcode package to display Matlab code, but I suppose the listings package (rather than mcode) is to blame here, because mcode uses the listings package; the problem likely occurs no matter which listings language is used.

Any idea?

enter image description here

\documentclass{article}

\usepackage{tikz} %to be used with package below:
\usepackage[confidentiel]{optional}
\newlength\heightconf
\newlength\widthconf
\newcommand\confidentiel[1]{%
\opt{confidentiel}{%
 \settoheight{\heightconf}{#1}%
 \settowidth{\widthconf}{#1}%
 \tikz{\node[inner sep=0pt,rectangle,draw,anchor=base,text height=\heightconf,text width=\widthconf,fill=black]{};}%
}%
\opt{libre}{#1}}

% package to display matlab code:

\usepackage[framed,numbered,autolinebreaks,useliterate]{mcode}

%starting document 
\begin{document}

  \confidentiel{this text is hidden with black box}
  this text is not hidden

    \begin{lstlisting}
    for i=1:3 do 
        a=b;
        \confidentiel{b=c;}
        c=d
    end
     \end{lstlisting}
% the code above does not hide b=c; but
% prints literaly \confidentiel{b=c} but i don't want that !

\end{document}
share|improve this question
1  
Welcome to TeX.SE. While code snippets are useful in explanations, it is always best to compose a fully compilable MWE that illustrates the problem including the \documentclass and the appropriate packages so that those trying to help don't have to recreate it. You probably just need to use \escapechar, so if I had a compilable example I could test it. –  Peter Grill Aug 2 at 18:04

2 Answers 2

up vote 5 down vote accepted

Here, all code is shown:

enter image description here

Here, some code is hidden:

enter image description here

Here are some implementation details.

Invoke the "ghosts" of Martin Scharrer and Donald Arseneau

The \confidentiel macro defined below is based on a modified version of Martin Scharrer's \UL@putbox, which is itself a "phantom" version of a macro defined in Donald Arseneau's ulem package.

Such a macro applies cleanly over multiple lines, both inside and outside listings, and will prevent your readers from copying & pasting the hidden parts, no matter which PDF viewer they use.

Indulge yourself

Instead of escaping to LaTeX only to invoke your \confidentiel macro, the following approach defines delimiters that apply \confidentiel to what they delimit.

The backtick character, `, is an adequate (opening and closing) delimiter here, because it's unlikely to occur in Matlab code (it's only valid in Matlab string literals and system commands, nowhere else).

The main benefits of this approach is that hiding/unveiling stuff, either locally or globally, is fast and easy.

  • Hiding/unveiling stuff locally only requires adding/removing two backticks (`...`), as opposed to adding/removing \confidentiel{...} each time;
  • Hiding/unveiling stuff globally can be done by at the flip of the \ifconfid switch (comment/uncomment the line \confidtrue).

Use matlab-prettifier

I recommend using the matlab-prettifier package instead of mcode... but, as the author of the former, I'm somewhat biased :p Have a look at this answer, and see if you like matlab-prettifier enough to migrate from mcode.

\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage{matlab-prettifier}
\usepackage[normalem]{ulem}

\newif\ifconfid
\confidtrue                   % comment this line out to unveil all hidden text
\colorlet{confidcolor}{black} % change the colour of boxes here (e.g. "red")


% ----------- implementation details -----------
\makeatletter

% from Martin's Scharrer's answer (http://tex.stackexchange.com/a/16004/21891)
\def\confid@UL@putbox{%
  \ifx\UL@start\@empty%
  \else % not inner
    \vrule\@width\z@ \LA@penalty\@M
    {\UL@skip\wd\UL@box \UL@leaders \kern-\UL@skip}%
    \phantom{\box\UL@box}%
  \fi
}

\newcommand\confidentiel{}%

\ifconfid
\renewcommand\confidentiel[1][confidcolor]{%
 \bgroup%
 \let\UL@putbox\confid@UL@putbox%
 \markoverwith{\hbox to.01em{\hss\textcolor{#1}{|}\hss}}\ULon%
}
\fi

\lst@AddToHook{Init}{%
  \ifconfid%
    \lstset{moredelim=[is][\confidentiel]``,keepspaces}%
  \else
    \lstset{moredelim=**[is][]``}%
  \fi
}
\makeatother
% ----------- end of implementation details -----------


\lstset{
  style=Matlab-editor,
  basicstyle=\mlttfamily,
}

\begin{document}
\confidentiel{%
    this text is hidden\\
    this text is hidden\\
    this text is hidden\\
}%
\xout{test that \textsf{ulem} works}
\begin{lstlisting}
for i=1:3
  a=b;
  % Guess what's next...
  `b=c;`
  c=d;
end
`% this text is hidden
% this text is hidden
% this text is hidden
`
\end{lstlisting}

\end{document}
share|improve this answer
    
I compared both matlab-prettifier and mcode: with mcode the result is just... horrible! The code is not automatically line-breaked on the right and the font is not as beautiful as matlab-prettifier. Moreover if I tried some commands like \confidentiel with an escapechar inside a big code.m included with \lstinputlisting{code.m}, the boxes are gray, not black. Moreover, I got a strange bug (also with your package) with \blackout command of censor package (escapechar used : ç): using it twice inside an included code, that doesn't work : code after \blackout{ doesn't display. –  jyloup Aug 8 at 14:26
    
Félicitations Julien et merci pour ta fonction \confidentiel qui réalise à merveille ce que je souhaitais ! Finally, how could I add an option in the preamble to change the color of boxes hiding the code ? Something like \confidentiel[red]{text to hide} would produce a red rectangle. Useful to hide different kinds of text in a PDF (code, normal text, etc...) without being able to copy/paste it. –  jyloup Aug 8 at 14:30
    
@jyloup Thanks but, to be fair to mcode, you can also use any font with it, and you can always "manually" set the breaklines key to have automatic line-breaking. I also tried using the censor package in my attempt at answering the question, but I didn't manage to get it to work in this particular case; the ulem package ended up being more convenient. Adding a colour option for \confidentiel should be easy; stay tuned. –  Jubobs Aug 8 at 14:40
    
You can now use \confidentiel[red]{stuff}. –  Jubobs Aug 8 at 16:42
    
Wow I tested it and the result is just great ! In fact, about mcode, the line-breaking is not set by default, but is set up automatically on matlab-prettifier and is more handy and more natural for PDF rendering. Thanks 1000 times! your solution closes this post. –  jyloup Aug 8 at 20:43

As suspected you simply need to add the escapechar so that listings knows that you want to execute this code:

enter image description here

Notes:

  • The escapechar can be any character that does not appear in the listing, and indicates the start and end of the code that is to be executed. In the MWE below I used the $ charaacter.

  • As the mcode package is not part of the standard distribution, I used the listings package directly, but should work with mcode as well.

Code:

\documentclass{article}

\usepackage{tikz} %to be used with package below:
\usepackage[confidentiel]{optional}
\newlength\heightconf
\newlength\widthconf
\newcommand\confidentiel[1]{%
\opt{confidentiel}{%
 \settoheight{\heightconf}{#1}%
 \settowidth{\widthconf}{#1}%
 \tikz{\node[inner sep=0pt,rectangle,draw,anchor=base,text height=\heightconf,text width=\widthconf,fill=black]{};}%
}%
\opt{libre}{#1}}

% package to display matlab code:

%\usepackage[framed,numbered,autolinebreaks,useliterate]{mcode}
\usepackage{listings}

%starting document 
\begin{document}

  \confidentiel{this text is hidden with black box}
  this text IS hidden outside of \verb|listings|

    \begin{lstlisting}[escapechar=$]
    for i=1:3 do 
        a=b;
        $\confidentiel{b=c;}$ And now, also hidden IN listings
        c=d
    end
     \end{lstlisting}
% the code above does not hide b=c; but
% prints literaly \confidentiel{b=c} but i don't want that !

\end{document}
share|improve this answer
    
Perfect I didnt know this command escapechar that's exactly what I need. Thanks a lot for all your helps.:-) –  jyloup Aug 3 at 18:26
    
Nice trick to draw a rectangle of the same size as the hidden text to prevent copy. However, this approach doesn't work well if \confidentiel's argument contains line breaks; try, for instance, \confidentiel{this text is hidden\\ with black box} –  Jubobs Aug 8 at 17:32
    
@Jubobs: The \confidentiel macro was provided in the question, so I did not do anything with that. I guess with the given definition of \confidentiel, one would have to use it on each line. There are ways to get it work across multiple lines, but I don't think that that is related to being in a listings environment. –  Peter Grill Aug 8 at 18:13
    
@PeterGrill You're right. I hadn't noticed you used the same macro as given in the question and, in fact, the OP does not require the macro to be compatible with a multi-line argument in his question. I was referring to the OP's feedback in his (now deleted) answer. –  Jubobs Aug 8 at 20:39

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.