Desativar a cópia de texto da listagem cunhada

Desativar a cópia de texto da listagem cunhada

Quero que minhas listagens cunhadas não tenham texto copiável. Eu encontrei isso:

É possível produzir um PDF com texto não copiável?

Mas depois de algumas horas de testes não consigo integrá-lo ao meu documento. Estou usando um reportdocumento LaTeX simples e sou capaz de construí-lo com XeTeX ou LuaLaTeX.

Exemplo de documento:

% lualatex -shell-escape minted.tex

\begin{filecontents*}{test.rb}
# this should not be copyable
def hello
  "world"
end
\end{filecontents*}

\documentclass[12pt,twoside,openright,a4paper]{report}
\usepackage[T1]{fontenc}
\usepackage{fontspec}
\usepackage[dvipsnames]{xcolor}
\usepackage{minted}
\setmainfont{Times New Roman}
\definecolor{bg}{rgb}{0.95,0.95,0.95}
\begin{document}
\chapter{Foo}
\section{Bar}
This should be copyable.
\inputminted[linenos, numbersep=5pt, tabsize=2, bgcolor=bg]{ruby}{test.rb}
And this again should be copyable.
\end{document}

Documento

Como eu gostaria que o texto copiado fosse:

Chapter 1 Foo
1.1 Bar
This should be copyable.

And this again should be copyable.

Responder1

Primeiro, concordo plenamente com Jesse Knight:

  • Quem fez essa exigência na sua faculdade é um sádico

Mas se você usar LuaTeX você pode destruir o glifo para mapeamento unicode no arquivo PDF criando um recurso de fonte especial:

% lualatex -shell-escape minted.tex

\begin{filecontents*}{test.rb}
# this should not be copyable
def hello
  "world"
end
\end{filecontents*}

\documentclass[12pt,twoside,openright,a4paper]{report}
\usepackage[T1]{fontenc}
\usepackage{fontspec}
\usepackage[dvipsnames]{xcolor}
\usepackage{minted}
\setmainfont{Times New Roman}
\usepackage{luacode}
\begin{luacode*}
  local function nocopy(tfmdata)
    for _, c in next, tfmdata.characters do
      c.tounicode = nil
    end
  end
  fonts.handlers.otf.features.register {
    name        = "nocopy",
    description = "disallow copying for this font",
    manipulators = {
        base = nocopy,
        node = nocopy,
        plug = nocopy,
    }
  }
\end{luacode*}
\setmonofont[RawFeature=nocopy]{Latin Modern Mono}
\definecolor{bg}{rgb}{0.95,0.95,0.95}
\begin{document}
\chapter{Foo}
\section{Bar}
This should be copyable.
\inputminted[linenos, numbersep=5pt, tabsize=2, bgcolor=bg]{ruby}{test.rb}
And this again should be copyable.
\end{document}

Com esta abordagem você não pode usar a mesma fonte na parte copiável e na parte não copiável, então se você carregar qualquer fonte uma vez com nocopye outra sem, apenas a primeira configuração será respeitada.

Se você não quiser afetar o texto \texttt "normal" e o material literal, você pode selecionar uma fonte especial para blocos cunhados:

% lualatex -shell-escape minted.tex

\begin{filecontents*}{test.rb}
# this should not be copyable
def hello
  "world"
end
\end{filecontents*}

\documentclass[12pt,twoside,openright,a4paper]{report}
\usepackage[T1]{fontenc}
\usepackage{fontspec}
\usepackage[dvipsnames]{xcolor}
\usepackage{minted}
\setmainfont{Times New Roman}
\usepackage{luacode}
\begin{luacode*}
  local function nocopy(tfmdata)
    for _, c in next, tfmdata.characters do
      c.tounicode = nil
    end
  end
  fonts.handlers.otf.features.register {
    name        = "nocopy",
    description = "disallow copying for this font",
    manipulators = {
        base = nocopy,
        node = nocopy,
        plug = nocopy,
    }
  }
\end{luacode*}
\newfontfamily\nocopyfont[RawFeature=nocopy]{Courier New}
\renewcommand\myFont{\nocopyfont}
\fvset{fontfamily=myFont}
\definecolor{bg}{rgb}{0.95,0.95,0.95}
\begin{document}
\chapter{Foo}
\section{Bar}
This should be copyable.
\inputminted[linenos, numbersep=5pt, tabsize=2, bgcolor=bg]{ruby}{test.rb}
And this again should be copyable (\texttt{This too}).
{
\tracingall\nocopyfont
}
\end{document}

Responder2

Solução

Talvez meu maior hack até agora ...

main.tex: compilar com --shell-escapepara permitir\write18elogiar

\documentclass[12pt,twoside,openright,a4paper]{report}
\usepackage{graphicx}
\newcommand{\nocopycode}[2]{%
  \immediate\write18{./code.sh #1 #2}
  \\[\textfloatsep]
  \includegraphics[width=\linewidth]{{#2}.png}%
  \\[\textfloatsep]
}
\usepackage{listings}
\begin{document}
\chapter{Foo}
\section{Bar}
This should be copyable.
\nocopycode{ruby}{hello.rb}
And this again should be copyable.
\end{document}

code.sh: pode ser necessário chmod +x code.shpermitir que o script seja executado

echo \\def\\xstyle{$1} \\def\\xfile{$2} > code-config.tex
pdflatex -interaction=nonstopmode code.tex
convert -trim -density 300 code.pdf $2.png

code.tex: Onde convertéimagemagick

\documentclass{article}
\usepackage{listings}
\usepackage{xcolor}
\lstset{
  basicstyle=\ttfamily,
  backgroundcolor=\color{lightgray},
}
\input{code-config.tex}
\begin{document}
  \pagenumbering{gobble}
  \lstinputlisting[language={\xstyle}]{\xfile}
\end{document}

... produzindo main.pdf:

saída

Notas:

  • Sinta-se à vontade para brincar e code.texobter o estilo que você gosta
  • Você pode descobrir que há artefatos de alias nas imagens de código, não há muito que possamos fazer
  • Se você tiver muito código, o tamanho do documento será grande
  • Não me peça para fazer isso funcionar no Windows
  • Quem fez essa exigência na sua faculdade é um sádico

Responder3

Se eu estivesse na sua situação, seguiria estas três etapas:

  1. Exporte a listagem tipográfica cunhada para um PDF (autônomo se couber na mesma página ou use outra classe de documento se a listagem abranger várias páginas),
  2. Execute o ghostscript para converter texto em caminhos vetoriais,
  3. Importe o pdf do caminho vetorial produzido pelo ghostscript na posição do ambiente cunhado.

Aqui está um exemplo (com autônomo):

  1. Etapa 1: digamos que temos todos os códigos criados em um arquivo independente (pode haver outras maneiras de exportar o código embutido para um PDF separado, não sei como)
% minted.tex
\documentclass{standalone}
\usepackage{minted}
\begin{document}
\begin{minipage}[t]{0.5\textwidth}
\begin{minted}{bash}
echo "Hello, world!"
\end{minted}
\end{minipage}
\end{document}

Execute seu mecanismo de látex favorito, eu usei >>lualatex --shell-escape minted.tex. Ele produzirá minted.pdf semelhante a: texto copiável

  1. Execute o seguinte script usando o comando:>>./fonttopath.sh minted.pdf mintedpath.pdf
% fonttopath.sh
#!/bin/sh
if [ "x$1" = "x" -o "x$2" = "x" ]; then
        echo Usage: `basename "$0"` "<input.pdf>" "<output.pdf>" >&2
        exit 1
fi
gs -o "$2" -sDEVICE=pdfwrite -dNOCACHE -dNoOutputFonts -dNOSUBSTDEVICECOLORS -c 60000000 setvmthreshold -f "$1"
  1. Importe mintedpath.pdf no local onde você planejava ter seu código criado.*

Vantagem desta solução: 1. nada será rasterizado, 2. o tamanho do arquivo será menor em comparação com a exportação e importação de formatos de imagem como jpeg, etc., 3. a qualidade de impressão não será degradada,4. Conforme solicitado em seus comentários, isso também funciona para blocos de código longos que abrangem várias páginas, para isso use documentclass como artigo em vez de autônomo e defina a geometria da página para corresponder à do seu relatório. O Ghostscript pode converter páginas abrangendo um PDF em um PDF de caminho vetorial equivalente abrangendo várias páginas que podem ser importadas como se você estivesse adicionando outro documento PDF em seu código látex.

  • Nota: Dependendo do visualizador de PDF, você ainda poderá selecionar esses caminhos vetoriais, mas tente colá-los em um processador de texto ou editor para perceber que ele não copia nenhum texto (porque nenhum texto foi deixado neste momento).

informação relacionada