Using perl Syntax Highlighting
- #!/usr/bin/perl
- use v5.18;
- use re 'eval';
- use autodie; # muere si ocurre un error
- use File::Basename; # separa el archivo de entrada
- use Config;
- # Constantes
- my $tempDir = "."; # temporary directory
- my $imageDir = "images"; # where to save the images
- my $ignore = "ignore"; # ignore verbatim environment
- my $exacount = 1; # Counter for images
- my $other = "other"; # otro entorno
- #--------------------- Arreglo de la extensión -------------------------
- my @SuffixList = ('.tex', '', '.ltx'); # posible extensión
- my ($name, $path, $ext) = fileparse($ARGV[0], @SuffixList);
- $ext = '.tex' if not $ext;
- #---------------- Creamos el directorio para las imágenes --------------
- -e $imageDir or mkdir($imageDir,0744) or die "No puedo crear $imageDir: $!\n";
- # Constantes para regex
- my $BP = '\\\\begin{postscript}';
- my $EP = '\\\\end{postscript}';
- my $BPL = '\begin{postscript}';
- my $EPL = '\end{postscript}';
- my $sipgf = 'pgfpicture';
- my $nopgf = 'pgfinterruptpicture';
- my $graphics = "graphic=\{\[scale=1\]$imageDir/$name-fig";
- ############################# PARTE 1 ##################################
- #---------------- Creamos un hash con los cambios ----------------------
- my %cambios = (
- # pspicture
- '\pspicture' => '\TRICKS',
- '\endpspicture' => '\ENDTRICKS',
- # pspicture
- '\begin{pspicture' => '\begin{TRICKS',
- '\end{pspicture' => '\end{TRICKS',
- # postscript
- '\begin{postscript}' => '\begin{POSTRICKS}',
- '\end{postscript}' => '\end{POSTRICKS}',
- # $other
- "\\begin\{$other" => '\begin{OTHER',
- "\\end\{$other" => '\end{OTHER',
- # document
- '\begin{document}' => '\begin{DOCTRICKS}',
- '\end{document}' => '\end{DOCTRICKS}',
- # tikzpicture
- '\begin{tikzpicture}' => '\begin{TIKZPICTURE}',
- '\end{tikzpicture}' => '\end{TIKZPICTURE}',
- # pgfinterruptpicture
- '\begin{pgfinterruptpicture'=> '\begin{PGFINTERRUPTPICTURE',
- '\end{pgfinterruptpicture' => '\end{PGFINTERRUPTPICTURE',
- # pgfpicture
- '\begin{pgfpicture}' => '\begin{PGFPICTURE}',
- '\end{pgfpicture}' => '\end{PGFPICTURE}',
- # ganttchart
- '\begin{ganttchart}' => '\begin{GANTTCHART}',
- '\end{ganttchart}' => '\end{GANTTCHART}',
- # circuitikz
- '\begin{circuitikz}' => '\begin{CIRCUITIKZ}',
- '\end{circuitikz}' => '\end{CIRCUITIKZ}',
- # forest
- '\begin{forest}' => '\begin{FOREST}',
- '\end{forest}' => '\end{FOREST}',
- # tikzcd
- '\begin{tikzcd}' => '\begin{TIKZCD}',
- '\end{tikzcd}' => '\end{TIKZCD}',
- # dependency
- '\begin{dependency}' => '\begin{DEPENDENCY}',
- '\end{dependency}' => '\end{DEPENDENCY}',
- );
- #--------------------------- Coment Verbatim --------------------------#
- open my $ENTRADA, '<', "$name$ext";
- my $archivo;
- {
- local $/;
- $archivo = <$ENTRADA>;
- }
- close $ENTRADA;
- # Variables y constantes
- my $no_del = "\0";
- my $del = $no_del;
- # Reglas
- my $llaves = qr/\{ .+? \} /x;
- my $no_corchete = qr/(?:\[ .+? \])? /x;
- my $delimitador = qr/\{ (?<del>.+?) \} /x;
- my $verb = qr/(spv|v|V)erb [*]? /ix;
- my $lst = qr/lstinline (?!\*) $no_corchete /ix;
- my $mint = qr/mint (?!\*) $no_corchete $llaves /ix;
- my $marca = qr/\\ (?:$verb | $lst | $mint ) (\S) .+? \g{-1} /x;
- my $comentario = qr/^ \s* \%+ .+? $ /mx;
- my $definedel = qr/\\ (?: DefineShortVerb | lstMakeShortInline ) $no_corchete $delimitador /ix;
- my $indefinedel = qr/\\ (?: UndefineShortVerb | lstDeleteShortInline) $llaves /ix;
- while ($archivo =~
- / $marca
- | $comentario
- | $definedel
- | $indefinedel
- | $del .+? $del # delimitado
- /pgmx) {
- my($pos_inicial, $pos_final) = ($-[0], $+[0]); # posiciones
- my $encontrado = ${^MATCH}; # lo encontrado
- if ($encontrado =~ /$definedel/){ # definimos delimitador
- $del = $+{del};
- $del = "\Q$+{del}" if substr($del,0,1) ne '\\'; # es necesario "escapar" el delimitador
- }
- elsif($encontrado =~ /$indefinedel/) { # indefinimos delimitador
- $del = $no_del;
- }
- else { # aquí se hacen los cambios
- while (my($busco, $cambio) = each %cambios) {
- $encontrado =~ s/\Q$busco\E/$cambio/g; # es necesario escapar $busco
- }
- substr $archivo, $pos_inicial, $pos_final-$pos_inicial, $encontrado; # insertamos los nuevos cambios
- pos($archivo)= $pos_inicial + length $encontrado; # re posicionamos la siguiente búsqueda
- }
- }
- # Write
- open my $SALIDA, '>', "$tempDir/$name-tmp$ext";
- print $SALIDA "$archivo";
- close $SALIDA;
- #--------------------- Coment Verbatim environment --------------------#
- my @lineas;
- {
- open my $FILE,'<',"$tempDir/$name-tmp$ext";
- @lineas = <$FILE>;
- close $FILE;
- }
- # Verbatim environments
- my $ENTORNO = qr/(?: (v|V)erbatim\*?| PSTexample | LTXexample| $ignore\*? | PSTcode | tcblisting\*? | spverbatim | minted | lstlisting | alltt | comment\*? | xcomment)/xi;
- # postscript environment
- my $POSTSCRIPT = qr/(?: postscript)/xi;
- # tikzpicture environment
- my $TIKZENV = qr/(?: tikzpicture)/xi;
- #
- my $DEL;
- # tcbverb verbatim
- my $tcbverb = qr/\\(?:tcboxverb|myverb)/;
- my $arg_brac = qr/(?:\[.+?\])?/;
- my $arg_curl = qr/\{(.+)\}/;
- # coment verbatim environment
- for (@lineas) {
- if (/\\begin\{($ENTORNO)(?{ $DEL = "\Q$^N" })\}/ .. /\\end\{$DEL\}/) {
- while (my($busco, $cambio) = each %cambios) {
- s/\Q$busco\E/$cambio/g;
- }
- }
- }
- # coment tcolorbox inline
- for (@lineas) {
- if (m/$tcbverb$arg_brac$arg_curl/) {
- while (my($busco, $cambio) = each %cambios) {
- s/\Q$busco\E/$cambio/g;
- }
- } # close
- }
- # remove postscript from hash
- delete @cambios{'\begin{postscript}','\end{postscript}'};
- # coment in postscript environment
- for (@lineas) {
- if (/\\begin\{($POSTSCRIPT)(?{ $DEL = "\Q$^N" })\}/ .. /\\end\{$DEL\}/) {
- while (my($busco, $cambio) = each %cambios) {
- s/\Q$busco\E/$cambio/g;
- }
- } # close postcript environment
- }
- # remove tikzpicture from hash
- delete @cambios{'\begin{tikzpicture}','\end{tikzpicture}'};
- # coment in tikzpicture environment
- for (@lineas) {
- if (/\\begin\{($TIKZENV)(?{ $DEL = "\Q$^N" })\}/ .. /\\end\{$DEL\}/) {
- while (my($busco, $cambio) = each %cambios) {
- s/\Q$busco\E/$cambio/g;
- }
- } # close TIKZ environment
- }
- # Write file
- open my $SALIDA, '>', "$tempDir/$name-tmp$ext";
- print $SALIDA @lineas;
- close $SALIDA;
- ############################# PARTE 2 ##################################
- #------------- Convert ALL into Postscript environments ---------------#
- open my $ENTRADA, '<', "$tempDir/$name-tmp$ext";
- my $archivo;
- {
- local $/;
- $archivo = <$ENTRADA>;
- }
- close $ENTRADA;
- ## Partición del documento
- my($cabeza,$cuerpo,$final) = $archivo =~ m/\A (.+?) (^\\begin{document} .+)(^\\end{document}.*)\z/msx;
- # \pspicture to \begin{pspicture}
- $cuerpo =~ s/\\pspicture(\*)?(.+?)\\endpspicture/\\begin{pspicture$1}$2\\end{pspicture$1}/gmsx;
- # pspicture to Postscript
- $cuerpo =~ s/
- (
- (?:\\psset\{[^\}]+\}.*?)?
- (?:\\begin\{pspicture(\*)?\})
- .*?
- (?:\\end\{pspicture(\*)?\})
- )
- /$BPL\n$1\n$EPL/gmsx;
- # pgfpicture to Postscript
- $cuerpo =~ s/
- (
- \\begin{$sipgf}
- .*?
- (
- \\begin{$nopgf}
- .+?
- \\end{$nopgf}
- .*?
- )*?
- \\end{$sipgf}
- )
- /$BPL\n$1\n$EPL/gmsx;
- # tikz to Postscript
- $cuerpo =~ s/
- (
- (?:\\tikzset(\{(?:\{.*?\}|[^\{])*\}).*?)? # si está lo guardo
- (?:\\begin\{tikzpicture\}) # aquí comienza la búsqueda
- .*? # guardo el contenido en $1
- (?:\\end\{tikzpicture\}) # termina la búsqueda
- ) # cierra $1
- /$BPL\n$1\n$EPL/gmsx;
- # rest to Postscript
- my $export = qr/(forest|ganttchart|tikzcd|circuitikz|dependency|$other\*?)/x;
- $cuerpo =~ s/(\\begin\{($export)\} (.*?) \\end\{\g{-2}\})/$BPL\n$1\n$EPL/gmsx;
- # Write
- open my $SALIDA, '>', "$tempDir/$name-tmp$ext";
- print $SALIDA "$cabeza$cuerpo$final";
- close $SALIDA;
- ##---------------------------- PARTE 3 -------------------------------##
- #-------------------------- Reverse changes ---------------------------#
- my %cambios = (
- # pst/tikz set
- '\PSSET' => '\psset',
- '\TIKZSET' => '\tikzset',
- # pspicture
- '\TRICKS' => '\pspicture',
- '\ENDTRICKS' => '\endpspicture',
- # pspicture
- '\begin{TRICKS' => '\begin{pspicture',
- '\end{TRICKS' => '\end{pspicture',
- # $other
- '\begin{OTHER' => "\\begin\{$other",
- '\end{OTHER' => "\\end\{$other",
- # document
- '\begin{DOCTRICKS}' => '\begin{document}',
- '\end{DOCTRICKS}' => '\end{document}',
- # tikzpicture
- '\begin{TIKZPICTURE}' => '\begin{tikzpicture}',
- '\end{TIKZPICTURE}' => '\end{tikzpicture}',
- # pgfinterruptpicture
- '\begin{PGFINTERRUPTPICTURE'=> '\begin{pgfinterruptpicture',
- '\end{PGFINTERRUPTPICTURE' => '\end{pgfinterruptpicture',
- # pgfpicture
- '\begin{PGFPICTURE}' => '\begin{pgfpicture}',
- '\end{PGFPICTURE}' => '\end{pgfpicture}',
- # ganttchart
- '\begin{GANTTCHART}' => '\begin{ganttchart}',
- '\end{GANTTCHART}' => '\end{ganttchart}',
- # circuitikz
- '\begin{CIRCUITIKZ}' => '\begin{circuitikz}',
- '\end{CIRCUITIKZ}' => '\end{circuitikz}',
- # forest
- '\begin{FOREST}' => '\begin{forest}',
- '\end{FOREST}' => '\end{forest}',
- # tikzcd
- '\begin{TIKZCD}' => '\begin{tikzcd}',
- '\end{TIKZCD}' => '\end{tikzcd}',
- # dependency
- '\begin{DEPENDENCY}' => '\begin{dependency}',
- '\end{DEPENDENCY}' => '\end{dependency}',
- );
- #-------------------------- Back Postscript ---------------------------#
- my @lineas;
- {
- open my $FILE,'<',"$tempDir/$name-tmp$ext";
- @lineas = <$FILE>;
- close $FILE;
- }
- # reverse in postscript environment
- for (@lineas) {
- if (/\\begin\{($POSTSCRIPT)(?{ $DEL = "\Q$^N" })\}/ .. /\\end\{$DEL\}/) {
- while (my($busco, $cambio) = each %cambios) {
- s/\Q$busco\E/$cambio/g;
- }
- } # close postscript environment changes
- }
- # Write
- open my $SALIDA, '>', "$tempDir/$name-tmp$ext";
- print $SALIDA @lineas;
- close $SALIDA;
- ##---------------------------- PARTE 4 -------------------------------##
- #--------------- Extract source code for PST/PGF/TIKZ -----------------#
- open my $ENTRADA, '<',"$tempDir/$name-tmp$ext";
- my $archivo;
- {
- local $/;
- $archivo = <$ENTRADA>;
- }
- close $ENTRADA;
- # Dividir el archivo
- my($cabeza,$cuerpo,$final) = $archivo =~ m/\A (.+?) (^\\begin{document} .+)(^\\end{document}.*)\z/msx;
- $cabeza .= <<"EXTRA";
- \\newenvironment{postscript}{}{}
- \\pagestyle{empty}
- EXTRA
- # Poner el atributo añadido a PostScript
- while ($cuerpo =~ /\\begin\{postscript\}/gsm) {
- my $corchetes = $1;
- my($pos_inicial, $pos_final) = ($-[1], $+[1]); # posición donde están los corchetes
- if (not $corchetes) {
- $pos_inicial = $pos_final = $+[0]; # si no hay corchetes, nos ponemos al final de \begin
- }
- if (not $corchetes or $corchetes =~ /\[\s*\]/) { # si no hay corchetes, o están vacíos,
- $corchetes = "[$graphics-$exacount}]"; # ponemos los nuestros
- }
- substr($cuerpo, $pos_inicial, $pos_final - $pos_inicial) = $corchetes;
- pos($cuerpo) = $pos_inicial + length $corchetes; # reposicionamos la búsqueda de la exp. reg.
- }
- continue {
- $exacount++;
- }
- #---------------------- Extract source code in images -----------------#
- while ($cuerpo =~ /$BP\[.+?(?<img_src_name>$imageDir\/.+?-\d+)\}\](?<code>.+?)(?=^$EP)/gsm) {
- open my $SALIDA, '>', "$+{'img_src_name'}$ext";
- print $SALIDA <<"EOC";
- $cabeza\\begin{document}$+{'code'}\\end{document}
- EOC
- close $SALIDA;
- }
- __END__
Coloreado en 0.012 segundos, usando GeSHi 1.0.8.4
Después de mucho pensar en el asunto de los anidados (son realmente un dolor de cabeza) me decidí por atacar el problema desde otro punto de vista:
- Creo un hash con las palabras que deseo cambiar dentro de líneas que me dan problemas y recorro todo el archivo haciendo los cambios y lo guardo.
- Como tengo varios entornos donde no deseo hacer cambios (postscript, y tikzpicture}), leo el archivo por líneas y usando for y quitando algunas claves del hash hago los cambios dentro de lo que no deseo modificar y guardo el archivo.
- Vuelvo a abrir el archivo y con expresiones regulares modifico lo que me interesa, ya no tengo anidados, puesto que modifiqué las palabras que me interferían y lo vuelvo a guardar.
- Creo un nuevo hash para volver las palabras a la normalidad solo dentro de \begin{postscript} ... \end{postscript} y lo guardo. Ahora está todo como lo deseo.
- Vuelvo a abrir el archivo y extraigo lo que me interesa.
Saludos.