
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 report
documento 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}
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 nocopy
e 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-escape
para permitir\write18
elogiar
\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.sh
permitir 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
:
Notas:
- Sinta-se à vontade para brincar e
code.tex
obter 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:
- 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),
- Execute o ghostscript para converter texto em caminhos vetoriais,
- Importe o pdf do caminho vetorial produzido pelo ghostscript na posição do ambiente cunhado.
Aqui está um exemplo (com autônomo):
- 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:
- 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"
- 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).