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.

Martin Thoma
  • 18,799
  • 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). – Konrad Rudolph Nov 18 '12 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 Nov 18 '12 at 18:20

3 Answers3

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}
  • I have tried attachfile (and embedfile with navigator), but it seems not to work: https://github.com/MartinThoma/LaTeX-examples/tree/master/documents/attachfile-example Am I using it wrong? Is there any minimal example how to use attachfile? – Martin Thoma Dec 19 '12 at 09: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? – cyberSingularity Dec 19 '12 at 09:23
  • Yes, it doesn't work with evince and Google Chromes internal PDF-viewer, but it does work with Adobe Reader. Thanks :-) – Martin Thoma Dec 19 '12 at 09: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] = &quot;MUC&quot;;
    // Flughafen Berlin Brandenburg
    iataCodes[1] = &quot;BER&quot;;
    // Flughafen Augsburg
    iataCodes[2] = &quot;AGB&quot;;
    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

user202729
  • 7,143
Marijn
  • 37,699
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] = &quot;MUC&quot;;
    // Flughafen Berlin Brandenburg
    iataCodes[1] = &quot;BER&quot;;
    // Flughafen Augsburg
    iataCodes[2] = &quot;AGB&quot;;
    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] = &quot;MUC&quot;;
    // Flughafen Berlin Brandenburg
    iataCodes[1] = &quot;BER&quot;;
    // Flughafen Augsburg
    iataCodes[2] = &quot;AGB&quot;;
    printIATACodes(iataCodes);
}

} \end{minted} \end{document}

user202729
  • 7,143