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

27

Eu gostaria de converter o código-fonte de alguns projetos em um arquivo imprimível para salvar em um usb e imprimi-lo facilmente mais tarde. Como posso fazer isso?

Editar

Primeiramente, quero esclarecer que desejo apenas imprimir os arquivos e diretórios não ocultos (portanto, nenhum conteúdo de .git , por exemplo).

Para obter uma lista de todos os arquivos não ocultos em diretórios não ocultos no diretório atual , é possível executar o comando find . -type f ! -regex ".*/\..*" ! -name ".*" como visto na resposta em este tópico .

Como 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 pdf , mas infelizmente o arquivo pdf resultante é uma bagunça completa .

    
por Bentley4 29.05.2013 / 12:55

3 respostas

46

Fiquei intrigado com a sua pergunta e fiquei meio empolgado. Essa solução gerará um arquivo PDF agradável com um índice clicável e um código destacado colorido. Ele localizará todos os arquivos no diretório atual e nos subdiretórios e criará uma seção no arquivo PDF para cada um deles (veja 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 estas devem estar disponíveis nos repositórios de sua distribuição):

  • pdflatex , color e listings

    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.

Depois de instalados, use este script para criar um documento LaTeX com seu código-fonte. O truque é usar o listings (parte de texlive-latex-recommended ) e color (instalado por latex-xcolor ) Pacotes LaTeX. O \usepackage[..]{hyperref} é o que torna as listagens nos links clicáveis do índice.

#!/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.pdf no diretório atual. Eu tentei isso com um par de arquivos fonte 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:

Algunscomentários:

  • Oscriptnãofuncionaráseosnomesdosarquivosdecódigo-fontecontiveremespaços.Jáqueestamosfalandodecódigo-fonte,vouassumirquenão.
  • Euadicionei!-name"*~" para evitar arquivos de backup.
  • Recomendo que você use um comando find 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 ( .c e .h , por exemplo), você deve substituir o find no script por algo assim

    find . -name "*\.c" -o -name "\.h" | sed 's/^\..//' | 
    
  • Brinque com as opções listings , você pode ajustar isso para ser exatamente como você deseja.
por 29.05.2013 / 22:29
2

(de StackOverflow )

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

Isso resultará em um resultado.txt contendo:

  • Nome do arquivo
  • separador (---)
  • Conteúdo do arquivo .src
  • Repita desde o início até que todos os arquivos * .src sejam feitos

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

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

O código será executado perfeitamente a partir de um terminal bash (apenas testado em um Ubuntu VirtualBox)

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

cat *.src > result.txt

funcionará perfeitamente bem.

Outro método sugerido foi:

grep "" *.src > result.txt

O qual prefixará cada linha com o nome do arquivo, o que pode ser bom para algumas pessoas, pessoalmente acho que é muita informação, daí porque minha primeira sugestão é o loop for acima.

Acredite nas pessoas do fórum do StackOverflow.

EDITAR: Acabei de perceber que você está atrás especificamente de HTML ou PDF como resultado final, algumas soluções que já vi é imprimir o arquivo de texto em PostScript e depois converter postscript em PDF. Algum código que vi:

groff -Tps result.txt > res.ps

então

ps2pdf res.ps res.pdf 

(requer que você tenha ghostscript)

Espero que isso ajude.

    
por 29.05.2013 / 17:57
2

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

Com base na resposta de @ terdon, criei um script BASH que faz o trabalho: link

    
por 24.06.2016 / 23:00