Extraire les \newcommand d'un source Latex

Extraire les \newcommand d'un source Latex - Perl - Programmation

Marsh Posté le 14-09-2023 à 15:29:03    

Bonjour.  
Après de nombreuses heures de recherche, en vain, avec l'intention de parcourir mes sources LaTeX pour en isoler les tikzpictures, qui nécessitent des \newcommand, des \tikzset  ...,  j'ai fini par opter pour  Text::Balanced qw(extract_multiple extract_bracketed); et comme c'est loin d'être trivial autant laisser une place à la poursuite. 80)
 
Ce script parcourt les fichiers LaTeX dans un répertoire donné, extrait les blocs \tikzpicture, les commandes \newcommand et les commandes \tikzset, puis génère de nouveaux fichiers LaTeX pour chaque bloc tikzpicture avec les commandes appropriées incluses. Ces nouveaux fichiers garderont leur nom d'origine préfixé de la date de création et suffixé d'un numéro d'ordre pour chaque tikzpicture

Citation :


 
#!/usr/bin/perl
use strict;
use warnings;
use File::Find;
use File::Basename;
use POSIX qw(strftime);
use Text::Balanced qw(extract_multiple extract_bracketed);
 
#Un seul argument (répertoire source).
die "Usage: $0 <repertoire_de_depart>\n" unless @ARGV == 1;
 
my ($input_directory) = @ARGV;
 
# Définissez le répertoire de sortie où les fichiers seront enregistrés.
my $output_directory = "../Travaux_en_cours/tikzpictures/";
 
# Initialisation de variables.
my $num = 1;            # Numéro de départ
my $date = "";
my $filename = "";
my @newcommands = ();
my @tikzsets = ();
my $suffix = "";
my $file_contents = "";
my $content = "";
my $substring = "";
my $remainder = "";
my $prefix = "";
 
# Parcourir le répertoire  
find(\&extract_tikzpictures, $input_directory);
 
# Extraire les blocs tikzpicture.
sub extract_tikzpictures {
    if (-f $_ && /\.tex$/) {
        {
            local $/ = undef;
            open my $file, "<", $_ or die "Impossible d'ouvrir le fichier $_ : $!";
            $file_contents = <$file>;
            close $file;
 
            # Date de création du fichier.
            if (my ($atime) = (stat $_)[8]) {
                $date = strftime("%y%m%d", localtime($atime));
            } else {
                return; # Ne pas traiter les fichiers sans date de création.
            }
            ($filename, $suffix) = fileparse($_, qr/\.[^.]*/);
 
            # Tableaux pour stocker les commandes \newcommand et \tikzset
            @newcommands = ();
            @tikzsets = ();
 
            $num = 1;
 
            # Premier balayage pour extraire les commandes \newcommand
            my @matches = extract_multiple($file_contents, [
                sub { extract_bracketed($_[0], '{}') },
                #                 qr/(?:\\newcommand|\\renewcommand)(\\[^{}]*)(\{[^{}]*\})/s,
            ]);
 
            for my $i (0 .. $#matches / 2) {
                $prefix = $matches[$i * 2];      # Élément pair (préfixe)
                $content = $matches[$i * 2 + 1]; # Élément impair (contenu)
 
                # Affichez le préfixe et le contenu du couple actuel, sauf si le préfixe est vide ou ne contient pas "newcommand".
                unless (!$prefix || $prefix =~ /newcommand/) {
                    $prefix =~ s/^[^\n%]*%/%/gm;
                    push @newcommands, "$prefix$content";
                }
            }
 
            # Deuxième balayage pour extraire les commandes \tikzset
            @matches = extract_multiple($file_contents, [
                sub { extract_bracketed($_[0], '{}') },
                qr/\\tikzset/s,
            ]);
 
            for my $i (0 .. $#matches / 2) {
                $prefix = $matches[$i * 2];      # Élément pair (préfixe)
                $content = $matches[$i * 2 + 1]; # Élément impair (contenu)
 
                # Idem pour  "tikzset".
                unless (!$prefix || $prefix =~ /tikzset/) {
                    $prefix =~ s/^[^\n%]*%/%/gm;
                    $prefix =~ s/^[^\n%]*%//gm;
                    push @tikzsets, "$prefix$content";
                }
            }
 
            # Divisez le contenu du fichier en blocs tikzpicture.
            my @tikzpictures = ();
            my $tikzpicture = "";
            @tikzpictures = ();
            @tikzpictures = split /\\begin\{tikzpicture\}/, $file_contents;
 
            # Le premier élément (index 0) est vide car il précède la première \begin{tikzpicture}.
            shift @tikzpictures; # Supprimez le premier élément vide
 
            # Supprimer les espaces en début et fin de chaque tikzpicture si nécessaire
            # s/^\s+|\s+$//g for @tikzpictures;
 
            my $nombre_elements = scalar @tikzpictures;
 
            foreach my $dessin (@tikzpictures) {
                my $num_str = sprintf("%02d", $num);
                my $output_filename = $date . "_" . $filename . "_" . $num_str . ".tex";
                my $output_path = $output_directory . $output_filename;
 
                open my $output_file, ">", $output_path or die "Impossible de créer le fichier $output_path : $!";
 
                # Écrire le contenu du bloc d'entête dans le fichier de sortie.
                # Ce bloc facilitera la compilation isolée ou depuis un appel \input précédé de define COMPLETE  
                print $output_file "\\ifdefined\\COMPLETE\n";
                print $output_file "\\else\n";
                print $output_file "    \\input{/Users/dhenin/Desktop/14_Travaux_en_cours/preambule_texte.tex}\n";
                print $output_file " %   \\input{/Users/dhenin/Desktop/14_Travaux_en_cours/preambule-utf8.ltx}\n";
                print $output_file "    \\begin{document}\n";
                print $output_file "\\fi\n\n";
 
                # Inclure les commandes \newcommand et \tikzset du fichier d'origine.
                print $output_file join("\n", @newcommands) . "\n";
                print $output_file join("\n", @tikzsets) . "\n";
 
                # Inclure le bloc de dessin dans le fichier de sortie.
                print $output_file "\\begin{tikzpicture}$dessin";
 
                # Inclure la partie finale du fichier de sortie, y compris la fin du document LaTeX.
                print $output_file "\\ifdefined\\COMPLETE\n";
                print $output_file "\\else\n";
                print $output_file "    \\end{document}\n";
                print $output_file "\\fi\n";
 
                close $output_file;
 
                $num++; # Incrémenter le numéro de fichier pour le prochain bloc tikzpicture
            }
        }
    }
}
 


 
Attention s'il y a des include graphics ils ne sont pas traités.
Pour compiler les fichiers céées : for i in *.tex ; do  pdflatex -halt-on-error  -interaction=nonstopmode $i.tex  ; done
 
Bonjour chez vous

Reply

Marsh Posté le 14-09-2023 à 15:29:03   

Reply

Marsh Posté le 16-09-2023 à 14:40:56    

Citation :

@tikzpictures = split /\\begin\{tikzpicture\}/, $file_contents;
# Le premier élément (index 0) est vide car il précède la première \begin{tikzpicture}.
shift @tikzpictures; # Supprimez le premier élément vide


 
OK jusque la, mais après, je ferais  
@tikzpictures = map {shift(split(/\\end\{tikzpicture\}/, $_))}, @tikzpictures;
pour ne récupérer dans @tikzpictures que les portions qui étaient entre un \begin{tikzpicture} et un \end{tikzpicture}
ou @tikzpictures = map {'\\begin{tikzpicture}\n'.shift(split(/\\end\{tikzpicture\}/, $_)).'\n\\end{tikzpicture}'}, @tikzpictures;
si tu les veux avec délimiteur
 
Bon, c'est sans garantie, car je ne code presque plus en perl ces derniers temps.
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 17-09-2023 à 15:58:48    

Pourquoi ne pas utiliser une librairie de parsing latex, genre : https://github.com/xemlock/php-latex
 


---------------
Expert en expertises
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed