21

Is it possible to make source code with minted copyable?

Here is a minimal example how I include source code (completely, with minimal java code, on GitHub):

\documentclass{beamer}
\usepackage[utf8]{inputenc} % this is needed for german umlauts
\usepackage[ngerman]{babel} % this is needed for german umlauts
\usepackage[T1]{fontenc}    % this is needed for correct output of umlauts in pdf
\usepackage{minted}         % needed for the inclusion of source code

\begin{document}
    \section{Section}
    \subsection{MySubSection}
    \begin{frame}{Blubtitle}
        \inputminted[linenos=true, numbersep=5pt, tabsize=4, fontsize=\small]{java}{IataCode.java}
    \end{frame}
\end{document}

When I copy the results, I get this:

public class IataCode {
public static void printIATACodes(String[] myArray) {
for (int i = 0; i < myArray.length; i++) {
System.out.println(myArray[i]);
}
}
7
public static void main(String[] args) {
String[] iataCodes = new String[4];
// Flughafen München
iataCodes[0] = "MUC";
// Flughafen Berlin Brandenburg
iataCodes[1] = "BER";
// Flughafen Augsburg
iataCodes[2] = "AGB";
printIATACodes(iataCodes);
}
8
9
10
11
12
13
14
15
16
17
18
}

But I would like to get this:

public class IataCode {
    public static void printIATACodes(String[] myArray) {
        for (int i = 0; i < myArray.length; i++) {
            System.out.println(myArray[i]);
        }
    }

    public static void main(String[] args) {
        String[] iataCodes = new String[4];
        // Flughafen München
        iataCodes[0] = "MUC";
        // Flughafen Berlin Brandenburg
        iataCodes[1] = "BER";
        // Flughafen Augsburg
        iataCodes[2] = "AGB";
        printIATACodes(iataCodes);
    }
}

So, I basicly want to know if I can achieve this (see compiled PDF and minimal source code example to try it yourself) for minted, too.

2
  • I’d say: forget it. Copying from PDFs simply doesn’t work. So far I haven’t seen a satisfactory solution for this (this applies in general, not just to minted, and not even just to preformatted code). Commented Nov 18, 2012 at 14:01
  • An aside about your comments: babel isn't really needed for German umlauts, but to use German hyphenation patterns instead of the default English ones.
    – doncherry
    Commented Nov 18, 2012 at 18:20

3 Answers 3

14

I can help with the line numbers, but not with the indenting. I am not sure it is possible to specify in the PDF (at least in a viewer-independent way) that the indentation should be copied too. You might consider instead attaching the source code file to the PDF (see eg the attachfile, attachfile2 and embedfile packages for that).

The line numbers are produced by the fancyvrb package rather than by minted itself, so an accsupp patch to fancyvrb is needed, similar to the one for listings in the linked answer. There is no style key like there is for the line numbers in listings, but the fancyvrb manual suggests modifying the \theFancyVerbLine macro. This is the approach I have taken in the following (I have just overwritten the existing definition instead of patching):

\documentclass{beamer}
\usepackage[utf8]{inputenc} % this is needed for german umlauts
\usepackage[ngerman]{babel} % this is needed for german umlauts
\usepackage[T1]{fontenc}    % this is needed for correct output of umlauts in pdf
\usepackage{minted}         % needed for the inclusion of source code

% from http://tex.stackexchange.com/questions/57151/how-do-i-prevent-conflicts-between-accsupp-and-hyperref
\usepackage{accsupp}
\newcommand\emptyaccsupp[1]{\BeginAccSupp{ActualText={}}#1\EndAccSupp{}}


%default definition is: \def\theFancyVerbLine{\rmfamily\tiny\arabic{FancyVerbLine}}
\let\theHFancyVerbLine\theFancyVerbLine% don't apply our patch to hyperref's version
\def\theFancyVerbLine{\rmfamily\tiny\emptyaccsupp{\arabic{FancyVerbLine}}}

\begin{document}
    \section{Section}
    \subsection{MySubSection}
    \begin{frame}{Blubtitle}
        \inputminted[linenos=true, numbersep=5pt, tabsize=4, fontsize=\small]{java}{IataCode.java}
    \end{frame}
\end{document}
3
  • I have tried attachfile (and embedfile with navigator), but it seems not to work: github.com/MartinThoma/LaTeX-examples/tree/master/documents/… Am I using it wrong? Is there any minimal example how to use attachfile? Commented Dec 19, 2012 at 9:10
  • 1
    @moose: Your example seems to work. It generates an icon in the document at the point of the \attachfile (which one can double-click to open the attachment), and an entry in the attachments sidebar (where you can do the same). Perhaps it is a problem with your viewer? Commented Dec 19, 2012 at 9:23
  • Yes, it doesn't work with evince and Google Chromes internal PDF-viewer, but it does work with Adobe Reader. Thanks :-) Commented Dec 19, 2012 at 9:26
1

An alternative in case accsupp does not work as expected.

The idea is to replace the line numbers by (scalable) vector images of the numbers, which are not copied.

First, you create 10 files num0.tex, num1.tex, ..., num9.tex:

\documentclass[border=0.15pt]{standalone} % small border to prevent cutoff for 2,3,6,8,9
\begin{document}
\tiny 0
\end{document}
\documentclass[border=0.15pt]{standalone} % small border to prevent cutoff for 2,3,6,8,9
\begin{document}
\tiny 1
\end{document}

etc.

Compile all of them with pdflatex, then convert them to outlines with Ghostscript:

gs -dNoOutputFonts -sDEVICE=pdfwrite -o vec0.pdf num0.pdf

etc.

Then redefine \theFancyVerbLine to do a regex replace of each number with \includegraphics{vecN}.

\documentclass{article}
\usepackage{minted}
\usepackage{graphicx}
\begin{document}

\ExplSyntaxOn
\RenewDocumentCommand{\theFancyVerbLine}{}
{
    \tl_set:Nx \l_tmpa_tl { \arabic{FancyVerbLine} }
    \regex_replace_all:nnN { (\d) } { \c{includegraphics}\cB{ vec\1 \cE} } \l_tmpa_tl
    \tl_use:N \l_tmpa_tl
}
\ExplSyntaxOff

\begin{minted}[linenos]{java}
public class IataCode {
    public static void printIATACodes(String[] myArray) {
        for (int i = 0; i < myArray.length; i++) {
            System.out.println(myArray[i]);
        }
    }

    public static void main(String[] args) {
        String[] iataCodes = new String[4];
        // Flughafen München
        iataCodes[0] = "MUC";
        // Flughafen Berlin Brandenburg
        iataCodes[1] = "BER";
        // Flughafen Augsburg
        iataCodes[2] = "AGB";
        printIATACodes(iataCodes);
    }
}
\end{minted}
\end{document}

The downside is that the kerning of the numbers is lost. Another downside is that you can't style the numbers without going through the whole process again.

Screenshot with some of the code selected:

enter image description here

0

I port my answer https://tex.stackexchange.com/a/680651/250119 for listings package to minted package. Explanation how it works etc. is in that answer.

\documentclass{article}
\usepackage{minted}
\usepackage{graphicx}
\usepackage{tikz}
\begin{document}


\RenewDocumentCommand\theFancyVerbLine{}{%
    \tikz[remember picture] \coordinate (line\the\value{FancyVerbLine});% remember this location
    % --
    \rmfamily\tiny\phantom{\arabic{FancyVerbLine}}% leave space equal to the line number itself
    % \tiny must be outside any group so that it applies to the following \kern
    % --
    \xappto\typesetPendingLineNumbers{\actualTypesetLineNumber{\the\value{FancyVerbLine}}}% remember to typeset it later
}

% this command must be robust because it's used inside \xappto
\NewDocumentCommand\actualTypesetLineNumber{m}{%
    \node [anchor=south west, inner sep=0pt] at (line#1){\rmfamily\tiny#1};% actually typeset it now, need to copy the \tiny here
}

\AddToHook{env/minted/begin}{%
    \gdef\typesetPendingLineNumbers{}%
}

\AddToHook{env/minted/after}{%
    \begin{tikzpicture}[remember picture, overlay]%
    \typesetPendingLineNumbers
    \end{tikzpicture}%
}

\begin{minted}[linenos]{java}
public class IataCode {
    public static void printIATACodes(String[] myArray) {
        for (int i = 0; i < myArray.length; i++) {
            System.out.println(myArray[i]);
        }
    }

    public static void main(String[] args) {
        String[] iataCodes = new String[4];
        // Flughafen München
        iataCodes[0] = "MUC";
        // Flughafen Berlin Brandenburg
        iataCodes[1] = "BER";
        // Flughafen Augsburg
        iataCodes[2] = "AGB";
        printIATACodes(iataCodes);
    }
}
\end{minted}

\RenewDocumentCommand\theFancyVerbLine{}{\rmfamily \tiny \arabic {FancyVerbLine}}  % default definition

\begin{minted}[linenos]{java}
public class IataCode {
    public static void printIATACodes(String[] myArray) {
        for (int i = 0; i < myArray.length; i++) {
            System.out.println(myArray[i]);
        }
    }

    public static void main(String[] args) {
        String[] iataCodes = new String[4];
        // Flughafen München
        iataCodes[0] = "MUC";
        // Flughafen Berlin Brandenburg
        iataCodes[1] = "BER";
        // Flughafen Augsburg
        iataCodes[2] = "AGB";
        printIATACodes(iataCodes);
    }
}
\end{minted}
\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .