Como converter automaticamente todos os arquivos de código-fonte em uma pasta (recursivamente) em um único PDF com destaque de sintaxe?

29

Gostaria de converter o código fonte de alguns projetos em um arquivo imprimível para economizar em um usb e imprimir facilmente mais tarde. Como eu posso fazer isso?

Editar

Primeiro, quero esclarecer que só quero imprimir os arquivos e diretórios não ocultos (portanto, sem conteúdo .git).

Para obter uma lista de todos os arquivos não ocultos em diretórios não ocultos no diretório atual, você pode executar o find . -type f ! -regex ".*/\..*" ! -name ".*"comando como visto como a resposta neste encadeamento .

Conforme sugerido no mesmo tópico, tentei criar um arquivo pdf dos arquivos usando o comando, find . -type f ! -regex ".*/\..*" ! -name ".*" ! -empty -print0 | xargs -0 a2ps -1 --delegate no -P pdfmas infelizmente o arquivo pdf resultante é uma bagunça completa .

Bentley4
fonte
Não sei se isso se adapta às suas necessidades, mas a2ps -P file *.srcvocê pode produzir arquivos postscript a partir do seu código-fonte. Mas os arquivos PS precisam ser convertidos e combinados posteriormente.
Mpy
Usando convert ( linux.about.com/od/commands/l/blcmdl1_convert.htm , imagemagick), você poderá criar um pdf a partir dos arquivos ps.
SBI
Você pode comentar o que você quer dizer com "bagunça completa"? Isso ( i.stack.imgur.com/LoRhv.png ) não parece muito ruim para mim, usando a2ps -1 --delegate=0 -l 100 --line-numbers=5 -P pdf- eu adicionei -l100 caracteres por linha para evitar que algumas palavras sejam digitadas e números de linha, mas isso é apenas uma preferência pessoal.
Mpy
Para converter esse projeto (4 arquivos não ocultos e não ocultos, cada um com uma página em diretórios não ocultos) em pdf, eu tinha cerca de 5 páginas de código-fonte e 39 páginas de rabiscos.
Bentley4

Respostas:

47

Fiquei intrigado com sua pergunta e fiquei meio empolgado. Esta solução irá gerar um bom arquivo PDF com um índice clicável e código destacado em cores. Ele localizará todos os arquivos no diretório e subdiretórios atuais e criará uma seção no arquivo PDF para cada um deles (consulte as notas abaixo para saber como tornar seu comando find mais específico).

Requer que você tenha o seguinte instalado (as instruções de instalação são para sistemas baseados em Debian, mas elas devem estar disponíveis nos repositórios da sua distribuição):

  • pdflatex, colorelistings

    sudo apt-get install texlive-latex-extra latex-xcolor texlive-latex-recommended

    Isso também deve instalar um sistema LaTeX básico, se você não tiver um instalado.

Uma vez instalados, use este script para criar um documento LaTeX com o seu código-fonte. O truque é usar os pacotes listings(parte dos texlive-latex-recommended) e color(instalados pelos latex-xcolor) LaTeX. O \usepackage[..]{hyperref}é o que faz com que as listagens na tabela de conteúdo links clicáveis.

#!/usr/bin/env bash

tex_file=$(mktemp) ## Random temp file name

cat<<EOF >$tex_file   ## Print the tex file header
\documentclass{article}
\usepackage{listings}
\usepackage[usenames,dvipsnames]{color}  %% Allow color names
\lstdefinestyle{customasm}{
  belowcaptionskip=1\baselineskip,
  xleftmargin=\parindent,
  language=C++,   %% Change this to whatever you write in
  breaklines=true, %% Wrap long lines
  basicstyle=\footnotesize\ttfamily,
  commentstyle=\itshape\color{Gray},
  stringstyle=\color{Black},
  keywordstyle=\bfseries\color{OliveGreen},
  identifierstyle=\color{blue},
  xleftmargin=-8em,
}        
\usepackage[colorlinks=true,linkcolor=blue]{hyperref} 
\begin{document}
\tableofcontents

EOF

find . -type f ! -regex ".*/\..*" ! -name ".*" ! -name "*~" ! -name 'src2pdf'|
sed 's/^\..//' |                 ## Change ./foo/bar.src to foo/bar.src

while read  i; do                ## Loop through each file
    name=${i//_/\\_}             ## escape underscores
    echo "\newpage" >> $tex_file   ## start each section on a new page
    echo "\section{$i}" >> $tex_file  ## Create a section for each filename

   ## This command will include the file in the PDF
    echo "\lstinputlisting[style=customasm]{$i}" >>$tex_file
done &&
echo "\end{document}" >> $tex_file &&
pdflatex $tex_file -output-directory . && 
pdflatex $tex_file -output-directory .  ## This needs to be run twice 
                                           ## for the TOC to be generated    

Execute o script no diretório que contém os arquivos de origem

bash src2pdf

Isso criará um arquivo chamado all.pdfno diretório atual. Eu tentei isso com alguns arquivos de origem aleatórios que encontrei no meu sistema (especificamente, dois arquivos da fonte de vlc-2.0.0) e esta é uma captura de tela das duas primeiras páginas do PDF resultante:

insira a descrição da imagem aqui


Alguns comentários:

  • O script não funcionará se os nomes dos arquivos de código-fonte contiverem espaços. Como estamos falando de código fonte, assumirei que não.
  • Eu adicionei ! -name "*~"para evitar arquivos de backup.
  • Eu recomendo que você use um findcomando mais específico para encontrar seus arquivos; caso contrário, qualquer arquivo aleatório será incluído no PDF. Se todos os seus arquivos tiverem extensões específicas ( .ce .hpor exemplo), você deverá substituir o findno script por algo como isto

    find . -name "*\.c" -o -name "\.h" | sed 's/^\..//' | 
  • Brinque com as listings opções , você pode ajustá-lo exatamente como você deseja.
Terdon
fonte
1
Uau, é isso que chamo de resposta! :)
Mpy
1
OMG Terdon, você era o dono dessa pergunta ^^. Para outras pessoas que tentam o script: se você se deparar src2pdf: line 36: warning: here-document at line 5 delimited by end-of-file (wanted EOF')ao executar o script, precisará excluir o espaço em branco na linha EOF para que funcione.
Bentley4
1
Se o seu arquivo for chamado src2pdf, insira ! -name "src2pdf"a findlinha no script como esta find . -type f ! -regex ".*/\..*" ! -name "src2pdf" ! -name ".*" ! -name "*~" |para omiti-lo no pdf.
Bentley4
1
@ Bentley4 obrigado! Eu removi o espaço em branco (foi adicionado quando colei o script na resposta) e adicionei o filtro para remover o próprio script dos findresultados (eu salvei o script em outro diretório que estava no meu $ PATH, então não tinha esse problema). Além disso, você pode alterar o idioma usado para que os arquivos de origem tenham uma melhor marcação, alterando language=C++para o que quiser, pois ele pode lidar com vários idiomas diferentes, veja aqui .
terdon
1
@ Qubodup Eu realmente não sei. LaTeX e UTF8 podem ser complicados. Ele deve trabalhar com \usepackage[utf8]{inputenc} \ usepackage [german] {babel} `mas falha em meus testes. No entanto, eu suspeito que não estou alimentando o utf8 de verdade. Isso pode valer a pena, mas eu sugiro que você pergunte no TeX - LaTeX , eles devem saber.
terdon
2

(do StackOverflow )

for i in *.src; do echo "$i"; echo "---"; cat "$i"; echo ; done > result.txt

Isso resultará em um result.txt contendo:

  • Nome do arquivo
  • separador (---)
  • Conteúdo do arquivo .src
  • Repita a partir do topo até que todos os arquivos * .src sejam concluídos

Se o seu código-fonte tiver extensão diferente, basta alterar conforme necessário. Você também pode editar o bit de eco para adicionar as informações necessárias (talvez faça eco "nome do arquivo $ 1" ou altere o separador ou adicione um separador de fim de arquivo).

o link tem outros métodos; portanto, use o método que você mais gosta. Acho que este é o mais flexível, embora venha com uma ligeira curva de aprendizado.

O código funcionará perfeitamente em um terminal bash (apenas testado em um Ubuntu VirtualBox)

Se você não se importa com o nome do arquivo e apenas se importa com o conteúdo dos arquivos mesclados:

cat *.src > result.txt

funcionará perfeitamente bem.

Outro método sugerido foi:

grep "" *.src > result.txt

Que prefixará cada linha com o nome do arquivo, o que pode ser bom para algumas pessoas. Pessoalmente, encontro muitas informações. Por isso, minha primeira sugestão é o loop for acima.

Crédito para as pessoas do fórum StackOverflow.

Edição: Acabei de perceber que você está buscando especificamente HTML ou PDF como resultado final. Algumas soluções que vi foram imprimir o arquivo de texto em PostScript e depois converter o postscript em PDF. Algum código que eu já vi:

groff -Tps result.txt > res.ps

então

ps2pdf res.ps res.pdf 

(Requer que você tenha o ghostscript)

Espero que isto ajude.

Darius
fonte
Isso funciona apenas para arquivos de uma extensão específica (.src), mas quero que todos os arquivos sejam colocados nesse pdf, independentemente da extensão. Eu gostaria de omitir diretórios não ocultos e arquivos não ocultos. Eu editei o post original, você poderia dar uma olhada?
Bentley4
2

Sei que estou muito atrasado, mas alguém que procura uma solução pode achar isso útil.

Com base na resposta de @ terdon, criei um script BASH que faz o trabalho: https://github.com/eljuanchosf/source-code-to-pdf

eljuanchosf
fonte
Cite as partes essenciais da resposta nos links de referência, pois a resposta pode se tornar inválida se as páginas vinculadas forem alteradas.
DavidPostill