6

Consider following code posted for What can I use to typeset MATLAB code in my document?

\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage{bigfoot} % to allow verbatim in footnote
\usepackage[numbered,framed]{matlab-prettifier}

\usepackage{filecontents}
\begin{filecontents*}{person.m}
classdef person
   properties %(here, properties is a keyword)
       mass=80;
       height=1.80;
   end
   methods
       function BMI = getBMI(height,weight)
           BMI = person.mass/person.mass^2;
       end
   end
end
\end{filecontents*}
\end{document}

and its output is enter image description here

How can I highlight a portion of code likeenter image description here

NAASI
  • 2,809
  • 3
    @Nasi, your current MWE does not reflect the visual output, could you please update your snippet ? – BambOo Aug 14 '18 at 23:21
  • 4
    I would be very interested to see a solution to this that doesn't require marking up the listings — triggered either by a comment in the source or a line number passed as an option in the listings setup... – Will Robertson Aug 15 '18 at 00:53
  • 1
    @WillRobertson That's a good point, I updated my answer accordingly. –  Aug 15 '18 at 01:29

3 Answers3

13

The tikzmark library can be used here. Some parts are borrowed from this nice answer. UPDATE: No changes in the listing, as implicitly requested by Will Robertson.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{bigfoot} % to allow verbatim in footnote
\usepackage[numbered,framed]{matlab-prettifier}
\usepackage{tikz} 
\usetikzlibrary{tikzmark}
\usetikzmarklibrary{listings}
\newcounter{tmkcount}

\tikzset{
  use tikzmark/.style={
    remember picture,
    overlay,
    execute at end picture={
      \stepcounter{tmkcount}
    },
  },
  tikzmark suffix={-\thetmkcount}
}

\begin{document}

\begin{lstlisting}[style=Matlab-editor,name=4Will]
classdef person
   properties %(here, properties is a keyword)
       mass=80;
       height=1.80;
   end
   methods
       function BMI = getBMI(height,weight)
           BMI = person.mass/person.mass^2;
       end
   end
end
\end{lstlisting}
\begin{tikzpicture}[use tikzmark]
\draw[red,thick]
  ([shift={(-3pt,2ex)}]pic cs:line-4Will-8-first) 
    rectangle 
  ([shift={(3pt,-0.75ex)}]pic cs:line-4Will-8-end);
\end{tikzpicture}
\end{document}

enter image description here

Of course, that also works with external files. The good thing is that you do not need to put stuff in the code. (Of course, you need to know that you want to annotate line 8.) This gives the same output as above.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{bigfoot} % to allow verbatim in footnote
\usepackage[numbered,framed]{matlab-prettifier}
\usepackage{tikz} 
\usetikzlibrary{tikzmark}
\usetikzmarklibrary{listings}
\newcounter{tmkcount}

\tikzset{
  use tikzmark/.style={
    remember picture,
    overlay,
    execute at end picture={
      \stepcounter{tmkcount}
    },
  },
  tikzmark suffix={-\thetmkcount}
}
\usepackage{filecontents}
\begin{filecontents*}{person.m}
classdef person
   properties %(here, properties is a keyword)
       mass=80;
       height=1.80;
   end
   methods
       function BMI = getBMI(height,weight)
           BMI = person.mass/person.mass^2;
       end
   end
end
\end{filecontents*}
\begin{document}
\lstinputlisting[style=Matlab-editor,name=4Will]{person.m}
\begin{tikzpicture}[use tikzmark]
\draw[red,thick]
  ([shift={(-3pt,2ex)}]pic cs:line-4Will-8-first) 
    rectangle 
  ([shift={(3pt,-0.75ex)}]pic cs:line-4Will-8-end);
\end{tikzpicture}
\end{document}

If you want to highlight several lines, you can make use of the -| syntax to draw the lines around extremal points. Alternatively, you could load the fit library. Here I present one simple example. And I would like to kindly ask you considering asking follow-up questions in case you have more requests.

\documentclass{beamer}
\usepackage[T1]{fontenc}
\usepackage{bigfoot} % to allow verbatim in footnote
\usepackage[numbered,framed]{matlab-prettifier}
\usepackage{tikz} 
\usetikzlibrary{tikzmark}
\usetikzmarklibrary{listings}
\newcounter{tmkcount}

\tikzset{
  use tikzmark/.style={
    remember picture,
    overlay,
    execute at end picture={
      \stepcounter{tmkcount}
    },
  },
  tikzmark suffix={-\thetmkcount}
}
\usepackage{filecontents}
\begin{filecontents*}{person.m}
classdef person
   properties %(here, properties is a keyword)
       mass=80;
       height=1.80;
   end
   methods
       function BMI = getBMI(height,weight)
           BMI = person.mass/person.mass^2;
       end
   end
end
\end{filecontents*}
\begin{document}
\lstinputlisting[style=Matlab-editor,name=4Will]{person.m}
\begin{tikzpicture}[use tikzmark]
\draw[red,thick]
  ([shift={(-3pt,2ex)}]pic cs:line-4Will-8-first) 
    rectangle 
  ([shift={(3pt,-0.75ex)}]pic cs:line-4Will-8-end);
\coordinate (aux1) at ([xshift=5pt]pic cs:line-4Will-8-end);
\coordinate (aux2) at ([yshift=-0.75ex]pic cs:line-4Will-9-end);
\draw[blue,thick]
  ([shift={(-3pt,2ex)}]pic cs:line-4Will-7-first) 
    rectangle 
  (aux1 |- aux2);
\end{tikzpicture}
\end{document}

enter image description here

  • 1
    I tried this solution but it does not work if I change \documentclass{article} to \documentclass{beamer}. I know my MWE did not make any mention of beamer but I would really appreciate if you could provide solution for it. – NAASI Aug 15 '18 at 14:09
  • 1
    @NAASI I just replaced article by beamer in the second example and it worked without problems. What precisely did you try? –  Aug 15 '18 at 14:11
  • 1
    for me the red box is showing up at the bottom of slide. Thats why I asked – NAASI Aug 15 '18 at 14:12
  • 1
    @NAASI You need to compile 2 or 3 times, did you do that? –  Aug 15 '18 at 14:13
  • 1
    I am using overleaf.com and it complies on the go. do you think its the online editor thats causing the issue – NAASI Aug 15 '18 at 14:15
  • 1
    @NAASI Probably. Can you tell it to compile three times? I never used overleaf but I can assure you that the solution works with beamer. Perhaps you can trick overleaf by adding \label{cheat} somewhere. –  Aug 15 '18 at 14:19
  • 1
    one more question. Lets say I want to draw box around two lines in which 1st is longer than 2nd. Your proposed solution draws a box that does not include all of 1st line. So what I am asking here is that how can we adjust the width of box automatically ? – NAASI Aug 15 '18 at 15:01
  • 1
    @NAASI I updated the answer accordingly. It is rather straightforward and there are many options. Please note that I will be out of touch now, but I am sure that, if you have additional questions and ask them here in form of a new question, you will get a very nice answer (and more reputation;-;). –  Aug 15 '18 at 15:14
  • This is genius and somewhat magic. What/where defines cs:line-4Will-8-first/end? I can see that it's line-<name>-\thetmkcount-<point> — I guess this an interface provided by \usetikzmarklibrary{listings} ? – Will Robertson Aug 16 '18 at 04:56
  • 1
    @WillRobertson What is genius is the nice package by Loop Space. And yes, you are right, it is that library plus the fact that you can use tikz to annotate stuff with an overlay. I think that Loop Space developed his own way of setting tikz marks. His way is even cooperating with forest, which the usual remember picture does not. –  Aug 16 '18 at 05:02
8

Here is a method which uses fbox. You simply add this command around the line of code you want to highlight and it will draw a box around it.

However, I've actually used a modified version called mycfbox which allows you to change the colour (from How to draw a colored framebox without filling the background?).

You have to take some care with the ^ character, so I've added \string before it to ensure it outputs correctly.

Remember, you need to enclose \mycfbox{red}{....} in the escapechar which I've set to ". You can change this if needed.

Updated: you need to enclose the fbox command in smash to remove the vertical space added around it. Additionally, you can control the line thickness of the box using \fboxrule and you can control the size of the box using \fboxsep.

enter image description here

\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage[numbered,framed]{matlab-prettifier}
\usepackage{xcolor} % <--- Added

\renewcommand{\fboxsep}{2pt} % <--- Size of box
\setlength\fboxrule{1.5pt}    % <--- Line thickness of box
\newcommand{\mycfbox}[2]{%
    \colorlet{currentcolor}{.}%
    {\color{#1}%
    \smash{\fbox{\color{currentcolor}#2}}}%
}

\usepackage{filecontents}
\begin{filecontents*}{person.m}
classdef person
   properties %(here, properties is a keyword)
       mass=80;
       height=1.80;
   end
   methods
       function BMI = getBMI(height,weight)
          "\mycfbox{red}{ BMI = person.mass/person.mass\string^2;}"
       end
   end
end
\end{filecontents*}

\lstset{
  style              = Matlab-editor,
  basicstyle         = \mlttfamily,
  escapechar         = ",
  mlshowsectionrules = true,
}

\begin{document}

\lstinputlisting[caption = {Some class definition}]{person.m}

\end{document}
Milo
  • 9,440
7

This question is relatively close to \fbox inside listings I merely used Martin Scharrer's answer and adapted it for the box coulouring with is other answer about \fcolorbox{<frame color>}{<background color>}{<text>}.

\documentclass{article}

\usepackage{listings}
\usepackage{newverbs}
\usepackage[numbered,framed]{matlab-prettifier}
\usepackage{xcolor}

\newsavebox{\mybox}
\begin{filecontents}{person.m}
classdef person
   properties %(here, properties is a keyword)
       mass=80;
       height=1.80;
   end
   methods
       function BMI = getBMI(height,weight)
           !\smash{\fcolorbox{red}{white}{\usebox\mybox}}!
       end
   end
end
\end{filecontents}
\begin{document}

\begin{lrbox}{\mybox}
    \lstinline[style=Matlab-editor]{BMI = person.mass/person.mass^2;}%
\end{lrbox}

\lstinputlisting[style=Matlab-editor,escapechar=!]{person.m}

\end{document}

enter image description here

BambOo
  • 8,801
  • 2
  • 20
  • 47