Comment puis-je convertir automatiquement tous les fichiers de code source d'un dossier (récursivement) en un seul PDF avec mise en évidence de la syntaxe?

29

Je voudrais convertir le code source de quelques projets en un seul fichier imprimable pour économiser sur une clé USB et l'imprimer facilement plus tard. Comment puis je faire ça?

modifier

Tout d'abord, je tiens à préciser que je souhaite uniquement imprimer les fichiers et répertoires non masqués (donc pas de contenu, .gitpar exemple).

Pour obtenir une liste de tous les fichiers non masqués dans les répertoires non masqués du répertoire en cours, vous pouvez exécuter la find . -type f ! -regex ".*/\..*" ! -name ".*"commande comme vu comme la réponse dans ce fil .

Comme suggéré dans ce même fil, j'ai essayé de créer un fichier pdf des fichiers en utilisant la commande find . -type f ! -regex ".*/\..*" ! -name ".*" ! -empty -print0 | xargs -0 a2ps -1 --delegate no -P pdfmais malheureusement le fichier pdf résultant est un gâchis complet .

Bentley4
la source
Je ne sais pas si cela correspond à vos besoins, mais avec a2ps -P file *.srcvous, vous pouvez produire des fichiers postscript à partir de votre code source. Mais les fichiers PS doivent être convertis et combinés par la suite.
mpy
En utilisant convert ( linux.about.com/od/commands/l/blcmdl1_convert.htm , imagemagick), vous devriez alors être en mesure de créer un pdf à partir des fichiers ps.
SBI
Pouvez-vous commenter ce que vous entendez par "désordre complet"? Cela ( i.stack.imgur.com/LoRhv.png ) ne me semble pas trop mal, en utilisant a2ps -1 --delegate=0 -l 100 --line-numbers=5 -P pdf- j'ai ajouté -l100 caractères par ligne pour éviter certains retours à la ligne et les numéros de ligne, mais ce n'est qu'une préférence personnelle.
mpy
Pour convertir ce projet (4 fichiers non vides non cachés chacun d'une page longue dans des répertoires non cachés) en pdf, j'avais environ 5 pages de code source et 39 pages de charabia.
Bentley4

Réponses:

47

J'ai été intrigué par votre question et je me suis un peu emporté. Cette solution va générer un joli fichier PDF avec un index cliquable et un code en couleur. Il trouvera tous les fichiers dans le répertoire et les sous-répertoires actuels et créera une section dans le fichier PDF pour chacun d'eux (voir les notes ci-dessous pour savoir comment rendre votre commande find plus spécifique).

Cela nécessite que vous ayez installé les éléments suivants (les instructions d'installation sont pour les systèmes basés sur Debian mais elles devraient être disponibles dans les référentiels de votre distribution):

  • pdflatex, coloretlistings

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

    Cela devrait également installer un système LaTeX de base si vous n'en avez pas installé.

Une fois ceux-ci installés, utilisez ce script pour créer un document LaTeX avec votre code source. L'astuce consiste à utiliser listings(une partie de texlive-latex-recommended) et color(installé par latex-xcolor) les packages LaTeX. C'est \usepackage[..]{hyperref}ce qui rend les listes dans la table des matières des liens cliquables.

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

Exécutez le script dans le répertoire contenant les fichiers source

bash src2pdf

Cela va créer un fichier appelé all.pdfdans le répertoire courant. J'ai essayé cela avec quelques fichiers source aléatoires que j'ai trouvés sur mon système (en particulier, deux fichiers de la source de vlc-2.0.0) et ceci est une capture d'écran des deux premières pages du PDF résultant:

entrez la description de l'image ici


Quelques commentaires:

  • Le script ne fonctionnera pas si vos noms de fichiers de code source contiennent des espaces. Puisque nous parlons de code source, je suppose qu'ils ne le font pas.
  • J'ai ajouté ! -name "*~"pour éviter les fichiers de sauvegarde.
  • Je vous recommande d'utiliser une findcommande plus spécifique pour trouver vos fichiers, sinon tout fichier aléatoire sera inclus dans le PDF. Si vos fichiers ont tous des extensions spécifiques ( .cet .hpar exemple), vous devez remplacer le finddans le script par quelque chose comme ceci

    find . -name "*\.c" -o -name "\.h" | sed 's/^\..//' | 
  • Jouez avec les listings options , vous pouvez modifier cela pour qu'il soit exactement comme vous le souhaitez.
terdon
la source
1
Wow, c'est ce que j'appelle une réponse! :)
mpy
1
OMG terdon, vous étiez propriétaire de cette question ^^. Pour les autres personnes qui essaient le script: si vous rencontrez src2pdf: line 36: warning: here-document at line 5 delimited by end-of-file (wanted EOF')lors de l'exécution du script, vous devez supprimer les espaces sur la ligne EOF pour que cela fonctionne.
Bentley4
1
Si votre fichier est appelé, src2pdfinsérez-le ! -name "src2pdf"dans la findligne du script comme ceci find . -type f ! -regex ".*/\..*" ! -name "src2pdf" ! -name ".*" ! -name "*~" |pour l'omettre dans le pdf.
Bentley4
1
@ Bentley4 merci! J'ai supprimé l'espace (il a été ajouté lorsque j'ai collé le script dans la réponse) et j'ai ajouté le filtre pour supprimer le script lui-même des findrésultats (j'avais enregistré le script dans un autre répertoire qui se trouvait dans mon $ PATH, donc je ne l'avais pas problème). De plus, vous pouvez changer la langue utilisée pour les fichiers source pour avoir un meilleur balisage en changeant language=C++pour ce que vous voulez, il peut traiter de nombreuses langues différentes, voir ici .
terdon
1
@qubodup je ne sais pas vraiment. LaTeX et UTF8 peuvent être délicats. Cela devrait fonctionner avec \usepackage[utf8]{inputenc} \ usepackage [german] {babel} `mais il échoue à mes tests. Cependant, je soupçonne que je ne le nourris pas vrai utf8. Cela pourrait valoir sa propre question mais je vous suggère de demander sur TeX - LaTeX , ils devraient savoir.
terdon
2

(à partir de StackOverflow )

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

Il en résultera un result.txt contenant:

  • Nom de fichier
  • séparateur (---)
  • Contenu du fichier .src
  • Répétez depuis le haut jusqu'à ce que tous les fichiers * .src soient terminés

Si votre code source a une extension différente, modifiez-la au besoin. Vous pouvez également modifier le bit d'écho pour ajouter les informations nécessaires (peut-être echo "filename $ 1" ou changer le séparateur, ou ajouter un séparateur de fin de fichier).

le lien a d'autres méthodes, utilisez donc la méthode que vous préférez. Je trouve que celui-ci est le plus flexible, bien qu'il s'accompagne d'une légère courbe d'apprentissage.

Le code fonctionnera parfaitement à partir d'un terminal bash (vient d'être testé sur un VirtualBox Ubuntu)

Si vous ne vous souciez pas du nom de fichier et ne vous souciez que du contenu des fichiers fusionnés:

cat *.src > result.txt

fonctionnera parfaitement bien.

Une autre méthode suggérée était:

grep "" *.src > result.txt

Ce qui préfixe chaque ligne avec le nom de fichier, ce qui peut être bon pour certaines personnes, personnellement, je trouve trop d'informations, c'est pourquoi ma première suggestion est la boucle for ci-dessus.

Nous remercions les membres du forum StackOverflow.

EDIT: Je viens de réaliser que vous recherchez spécifiquement HTML ou PDF comme résultat final, certaines solutions que j'ai vues consistent à imprimer le fichier texte en PostScript puis à convertir le PostScript en PDF. Un code que j'ai vu:

groff -Tps result.txt > res.ps

puis

ps2pdf res.ps res.pdf 

(Vous devez avoir ghostscript)

J'espère que cela t'aides.

Darius
la source
Cela ne fonctionne que pour les fichiers d'une extension spécifique (.src) mais je veux que chaque fichier soit placé dans ce pdf quelle que soit l'extension. Je voudrais cependant omettre les répertoires non cachés et les fichiers non cachés. J'ai édité le post original, pourriez-vous y jeter un œil?
Bentley4
2

Je sais que je suis trop tard, mais quelqu'un qui cherche une solution pourrait trouver cela utile.

Sur la base de la réponse de @ terdon, j'ai créé un script BASH qui fait le travail: https://github.com/eljuanchosf/source-code-to-pdf

eljuanchosf
la source
Veuillez citer les parties essentielles de la réponse à partir du ou des liens de référence, car la réponse peut devenir invalide si la ou les pages liées changent.
DavidPostill