#!/usr/bin/perl -s use strict; use warnings; use File::Basename; use English; use Encode; use File::Spec::Functions qw(rel2abs); use File::Temp qw/ cleanup /;#creation d un repertoire temporaire qui s efface automatiquement en sortie de programme => my ($handle, $nom_rep) = File::Temp->newdir(TEMPLATE => "toto_XXXX"); #fonction cleanup() => appel a cleanup() pour forcer la destruction des repertoires et fichier temporaires my $NOM_PROG = basename $PROGRAM_NAME;#$NOM_PROG contient le nom de ce script (utile pour afficher le nom du script dans les warning (warn) ou les messages d erreur (die) ) #pattern d un reel pour les regex (pour eviter d utiliser $RE{num}{real} du package Regexp::Common qui n est pas toujours disponible) my $format_reel = '[+-]?[\.]?\d+[\.]?\d*(?:[eE][+-]?\d*)?'; ##################################################################################################### # script pour generer automatiquement un document pdf qui resume les tests # disponibles (recopie des rubriques "But du test" et "Description du calcul" du # fichier README de cahque repertoire de test) # # Notes aux utilisateurs : # les repertoires de tests sont recherches dans toute l arborescence depuis l endroit ou # ce script est lance (recherche de tous les repertoires commencant par Test_R ou Test_L # A noter que si un des repertoires n a pas de fichier README, le script s arrete sans # creation du .pdf # # Notes aux developpeurs : # - l une des plus grandes difficultes est l encodage des fichiers pour gerer les accents # (en cas de gros probleme, la meilleure solution est de supprimer/remplacer les caracteres # les plus problematiques des fichiers README) # - c est difficile d anticiper ce que les gens vont ecrire dans les fichiers README. # un certain nombre de caracteres ou de groupes de caracteres ne sont pas directement utilisables # dans un fichier .tex # (par exemple : <, >, _, etc... ou bien encore les exposants ^3.14159265) # la gestion de ces caracteres se fait au cas par cas dans la subroutine ecrire_rubrique_README() # au niveau du bloc suivant (substitution de caracteres s///) : #-------------------------------------------------------------------------------- #-------------------------------------------------------------------------------- #A FAIRE EVOLUER : gestion au cas par cas des caracteres speciaux dans Latex #-------------------------------------------------------------------------------- #-------------------------------------------------------------------------------- # ... # ... # ... #-------------------------------------------------------------------------------- #-------------------------------------------------------------------------------- ##################################################################################################### #nom du fichier catalogue de tests my $NOM_PDF_CATALOGUE = "documentation_tests.pdf"; #encodage du fichier .tex temporaire (pour accepter les accents) my $ENCODAGE_TEX = 'iso-8859-15'; ######################################################################################################### # verifications prealables ######################################################################################################### #verif validite de l encodage $ENCODAGE_TEX @_ = grep {/^$ENCODAGE_TEX$/i} Encode->encodings(":all"); ($#_ > -1) or die "\nErreur (prog:$NOM_PROG) : encodage $ENCODAGE_TEX non disponible (changer la variable \$ENCODAGE_TEX dans l en-tete de ce script)...\n\n"; $ENCODAGE_TEX = $_[0]; #verif validite de la commande pdflatex verif_commande('pdflatex') or die "\nErreur (prog:$NOM_PROG) : commande pdflatex introuvable...\n\n"; #-verif validite de l option -halt-on-error de la commande pdflatex @_ = qx(pdflatex -help | grep -- -halt-on-error); ($#_ > -1) or die "\nErreur (prog:$NOM_PROG) : commande pdflatex => option -halt-on-error non existante...\n\n"; ######################################################################################################### # liste des repertoires de test ######################################################################################################### #liste des repertoires de tests rapides (Test_R) my @REP_TESTS_R = map {chomp($_); $_} qx(find . -name "Test_R*" -type d); #print "$_\n" for @REP_TESTS_R; #liste des repertoires de tests rapides (Test_R) my @REP_TESTS_L = map {chomp($_); $_} qx(find . -name "Test_L*" -type d); #print "$_\n" for @REP_TESTS_L; ######################################################################################################### # verification de la presence d un fichier README dans les tests rapides @REP_TESTS_R et les tests longs @REP_TESTS_L ######################################################################################################### my $is_absence_README = 0; #-dans les tests rapides foreach my $rep_test (@REP_TESTS_R,@REP_TESTS_L) { (-e "$rep_test/README") or do { print "\n" if(not $is_absence_README);#on passe une ligne si c est le premier repertoire defaillant warn "Erreur (prog:$NOM_PROG) : repertoire de test $rep_test ne contient pas de fichier README...\n"; $is_absence_README = 1; }; } #arret du programme si il y a absence d au moins 1 fichier README if($is_absence_README) { print "\n"; print_ligne_pointilles(); print "Erreur (prog:$NOM_PROG) : arret a cause de l absence de fichiers README\n"; print_ligne_pointilles(); die "\n"; } ######################################################################################################### # generation du catalogue des tests au format .pdf # rq : generation d un document latex puis d un document .pdf via pdflatex # a la fin, seul le .pdf restera, tous les fichiers intermediaires seront effaces) ######################################################################################################### #on va creer un repertoire temporaire qui est sense s effacer automatiquement # le probleme est que si un signal d interruption est envoye (ctrl-c par exemple), le repertoire ne sera pas efface. # donc, on va capturer certains signaux pour faire un appel a la subroutine sortie_programme() $SIG{INT} = \&sortie_programme;#INT => capture signal : ctrl-c ou kill -2 $SIG{TERM} = \&sortie_programme;#TERM => capture signal : kill -15 #remarque : par essence, le signal kill -9 ne peut pas etre capture #creation d un repertoire temporaire (... qui s effacera automatiquement en sortie de programme grace a l utilisation de la construction objet File::Temp->newdir() my $rep_tmp = File::Temp->newdir("rep_tmp_".$NOM_PROG.'_XXXXX'); my $racine_fic_latex = "toto"; #deplacement vers le repertoire temporaire chdir $rep_tmp; #------------------------------------------------------------------------------------------ #creation du fichier .tex avec encodage $ENCODAGE_TEX (et debut du document : preambule) #------------------------------------------------------------------------------------------ open(my $HANDLE_TEX, ">:encoding($ENCODAGE_TEX)", "$racine_fic_latex.tex"); preambule_fic_tex_tmp($HANDLE_TEX); #------------------------------------------------------------------------------------------ #corps du texte (d abord les tests rapides, ensuite les tests longs) #------------------------------------------------------------------------------------------ #--- tests rapides --- print $HANDLE_TEX "\\clearpage\\newpage\n"; print $HANDLE_TEX "\\section{Tests rapides}\n"; my $no_test = 0; foreach my $rep_test (@REP_TESTS_R) { $_ = $rep_test; s/^\.+\///; print "ajout test : $_\n"; #incrementation numero test $no_test++; #chemin du fichier README my $fic_README = "../$rep_test/README"; #derniere partie du nom du repertoire my $nom_test = basename $rep_test; $nom_test =~ s/_/\$\\_\$/g;#tiret bas entre dollars #ecriture d une nouvelle sous-section pour ce test print $HANDLE_TEX "\\subsection{Test\$\\_\$R n\$^\\circ\$$no_test : $nom_test}\n"; #ecriture du nom complet du repertoire sous forme d une arborescence simple print $HANDLE_TEX "\\noindent \\underline{R\\\'epertoire} :\\\\\n"; my @rep_arbo = split(/\/+/, $rep_test); shift(@rep_arbo) if($rep_arbo[0] =~ /^\.+$/);#suppression d un eventuel ./ ou ../ devant le nom du repertoire #--variables pour faire une jolie indentation via \hspace my $hspace_cm = 0.5; my $hspace_cm_incr = 0.35; foreach my $rep_arbo (@rep_arbo) { $rep_arbo =~ s/_/\$\\_\$/g; print $HANDLE_TEX "\\hspace*{${hspace_cm}cm}\$\\triangleright\$ $rep_arbo\\\\\n"; $hspace_cm += $hspace_cm_incr; } #saisie de l encodage du README (par defaut : rien) (rq : on utilise la commande linux/Unix "file") my $encodage_source = ''; #cas UTF-nombre (exemples : UTF-8, UTF-16, etc...) if(qx(file $fic_README) =~ /utf-(\d+)/i) { $encodage_source = ":encoding(UTF-$1)"; } #ecriture de la partie "But du test" ecrire_rubrique_README($fic_README, $encodage_source, $HANDLE_TEX, qw(But du test) ); #ecriture de la partie "Description du calcul" ecrire_rubrique_README($fic_README, $encodage_source, $HANDLE_TEX, qw(Description du calcul) ); } #--- tests longs --- print $HANDLE_TEX "\\clearpage\\newpage\n"; print $HANDLE_TEX "\\section{Tests longs}\n"; $no_test = 0; foreach my $rep_test (@REP_TESTS_L) { $_ = $rep_test; s/^\.+\///; print "ajout test : $_\n"; #incrementation numero test $no_test++; #chemin du fichier README my $fic_README = "../$rep_test/README"; #derniere partie du nom du repertoire my $nom_test = basename $rep_test; $nom_test =~ s/_/\$\\_\$/g;#tiret bas entre dollars #ecriture d une nouvelle sous-section pour ce test print $HANDLE_TEX "\\subsection{Test\$\\_\$L n\$^\\circ\$$no_test : $nom_test}\n"; #ecriture du nom complet du repertoire sous forme d une arborescence simple print $HANDLE_TEX "\\noindent \\underline{R\\\'epertoire} :\\\\\n"; my @rep_arbo = split(/\/+/, $rep_test); shift(@rep_arbo) if($rep_arbo[0] =~ /^\.+$/);#suppression d un eventuel ./ ou ../ devant le nom du repertoire #--variables pour faire une jolie indentation via \hspace my $hspace_cm = 0.5; my $hspace_cm_incr = 0.35; foreach my $rep_arbo (@rep_arbo) { $rep_arbo =~ s/_/\$\\_\$/g; print $HANDLE_TEX "\\hspace*{${hspace_cm}cm}\$\\triangleright\$ $rep_arbo\\\\\n"; $hspace_cm += $hspace_cm_incr; } #saisie de l encodage du README (par defaut : rien) (rq : on utilise la commande linux/Unix "file") my $encodage_source = ''; #cas UTF-nombre (exemples : UTF-8, UTF-16, etc...) if(qx(file $fic_README) =~ /utf-(\d+)/i) { $encodage_source = ":encoding(UTF-$1)"; } #ecriture de la partie "But du test" ecrire_rubrique_README($fic_README, $encodage_source, $HANDLE_TEX, qw(But du test) ); #ecriture de la partie "Description du calcul" ecrire_rubrique_README($fic_README, $encodage_source, $HANDLE_TEX, qw(Description du calcul) ); } #------------------------------------------------------------------------------------------ #fin de l ecriture du fichier .tex : ajout de end{document} #------------------------------------------------------------------------------------------ print $HANDLE_TEX "\\end{document}\n"; close($HANDLE_TEX); #------------------------------------------------------------------------------------------ #compilation pdflatex (1 premiere fois pour voir si ca marche et une 2eme fois pour generer la table des matieres et les hyperliens #------------------------------------------------------------------------------------------ print "\n"; print "compilation pdflatex (1ere fois)\n"; #-1ere comilation (pdflatex avec option -halt-on-error pour forcer a quitter a la moindre erreur) system("pdflatex -halt-on-error $racine_fic_latex.tex > toto.log"); #-verif presence .pdf if(not -e "$racine_fic_latex.pdf") { warn "\nErreur (prog:$NOM_PROG) : erreur a l execution de pdflatex.\n"; warn " Les fichiers suivants ont ete cree a des fins de debug :\n"; warn " - $NOM_PDF_CATALOGUE.tex (fichier .tex donne en argument de pdflatex)\n"; warn " - $NOM_PDF_CATALOGUE.error_log (affichage renvoye par pdflatex)\n"; warn "\n"; system("mv -f $racine_fic_latex.tex ../$NOM_PDF_CATALOGUE.tex"); system("mv -f toto.log ../$NOM_PDF_CATALOGUE.error_log"); chdir ".."; sortie_programme(); } #-2eme compilation (etant donne que ca a marche la 1ere fois, pdflatex ne peut pas echouer cette 2eme fois) print "compilation pdflatex (2eme fois)\n"; system("pdflatex $racine_fic_latex.tex > toto.log"); #deplacement du catalogue final vers le repertoire de depart sous le nom prevu par la variable $NOM_PDF_CATALOGUE system("mv -f $racine_fic_latex.pdf ../$NOM_PDF_CATALOGUE"); #retour au repertoire de depart chdir ".."; #affichage fin programme print "\n"; print_ligne_pointilles(); print "Le fichier $NOM_PDF_CATALOGUE a ete cree...\n"; print_ligne_pointilles(); print "\n"; #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #remarque : fin du programme => le repertoire temporaire $rep_tmp sera efface automatiquement # car utilisation de File::Temp->newdir() #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #-------------------------------------------------- #subroutine de sortie du programme #-------------------------------------------------- sub sortie_programme { #effacement du repertoire temporaire (subroutine cleanup() du package File::Temp) cleanup(); exit; } #-------------------------------------------------- #subroutine qui ecrit une rubrique du fichier du README #-------------------------------------------------- sub ecrire_rubrique_README { my $fic_source = shift; my $encodage_source = shift; my $handle_fic_destination = shift; my @mots_rubriques = @_; my $regexp = shift(@mots_rubriques); foreach my $mot (@mots_rubriques) { $regexp .= '\s+'."$mot"; } open(my $Hlocal, "<$encodage_source", "$fic_source"); while(<$Hlocal>) { next if(not /^\s*$regexp\s*$/i); $_ = <$Hlocal>; print $handle_fic_destination "\\subsubsection{Description du calcul}\n"; while(<$Hlocal>) { last if(/^\s*-+$/); chomp(); #-------------------------------------------------------------------------------- #-------------------------------------------------------------------------------- #A FAIRE EVOLUER : gestion au cas par cas des caracteres speciaux dans Latex #-------------------------------------------------------------------------------- #-------------------------------------------------------------------------------- s/_/\$\\_\$/g;#tiret bas (solution : entre dollars) s/\^($format_reel)/\$\^$1\$/g;#cas d un exposant mathematique : symbole circonflexe suivi d un nombre (solution : entre dollars) s/([<>])/\$$1\$/;#symboles inferieur et superieur (solution : entre dollars) #-------------------------------------------------------------------------------- #-------------------------------------------------------------------------------- print $handle_fic_destination "$_\\\\\n"; } last; } close($Hlocal); }#sub ecrire_rubrique_README #-------------------------------------------------- #subroutine permettant d ecrire une ligne de pointilles de la largeur du terminal #-------------------------------------------------- sub print_ligne_pointilles { use Term::ReadKey; my $nb_char_largeur_terminal = ( GetTerminalSize() )[0]; my $ligne_pointilles = ''; $ligne_pointilles .= '-' for(1 .. $nb_char_largeur_terminal); print "$ligne_pointilles\n"; }#sub print_message_avec_pointilles #-------------------------------------------------- #subroutine d ecriture du preambule du fichier .tex temporaire #-------------------------------------------------- sub preambule_fic_tex_tmp { my $handle = shift; print $handle '\documentclass[a4paper,12pt]{scrartcl} \usepackage[latin1]{inputenc} \usepackage[francais]{babel} \usepackage{epsfig,color} \usepackage{graphicx} \usepackage{hyperref} \usepackage{fancybox} \usepackage{wrapfig} %\usepackage{pslatex} \usepackage{amsmath} \usepackage{subfigure} %\usepackage{/Users/troufflard/LATEX/BIBLIOTHEQUE/macro_figure} %\usepackage{eurosym} \usepackage{calc} %\usepackage{t1enc} \usepackage{ifthen} \usepackage{lscape} \usepackage{tabularx} \usepackage{multirow} \usepackage{colortbl} %\newcolumntype{M}[1]{>{\raggedright}m{#1}} \usepackage{tikz} \usetikzlibrary{trees} \addto\captionsfrench{\def\figurename{Figure}} \addto\captionsfrench{\def\tablename{Tableau}} %\usepackage{hangcaption} \oddsidemargin 0.1cm \evensidemargin -0.9cm \topmargin -1cm \headsep 1cm \textwidth 17cm \textheight 24cm \parindent 0.5cm \raggedbottom \sloppy \setcounter{tocdepth}{2} \usepackage{hyperref} \hypersetup{ colorlinks=true, %colorise les liens breaklinks=true, %permet le retour à la ligne dans les liens trop longs urlcolor= blue, %couleur des hyperliens linkcolor= blue, %couleur des liens internes citecolor= green %couleur citation biblio } %creation d une longueur egale a \baselineskip pour l utiliser dans les tabular (car un bug incroyable fait que \baselineskip est egal a 0 dans les tabular!!!!) \newlength{\savebaselineskip} \setlength{\savebaselineskip}{\baselineskip} \title{Catalogue des tests} \date{\today} %\pagestyle{arabic} \pagenumbering{arabic} \begin{document} \maketitle \tableofcontents '; }#sub preambule_fic_tex_tmp ##################################################################################################### #subroutine qui recherche l existence d une commande et renvoie le premier path trouve (renvoie 0 si commande introuvable) ##################################################################################################### # en entree : # - nom de la commande # # en sortie : # - chemin aboslu de la commande (0 si commande introuvable) # sub verif_commande { my $cmd = shift;#nom de la commande #cas d un chemin absolu ou relatif (si la commande commence par . ou /. Par exemple : ./HZpp ../HZppfast ou /Users/dupont/bin/HZppfast) if($cmd =~ /^\./ or $cmd =~ /^\//) { #on passe la commande en chemin absolu $cmd = rel2abs($cmd); return $cmd; } #sinon on regarde dans la variable environnement $PATH foreach my $path (split(/\s*:\s*/, $ENV{PATH})) { if(-x "$path/$cmd") { #on s assure que c est un chemin absolu $cmd = rel2abs("$path/$cmd"); return $cmd; } } #on regarde a nouveau si la commande est en chemin absolu ou relatif # (cas d une commande qui ne commence pas par . ou / et qui n est pas dans les PATH. Par exemple : rep/HZpp) if(-x $cmd) { #on passe la commande en chemin absolu $cmd = rel2abs($cmd); return $cmd; } #cas ou la commande est introuvable return 0; }#sub verif_commande