¿Cómo puedo convertir automáticamente todos los archivos de código fuente en una carpeta (recursivamente) a un solo PDF con resaltado de sintaxis?

29

Me gustaría convertir el código fuente de algunos proyectos en un archivo imprimible para guardarlo en un usb e imprimirlo fácilmente más tarde. ¿Cómo puedo hacer eso?

Editar

En primer lugar, quiero aclarar que solo quiero imprimir los archivos y directorios no ocultos (por lo que no hay contenido de, .gitpor ejemplo).

Para obtener una lista de todos los archivos no ocultos en directorios no ocultos en el directorio actual , puede ejecutar el find . -type f ! -regex ".*/\..*" ! -name ".*"comando como se ve como la respuesta en este hilo .

Como se sugirió en ese mismo hilo, intenté hacer un archivo pdf de los archivos usando el comando, find . -type f ! -regex ".*/\..*" ! -name ".*" ! -empty -print0 | xargs -0 a2ps -1 --delegate no -P pdfpero desafortunadamente el archivo pdf resultante es un completo desastre .

Bentley4
fuente
No sé si se ajusta a sus necesidades, pero con a2ps -P file *.srcusted puede producir archivos postscript a partir de su código fuente. Pero los archivos PS deben convertirse y combinarse después.
mpy
Usando convert ( linux.about.com/od/commands/l/blcmdl1_convert.htm , imagemagick) debería poder crear un pdf desde los archivos ps.
OSE
¿Puedes comentar qué quieres decir con "desorden completo"? Esto ( i.stack.imgur.com/LoRhv.png ) no me parece tan malo, usando a2ps -1 --delegate=0 -l 100 --line-numbers=5 -P pdf: agregué -l100 caracteres por fila para evitar algunos ajustes de palabras y números de línea, pero eso es solo una preferencia personal.
Mpy
Para convertir este proyecto (4 archivos no vacíos no ocultos, cada uno de aproximadamente una página en directorios no ocultos) a pdf, tenía aproximadamente 5 páginas de código fuente y 39 páginas de galimatías.
Bentley4

Respuestas:

47

Tu pregunta me intrigó y me dejé llevar. Esta solución generará un buen archivo PDF con un índice en el que se puede hacer clic y un código resaltado en color. Encontrará todos los archivos en el directorio y subdirectorios actuales y creará una sección en el archivo PDF para cada uno de ellos (consulte las notas a continuación para saber cómo hacer que su comando de búsqueda sea más específico).

Requiere que tenga instalado lo siguiente (las instrucciones de instalación son para sistemas basados ​​en Debian, pero deben estar disponibles en los repositorios de su distribución):

  • pdflatex, colorylistings

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

    Esto también debería instalar un sistema LaTeX básico si no tiene uno instalado.

Una vez que estén instalados, use este script para crear un documento LaTeX con su código fuente. El truco es usar los paquetes listings(parte de texlive-latex-recommended) e color(instalados por latex-xcolor) LaTeX. Esto \usepackage[..]{hyperref}es lo que hace que los listados en la tabla de contenido hagan clic en enlaces.

#!/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    

Ejecute el script en el directorio que contiene los archivos de origen.

bash src2pdf

Eso creará un archivo llamado all.pdfen el directorio actual. Intenté esto con un par de archivos fuente aleatorios que encontré en mi sistema (específicamente, dos archivos de la fuente de vlc-2.0.0) y esta es una captura de pantalla de las dos primeras páginas del PDF resultante:

ingrese la descripción de la imagen aquí


Un par de comentarios:

  • El script no funcionará si sus nombres de archivo de código fuente contienen espacios. Como estamos hablando del código fuente, supondré que no.
  • Agregué ! -name "*~"para evitar archivos de respaldo.
  • Sin findembargo, le recomiendo que use un comando más específico para encontrar sus archivos, de lo contrario, cualquier archivo aleatorio se incluirá en el PDF. Si todos sus archivos tienen extensiones específicas ( .cy, .hpor ejemplo), debe reemplazar findel script en algo como esto

    find . -name "*\.c" -o -name "\.h" | sed 's/^\..//' | 
  • Juegue con las listings opciones , puede ajustar esto para que sea exactamente como lo desee.
terdon
fuente
1
Wow, eso es lo que yo llamo una respuesta! :)
mpy
1
OMG terdon, tenías esa pregunta ^^. Para otras personas que prueban el script: si te encuentras src2pdf: line 36: warning: here-document at line 5 delimited by end-of-file (wanted EOF')con el script, debes eliminar el espacio en blanco en la línea EOF para que funcione.
Bentley4
1
Si se llama a su archivo src2pdf, inserte ! -name "src2pdf"en la findlínea en el script como este find . -type f ! -regex ".*/\..*" ! -name "src2pdf" ! -name ".*" ! -name "*~" |para omitirlo en el pdf.
Bentley4
1
@ Bentley4 gracias! Eliminé el espacio en blanco (se agregó cuando pegué el script en la respuesta) y agregué el filtro para eliminar el script de los findresultados (había guardado el script en otro directorio que estaba en mi $ PATH, así que no tenía eso problema). Además, puede cambiar el idioma utilizado para que los archivos de origen tengan un mejor marcado cambiando language=C++a lo que desee, puede manejar muchos idiomas diferentes, consulte aquí .
terdon
1
@qubodup Realmente no lo sé. LaTeX y UTF8 pueden ser complicados. Se debe trabajar con \usepackage[utf8]{inputenc} \ usepackage [alemán] {babel} `pero falla en mis pruebas. Sin embargo, sospecho que no lo estoy alimentando con utf8 verdadero. Puede que valga la pena su propia pregunta, pero le sugiero que pregunte en TeX - LaTeX , deberían saberlo.
terdon
2

(de StackOverflow )

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

Esto dará como resultado un resultado.txt que contiene:

  • Nombre del archivo
  • separador (---)
  • Contenido del archivo .src
  • Repita desde arriba hasta que todos los archivos * .src estén listos

Si su código fuente tiene una extensión diferente, simplemente cambie según sea necesario. También puede editar el bit de eco para agregar la información necesaria (tal vez echo "nombre de archivo $ 1" o cambiar el separador o agregar un separador de fin de archivo).

el enlace tiene otros métodos, así que usa el método que más te guste. Creo que este es el más flexible, aunque viene con una ligera curva de aprendizaje.

El código se ejecutará perfectamente desde un terminal bash (recién probado en un Ubuntu VirtualBox)

Si no te importa el nombre de archivo y solo te importa el contenido de los archivos combinados:

cat *.src > result.txt

Funcionará perfectamente bien.

Otro método sugerido fue:

grep "" *.src > result.txt

Que prefijará cada línea con el nombre del archivo, lo que puede ser bueno para algunas personas, personalmente encuentro demasiada información, de ahí que mi primera sugerencia sea el bucle for anterior.

Crédito para aquellos en el foro de StackOverflow personas.

EDITAR: Acabo de darme cuenta de que buscas específicamente HTML o PDF como resultado final, algunas soluciones que he visto es imprimir el archivo de texto en PostScript y luego convertir PostScript a PDF. Algún código que he visto:

groff -Tps result.txt > res.ps

luego

ps2pdf res.ps res.pdf 

(Requiere que tengas ghostscript)

Espero que esto ayude.

Darius
fuente
Esto solo funciona para archivos de una extensión específica (.src) pero quiero que cada archivo se coloque en ese pdf independientemente de la extensión. Sin embargo, me gustaría omitir directorios no ocultos y archivos no ocultos. Edité la publicación original, ¿podrías echarle un vistazo?
Bentley4
2

Sé que estoy muuuy tarde, pero alguien que busque una solución puede encontrar esto útil.

Basado en la respuesta de @ terdon, he creado un script BASH que hace el trabajo: https://github.com/eljuanchosf/source-code-to-pdf

eljuanchosf
fuente
Cite las partes esenciales de la respuesta de los enlaces de referencia, ya que la respuesta puede volverse inválida si las páginas enlazadas cambian.
DavidPostill