From c5c0896410d21895e17ad7390044b4a9c78dc9a5 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Fri, 21 Aug 2020 21:01:17 +0000 Subject: pst2pdf (21aug20) git-svn-id: svn://tug.org/texlive/trunk@56149 c570f23f-e606-0410-a88d-b1316a301751 --- .../texk/texlive/linked_scripts/pst2pdf/pst2pdf.pl | 3209 +++++++++++++------- 1 file changed, 2091 insertions(+), 1118 deletions(-) (limited to 'Build/source') diff --git a/Build/source/texk/texlive/linked_scripts/pst2pdf/pst2pdf.pl b/Build/source/texk/texlive/linked_scripts/pst2pdf/pst2pdf.pl index e53aa94fc2c..3b33bdbf91c 100755 --- a/Build/source/texk/texlive/linked_scripts/pst2pdf/pst2pdf.pl +++ b/Build/source/texk/texlive/linked_scripts/pst2pdf/pst2pdf.pl @@ -1,236 +1,487 @@ -eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' && eval 'exec perl -S $0 $argv:q' - if 0; - -use strict; # to be sure, that all is safe ... :-) -use v5.18; -# $Id: pst2pdf.pl 119 2014-09-24 12:04:09Z herbert $ -# v. 0.18 2017-10-04 simplify the use of PSTricks with pdf -# (c) Herbert Voss -# Pablo González Luengo -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at -# your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, -# MA 02111-1307 USA -# -use re 'eval'; -use File::Path; # creating/removing dirs -use File::Copy; # copying files -use File::Basename; # scan argument -use IO::File; # simple IO operation -use Getopt::Long qw(:config bundling_override); # read parameter and activate "bundling" -use autodie; # more safe -use Config; -use File::Spec; +#!/usr/bin/env perl +use v5.26; + +############################# LICENCE ################################## +# $Id: pst2pdf.pl 119 2014-09-24 12:04:09Z herbert $ # +# v0.19 2020-08-16 simplify the use of PSTricks with pdf # +# (c) Herbert Voss # +# Pablo González L # +# # +# This program is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, but # +# WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # +# General Public License for more details. # +######################################################################## + +use Getopt::Long qw(:config bundling_override no_ignore_case); # require_order +use File::Spec::Functions qw(catfile devnull); +use File::Basename; +use Archive::Tar; +use Data::Dumper; +use FileHandle; +use IO::Compress::Zip qw(:all); +use File::Path qw(remove_tree); +use File::Temp qw(tempdir); +use POSIX qw(strftime); +use File::Copy; use File::Find; +use Env qw(PATH); +use autodie; +use Config; +use Cwd; +use if $^O eq 'MSWin32', 'Win32'; +use if $^O eq 'MSWin32', 'Win32::Console::ANSI'; # need for color :) +use Term::ANSIColor; + +### Internal vars +my $tempDir = tempdir( CLEANUP => 1); # temporary directory +my $workdir = cwd; # current working dir +my $imgdir = 'images'; # where to save the images +my $margins = '1'; # margins in pdfcrop +my $clear = 0; # 0 or 1, clears all temporary files +my $dpi = '300'; # very low value for the png's +my $runs = '1'; # set runs for compliler +my $nocorp = 0; # 1->no crop pdf files created +my $norun = 0; # 1->no create images +my $noprew = 0; # 1->create images in nopreview mode +my $runbibtex = 0; # 1->runs bibtex +my $runbiber = 0; # 1->runs biber and sets $runbibtex=0 +my $all = 0; # 1->create all images and files for type +my $xetex = 0; # 1->Using (Xe)LaTeX for compilation. +my $luatex = 0; # 1->Using dvilualatex for compilation. +my $latexmk = 0; # 1->Using latexmk for compiler output file. +my $arara; # 1->Using arara for compiler output file. +my $nosource = 0; # Delete TeX source for images +my $srcenv; # write only source code of environments +my $nopdf; # Don't create a pdf image files +my $force; # try to capture \psset +my $nocrop; # Don't crop image files +my $zip; # compress files generated in .zip +my $tar; # compress files generated in .tar.gz +my $help; # help info +my $version; # version info +my $shell; # enable -shell-escape +my $verbose = 0; # verbose info +my @verb_env_tmp; # store verbatim environments +my $tmpverbenv; # save verbatim environment +my $myverb = 'myverb' ; # internal \myverb macro +my $write18; # storing write18 for compiler in TeXLive and MikTeX +my $gscmd; # ghostscript executable name +my $gray; # gray scale ghostscript +my $log = 0; # log file +my $PSTexa = 0; # run extract PSTexample environments +my $STDenv = 0; # run extract pspicture/psfrag environments +my @currentopt; # storing current options for log file +my %opts_cmd; # hash to store options for Getopt::Long and log + +### Script identification +my $scriptname = 'pst2pdf'; +my $nv = 'v0.19'; +my $date = '2020-08-17'; +my $ident = '$Id: pst2pdf.pl 119 2020-08-16 12:04:09Z herbert $'; + +### Log vars +my $LogFile = "$scriptname.log"; +my $LogWrite; +my $LogTime = strftime("%y/%m/%d %H:%M:%S", localtime); + +### Error in command line +sub errorUsage { + my $msg = shift; + die color('red').'* Error!!: '.color('reset').$msg. + " (run $scriptname --help for more information)\n"; + return; +} + +### Extended error messages +sub exterr { + chomp(my $msg_errno = $!); + chomp(my $msg_extended_os_error = $^E); + if ($msg_errno eq $msg_extended_os_error) { + $msg_errno; + } + else { + "$msg_errno/$msg_extended_os_error"; + } +} + +### Funtion uniq +sub uniq { + my %seen; + return grep !$seen{$_}++, @_; +} + +### Funtion array_minus +sub array_minus(\@\@) { + my %e = map{ $_ => undef } @{$_[1]}; + return grep !exists $e{$_}, @{$_[0]}; +} + +### Funtion to create hash begin -> BEGIN, end -> END +sub crearhash { + my %cambios; + for my $aentra(@_){ + for my $initend (qw(begin end)) { + $cambios{"\\$initend\{$aentra"} = "\\\U$initend\E\{$aentra"; + } + } + return %cambios; +} + +### Print colored info in screen +sub Infocolor { + my $type = shift; + my $info = shift; + if ($type eq 'Running') { + print color('cyan'), '* ', color('reset'), color('green'), + "$type: ", color('reset'), color('cyan'), "$info\r\n", color('reset'); + } + if ($type eq 'Warning') { + print color('bold red'), "* $type: ", color('reset'), + color('yellow'), "$info\r\n", color('reset'); + } + if ($type eq 'Finish') { + print color('cyan'), '* ', color('reset'), color('magenta'), + "$type!: ", color('reset'), color('green'), "$info\r\n",color('reset'); + } + return; +} -#----------------------- User part begin ------------------------ -my $tempDir = "."; # temporary directory -my $imageDir = "images"; # where to save the images -my $margins = "1"; # margins in pdfcrop -my $Verbose = 0; # 0 or 1, logfile -my $clear = 0; # 0 or 1, clears all temporary files -my $DPI = 300; # very low value for the png's -my $noImages = 0; # 1->no create images -my $nopreview = 0; # 1->create images in nopreview mode -my $runBibTeX = 0; # 1->runs bibtex -my $runBiber = 0; # 1->runs biber and sets $runBibTeX=0 -my $jpg = 0; # 1->create .jpg files -my $png = 0; # 1->create .png files -my $ppm = 0; # 1->create .ppm files -my $eps = 0; # 1->create .eps files -my $svg = 0; # 1->create .svg files -my $all = 0; # 1->create all images and files for type -my $xetex = 0; # 1->Using (Xe)LaTeX for compilation. -my $exacount = 1; # Counter for PSTexample -my $noSource = 0; # Delete TeX source for images -my $other = "other"; # search other verbatim environment -#------------------------- User part end ------------------------------- - -#---------------- Program identification, options and help ------------- -my $program = 'pst2pdf'; -my $nv='v0.18'; -my $ident = '$Id: pst2pdf.pl 119 2017-09-11 12:04:09Z herbert $'; -my $copyright = < and Pablo González. +### Write Log line and print msg (common) +sub Infoline { + my $msg = shift; + my $now = strftime("%y/%m/%d %H:%M:%S", localtime); + if ($log) { $LogWrite->print(sprintf "[%s] * %s\n", $now, $msg); } + say $msg; + return; +} + +### Write Log line (no print msg and time stamp) +sub Logline { + my $msg = shift; + if ($log) { $LogWrite->print("$msg\n"); } + return; +} + +### Write Log line (time stamp) +sub Log { + my $msg = shift; + my $now = strftime("%y/%m/%d %H:%M:%S", localtime); + if ($log) { $LogWrite->print(sprintf "[%s] * %s\n", $now, $msg); } + return; +} + +### Write array env in Log +sub Logarray { + my ($env_ref) = @_; + my @env_tmp = @{ $env_ref }; # dereferencing and copying each array + if ($log) { + if (@env_tmp) { + my $tmp = join "\n", map { qq/* $_/ } @env_tmp; + print {$LogWrite} "$tmp\n"; + } + else { + print {$LogWrite} "Not found\n"; + } + } + return; +} + +### Extended print info for execute system commands using $ command +sub Logrun { + my $msg = shift; + my $now = strftime("%y/%m/%d %H:%M:%S", localtime); + if ($log) { $LogWrite->print(sprintf "[%s] \$ %s\n", $now, $msg); } + return; +} + +### Capture and execute system commands +sub RUNOSCMD { + my $cmdname = shift; + my $argcmd = shift; + my $showmsg = shift; + my $captured = "$cmdname $argcmd"; + Logrun($captured); + if ($showmsg eq 'show') { + if ($verbose) { + Infocolor('Running', $captured); + } + else{ Infocolor('Running', $cmdname); } + } + if ($showmsg eq 'only' and $verbose) { + Infocolor('Running', $captured); + } + # Run system system command + $captured = qx{$captured}; + if ($log) { $LogWrite->print($captured); } + if ($? == -1) { + my $errorlog = "* Error!!: ".$cmdname." failed to execute (%s)!\n"; + my $errorprint = "* Error!!: ".color('reset').$cmdname." failed to execute (%s)!\n"; + if ($log) { $LogWrite->print(sprintf $errorlog, exterr); } + print STDERR color('red'); + die sprintf $errorprint, exterr; + } elsif ($? & 127) { + my $errorlog = "* Error!!: ".$cmdname." died with signal %d!\n"; + my $errorprint = "* Error!!: ".color('reset').$cmdname." died with signal %d!\n"; + if ($log) { $LogWrite->print(sprintf $errorlog, ($? & 127)); } + print STDERR color('red'); + die sprintf $errorprint, ($? & 127); + } elsif ($? != 0 ) { + my $errorlog = "* Error!!: ".$cmdname." exited with error code %d!\n"; + my $errorprint = "* Error!!: ".color('reset').$cmdname." exited with error code %d!\n"; + if ($log) { $LogWrite->print(sprintf $errorlog, $? >> 8); } + print STDERR color('red'); + die sprintf $errorprint, $? >> 8; + } + if ($verbose) { print $captured; } + return; +} + +### General information +my $copyright = <<"END_COPYRIGHT" ; +[$date] (c) Herbert Voss and Pablo González L . END_COPYRIGHT -my $licensetxt= < [Options] -pst2pdf run a TeX source, read all PS-related part and convert in images - in pdf,eps,jpg or png format (default pdf) and create new file - whitout pst-environment and runs (pdf/Xe)latex. - See pst2pdf documentation for more info. +${title} + pst2pdf is a Perl script which isolates all PostScript or PSTricks related + parts of the TeX document, read all postscript, pspicture, psgraph and + PSTexample environments, extract source code in standalone files and + converting them into image format. Create new file with all extracted + environments converted to \\includegraphics and runs (pdf/xe/lua)latex. + +Usage: $scriptname [] [.tex|.ltx] + $scriptname [.tex|.ltx] [options] + + If used without [] the extracted environments are saved in + standalone files and converted to pdf image format in the "./images" + directory using "latex>dvips>ps2pdf" and "preview" package to process + and "pdflatex" for compiler . + Options: - -h,--help - display this help and exit - -l,--license - display license information and exit - -v,--version - display version (current $nv) and exit - -d,--dpi= - the dots per inch for images (default 300) - -j,--jpg - create .jpg files (need Ghostscript) - -p,--png - create .png files (need Ghostscript) - -e,--eps - create .eps files (need pdftops) - -s,--svg - create .svg files (need pdf2svg) - -P,--ppm - create .ppm files (need pdftoppm) - -a,--all - create .(pdf,eps,jpg,png,ppm,svg) images - -c,--clear - delete all temp and aux files - -x,--xetex - using (Xe)LaTeX for create images - -m,--margins= - margins for pdfcrop (in bp) (default 1) - -ni,--noimages - generate file-pdf.tex, but not images - -np,--single - create images files whitout preview and Ghostscript - -ns,--nosource - delete all source(.tex) for images files - --imgdir= - the folder for the created images (default images) - --ignore= - skip other verbatim environment (default other) - --bibtex - run bibtex on the aux file, if exists - --biber - run biber on the bcf file, if exists - --Verbose - creates a long log file (.plog) - -Examples: -* $program test.tex -e -p -j -c --imgdir=pics -* produce test-pdf.tex whitout pstriks related parts and create image -* dir whit all images (pdf,eps,png,jpg) and source (.tex) for all pst -* environment in "pics" dir using Ghostscript and cleaning all tmp files. -* suport bundling for short options $program test.tex -epjc --imgdir=pics + [default] + -l, --log Write .log file with debug information [off] + -h, --help Display command line help and exit [off] + -v, --version Display current version ($nv) and exit [off] + -V, --verbose Verbose printing information [off] + -t, --tif Create .tif files using ghostscript [$gscmd] + -b, --bmp Create .bmp files using ghostscript [$gscmd] + -j, --jpg Create .jpg files using ghostscript [$gscmd] + -p, --png Create .png files using ghostscript [$gscmd] + -e, --eps Create .eps files using poppler-utils [pdftops] + -s, --svg Create .svg files using poppler-utils [pdftocairo] + -P, --ppm Create .ppm files using poppler-utils [pdftoppm] + -g, --gray Gray scale for images using ghostscript [off] + -f, --force Try to capture \\psset{...} to extract [off] + -x, --xetex Using xelatex for compiler input and output [off] + -ns,--nosource Do not create standalone files [off] + -np, --noprew, --single + Create images files without preview package [off] + -ni,--norun, --noimages + Generate file-pdf.tex, but not images [off] + -d , --dpi + Dots per inch resolution for images [150] + -r , --runs + Set the number of times the compiler will + run on the input file for extraction [1] + -m , --margins + Set margins in bp for pdfcrop [0] + --myverb Add "\\macroname" to verbatim inline search [myverb] + --ignore + Add "environment" to verbatim environments [empty] + --srcenv Create files with only code environment [off] + --shell Enable \\write18\{SHELL COMMAND\} [off] + --nopdf Do not create images in pdf format [off] + --nocrop Does not run pdfcrop [off] + --imgdir Set name of directory to save images/files [images] + --luatex Using dvilualatex>dvips>ps2pdf for compiler + input and lualatex for compiler output file [off] + --arara Use arara for compiler output file [off] + --latexmk Using latexmk for compiler output file [off] + --zip Compress generated files in .zip format [off] + --tar Compress generated files in .tar.gz format [off] + --bibtex Run bibtex on the .aux file (if exists) [off] + --biber Run biber on the .bcf file (if exists) [off] + +Example: +\$ $scriptname -e -p --imgdir pics test.tex +* Create a ./pics directory (if it doesn't exist) with all extracted +* environments converted to individual files (.pdf, .eps, .png, .tex), +* a file test-fig-all.tex with all extracted environments and the file +* test-pdf.tex with all environments converted to \\includegraphics using +* latex>dvips>ps2pdf and preview package for and pdflatex +* for . + +See texdoc pst2pdf for full documentation. END_OF_USAGE -# -my $result=GetOptions ( - 'h|help' => \$::opt_help, - 'v|version' => \$::opt_version, - 'l|license' => \$::opt_license, - 'd|dpi=i' => \$DPI,# numeric - 'm|margins=i' => \$margins,# numeric - 'imgdir=s' => \$imageDir, # string - 'ignore=s' => \$other, # string - 'c|clear' => \$clear, # flag - 'ni|noimages' => \$noImages, # flag - 'np|single' => \$nopreview, # flag - 'bibtex' => \$runBibTeX,# flag - 'e|eps' => \$eps, # flag - 'j|jpg' => \$jpg, # flag - 'p|png' => \$png, # flag - 'P|ppm' => \$ppm, # flag - 's|svg' => \$svg, # flag - 'a|all' => \$all, # flag - 'x|xetex' => \$xetex, # flag - 'biber' => \$runBiber, # flag - 'ns|nosource' => \$noSource, # flag - 'Verbose' => \$Verbose, -) or die $usage; -#------------------------ Help functions -------------------------- -sub errorUsage { - die "Error: @_ (try --help for more information)\n"; - } - -# options for command line -if ($::opt_help) { print $usage; - exit (0); +exit 0; } -if ($::opt_license) { - print $title; - print "$copyright\n"; - print $licensetxt; - exit (0); + +### Options in terminal +my $result=GetOptions ( + 'h|help' => \$help, # flag + 'v|version' => \$version, # flag + 'l|log' => \$log, # flag + 'f|force' => \$force, # flag + 'd|dpi=i' => \$dpi, # numeric + 'runs=i' => \$runs, # numeric + 'm|margins=i' => \$margins, # numeric + 'imgdir=s' => \$imgdir, # string + 'myverb=s' => \$myverb, # string + 'ignore=s' => \$tmpverbenv, # string + 'c|clear' => \$clear, # flag + 'ni|norun|noimages' => \$norun, # flag + 'np|noprew|single' => \$noprew, # flag + 'bibtex' => \$runbibtex,# flag + 'biber' => \$runbiber, # flag + 'arara' => \$arara, # flag + 'latexmk' => \$latexmk, # flag + 'srcenv' => \$srcenv, # flag + 'nopdf' => \$nopdf, # flag + 'shell' => \$shell, # flag + 'nocrop' => \$nocrop, # flag + 'zip' => \$zip, # flag + 'tar' => \$tar, # flag + 'g|gray' => \$gray, # flag + 'b|bmp' => \$opts_cmd{image}{bmp}, # gs + 't|tif' => \$opts_cmd{image}{tif}, # gs + 'j|jpg' => \$opts_cmd{image}{jpg}, # gs + 'p|png' => \$opts_cmd{image}{png}, # gs + 's|svg' => \$opts_cmd{image}{svg}, # pdftocairo + 'e|eps' => \$opts_cmd{image}{eps}, # pdftops + 'P|ppm' => \$opts_cmd{image}{ppm}, # pdftoppm + 'a|all' => \$all, # flag + 'x|xetex' => \$xetex, # flag + 'luatex' => \$luatex, # flag + 'ns|nosource' => \$nosource, # flag + 'V|Verbose' => \$verbose, # flag +) or do { $log = 0 ; die usage(0); }; + +### Open pst2pdf.log file +if ($log) { + if (!defined $ARGV[0]) { errorUsage('Input filename missing'); } + my $tempname = $ARGV[0]; + $tempname =~ s/\.(tex|ltx)$//; + if ($LogFile eq "$tempname.log") { $LogFile = "$scriptname-log.log"; } + $LogWrite = FileHandle->new("> $LogFile"); } -if ($::opt_version) { -print $version; - exit (0); + +### Init pst2pdf.log file +Log("The script $scriptname $nv was started in $workdir"); +Log("Creating the temporary directory $tempDir"); + +### Check --arara and --latexmk +if ($arara && $latexmk) { + Log('Error!!: Options --arara and --latexmk are mutually exclusive'); + errorUsage('Options --arara and --latexmk are mutually exclusive'); } -# open file -my $InputFilename = ""; - @ARGV > 0 or errorUsage "Input filename missing"; - @ARGV < 2 or errorUsage "Unknown option or too many input files"; - $InputFilename = $ARGV[0]; +### Check --biber and --bibtex +if ($runbiber && $runbibtex) { + Log('Error!!: Options --biber and --bibtex are mutually exclusive'); + errorUsage('Options --biber and --bibtex are mutually exclusive'); +} -#------------------------ 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; +### Check --runs +if( $runs <= 0 or $runs >= 3) { + Log('Error!!: Invalid argument for --runs, argument out of range'); + errorUsage('Invalid argument for --runs option'); +} -#--------------------- Directorio destino de imágenes ------------------ --e $imageDir or mkdir($imageDir,0744) or die "No puedo crear $imageDir: $!\n"; +### Check --dpi +if( $dpi <= 0 or $dpi >= 2500) { + Log('Error!!: Invalid argument for --dpi, argument out of range'); + errorUsage('Invalid argument for --dpi option'); +} -# expresion regular para swpl -my $graphics = "graphic=\{\[scale=1\]$imageDir/$name-exa"; +### Validate --myverb +if ($myverb =~ /^(?:\\|\-).+?/) { + Log('Error!!: Invalid argument for --myverb option, argument begin with \ or -'); + errorUsage('Invalid argument for --myverb'); +} -# directorio en el cual están las imágenes -my $dir = "$tempDir/$imageDir"; +### Validate --ignore +if ($tmpverbenv =~ /^(?:\\|\-).+?/) { + Log('Error!!: Invalid argument for --ignore option, argument begin with \ or -'); + errorUsage('Invalid argument for --ignore'); +} -# archivo de entrada para el resto del script -my $TeXfile = "$tempDir/$name-tmp$ext"; +### If $tmpverbenv is valid pass to @verb_env_tmp +if ($tmpverbenv) { @verb_env_tmp = $tmpverbenv; } +### Make ENV safer, see perldoc perlsec +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; -#----------------------------- Search GS ------------------------------ -# The next code its part of pdfcrop from TexLive 2014 -# Windows detection +### The next code it's part of pdfcrop (adapted from TexLive 2014) +# Windows detection my $Win = 0; -$Win = 1 if $^O =~ /mswin32/i; -$Win = 1 if $^O =~ /cygwin/i; +if ($^O =~ /mswin32/i) { $Win = 1; } my $archname = $Config{'archname'}; $archname = 'unknown' unless defined $Config{'archname'}; -# get Ghostscript command name -$::opt_gscmd = ''; +# Get ghostscript command name sub find_ghostscript () { - return if $::opt_gscmd; - if ($Verbose) { - print "* Perl executable: $^X\n"; + if ($log) { + Log('General information about the Perl instalation and operating system'); + print {$LogWrite} "* Perl executable: $^X\n"; if ($] < 5.006) { - print "* Perl version: $]\n"; + print {$LogWrite} "* Perl version: $]\n"; } else { - printf "* Perl version: v%vd\n", $^V; + printf {$LogWrite} "* Perl version: v%vd\n", $^V; } if (defined &ActivePerl::BUILD) { - printf "* Perl product: ActivePerl, build %s\n", ActivePerl::BUILD(); + printf {$LogWrite} "* Perl product: ActivePerl, build %s\n", ActivePerl::BUILD(); } - printf "* Pointer size: $Config{'ptrsize'}\n"; - printf "* Pipe support: %s\n", - (defined($Config{'d_pipe'}) ? 'yes' : 'no'); - printf "* Fork support: %s\n", - (defined($Config{'d_fork'}) ? 'yes' : 'no'); + printf {$LogWrite} "* Pointer size: $Config{'ptrsize'}\n"; + printf {$LogWrite} "* Pipe support: %s\n", + (defined $Config{'d_pipe'} ? 'yes' : 'no'); + printf {$LogWrite} "* Fork support: %s\n", + (defined $Config{'d_fork'} ? 'yes' : 'no'); } my $system = 'unix'; - $system = "dos" if $^O =~ /dos/i; - $system = "os2" if $^O =~ /os2/i; - $system = "win" if $^O =~ /mswin32/i; - $system = "cygwin" if $^O =~ /cygwin/i; - $system = "miktex" if defined($ENV{"TEXSYSTEM"}) and - $ENV{"TEXSYSTEM"} =~ /miktex/i; - print "* OS name: $^O\n" if $Verbose; - print "* Arch name: $archname\n" if $Verbose; - print "* System: $system\n" if $Verbose; + $system = 'win' if $^O =~ /mswin32/i; + $system = 'msys' if $^O =~ /msys/i; + $system = 'cygwin' if $^O =~ /cygwin/i; + $system = 'miktex' if defined $ENV{'TEXSYSTEM'} and + $ENV{'TEXSYSTEM'} =~ /miktex/i; + if ($log) { + print {$LogWrite} "* OS name: $^O\n"; + print {$LogWrite} "* Arch name: $archname\n"; + if ($^O eq 'MSWin32') { + my $tmp = Win32::GetOSName(); + print {$LogWrite} "* System: $tmp\n"; + } + else { print {$LogWrite} "* System: $system\n"; } + } + Log('Trying to locate the executable for Ghostscript'); my %candidates = ( - 'unix' => [qw|gs gsc|], - 'dos' => [qw|gs386 gs|], - 'os2' => [qw|gsos2 gs|], - 'win' => [qw|gswin32c gs|], - 'cygwin' => [qw|gs gswin32c|], - 'miktex' => [qw|mgs gswin32c gs|] + 'unix' => [qw|gs|], + 'win' => [qw|gswin32c|], + 'msys' => [qw|gswin64c gswin32c|], + 'cygwin' => [qw|gs|], + 'miktex' => [qw|mgs gswin32c|], ); - if ($system eq 'win' or $system eq 'cygwin' or $system eq 'miktex') { + if ($system eq 'win' or $system eq 'miktex') { if ($archname =~ /mswin32-x64/i) { my @a = (); foreach my $name (@{$candidates{$system}}) { @@ -241,12 +492,11 @@ sub find_ghostscript () { } } my %exe = ( - 'unix' => '', - 'dos' => '.exe', - 'os2' => '.exe', - 'win' => '.exe', + 'unix' => q{}, + 'win' => '.exe', + 'msys' => '.exe', 'cygwin' => '.exe', - 'miktex' => '.exe' + 'miktex' => '.exe', ); my $candidates_ref = $candidates{$system}; my $exe = $Config{'_exe'}; @@ -257,65 +507,70 @@ sub find_ghostscript () { foreach my $dir (@path) { my $file = File::Spec->catfile($dir, "$candidate$exe"); if (-x $file) { - $::opt_gscmd = $candidate; + $gscmd = $candidate; $found = 1; - print "* Found ($candidate): $file\n" if $Verbose; + if ($log) { print {$LogWrite} "* Found ($candidate): $file\n"; } last; } - print "* Not found ($candidate): $file\n" if $Verbose; + if ($log) { print {$LogWrite} "* Not found ($candidate): $file\n"; } } last if $found; } - if (not $found and $Win) { + if (not $found and $Win and $system ne 'msys') { $found = SearchRegistry(); } + if (not $found and $system eq 'msys') { + $found = Searchbyregquery(); + } if ($found) { - print "* Autodetected ghostscript command: $::opt_gscmd\n" if $Verbose; + if ($log) { print {$LogWrite} "* Autodetected ghostscript command: $gscmd\n"; } } else { - $::opt_gscmd = $$candidates_ref[0]; - print "* Default ghostscript command: $::opt_gscmd\n" if $Verbose; + $gscmd = $$candidates_ref[0]; + if ($log) { print {$LogWrite} "* Default ghostscript command: $gscmd\n"; } } } -sub SearchRegistry () { +sub SearchRegistry { my $found = 0; - eval 'use Win32::TieRegistry qw|KEY_READ REG_SZ|;'; + # The module Win32::TieRegistry not aviable in cygwin/msys + eval 'use Win32::TieRegistry qw|KEY_READ REG_SZ|'; if ($@) { - if ($Verbose) { - print "* Registry lookup for Ghostscript failed:\n"; + if ($log) { + print {$LogWrite} "* Registry lookup for Ghostscript failed:\n"; my $msg = $@; $msg =~ s/\s+$//; foreach (split /\r?\n/, $msg) { - print " $_\n"; + print {$LogWrite} " $_\n"; } } return $found; } - my $open_params = {Access => KEY_READ(), Delimiter => '/'}; + my $open_params = {Access => KEY_READ(), Delimiter => q{/}}; my $key_name_software = 'HKEY_LOCAL_MACHINE/SOFTWARE/'; my $current_key = $key_name_software; my $software = new Win32::TieRegistry $current_key, $open_params; if (not $software) { - print "* Cannot find or access registry key `$current_key'!\n" - if $::opt_verbose; + if ($log) { + print {$LogWrite} "* Cannot find or access registry key `$current_key'!\n"; + } return $found; } - print "* Search registry at `$current_key'.\n" if $Verbose; + if ($log) { print {$LogWrite} "* Search registry at `$current_key'.\n"; } my %list; foreach my $key_name_gs (grep /Ghostscript/i, $software->SubKeyNames()) { $current_key = "$key_name_software$key_name_gs/"; - print "* Registry entry found: $current_key\n" if $Verbose; + if ($log) { print {$LogWrite} "* Registry entry found: $current_key\n"; } my $key_gs = $software->Open($key_name_gs, $open_params); if (not $key_gs) { - print "* Cannot open registry key `$current_key'!\n" if $Verbose; + if ($log) { print {$LogWrite} "* Cannot open registry key `$current_key'!\n"; } next; } foreach my $key_name_version ($key_gs->SubKeyNames()) { $current_key = "$key_name_software$key_name_gs/$key_name_version/"; - print "* Registry entry found: $current_key\n" if $Verbose; + if ($log) { print {$LogWrite} "* Registry entry found: $current_key\n"; } if (not $key_name_version =~ /^(\d+)\.(\d+)$/) { - print " The sub key is not a version number!\n" if $Verbose; + if ($log) { print {$LogWrite} " The sub key is not a version number!\n"; } next; } my $version_main = $1; @@ -323,13 +578,13 @@ sub SearchRegistry () { $current_key = "$key_name_software$key_name_gs/$key_name_version/"; my $key_version = $key_gs->Open($key_name_version, $open_params); if (not $key_version) { - print "* Cannot open registry key `$current_key'!\n" if $Verbose; + if ($log) { print {$LogWrite} "* Cannot open registry key `$current_key'!\n"; } next; } $key_version->FixSzNulls(1); my ($value, $type) = $key_version->GetValue('GS_DLL'); if ($value and $type == REG_SZ()) { - print " GS_DLL = $value\n" if $Verbose; + if ($log) { print {$LogWrite} " GS_DLL = $value\n"; } $value =~ s|([\\/])([^\\/]+\.dll)$|$1gswin32c.exe|i; my $value64 = $value; $value64 =~ s/gswin32c\.exe$/gswin64c.exe/; @@ -337,10 +592,10 @@ sub SearchRegistry () { $value = $value64; } if (-f $value) { - print " EXE found: $value\n" if $Verbose; + if ($log) { print {$LogWrite} "EXE found: $value\n"; } } else { - print " EXE not found!\n" if $Verbose; + if ($log) { print {$LogWrite} "EXE not found!\n"; } next; } my $sortkey = sprintf '%02d.%03d %s', @@ -348,961 +603,1679 @@ sub SearchRegistry () { $list{$sortkey} = $value; } else { - print " Missing key `GS_DLL' with type `REG_SZ'!\n" if $Verbose; + if ($log) { print {$LogWrite} "Missing key `GS_DLL' with type `REG_SZ'!\n"; } } } } foreach my $entry (reverse sort keys %list) { - $::opt_gscmd = $list{$entry}; - print "* Found (via registry): $::opt_gscmd\n" if $Verbose; + $gscmd = $list{$entry}; + if ($log) { print {$LogWrite} "* Found (via registry): $gscmd\n"; } $found = 1; last; } return $found; +} # end GS search registry + +### This part is only necessary if you're using Git on windows and don't +### have gs configured in PATH. Git for windows don't have a Win32::TieRegistry +### module for perl (is not supported in the current versions of msys). +sub Searchbyregquery { + my $found = 0; + my $gs_regkey; + my $opt_reg = '//s //v'; + if ($log) { print {$LogWrite} "* Search Ghostscript in Windows registry under mingw/msys:\n";} + $gs_regkey = qx{reg query "HKLM\\Software\\GPL Ghostscript" $opt_reg GS_DLL}; + if ($? == 0) { + if ($log) { print {$LogWrite} "* Registry entry found for GS_DLL (64 bits version)\n";} + } + else { + $gs_regkey = qx{reg query "HKLM\\Software\\Wow6432Node\\GPL Ghostscript" $opt_reg GS_DLL}; + if ($? == 0) { + if ($log) { print {$LogWrite} "* Registry entry found for GS_DLL (32 bits version)\n";} + } + } + my ($gs_find) = $gs_regkey =~ m/(?:\s* GS_DLL \s* REG_SZ \s*) (.+?)(?:\.dll.+?\R)/s; + if ($gs_find) { + my ($gs_vol, $gs_path, $gs_ver) = $gs_find =~ m/ + (\w{1})(?:\:) # volumen + (.+?) # path to executable + (?:\\gsdll) # LIB + (\d{2}) # Version + /xs; + # Adjust + $gs_vol = lc($gs_vol); + $gs_path = '/'.$gs_vol.$gs_path; + $gs_path =~ s|\\|/|gmsxi; + # Add to PATH + if ($log) { print {$LogWrite} "* Add $gs_path to PATH for current session\n"; } + $PATH .= ":$gs_path"; + # Set executable + $gscmd = 'gswin'.$gs_ver.'c'; + if ($log) { print {$LogWrite} "* Found (via reg query): $gscmd\n"; } + $found = 1; + } + if ($@) { + if ($log) { + print {$LogWrite} "* Registry lookup for Ghostscript by reg query failed:\n"; + my $msg = $@; + $msg =~ s/\s+$//; + foreach (split /\r?\n/, $msg) { + print {$LogWrite} " $_\n"; + } + } + return $found; + } + return $found; } +### Call GS find_ghostscript(); -if ($Win and $::opt_gscmd =~ /\s/) { - $::opt_gscmd = "\"$::opt_gscmd\""; -} -# end GS search - -open my $LOGfile,'>', "$tempDir/$name.plog"; # our own log file - LOG ("Parameters:"); - LOG ("==> imageDir = $imageDir"); - LOG ("==> dpi = $DPI"); - LOG ("==> tempDir = $tempDir"); - LOG ("==> Verbose = $Verbose"); - LOG ("==> clear = $clear"); - LOG ("==> noImages = $noImages"); - LOG ("==> noSource = $noSource"); - LOG ("==> nopreview = $nopreview"); - LOG ("==> runBibTeX = $runBibTeX"); - LOG ("==> runBiber = $runBiber"); - LOG ("==> ppm = $ppm"); - LOG ("==> eps = $eps"); - LOG ("==> jpg = $jpg"); - LOG ("==> png = $png"); - LOG ("==> svg = $svg"); - LOG ("==> xetex = $xetex"); - -if ($runBibTeX && $runBiber) { - LOG ("!!! you cannot run BibTeX and Biber at the same document ..."); - LOG ("!!! Assuming to run Biber"); - $runBibTeX = 0; -} -if ($ppm) { - LOG ("Generate .ppm files ..."); - $ppm = 1; -} -if ($eps) { - LOG ("Generate .eps files ..."); - $eps = 1; -} -if ($jpg) { - LOG ("Generate .jpg files ..."); - $jpg = 1; -} -if ($png) { - LOG ("Generate .png files ..."); - $png = 1; -} -if ($svg) { - LOG ("Generate .svg files ..."); - $svg = 1; -} -if ($all) { - LOG ("Generate images eps/pdf/files and clear..."); - $eps =$ppm=$jpg=$png=$svg=$clear = 1; -} -if ($nopreview) { - LOG ("nopreview mode generate images files ..."); - $nopreview= 1; -} -if ($xetex) { - LOG ("Compiling using XeLaTeX ..."); - $xetex=1; -} -if ($noImages ) { - LOG ("no create images"); - $nopreview= 0; - } -if ($noSource) { - LOG ("Delete all source files"); - $noSource= 1; - } - -#----------------------------- Parte 1 --------------------------------- -# Comentamos los bloques PST dentro de verbatim de todo el archivo -# Abrimos el archivo -my $InputFilename = shift; -my @lineas; -{ - open my $FILE,'<:crlf',"$InputFilename"; - @lineas = <$FILE>; - close $FILE; -} - -# Creamos un hash con los cambios -my %cambios = ( - '\pspicture' => '\TRICKS', - '\endpspicture' => '\ENDTRICKS', - - '\begin{PSTexample' => '\begin{PSTEXAMPLE', - '\end{PSTexample' => '\end{PSTEXAMPLE', - - '\begin{pspicture' => '\begin{TRICKS', - '\end{pspicture' => '\end{TRICKS', - - '\begin{postscript}' => '\begin{POSTRICKS}', - '\end{postscript}' => '\end{POSTRICKS}', - - '\begin{document}' => '\begin{DOCTRICKS}', - '\end{document}' => '\end{DOCTRICKS}' -); +### Windows need suport space in path +if ($Win and $gscmd =~ /\s/) { $gscmd = "\"$gscmd\"";} -# Definimos los entonos verbatim donde comentaremos -my $ENTORNO = qr/(?: (v|V)erbatim\*?| LTXexample | PSTcode |$other\*? | tcblisting\*? | spverbatim | minted | lstlisting | alltt | comment\*? | xcomment)/xi; -# -my $DEL; +### Help +if (defined $help) { + usage(1); + exit 0; +} -my $tcbverb = qr/\\(?:tcboxverb|myverb)/; - -my $arg_brac = qr/(?:\[.+?\])?/; - -my $arg_curl = qr/\{(.+)\}/; # ATENCIÓN +### Version +if (defined $version) { + print $versiontxt; + exit 0; +} -for (@lineas) { - if (/^\\begin\{($ENTORNO)(?{ $DEL = "\Q$^N" })\}/ .. /^\\end\{$DEL\}/) { - while (my($busco, $cambio) = each %cambios) { - s/\Q$busco\E/$cambio/g; +### Set temp internal vars for and extraction +my $tmp = int(rand(10000)); +my $dtxverb = "verbatim$tmp"; +my $wrapping = "$scriptname$tmp"; # wraped for environment extraction + +Log("Set up the environment [$wrapping] to encapsulate the extraction"); + +### Set vars for match/regex +my $BP = "\\\\begin\{$wrapping\}"; +my $EP = "\\\\end\{$wrapping\}"; +my $BE = '\\\\begin\{PSTexample\}'; +my $EE = '\\\\end\{PSTexample\}'; + +### Define key = pdf for image format +if (!$nopdf) { + $opts_cmd{image}{pdf} = 1; +} + +### Store image formats in hash +my $format = join q{, },grep { defined $opts_cmd{image}{$_} } keys %{$opts_cmd{image}}; +if (!$norun) { + Log("Defined image formats for creating: $format"); +} + +### Check from command line +@ARGV > 0 or errorUsage('Input filename missing'); +@ARGV < 2 or errorUsage('Unknown option or too many input files'); + +### Check extention +my @SuffixList = ('.tex', '', '.ltx'); # posibles +my ($name, $path, $ext) = fileparse($ARGV[0], @SuffixList); +$ext = '.tex' if not $ext; + +### Read in memory +Log("Read input file $name$ext in memory"); +open my $inputfile, '<:crlf', "$name$ext"; + my $ltxfile; + { + local $/; + $ltxfile = <$inputfile>; } - } - elsif (m/$tcbverb$arg_brac$arg_curl/) { - while (my($busco, $cambio) = each %cambios) { - s/\Q$busco\E/$cambio/g; +close $inputfile; + +### Identification message in terminal +print $title; + +### Default environment to extract +my @extractenv = qw ( + postscript pspicture psgraph PSTexample + ); + +### Default verbatim environment +my @iverb_env = qw ( + Example CenterExample SideBySideExample PCenterExample PSideBySideExample + verbatim Verbatim BVerbatim LVerbatim SaveVerbatim PSTcode + LTXexample tcblisting spverbatim minted listing lstlisting + alltt comment chklisting verbatimtab listingcont boxedverbatim + demo sourcecode xcomment pygmented pyglist program programl + programL programs programf programsc programt + ); +push @verb_env_tmp, @iverb_env; + +### Default verbatim write environment +my @verw_env_tmp; +my @iverbw_env = qw ( + scontents filecontents tcboutputlisting tcbexternal tcbwritetmp extcolorbox extikzpicture + VerbatimOut verbatimwrite filecontentsdef filecontentshere filecontentsdefmacro + filecontentsdefstarred filecontentsgdef filecontentsdefmacro filecontentsgdefmacro + ); +push @verw_env_tmp, @iverbw_env; + +######################################################################## +# One problem that can arise is the filecontents environment, this can # +# contain a complete document and be anywhere, before dividing we will # +# make some replacements for this and comment lines # +######################################################################## + +### Create a Regex for verbatim write environment +@verw_env_tmp = uniq(@verw_env_tmp); +my $tmpverbw = join q{|}, map { quotemeta } sort { length $a <=> length $b } @verw_env_tmp; +$tmpverbw = qr/$tmpverbw/x; +my $tmp_verbw = qr { + ( + (?: + \\begin\{$tmpverbw\*?\} + (?: + (?>[^\\]+)| + \\ + (?!begin\{$tmpverbw\*?\}) + (?!end\{$tmpverbw\*?\})| + (?-1) + )* + \\end\{$tmpverbw\*?\} + ) + ) + }x; + +### A pre-regex for comment lines +my $tmpcomment = qr/^ \s* \%+ .+? $ /mx; + +### Hash for replace in verbatim's and comment lines +my %document = ( + '\begin{document}' => '\BEGIN{document}', + '\end{document}' => '\END{document}', + '\documentclass' => '\DOCUMENTCLASS', + '\pagestyle{' => '\PAGESTYLE{', + '\thispagestyle{' => '\THISPAGESTYLE{', + ); + +### Changes in input file for verbatim write and comment lines +while ($ltxfile =~ / $tmp_verbw | $tmpcomment /pgmx) { + my ($pos_inicial, $pos_final) = ($-[0], $+[0]); + my $encontrado = ${^MATCH}; + while (my($busco, $cambio) = each %document) { + $encontrado =~ s/\Q$busco\E/$cambio/g; } - } #close elsif - } - -# Escritura del resultado -open my $SALIDA, '>', "$tempDir/$name-tmp$ext"; -print $SALIDA @lineas; -close $SALIDA; - -#--------------------------------Parte 2-------------------------------- -# Comentamos el texto en verbatim a lo largo del cuerpo -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; - -## Variables y constantes + substr $ltxfile, $pos_inicial, $pos_final-$pos_inicial, $encontrado; + pos ($ltxfile) = $pos_inicial + length $encontrado; +} + +### Now, split +my ($atbegindoc, $document) = $ltxfile =~ m/\A (\s* .*? \s*) (\\documentclass.*)\z/msx; + +### Rules to capture for regex my $CORCHETES = qr/\[ [^]]*? \]/x; +my $braces = qr/ (?:\{)(.+?)(?:\}) /msx; +my $braquet = qr/ (?:\[)(.+?)(?:\]) /msx; +my $no_corchete = qr/ (?:\[ .*? \])? /msx; + +### Array for capture new verbatim environments defined in input file +my @cverb_env = qw ( + newtcblisting DeclareTCBListing ProvideTCBListing NewTCBListing + lstnewenvironment NewListingEnvironment NewProgram specialcomment + includecomment DefineVerbatimEnvironment newverbatim newtabverbatim + ); + +### Regex to capture names for new verbatim environments from input file +my $cverbenv = join q{|}, map { quotemeta} sort { length $a <=> length $b } @cverb_env; +$cverbenv = qr/\b(?:$cverbenv) $no_corchete $braces/msx; + +### Array for capture new verbatim write environments defined in input file +my @cverb_env_w = qw ( + renewtcbexternalizetcolorbox renewtcbexternalizeenvironment + newtcbexternalizeenvironment newtcbexternalizetcolorbox newenvsc + ); + +### Regex to capture names for new verbatim write environments from input file +my $cverbenvw = join q{|}, map { quotemeta} sort { length $a <=> length $b } @cverb_env_w; +$cverbenvw = qr/\b(?:$cverbenvw) $no_corchete $braces/msx; + +### Regex to capture MINTED related environments +my $mintdenv = qr/\\ newminted $braces (?:\{.+?\}) /x; +my $mintcenv = qr/\\ newminted $braquet (?:\{.+?\}) /x; +my $mintdshrt = qr/\\ newmint $braces (?:\{.+?\}) /x; +my $mintcshrt = qr/\\ newmint $braquet (?:\{.+?\}) /x; +my $mintdline = qr/\\ newmintinline $braces (?:\{.+?\}) /x; +my $mintcline = qr/\\ newmintinline $braquet (?:\{.+?\}) /x; + +### Filter input file, now $ltxfile is pass to $filecheck +Log("Filter $name$ext \(remove % and comments\)"); +my @filecheck = $ltxfile; +s/%.*\n//mg foreach @filecheck; # del comments +s/^\s*|\s*//mg foreach @filecheck; # del white space +my $filecheck = join q{}, @filecheck; + +### Search verbatim and verbatim write environments +Log("Search verbatim and verbatim write environments in $name$ext"); + +### Search new verbatim write names in +my @new_write_env = $filecheck =~ m/$cverbenvw/xg; +if (@new_write_env) { + Log("Found new verbatim write environments in $name$ext"); + Logarray(\@new_write_env); + push @verw_env_tmp, @new_write_env; +} + +### Search new verbatim environments in +my @verb_input = $filecheck =~ m/$cverbenv/xg; +if (@verb_input) { + Log("Found new verbatim environments in $name$ext"); + Logarray(\@verb_input); + push @verb_env_tmp, @verb_input; +} + +### Search \newminted{$mintdenv}{options} in , need add "code" +my @mint_denv = $filecheck =~ m/$mintdenv/xg; +if (@mint_denv) { + Log("Found \\newminted\{envname\} in $name$ext"); + # Append "code" + $mintdenv = join "\n", map { qq/$_\Qcode\E/ } @mint_denv; + @mint_denv = split /\n/, $mintdenv; + Logarray(\@mint_denv); + push @verb_env_tmp, @mint_denv; +} + +### Search \newminted[$mintcenv]{lang} in +my @mint_cenv = $filecheck =~ m/$mintcenv/xg; +if (@mint_cenv) { + Log("Found \\newminted\[envname\] in $name$ext"); + Logarray(\@mint_cenv); + push @verb_env_tmp, @mint_cenv; +} + +### Remove repetead again :) +@verb_env_tmp = uniq(@verb_env_tmp); + +### Capture verbatim inline macros in +Log("Search verbatim macros in $name$ext"); + +### Store all minted inline/short in @mintline +my @mintline; + +### Search \newmint{$mintdshrt}{options} in (while) +my @mint_dshrt = $filecheck =~ m/$mintdshrt/xg; +if (@mint_dshrt) { + Log("Found \\newmint\{macroname\} (short) in $name$ext"); + Logarray(\@mint_dshrt); + push @mintline, @mint_dshrt; +} + +### Search \newmint[$mintcshrt]{lang}{options} in (while) +my @mint_cshrt = $filecheck =~ m/$mintcshrt/xg; +if (@mint_cshrt) { + Log("Found \\newmint\[macroname\] (short) in $name$ext"); + Logarray(\@mint_cshrt); + push @mintline, @mint_cshrt; +} + +### Search \newmintinline{$mintdline}{options} in (while) +my @mint_dline = $filecheck =~ m/$mintdline/xg; +if (@mint_dline) { + Log("Found \\newmintinline\{macroname\} in $name$ext"); + # Append "inline" + $mintdline = join "\n", map { qq/$_\Qinline\E/ } @mint_dline; + @mint_dline = split /\n/, $mintdline; + Logarray(\@mint_dline); + push @mintline, @mint_dline; +} + +### Search \newmintinline[$mintcline]{lang}{options} in (while) +my @mint_cline = $filecheck =~ m/$mintcline/xg; +if (@mint_cline) { + Log("Found \\newmintinline\[macroname\] in $name$ext"); + Logarray(\@mint_cline); + push @mintline, @mint_cline; +} + +### Add standart mint, mintinline and lstinline +my @mint_tmp = qw(mint mintinline lstinline); + +### Join all inline verbatim macros captured +push @mintline, @mint_tmp; +@mintline = uniq(@mintline); + +### Create a regex using @mintline +my $mintline = join q{|}, map { quotemeta } sort { length $a <=> length $b } @mintline; +$mintline = qr/\b(?:$mintline)/x; + +### Reserved words in verbatim inline (while) +my %changes_in = ( + '%CleanPST' => '%PSTCLEAN', + '\psset' => '\PSSET', + '\pspicture' => '\TRICKS', + '\endpspicture' => '\ENDTRICKS', + '\psgraph' => '\PSGRAPHTRICKS', + '\endpsgraph' => '\ENDPSGRAPHTRICKS', + '\usepackage' => '\USEPACKAGE', + '{graphicx}' => '{GRAPHICX}', + '\graphicspath{' => '\GRAPHICSPATH{', + ); + +### Hash to replace \begin and \end in verbatim inline +my %init_end = ( + '\begin{' => '\BEGIN{', + '\end{' => '\END{', + ); + +### Join changes in new hash (while) for verbatim inline +my %cambios = (%changes_in,%init_end); + +### Variables and constantes my $no_del = "\0"; my $del = $no_del; -## Reglas -my $llaves = qr/\{ .+? \} /x; -my $no_corchete = qr/(?:\[ .+? \])? /x; -my $delimitador = qr/\{ (?.+?) \} /x; -my $spverb = qr/spverb [*]? /ix; -my $verb = qr/(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; - -## Cambiar -while ($cuerpo =~ - / $marca - | $comentario - | $definedel - | $indefinedel - | $del .+? $del # delimitado +### Rules +my $llaves = qr/\{ .+? \} /x; +my $no_llaves = qr/(?: $llaves )? /x; +my $corchetes = qr/\[ .+? \] /x; +my $delimitador = qr/\{ (?.+?) \} /x; +my $scontents = qr/Scontents [*]? $no_corchete /ix; +my $verb = qr/(?:((spv|(?:q|f)?v|V)erb|$myverb)[*]?) /ix; +my $lst = qr/(?:(lst|pyg)inline)(?!\*) $no_corchete /ix; +my $mint = qr/(?: $mintline |SaveVerb) (?!\*) $no_corchete $no_llaves $llaves /ix; +my $no_mint = qr/(?: $mintline) (?!\*) $no_corchete /ix; +my $marca = qr/\\ (?:$verb | $lst |$scontents | $mint |$no_mint) (?:\s*)? (\S) .+? \g{-1} /sx; +my $comentario = qr/^ \s* \%+ .+? $ /mx; +my $definedel = qr/\\ (?: DefineShortVerb | lstMakeShortInline| MakeSpecialShortVerb ) [*]? $no_corchete $delimitador /ix; +my $indefinedel = qr/\\ (?: (Undefine|Delete)ShortVerb | lstDeleteShortInline) $llaves /ix; + +Log('Making changes to inline/multiline verbatim macro before extraction'); + +### Changes in input file for verbatim inline/multiline +while ($document =~ + / $marca + | $comentario + | $definedel + | $indefinedel + | $del .+? $del /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 + my ($pos_inicial, $pos_final) = ($-[0], $+[0]); + my $encontrado = ${^MATCH}; + if ($encontrado =~ /$definedel/) { + $del = $+{del}; + $del = "\Q$+{del}" if substr($del,0,1) ne '\\'; + } + elsif ($encontrado =~ /$indefinedel/) { + $del = $no_del; + } + else { while (my($busco, $cambio) = each %cambios) { - $encontrado =~ s/\Q$busco\E/$cambio/g; # es necesario escapar $busco - } - substr $cuerpo, $pos_inicial, $pos_final-$pos_inicial, $encontrado; # insertamos los nuevos cambios - - pos($cuerpo)= $pos_inicial + length $encontrado; # re posicionamos la siguiente búsqueda + $encontrado =~ s/\Q$busco\E/$cambio/g; } + substr $document, $pos_inicial, $pos_final-$pos_inicial, $encontrado; + pos ($document) = $pos_inicial + length $encontrado; + } } +### Change "escaped braces" to (this label is not the one in the document) +$document =~ s/\\[{]//g; +$document =~ s/\\[}]//g; + +### Regex for verbatim inline/multiline with braces {...} +my $nestedbr = qr / ( [{] (?: [^{}]++ | (?-1) )*+ [}] ) /x; +my $fvextra = qr /\\ (?: (Save|Esc)Verb [*]?) $no_corchete /x; +my $mintedbr = qr /\\ (?:$mintline|pygment) (?!\*) $no_corchete $no_llaves /x; +my $tcbxverb = qr /\\ (?: tcboxverb [*]?| Scontents [*]? |$myverb [*]?|lstinline) $no_corchete /x; +my $verb_brace = qr / (?:$tcbxverb|$mintedbr|$fvextra) (?:\s*)? $nestedbr /x; + +### Change \verb*{code} for verbatim inline/multiline +while ($document =~ /$verb_brace/pgmx) { + my ($pos_inicial, $pos_final) = ($-[0], $+[0]); + my $encontrado = ${^MATCH}; + while (my($busco, $cambio) = each %cambios) { + $encontrado =~ s/\Q$busco\E/$cambio/g; + } + substr $document, $pos_inicial, $pos_final-$pos_inicial, $encontrado; + pos ($document) = $pos_inicial + length $encontrado; +} + +### We recovered the escaped braces +$document =~ s//\\{/g; +$document =~ s//\\}/g; + +### We recovered CleanPST in all file, but only at begin of line +$document =~ s/^%PSTCLEAN/%CleanPST/gmsx; + +### First we do some security checks to ensure that they are verbatim and +### verbatim write environments are unique and disjointed +@verb_env_tmp = array_minus(@verb_env_tmp, @verw_env_tmp); #disjointed +my @verbatim = uniq(@verb_env_tmp); + +Log('The environments that are considered verbatim:'); +Logarray(\@verbatim); + +### Create a Regex for verbatim standart environment +my $verbatim = join q{|}, map { quotemeta } sort { length $a <=> length $b } @verbatim; +$verbatim = qr/$verbatim/x; +my $verb_std = qr { + ( + (?: + \\begin\{$verbatim\*?\} + (?: + (?>[^\\]+)| + \\ + (?!begin\{$verbatim\*?\}) + (?!end\{$verbatim\*?\})| + (?-1) + )* + \\end\{$verbatim\*?\} + ) + ) + }x; + +### Verbatim write +@verw_env_tmp = array_minus(@verw_env_tmp, @verb_env_tmp); #disjointed +my @verbatim_w = uniq(@verw_env_tmp); + +Log('The environments that are considered verbatim write:'); +Logarray(\@verbatim_w); + +### Create a Regex for verbatim write environment +my $verbatim_w = join q{|}, map { quotemeta } sort { length $a <=> length $b } @verbatim_w; +$verbatim_w = qr/$verbatim_w/x; +my $verb_wrt = qr { + ( + (?: + \\begin\{$verbatim_w\*?\} + (?: + (?>[^\\]+)| + \\ + (?!begin\{$verbatim_w\*?\}) + (?!end\{$verbatim_w\*?\})| + (?-1) + )* + \\end\{$verbatim_w\*?\} + ) + ) + }x; + +### The environments that will be searched for extraction +Log('The environments that will be searched for extraction:'); +Logarray(\@extractenv); + +### Create a regex to extract environments +my $environ = join q{|}, map { quotemeta } sort { length $a <=> length $b } @extractenv; +$environ = qr/$environ/x; +my $extr_tmp = qr { + ( + (?: + \\begin\{$environ\*?\} + (?: + (?>[^\\]+)| + \\ + (?!begin\{$environ\*?\}) + (?!end\{$environ\*?\})| + (?-1) + )* + \\end\{$environ\*?\} + ) + ) + }x; + +### Hash for replace in verbatim begin -> Begin end -> END +my %extract_env = crearhash(@extractenv); + +### The preview and nopreview environments are "special", need replace +### in verbatim's environments begin -> Begin end -> END +my @preview_env = qw(preview nopreview); +my %preview_env = crearhash(@preview_env); + +Log('Making changes to verbatim/verbatim write environments before extraction'); + +### Hash and Regex for changes, this "regex" is re-used in ALL script +my %replace = (%extract_env, %preview_env, %changes_in, %document); +my $find = join q{|}, map { quotemeta } sort { length $a <=> length $b } keys %replace; + +### We go line by line and make the changes [need /p for ${^MATCH}] +while ($document =~ /$verb_wrt | $verb_std /pgmx) { + my ($pos_inicial, $pos_final) = ($-[0], $+[0]); + my $encontrado = ${^MATCH}; + $encontrado =~ s/($find)/$replace{$1}/g; + substr $document, $pos_inicial, $pos_final-$pos_inicial, $encontrado; + pos ($document) = $pos_inicial + length $encontrado; +} -# Poner el atributo añadido a \begin{PSTexample} -while ($cuerpo =~ /^\\begin\{PSTexample\}(\[.+?\])?/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 +### Now match preview environment in +my @env_preview = $document =~ m/(\\begin\{preview\}.+?\\end\{preview\})/gmsx; + +### Convert preview to nopreview environment +if (@env_preview) { + my $preNo = scalar @env_preview; + Log("Found $preNo preview environments in $name$ext"); + Log("Pass all preview environments to \\begin{nopreview}\%TMP$tmp ... \\end{nopreview}\%TMP$tmp"); + $document =~ s/(?:(\\begin\{|\\end\{))(preview\})/$1no$2\%TMP$tmp/gmsx; +} + +### Pass verbatim write environments to dtxtag +Log("Pass verbatim write environments to %<*$dtxverb> ... %"); +$document =~ s/\\begin\{nopreview\}.+?\\end\{nopreview\}(*SKIP)(*F)| + ($verb_wrt)/\%<\*$dtxverb>$1\%<\/$dtxverb>/gmsx; + +### Pass verbatim environments to dtxtag +Log("Pass verbatim environments to %<*$dtxverb> ... %"); +$document =~ s/\\begin\{nopreview\}.+?\\end\{nopreview\}(*SKIP)(*F)| + \%<\*$dtxverb> .+?\%<\/$dtxverb>(*SKIP)(*F)| + ($verb_std)/\%<\*$dtxverb>$1\%<\/$dtxverb>/gmsx; + +### Pass %CleanPST to dtxtag +Log("Pass %CleanPST ... %CleanPST to %<*remove$tmp> ... %"); +$document =~ s/\%<\*$dtxverb> .+?\%<\/$dtxverb>(*SKIP)(*F)| + ^(?:%CleanPST) (.+?) (?:%CleanPST)/\%<\*remove$tmp>$1\%<\/remove$tmp>/gmsx; + +### Check plain TeX syntax for pspicture [skip PSTexample] +Log('Convert plain \pspicture to LaTeX syntax [skip in PSTexample]'); +$document =~ s/\%<\*$dtxverb> .+?\%<\/$dtxverb>(*SKIP)(*F)| + \\begin\{nopreview\}.+?\\end\{nopreview\}(*SKIP)(*F)| + \\begin\{PSTexample\}.+?\\end\{PSTexample\}(*SKIP)(*F)| + \\pspicture(\*)?(.+?)\\endpspicture/\\begin\{pspicture$1\}$2\\end\{pspicture$1\}/gmsx; + +### Check plain TeX syntax for psgraph [skip PSTexample] +Log('Convert plain \psgraph to LaTeX syntax [skip in PSTexample]'); +$document =~ s/\%<\*$dtxverb> .+?\%<\/$dtxverb>(*SKIP)(*F)| + \\begin\{nopreview\}.+?\\end\{nopreview\}(*SKIP)(*F)| + \\begin\{PSTexample\}.+?\\end\{PSTexample\}(*SKIP)(*F)| + \\psgraph(\*)?(.+?)\\endpsgraph/\\begin\{psgraph$1\}$2\\end\{psgraph$1\}/gmsx; + +### Pass all postscript environments [skip in PSTexample] +Log("Pass all postscript environments to \\begin{$wrapping} ... \\end{$wrapping}"); +$document =~ s/\%<\*$dtxverb> .+?\%<\/$dtxverb>(*SKIP)(*F)| + \\begin\{PSTexample\}.+?\\end\{PSTexample\}(*SKIP)(*F)| + \\begin\{nopreview\}.+?\\end\{nopreview\}(*SKIP)(*F)| + (?:\\begin\{postscript\})(?:\s*\[ [^]]*? \])? + (?.+?) + (?:\\end\{postscript\}) + /\\begin\{$wrapping\}$+{code}\\end\{$wrapping\}/gmsx; + +### Pass all pstricks environments to \\begin{$wrapping} ... \\end{$wrapping}"); +if ($force) { + # Try to capture \psset{...} for pstricks and psgraph [force] + Log('Try to capture \psset{...} for pstricks environments [force mode]'); + Log("Pass all pstricks environments to \\begin{$wrapping} ... \\end{$wrapping} [force mode]"); + $document =~ s/\%<\*$dtxverb> .+?\%<\/$dtxverb>(*SKIP)(*F)| + \\begin\{nopreview\}.+?\\end\{nopreview\}(*SKIP)(*F)| + \\begin\{PSTexample\}.+?\\end\{PSTexample\}(*SKIP)(*F)| + \\begin\{$wrapping\}.+?\\end\{$wrapping\}(*SKIP)(*F)| + (? + (?:\\psset\{(?:\{.*?\}|[^\{])*\}.+?)? # if exist ...save + \\begin\{(? pspicture\*?| psgraph)\} .+? \\end\{\k\} + ) + /\\begin\{$wrapping\}$+{code}\\end\{$wrapping\}/gmsx; +} +else { + Log("Pass all pstricks environments to \\begin{$wrapping} ... \\end{$wrapping}"); + $document =~ s/\%<\*$dtxverb> .+?\%<\/$dtxverb>(*SKIP)(*F)| + \\begin\{nopreview\}.+?\\end\{nopreview\}(*SKIP)(*F)| + \\begin\{$wrapping\}.+?\\end\{$wrapping\}(*SKIP)(*F)| + ($extr_tmp)/\\begin\{$wrapping\}$1\\end\{$wrapping\}/gmsx; +} + +### All environments are now classified: +### Extraction -> \begin{$wrapping} ... \end{$wrapping} +### Verbatim's -> %<\*$dtxverb> ... <\/$dtxverb> + +### Now split document +my ($preamble,$bodydoc,$enddoc) = $document =~ m/\A (.+?) (\\begin\{document\} .+?)(\\end\{document\}.*)\z/msx; + +### Hash for reverse changes for extract and +my %changes_out = ( + '\PSSET' => '\psset', + '\TIKZSET' => '\tikzset', + '\TRICKS' => '\pspicture', + '\ENDTRICKS' => '\endpspicture', + '\PSGRAPHTRICKS' => '\psgraph', + '\ENDPSGRAPHTRICKS' => '\endpsgraph', + '\USEPACKAGE' => '\usepackage', + '{GRAPHICX}' => '{graphicx}', + '\GRAPHICSPATH{' => '\graphicspath{', + '\BEGIN{' => '\begin{', + '\END{' => '\end{', + '\DOCUMENTCLASS' => '\documentclass', + '\PAGESTYLE{' => '\pagestyle{', + '\THISPAGESTYLE{' => '\thispagestyle{', + '%PSTCLEAN' => '%CleanPST', + ); + +### We restore the changes in body of environments and dtxverb +%replace = (%changes_out); +$find = join q{|}, map { quotemeta } sort { length $a <=> length $b } keys %replace; +$bodydoc =~ s/($find)/$replace{$1}/g; +$preamble =~ s/($find)/$replace{$1}/g; + +### First search PSTexample environment for extract +my @exa_extract = $bodydoc =~ m/(?:\\begin\{$wrapping\})($BE.+?$EE)(?:\\end\{$wrapping\})/gmsx; +my $exaNo = scalar @exa_extract; + +### Set vars for log and print in terminal +my $envEXA = $exaNo > 1 ? 'PSTexample environments' : 'PSTexample environment'; +my $fileEXA = $exaNo > 1 ? 'files' : 'file'; + +### If PSTexample environment found +if ($exaNo!=0) { + $PSTexa = 1; + Log("Found $exaNo $envEXA in $name$ext"); + my $figNo = 1; + for my $item (@exa_extract) { + Logline("%##### PSTexample environment captured number $figNo ######%"); + Logline($item); + $figNo++; } - - if (not $corchetes or $corchetes =~ /\[\s*\]/) { # si no hay corchetes, o están vacíos, - $corchetes = "[$graphics-$exacount}]"; # ponemos los nuestros + # Add [graphic={[...]...}] to \begin{PSTexample}[...] + Log('Append [graphic={[...]...}] to \begin{PSTexample}[...]'); + $figNo = 1; + while ($bodydoc =~ /\\begin\{$wrapping\}(\s*)?\\begin\{PSTexample\}(\[.+?\])?/gsm) { + my $swpl_grap = "graphic=\{\[scale=1\]$imgdir/$name-fig-exa"; + my $corchetes = $1; + my ($pos_inicial, $pos_final) = ($-[1], $+[1]); + if (not $corchetes) { $pos_inicial = $pos_final = $+[0]; } + if (not $corchetes or $corchetes =~ /\[\s*\]/) { + $corchetes = "[$swpl_grap-$figNo}]"; + } + else { $corchetes =~ s/\]/,$swpl_grap-$figNo}]/; } + substr($bodydoc, $pos_inicial, $pos_final - $pos_inicial) = $corchetes; + pos($bodydoc) = $pos_inicial + length $corchetes; } - else { # si sí hay corchetes, - $corchetes =~ s/\]/,$graphics-$exacount}]/; # lo agregamos al final, dentro de los corchetes + continue { $figNo++; } + Log('Pass PSTexample environments to \begin{nopreview} ... \end{nopreview}'); + $bodydoc =~ s/\\begin\{$wrapping\} + (?\\begin\{PSTexample\} .+? \\end\{PSTexample\}) + \\end\{$wrapping\} + /\\begin\{nopreview\}\%$tmp$+{code}\\end\{nopreview\}\%$tmp/gmsx; +} + +### Second search any pstricks environment for extract +my @env_extract = $bodydoc =~ m/(?:$BP)(.+?)(?:$EP)/gmsx; +my $envNo = scalar @env_extract; + +### Set vars for log and print in terminal +my $envSTD = $envNo > 1 ? 'pstricks environments' : 'pstricks environment'; +my $fileSTD = $envNo > 1 ? 'files' : 'file'; + +### If any pstricks environments found +if ($envNo!=0) { + $STDenv = 1; + Log("Found $envNo $envSTD in $name$ext"); + my $fig = 1; + for my $item (@env_extract) { + Logline("%##### Environment pstricks captured number $fig ######%"); + Logline($item); + $fig++; } - - 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 PSTexample files ---------------------- - -while ($cuerpo =~ /^\\begin\{PSTexample\}\[.+?(?$imageDir\/.+?-\d+)\}\](?.+?)(?=^\\end\{PSTexample})/gsm) { - open my $SALIDA, '>', "$+{'nombre_archivo_secundario'}$ext"; - print $SALIDA <<"EOC"; -$cabeza\n\\thispagestyle{empty}$+{'contenido'}\\end{document} -EOC - close $SALIDA; -} -# Now, deault way join all PSTexample files -if(!$nopreview){ -if (-e "$imageDir/$name-exa-1$ext") { -# print "PSTexample environment found\n"; -# 1- Leer los PSTexa files -my @pstexafiles = glob("$imageDir/$name-exa-*$ext"); - -# 2- Ordenar según el índice y extención -@pstexafiles = - map { $_->[1] } - sort { $a->[0] <=> $b->[0] } - map { [ ($_ =~ /(\d+$ext)/), $_ ] } - @pstexafiles; - -# 3- Bucle para leer las secciones -my @almacen; -for my $exafile (@pstexafiles) { - - # 3.1- Leer el archivo - open my $FH, '<', $exafile; # - my $tex = join q{}, <$FH>; # - close $FH; - - # 3.2- Extraer la parte que nos interesa - my($pedazo) = $tex =~ m/\\thispagestyle\{empty\}\s*(.+?)\s*\\end\{document\}/sm; - - # 3.3- Almacenamos, si hemos encontrado algo - push @almacen, $pedazo if $pedazo; -} - -# 4- Salida -open my $SALIDA, '>', "$tempDir/$name-exa$ext"; - -print $SALIDA "$cabeza\n"; - -my $fig = 1; -for my $item (@almacen) { - print $SALIDA "\\thispagestyle\{empty\}\n"; - print $SALIDA $item; - print $SALIDA "%fig . $fig\n"; - print $SALIDA "\\newpage\n"; - $fig++; -} - -print $SALIDA '\end{document}'; -close $SALIDA; - } # close join exa files (if exist) -} # close nopreview - -### Escribimos en el mismo archivo con los cambios en verbatim -open my $SALIDA, '>', "$tempDir/$name-tmp$ext"; -print $SALIDA "$cabeza$cuerpo$final"; -close $SALIDA; - -## Comentamos pst-exa en el preambulo, para no entorpecer a preview -$cabeza =~ -s/(?\\usepackage\[(swpl|tcb)\]\{pst-exa\})/%$+{exapack}/gsmx; -## Eliminamos PSTexample y PSTcode para no entorpecer a preview -$cuerpo =~ -s/(?\\begin\{PSTexample\})(?.+?)(?\\end\{PSTexample\})//gsmx; -$cuerpo =~ -s/(?\\begin\{PSTcode\})(?.+?)(?\\end\{PSTcode\})//gsmx; - -## Escribimos el archivo completo para las figuras -if(!$nopreview){ -open my $OUTFILE, '>', "$tempDir/$name-pst$ext"; -print $OUTFILE "\\AtBeginDocument\{\n"; -if($xetex){ -print $OUTFILE "\\RequirePackage\[xetex,active,tightpage\]\{preview\}\n"; } -else{ -print $OUTFILE "\\RequirePackage\[active,tightpage\]\{preview\}\n"; + +### Run script process only if any enviroment(s) found in +if ($envNo == 0 and $exaNo == 0) { + errorUsage("$scriptname can not find any environment to extract in $name$ext"); +} + +### Storing ALL current options of script process for .log file +if ($zip) { $opts_cmd{boolean}{zip} = 1; } +if ($tar) { $opts_cmd{boolean}{tar} = 1; } +if ($shell) { $opts_cmd{boolean}{shell} = 1; } +if ($nopdf) { $opts_cmd{boolean}{nopdf} = 1; } +if ($norun) { $opts_cmd{boolean}{norun} = 1; } +if ($nocrop) { $opts_cmd{boolean}{nocrop} = 1; } +if ($srcenv) { $opts_cmd{boolean}{srcenv} = 1; } +if ($gray) { $opts_cmd{boolean}{gray} = 1; } +if ($force) { $opts_cmd{boolean}{force} = 1; } +if ($noprew) { $opts_cmd{boolean}{noprew} = 1; } +if ($runbibtex) { $opts_cmd{boolean}{bibtex} = 1; } +if ($runbiber) { $opts_cmd{boolean}{biber} = 1; } +if ($clear) { $opts_cmd{boolean}{clear} = 1; } +if ($nosource) { $opts_cmd{boolean}{nosource} = 1; } +if ($arara) { $opts_cmd{compiler}{arara} = 1; } +if ($latexmk) { $opts_cmd{compiler}{latexmk} = 1; } +if ($luatex) { $opts_cmd{compiler}{luatex} = 1; } +if ($xetex) { $opts_cmd{compiler}{xetex} = 1; } +if ($tmpverbenv) { $opts_cmd{string}{ignore} = $tmpverbenv; } +$opts_cmd{string}{myverb} = $myverb; +$opts_cmd{string}{dpi} = $dpi; +$opts_cmd{string}{runs} = $runs; +$opts_cmd{string}{margins} = $margins; +$opts_cmd{string}{imgdir} = $imgdir; + +foreach my $key (keys %{$opts_cmd{boolean}}) { + if (defined $opts_cmd{boolean}{$key}) { push @currentopt, "--$key"; } +} +foreach my $key (keys %{$opts_cmd{compiler}}) { + if (defined $opts_cmd{compiler}{$key}) { push @currentopt, "--$key"; } } -print $OUTFILE "\\renewcommand\\PreviewBbAdjust\{-60pt -60pt 60pt 60pt\}%\n"; -print $OUTFILE "\\PreviewEnvironment\{pspicture\}\n"; -print $OUTFILE "\\PreviewEnvironment\{postscript\}\}\n"; -print $OUTFILE "$cabeza$cuerpo\\end\{document\}"; -close $OUTFILE; +foreach my $key (keys %{$opts_cmd{image}}) { + if (defined $opts_cmd{image}{$key}) { push @currentopt, "--$key"; } } -## Escribimos en el mismo archivo, convirtiendo PSTexample -## esta sera el archivo de entrada en el resto del script +foreach my $key (keys %{$opts_cmd{string}}) { + if (defined $opts_cmd{string}{$key}) { push @currentopt, "--$key $opts_cmd{string}{$key}"; } +} + +@currentopt = grep !/--pdf/, @currentopt; +my @sorted_words = sort { length $a <=> length $b } @currentopt; + +Log('The script will execute the following options:'); +Logarray(\@sorted_words); -my @lineas; -{ - open my $FILE, "$tempDir/$name-tmp$ext"; - @lineas = <$FILE>; - close $FILE; +### Set directory to save generated files, need full path for goog log :) +my $imgdirpath = File::Spec->rel2abs($imgdir); + +if (-e $imgdir) { + Infoline("The generated files will be saved in $imgdirpath"); +} +else { + Infoline("Creating the directory $imgdirpath to save the generated files"); + Infocolor('Running', "mkdir $imgdirpath"); + Logline("[perl] mkdir($imgdir,0744)"); + mkdir $imgdir,0744 or errorUsage("Can't create the directory $imgdir"); } -my $PSTexample = qr/(?: PSTexample | PSTcode )/xi; -# -my $DEL; +### Set compiler for process +my $compiler = $xetex ? 'xelatex' + : $luatex ? 'dvilualatex' + : 'latex' + ; + +### Set options for pdfcrop +my $opt_crop = $xetex ? "--xetex --margins $margins" + : $luatex ? "--luatex --margins $margins" + : "--margins $margins" + ; + +### Set options for preview package +my $opt_prew = $xetex ? 'xetex,' : q{}; + +### Set message in terminal +my $msg_compiler = $xetex ? 'xelatex' + : $luatex ? 'dvilualatex>dvips>ps2pdf' + : 'latex>dvips>ps2pdf' + ; + +### Set write18 for compiler in TeXLive and MikTeX +if ($shell) { + $write18 = '-shell-escape'; + $write18 = '--enable-write18' if defined $ENV{'TEXSYSTEM'} and $ENV{'TEXSYSTEM'} =~ /miktex/i; +} +else { + $write18 = '-no-shell-escape'; + $write18 = '--disable-write18' if defined $ENV{'TEXSYSTEM'} and $ENV{'TEXSYSTEM'} =~ /miktex/i; +} -for (@lineas) { - if (/^\\begin\{($PSTexample)(?{ $DEL = "\Q$^N" })\}/ .. /^\\end\{$DEL\}/) { - while (my($busco, $cambio) = each %cambios) { - s/\Q$busco\E/$cambio/g; +### Set options for compiler +my $opt_compiler = "$write18 -interaction=nonstopmode -recorder"; + +if (!$norun) { + Log("The options '$opt_compiler' will be passed to $compiler"); +} + +### Set -q for system command line (gs, poppler-utils, dvips) +my $quiet = $verbose ? q{} + : '-q' + ; + +### Set options for ghostscript +my %opt_gs_dev = ( + pdf => '-dNOSAFER -dBATCH -dNOPAUSE -sDEVICE=pdfwrite', + gray => '-dNOSAFER -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sColorConversionStrategy=Gray -sProcessColorModel=DeviceGray', + png => "-dNOSAFER -dBATCH -dNOPAUSE -sDEVICE=pngalpha -r$dpi", + bmp => "-dNOSAFER -dBATCH -dNOPAUSE -sDEVICE=bmp32b -r$dpi", + jpg => "-dNOSAFER -dBATCH -dNOPAUSE -sDEVICE=jpeg -r$dpi -dJPEGQ=100 -dGraphicsAlphaBits=4 -dTextAlphaBits=4", + tif => "-dNOSAFER -dBATCH -dNOPAUSE -sDEVICE=tiff32nc -r$dpi", + ); + +### Set poppler-utils executables +my %cmd_poppler = ( + eps => "pdftops", + ppm => "pdftoppm", + svg => "pdftocairo", + ); + +### Set options for poppler-utils +my %opt_poppler = ( + eps => "$quiet -eps", + ppm => "$quiet -r $dpi", + svg => "$quiet -svg", + ); + +### Copy preamble and body for temp file with all environments +my $atbeginout = $atbegindoc; +my $preamout = $preamble; +my $tmpbodydoc = $bodydoc; + +### Match \pagestyle and \thispagestyle in preamble +my $style_page = qr /(?:\\)(?:this)?(?:pagestyle\{) (.+?) (?:\})/x; +my @style_page = $preamout =~ m/\%<\*$dtxverb> .+?\%<\/$dtxverb>(*SKIP)(*F)| $style_page/gmsx; +my %style_page = map { $_ => 1 } @style_page; # anon hash + +### Set \pagestyle{empty} for standalone files and process +if (@style_page) { + if (!exists $style_page{empty}) { + Log("Replacing page style for generated files"); + $preamout =~ s/\%<\*$dtxverb> .+?\%<\/$dtxverb>(*SKIP)(*F)| + (\\(this)?pagestyle)(?:\{.+?\})/$1\{empty\}/gmsx; + } +} +else { + Log('Add \pagestyle{empty} for generated files'); + $preamout = $preamout."\\pagestyle\{empty\}\n"; +} + +### We created a preamble for the individual files +my $sub_prea = "$atbeginout$preamout".'\begin{document}'; + +### Revert changes +$sub_prea =~ s/\%<\*$dtxverb>\s*(.+?)\s*\%<\/$dtxverb>/$1/gmsx; +%replace = (%changes_out); +$find = join q{|}, map { quotemeta } sort { length $a <=> length $b } keys %replace; +$sub_prea =~ s/($find)/$replace{$1}/g; +$sub_prea =~ s/^(?:\%<\*remove$tmp>)(.+?)(?:\%<\/remove$tmp>)/%CleanPST$1%CleanPST/gmsx; + +### Write standalone files for environments +if (!$nosource) { + my $src_name = "$name-fig-"; + my $srcNo = 1; + if ($srcenv) { + Log('Extract source code of all captured environments without preamble'); + if ($STDenv) { + if (-e "$imgdir/$name-fig-1$ext") { + Log("Recreating $envNo $fileSTD [$ext] with source code for $envSTD in $imgdirpath"); + print "Recreating $envNo $fileSTD ", color('magenta'), "[$ext]", + color('reset'), " with source code for $envSTD\r\n"; + } + else { + Log("Creating $envNo $fileSTD [$ext] with source code for $envSTD in $imgdirpath"); + print "Creating $envNo $fileSTD ", color('magenta'), "[$ext]", + color('reset'), " with source code for $envSTD\r\n"; + } + # Write files + while ($tmpbodydoc =~ m/$BP(?:\s*)?(?.+?)(?:\s*)?$EP/gms) { + open my $outexasrc, '>', "$imgdir/$src_name$srcNo$ext"; + print {$outexasrc} $+{'env_src'}; + close $outexasrc; + } + continue { $srcNo++; } + } + if ($PSTexa) { + if (-e "$imgdir/$name-fig-exa-1$ext") { + Log("Recreating $exaNo $fileEXA [$ext] with source code for $envEXA in $imgdirpath"); + print "Recreating $exaNo $fileEXA ", color('magenta'), "[$ext]", + color('reset'), " with source code for $envEXA\r\n"; + } + else { + Log("Creating $exaNo $fileEXA [$ext] with source code for $envEXA in $imgdirpath"); + print "Creating $exaNo $fileEXA ", color('magenta'), "[$ext]", + color('reset'), " with source code for $envEXA\r\n"; + } + # Write files + while ($tmpbodydoc =~ m/$BE\[.+?(?$imgdir\/.+?-\d+)\}\]\s*(?.+?)\s*$EE/gms) { + open my $outstdsrc, '>', "$+{'pst_exa_name'}$ext"; + print {$outstdsrc} $+{'exa_src'}; + close $outstdsrc; + } } } - } - -# Escritura del resultado -open my $SALIDA, '>', "$tempDir/$name-tmp$ext"; -print $SALIDA @lineas; -close $SALIDA; -# end code for pstexample - -my $imgNo = 1; # internal image counter -#----------------- nopreview mode, dont'n need gs ---------------------- -if ($nopreview) { -LOG ("Running on [$path][$name][$ext]"); -open my $FILE,'<', "$TeXfile" ; # the source -if (!$noImages ) { -LOG ("nopreview mode generate images..."); -savePreamble($name); -runFile($name); -runPSTimg($name); -close $FILE; # close source file -close $LOGfile; - } -} -#----------------------- Default way, using gs ------------------------- -else{ -LOG ("Running on [$path][$name][$ext]"); -open my $FILE,'<', "$TeXfile" ; # the source -if (!$noImages ) { -LOG ("Using gs for split images ... "); -savePreamble($name); -runFile($name); -runPSTimg($name); -LOG ("done!\n go to runFile ..."); -LOG ("done!"); -close $FILE; # close source file -close $LOGfile; - }# !noImages -}# close - - - -#-------------------------- Save Preamble ------------------------------ -# Now create a preamble file if we have a \input command inside the -# preamble, it doesn't hurt, we need it anyway for the postscript -# files and the pdf one. -sub savePreamble { -my $filename = pop; # get the file name - LOG ("----- Start Preamble -----"); -open my $FILEp,'>',"$tempDir/$filename.preamble"; -open my $FILE, '<', "$tempDir/$name-tmp$ext"; - while (<$FILE>) { # read all until \begin{document} - my $i = index($_,"begin{document}"); - if ($i > 0) { - if ($i > 1) { print $FILEp substr($_,0,--$i); } # write all until \begin{document} - if ($nopreview) { - print $FILEp "\\newenvironment{postscript}{}{}\n"; - print $FILEp "\\pagestyle{empty}\n"; - } -close $FILEp; # close preamble - LOG ("----- Close Preamble ------"); - return; - } -else { - print $FILEp "$_"; # write into preamble - LOG ("$_"); + else { + Log('Extract source code of all captured environments with preamble'); + if ($STDenv) { + if (-e "$imgdir/$name-fig-1$ext") { + Log("Recreating $envNo standalone $fileSTD [$ext] for $envSTD in $imgdirpath"); + print "Recreating $envNo standalone $fileSTD ", color('magenta'), "[$ext]", + color('reset'), " for $envSTD\r\n"; + } + else { + Log("Creating $envNo standalone $fileSTD [$ext] for $envSTD in $imgdirpath"); + print "Creating $envNo standalone $fileSTD ", color('magenta'), "[$ext]", + color('reset'), " for $envSTD\r\n"; + } + # Write files + while ($tmpbodydoc =~ m/$BP(?:\s*)?(?.+?)(?:\s*)?$EP/gms) { + open my $outstdfile, '>', "$imgdir/$src_name$srcNo$ext"; + print {$outstdfile} "$sub_prea\n$+{'env_src'}\n\\end\{document\}"; + close $outstdfile; + } + continue { $srcNo++; } + } + if ($PSTexa) { + if (-e "$imgdir/$name-fig-exa-1$ext") { + Log("Recreating $exaNo standalone $fileEXA [$ext] for $envEXA in $imgdirpath"); + print "Recreating $exaNo standalone $fileEXA ", color('magenta'), "[$ext]", + color('reset'), " for $envEXA\r\n"; + } + else { + Log("Creating $exaNo standalone $fileEXA [$ext] for $envEXA in $imgdirpath"); + print "Creating $exaNo standalone $fileEXA ", color('magenta'), "[$ext]", + color('reset'), " for $envEXA\r\n"; + } + # Write files + while ($tmpbodydoc =~ m/$BE\[.+?(?$imgdir\/.+?-\d+)\}\]\s*(?.+?)\s*$EE/gms) { + open my $outexafile, '>', "$+{'pst_exa_name'}$ext"; + print {$outexafile} "$sub_prea\n$+{'exa_src'}\n\\end\{document\}"; + close $outexafile; + } + } } } -close $FILE; -close $FILEp; -} -# Search in source-parser file -sub searchPS { # search the PostScript parts - my @PS = (); # nopreview PS sequence - my @PStotal = (); # all PS sequences as list of arrays - my $depth = -1; # counts nested macros - my $type = -1; # -1-> none; 1->PST; 2->PS; - my $EndDocument = 0; # ignore all after \end{document} - my $iVerb = 0; # test for verbatim or lstlisting environment, must be ignored - open my $FILE, '<', "$tempDir/$name-tmp$ext"; - while (<$FILE>) { # scan the input file - if (!$EndDocument) { - chomp; # delete EOL character - my $line = $_; # save line - if ( !$iVerb ) { - $iVerb = ((index($line,"begin{verbatim}") > 0) or ( index($line,"begin{lstlisting}") > 0)); - } # do nothing until \end{verbatim} - if ( !$iVerb ) { - my $iPS = index($line,"begin{postscript}"); - my $iPST = index($line,"begin{pspicture*}"); - if ($iPST < 0) { $iPST = index($line,"begin{pspicture}"); } # alternative - if ($iPST < 0) { $iPST = index($line,"pspicture"); } # alternative \pspicture... - if (($iPS > 0) && ( $type == 1 )){ print "postscript environment must be of outer level!\n"; exit 1; } - if ( $type < 0 ) { # no active environment - if ($iPS > 0) { # we have \begin{postscript} - $type = 2; - $line = substr($line,$iPS-1); # add rest of the line - LOG("PS-Zeile: $line"); - } - elsif ( $iPST > 0 ) { # we have \begin{pspicture} or \pspicture - $type = 1; - $depth++; - $line = substr($line,$iPST-1);# add all unitl pspicture - LOG("PST-Zeile: $line"); + +### Store options for preview and pst-pdf (add at begin document) +my $previewpkg = <<"EXTRA"; +\\PassOptionsToPackage\{inactive\}\{pst-pdf\}% +\\AtBeginDocument\{% +\\RequirePackage\[inactive\]\{pst-pdf\}% +\\RequirePackage\[${opt_prew}active,tightpage\]\{preview\}% +\\renewcommand\\PreviewBbAdjust\{-60pt -60pt 60pt 60pt\}\}% +EXTRA + +### Store options for pst-pdf (add at begin document) +my $pstpdfpkg = <<'EXTRA'; +\PassOptionsToPackage{inactive}{pst-pdf} +\AtBeginDocument{% +\RequirePackage[inactive]{pst-pdf}}% +EXTRA + +### First match preview package in preamble (prevent option clash) +my $REQPACK = quotemeta'\RequirePackage'; +my $USEPACK = quotemeta'\usepackage'; +my $CORCHETES = qr/\[ [^]]*? \]/x; + +my $PALABRAS = qr/\b (?: preview )/x; +my $FAMILIA = qr/\{ \s* $PALABRAS (?: \s* [,] \s* $PALABRAS )* \s* \}(\%*)?/x; + +Log('Remove preview package in preamble [memory]'); +$preamout =~ s/\%<\*$dtxverb> .+?\%<\/$dtxverb>(*SKIP)(*F)| + ^ $USEPACK (?: $CORCHETES )? $FAMILIA \s*//msxg; +$preamout =~ s/\%<\*$dtxverb> .+?\%<\/$dtxverb>(*SKIP)(*F)| + (?: ^ $USEPACK \{ | \G) [^}]*? \K (,?) \s* $PALABRAS (\s*) (,?) /$1 and $3 ? ',' : $1 ? $2 : ''/gemsx; +$preamout =~ s/^\\usepackage\{\}(?:[\t ]*(?:\r?\n|\r))+/\n/gmsx; + +### Remove %<*$dtxverb> ... % in tmpbodydoc and preamout +$tmpbodydoc =~ s/\%<\*$dtxverb>(.+?)\%<\/$dtxverb>/$1/gmsx; +$preamout =~ s/\%<\*$dtxverb>(.+?)\%<\/$dtxverb>/$1/gmsx; + +### Adjust nopreview environments +$tmpbodydoc =~ s/\\begin\{nopreview\}\%$tmp + (? .+?) + \\end\{nopreview\}\%$tmp + /\\begin\{nopreview\}\n$+{code}\n\\end\{nopreview\}/gmsx; + +### Adjust $wrapping environments (no need realy) +$tmpbodydoc =~ s/\\begin\{$wrapping\} + (?.+?) + \\end\{$wrapping\} + /\\begin\{$wrapping\}\n$+{code}\n\\end\{$wrapping\}/gmsx; + +### Reverse changes for temporary file with all env (no in -exa file) +$tmpbodydoc =~ s/($find)/$replace{$1}/g; +$tmpbodydoc =~ s/(\%TMP$tmp)//g; +$preamout =~ s/($find)/$replace{$1}/g; +$preamout =~ s/^(?:\%<\*remove$tmp>)(.+?)(?:\%<\/remove$tmp>)/%CleanPST$1%CleanPST/gmsx; +$atbeginout =~ s/($find)/$replace{$1}/g; + +### We created a preamble for individual files with all environments +$sub_prea = $noprew ? "$atbeginout$pstpdfpkg$preamout".'\begin{document}' + : "$atbeginout$previewpkg$preamout" + ; + +### Create a one file with "all" PSTexample environments extracted +if ($PSTexa) { + @exa_extract = undef; + Log("Adding packages to $name-fig-exa-$tmp$ext [memory]"); + Logline($pstpdfpkg); + Log('Convert plain Tex syntax for pspicture and psgraph to LaTeX syntax in PSTexample environments'); + while ($tmpbodydoc =~ m/$BE\[.+? $imgdir\/.+?-\d+\}\] .+?$EE/pgsmx ) { # search + my ($pos_inicial, $pos_final) = ($-[0], $+[0]); + my $encontrado = ${^MATCH}; + $encontrado =~ s/\\pspicture(\*)?(.+?)\\endpspicture/\\begin\{pspicture$1\}$2\\end\{pspicture$1\}/gmsx; + $encontrado =~ s/\\psgraph(\*)?(.+?)\\endpsgraph/\\begin\{psgraph$1\}$2\\end\{psgraph$1\}/gmsx; + substr $tmpbodydoc, $pos_inicial, $pos_final-$pos_inicial, $encontrado; + pos ($tmpbodydoc) = $pos_inicial + length $encontrado; + } + # Write file + Infoline("Creating $name-fig-exa-$tmp$ext with $exaNo $envEXA extracted"); + while ($tmpbodydoc =~ m/$BE\[.+? $imgdir\/.+?-\d+\}\](?.+?)$EE/gmsx ) { # search + push @exa_extract, $+{'exa_src'}."\\newpage\n"; + open my $allexaenv, '>', "$name-fig-exa-$tmp$ext"; + print {$allexaenv} "$atbeginout$pstpdfpkg$preamout".'\begin{document}'."@exa_extract"."\\end\{document\}"; + close $allexaenv; + } + # Remove [graphic={...}] in PSTexample example environments + $tmpbodydoc =~ s/($BE)(?:\[graphic=\{\[scale=1\]$imgdir\/.+?-\d+\}\])/$1/gmsx; + $tmpbodydoc =~ s/($BE\[.+?)(?:,graphic=\{\[scale=1\]$imgdir\/.+?-\d+\})(\])/$1$2/gmsx; + # Moving and renaming + if ($norun) { + Infoline("Moving and renaming $name-fig-exa-$tmp$ext to $name-fig-exa-all$ext"); + if (-e "$imgdir/$name-fig-exa-all$ext") { + Infocolor('Warning', "The file [$name-fig-exa-all$ext] already exists and will be rewritten"); + Log("Rewriting the file $name-fig-exa-all$ext in $imgdirpath"); + } + else { + Log("Writing the file $name-fig-exa-all$ext in $imgdirpath"); } - } -# we have now \begin{pspicture} or \begin{postscript} - if ($type > 0) { # start Scan, we have an environment - LOG ("searchPS: set \$type=$type"); - $iPST = index($line,"end{pspicture*}"); - if ($iPST < 0) { $iPST = index($line,"end{pspicture}"); } # alternative - if ($iPST < 0) { $iPST = index($line,"endpspicture"); } # alternative \endpspicture... - $iPS = index($line,"end{postscript}"); - if ($iPST > 0) { # test, we can have postscript and pspicture in one line - if ( $type < 2) { # found end of pspicture environment - LOG ("searchPS: $line"); - $depth--; - if ($depth < 0) { - $type = -1; - if (index($line,"endpspicture") > 0) # add line, depends to type - { push @PS,substr($line,0,$iPST+12); } # \endpspicture - elsif (index($line,"pspicture*") > 0) - { push @PS,substr($line,0,$iPST+15); }# \end{pspicture} - else { push @PS,substr($line,0,$iPST+14); } # \end{pspicture} - LOG ("searchPS: set \$type=$type"); - push @PStotal,[@PS]; # add PS sequence - LOG ("---->PS---->\n@PS\n<----PS<----"); - @PS = (); # start new PS sequence - } # no pspicture env left - } else { push @PS,$line; } # pspicture inside postscript - } elsif ($iPS > 0) { # must be type=1 -> stop Scan - LOG ("searchPS: $line"); - $type = -1; - push @PS,substr($line,0,$iPS+15); # add line - LOG ("searchPS: set \$type=$type"); - push @PStotal,[@PS]; # add PS sequence - LOG ("---->PS---->\n@PS\n<----PS<----"); - @PS =(); # start new PS sequence - } else { push @PS,$line; } # add line - } - my $i = index($line,"end{document}"); - if ($i > 0) { $EndDocument++; LOG("EndDocument in searchPS"); } - } # if ( $iVerb ) - if (( index($line,"end{verbatim}") > 0 ) or ( index($line,"end{lstlisting}") > 0 )) { $iVerb = 0; } - }} - if ( $Verbose ) { - LOG("---->PStotal---->"); - for my $aref ( @PStotal ) { - my @a = @$aref; - my $i = 1; - foreach ( @a ) { LOG ($a[$i]); $i=$i+1; } + if ($verbose) { + Infocolor('Running', "mv $workdir/$name-fig-exa-$tmp$ext $imgdirpath/$name-fig-exa-all$ext"); + } + else { + Infocolor('Running', "mv $name-fig-exa-$tmp$ext ./$imgdir/$name-fig-exa-all$ext"); + } + Logline("[perl] move($workdir/$name-fig-exa-$tmp$ext, $imgdirpath/$name-fig-exa-all$ext)"); + move("$workdir/$name-fig-exa-$tmp$ext", "$imgdir/$name-fig-exa-all$ext") + or die "* Error!!: Couldn't be renamed $name-fig-exa-$tmp$ext to ./$imgdir/$name-fig-exa-all$ext"; } - LOG ("<----PStotal<----"); - } - close $FILE; - return @PStotal; # return all PS sequences } -#---------------------- Create files.tex for images -------------------- -sub runFile { - - my $filename = pop; - my @PSarray = searchPS(); +### Create a one file with "all" standard environments extracted +if ($STDenv) { + if ($noprew) { + Log("Creating $name-fig-$tmp$ext with $envNo $envSTD extracted [no preview]"); + print "Creating $name-fig-$tmp$ext with $envNo $envSTD extracted", + color('magenta'), " [no preview]\r\n",color('reset'); + } + else { + Log("Creating $name-fig-$tmp$ext with $envNo $envSTD extracted [preview]"); + print "Creating $name-fig-$tmp$ext with $envNo $envSTD extracted", + color('magenta'), " [preview]\r\n",color('reset'); + } + open my $allstdenv, '>', "$name-fig-$tmp$ext"; + if ($noprew) { + my @env_extract; + while ($tmpbodydoc =~ m/(?:$BP)(?.+?)(?:$EP)/gms) { + push @env_extract,$+{'env_src'}."\\newpage\n"; + } + Log("Adding packages to $name-fig-$tmp$ext"); + Logline($pstpdfpkg); + print {$allstdenv} $sub_prea."@env_extract"."\\end{document}"; + } + else { + Log("Adding packages to $name-fig-$tmp$ext"); + Logline($previewpkg); + Log("Convert $wrapping to preview environments in $name-fig-$tmp$ext"); + # Convert $wrapping to preview environments + $tmpbodydoc =~ s/\\begin\{$wrapping\}(?.+?)\\end\{$wrapping\} + /\\begin\{preview\}\n$+{code}\n\\end\{preview\}\n/gmsx; + print {$allstdenv} $sub_prea.$tmpbodydoc."\n\\end{document}"; + } + close $allstdenv; + # Moving and renaming + if ($norun) { + Infoline("Moving and renaming $name-fig-$tmp$ext to $name-fig-all$ext"); + if (-e "$imgdir/$name-fig-all$ext") { + Infocolor('Warning', "The file [$name-fig-all$ext] already exists and will be rewritten"); + Log("Rewriting the file $name-fig-all$ext in $imgdirpath"); + } + else { + Log("Writing the file $name-fig-all$ext in $imgdirpath"); + } + if ($verbose) { + Infocolor('Running', "mv $workdir/$name-fig-$tmp$ext $imgdirpath/$name-fig-all$ext"); + } + else { + Infocolor('Running', "mv $name-fig-$tmp$ext ./$imgdir/$name-fig-all$ext"); + } + Logline("[perl] move($workdir/$name-fig-$tmp$ext, $imgdirpath/$name-fig-all$ext)"); + move("$workdir/$name-fig-$tmp$ext", "$imgdir/$name-fig-all$ext") + or die "* Error!!: Couldn't be renamed $name-fig-$tmp$ext to ./$imgdir/$name-fig-all$ext"; + } +} - if ( $Verbose ) { - LOG("---->PSarray---->"); - for my $aref ( @PSarray ) { - my @a = @$aref; - my $i = 1; - foreach ( @a ) { print LOG $a[$i]."\n"; $i=$i+1; } +### Compiler and generate PDF files +if (!$norun) { +Log('Generate a PDF file with all captured environments'); +my @compiler = (1..$runs); +opendir (my $DIR, $workdir); + while (readdir $DIR) { + if (/(?$name-fig(-exa)?)(?-$tmp$ext)/) { + Log("Compiling the file $+{name}$+{type} using [$msg_compiler]"); + print "Compiling the file $+{name}$+{type} using ", color('magenta'), "[$msg_compiler]\r\n",color('reset'); + # Compiling file + for (@compiler){ + RUNOSCMD("$compiler $opt_compiler","$+{name}$+{type}",'show'); + } + # Using dvips>ps2pdf + if ($compiler eq 'latex' or $compiler eq 'dvilualatex') { + RUNOSCMD("dvips $quiet -Ppdf", "-o $+{name}-$tmp.ps $+{name}-$tmp.dvi",'show'); + RUNOSCMD("ps2pdf -sPDFSETTINGS=prepress -sAutoRotatePages=None", "$+{name}-$tmp.ps $+{name}-$tmp.pdf",'show'); + } + # Moving and renaming temp files with source code + Infoline("Moving and renaming $+{name}$+{type} to $+{name}-all$ext"); + if (-e "$imgdir/$+{name}-all$ext") { + Infocolor('Warning', "The file [$+{name}-all$ext] already exists and will be rewritten"); + Log("Rewriting the file $+{name}-all$ext with all source for environments in $imgdirpath"); + } + else { + Log("Writing the file $+{name}-all$ext with all source for environments in $imgdirpath"); + } + if ($verbose){ + Infocolor('Running', "mv $workdir/$+{name}$+{type} $imgdirpath/$+{name}-all$ext"); + } + else { + Infocolor('Running', "mv $+{name}$+{type} ./$imgdir/$+{name}-all$ext"); + } + Logline("[perl] move($workdir/$+{name}$+{type}, $imgdirpath/$+{name}-all$ext)"); + move("$workdir/$+{name}$+{type}", "$imgdir/$+{name}-all$ext") + or die "* Error!!: Couldn't be renamed $+{name}$+{type} to $imgdir/$+{name}-all$ext"; + # pdfcrop + if (!$nocrop) { + Infoline("Cropping the file $+{name}-$tmp.pdf"); + RUNOSCMD("pdfcrop $opt_crop", "$+{name}-$tmp.pdf $+{name}-$tmp.pdf",'show'); + } + # gray + if ($gray) { + Infoline("Creating the file $+{name}-all.pdf [gray] in $tempDir"); + RUNOSCMD("$gscmd $quiet $opt_gs_dev{gray} ","-o $tempDir/$+{name}-all.pdf $workdir/$+{name}-$tmp.pdf",'show'); + } + else { + Infoline("Creating the file $+{name}-all.pdf in $tempDir"); + if ($verbose){ + Infocolor('Running', "mv $workdir/$+{name}-$tmp.pdf $tempDir/$+{name}-all.pdf"); + } + else { Infocolor('Running', "mv $+{name}-$tmp.pdf $tempDir/$+{name}-all.pdf"); } + # Renaming pdf file + Logline("[perl] move($workdir/$+{name}-$tmp.pdf, $tempDir/$+{name}-all.pdf)"); + move("$workdir/$+{name}-$tmp.pdf", "$tempDir/$+{name}-all.pdf") + or die "* Error!!: Couldn't be renamed $+{name}-$tmp.pdf to $tempDir/$+{name}-all.pdf"; + } + } } - LOG("<----PSarray<----"); - my $no = @PSarray; - LOG("PS: ".$no." PS sequence(s)"); - } - for my $aref ( @PSarray ) { - my @PS = @$aref; - open my $FILEp,'<',"$tempDir/$filename.preamble"; - open my $FILEsub,'>',"$tempDir/$filename-fig$ext"; - while (<$FILEp>) {print $FILEsub $_; } - print $FILEsub "\\begin{document}\n"; - if ( $Verbose ) { LOG("\@PS: $_"); } - foreach ( @PS ) { print $FILEsub "$_\n"; } - print $FILEsub "\\end{document}"; - close $FILEsub; - close $FILEp; - runTeX("$tempDir/$filename-fig"); - } -} -LOG ("runpdfTeX ... "); -runpdfTeX("$path$name",$name); -LOG ("all finished ... :-)"); - -#------------------- Copy files.tex for images in default mode --------- -sub runTeX{ - my $filename = pop; - copy("$filename$ext", "$imageDir/$filename-$imgNo$ext"); - $imgNo=$imgNo+1; -} -#------------------- Create images in PDF fromat ------------------------ -sub runPSTimg() { -# Option for gs -my $opt_gs_split='-q -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -dNOPAUSE -dBATCH '; - -# Option for pdfcrop -my $opt_pdfcrop="-margins $margins"; - -# Abrimos el directorio y creamos las imagenes en formato PDF -if ($nopreview) { -opendir(my $DIR, $imageDir); - while (readdir $DIR) { -if (/(?$name-(fig|exa)-\d+)(?$ext)/) { -if ($xetex){ - system("xelatex -interaction=batchmode -output-directory=$imageDir $imageDir/$+{nombre}$+{extension}"); - system("pdfcrop $opt_pdfcrop -xetex $imageDir/$+{nombre}.pdf $imageDir/$+{nombre}.pdf"); - } # close xelatex -else{ - system("latex -interaction=batchmode -output-directory=$imageDir $imageDir/$+{nombre}$+{extension}"); - system("dvips -q -P pdf -o $imageDir/$+{nombre}.ps $imageDir/$+{nombre}.dvi"); - system("ps2pdf $imageDir/$+{nombre}.ps $imageDir/$+{nombre}.pdf"); - system("pdfcrop $opt_pdfcrop $imageDir/$+{nombre}.pdf $imageDir/$+{nombre}.pdf"); - } # close latex>dvips>ps2pdf - } # close find regex in nopreview -} # close while closedir $DIR; -} # close $nopreview -# Cerramos y abrimos con nopreview (gs por defecto) -else{ -# Compilamos PSTexa usando gs -if (-e "$tempDir/$name-exa$ext") { -if ($xetex){ - system("xelatex -interaction=batchmode -output-directory=$imageDir $tempDir/$name-exa$ext"); - system("pdfcrop $opt_pdfcrop -xetex $imageDir/$name-exa.pdf $imageDir/$name-exa.pdf"); - } # xelatex -else{ - system("latex -interaction=batchmode -output-directory=$imageDir $tempDir/$name-exa$ext"); - system("dvips -q -Ppdf -o $imageDir/$name-exa.ps $imageDir/$name-exa.dvi"); - system("ps2pdf -dPDFSETTINGS=/prepress $imageDir/$name-exa.ps $imageDir/$name-exa.pdf"); - system("pdfcrop $opt_pdfcrop $imageDir/$name-exa.pdf $imageDir/$name-exa.pdf"); - } # close latex>dvips>ps2pdf -system("$::opt_gscmd $opt_gs_split -sOutputFile=$imageDir/$name-exa-%1d.pdf $imageDir/$name-exa.pdf"); - -# Eliminamos los fuentes -if ($clear) { - unlink "$imageDir/$name-exa.pdf"; - unlink "$tempDir/$name-exa$ext"; +} + +### Create image formats in separate files +if (!$norun) { + Log("Creating the image formats: $format, working on $tempDir"); + opendir(my $DIR, $tempDir); + while (readdir $DIR) { + # PDF/PNG/JPG/BMP/TIFF format suported by ghostscript + if (/(?$name-fig(-exa)?)(?-all\.pdf)/) { + for my $var (qw(pdf png jpg bmp tif)) { + if (defined $opts_cmd{image}{$var}) { + Log("Generating format [$var] from file $+{name}$+{type} in $imgdirpath using $gscmd"); + print 'Generating format', color('blue'), " [$var] ", color('reset'),"from file $+{name}$+{type}\r\n"; + RUNOSCMD("$gscmd $quiet $opt_gs_dev{$var} ", "-o $workdir/$imgdir/$+{name}-%1d.$var $tempDir/$+{name}$+{type}",'show'); + } + } + } + # EPS/PPM/SVG format suported by poppler-utils + if (/(?$name-fig-exa)(?-all\.pdf)/) { # pst-exa package + for my $var (qw(eps ppm svg)) { + if (defined $opts_cmd{image}{$var}) { + Log("Generating format [$var] from file $+{name}$+{type} in $imgdirpath using $cmd_poppler{$var}"); + print 'Generating format', color('blue'), " [$var] ", color('reset'),"from file $+{name}$+{type}\r\n"; + if (!$verbose){ + Infocolor('Running', "$cmd_poppler{$var} $opt_poppler{$var}"); + } + for (my $epsNo = 1; $epsNo <= $exaNo; $epsNo++) { + RUNOSCMD("$cmd_poppler{$var} $opt_poppler{$var}", "-f $epsNo -l $epsNo $tempDir/$+{name}$+{type} $workdir/$imgdir/$+{name}-$epsNo.$var",'only'); + } + } + } + } + if (/(?$name-fig)(?-all\.pdf)/) { + for my $var (qw(eps ppm svg)) { + if (defined $opts_cmd{image}{$var}) { + Log("Generating format [$var] from file $+{name}$+{type} in $imgdirpath using $cmd_poppler{$var}"); + print 'Generating format', color('blue'), " [$var] ", color('reset'),"from file $+{name}$+{type}\r\n"; + if (!$verbose){ + Infocolor('Running', "$cmd_poppler{$var} $opt_poppler{$var}"); + } + for (my $epsNo = 1; $epsNo <= $envNo; $epsNo++) { + RUNOSCMD("$cmd_poppler{$var} $opt_poppler{$var}", "-f $epsNo -l $epsNo $tempDir/$+{name}$+{type} $workdir/$imgdir/$+{name}-$epsNo.$var",'only'); + } + } + } + } + } # close while + closedir $DIR; + # Renaming PPM image files + if (defined $opts_cmd{image}{ppm}) { + Log("Renaming [ppm] images in $imgdirpath"); + if ($verbose){ + print 'Renaming', color('blue'), " [ppm] ", color('reset'),"images in $imgdirpath\r\n"; + } + opendir(my $DIR, $imgdir); + while (readdir $DIR) { + if (/(?$name-fig(-exa)?-\d+\.ppm)(?-\d+)(?\.ppm)/) { + if ($verbose){ + Infocolor('Running', "mv $+{name}$+{sep}$+{ppm} $+{name}"); + } + Logline("[perl] move($imgdirpath/$+{name}$+{sep}$+{ppm}, $imgdirpath/$+{name})"); + move("$imgdir/$+{name}$+{sep}$+{ppm}", "$imgdir/$+{name}") + or die "* Error!!: Couldn't be renamed $+{name}$+{sep}$+{ppm} to $+{name}"; + } + } + closedir $DIR; } -} # close check file exist - -# Compilamos las imagenes y las separamos usando gs -if (-e "$imageDir/$name-fig-1$ext") { -if ($xetex){ - system("xelatex -interaction=batchmode -output-directory=$imageDir $tempDir/$name-pst$ext"); - system("pdfcrop $opt_pdfcrop -xetex $imageDir/$name-pst.pdf $imageDir/$name-pst.pdf"); - } # xelatex -else{ - system("latex -interaction=batchmode -output-directory=$imageDir $tempDir/$name-pst$ext"); - system("dvips -q -Ppdf -o $imageDir/$name-pst.ps $imageDir/$name-pst.dvi"); - system("ps2pdf -dPDFSETTINGS=/prepress $imageDir/$name-pst.ps $imageDir/$name-pst.pdf"); - system("pdfcrop $opt_pdfcrop $imageDir/$name-pst.pdf $imageDir/$name-pst.pdf"); - } # close latex>dvips>ps2pdf -system("$::opt_gscmd $opt_gs_split -sOutputFile=$imageDir/$name-fig-%1d.pdf $imageDir/$name-pst.pdf"); -if ($clear) { -unlink "$imageDir/$name-pst.pdf"; -unlink "$tempDir/$name-pst$ext"; -unlink "$tempDir/$name-fig$ext"; - } # end clear - } # close check file exist -} # close !nopreview (ghostscript) -#--------------------------- Clear aux files --------------------------- -if ($clear) { -my @del_tmp; -find(\&del_aux_tex, $imageDir); -sub del_aux_tex{ -my $auximgfile = $_; - -# search .(aux|dvi|log|ps) -if(-f $auximgfile && $auximgfile =~ /\.(aux|dvi|log|ps)$/){ -push @del_tmp, $File::Find::name; - } -} -unlink @del_tmp; -}# end clear aux - -# Create xpdfrc conf for silent output pdftops/pdftoppm mesagge -if ($^O eq 'MSWin32' || $^O eq 'MSWin64'){ - -if ($eps or $ppm) { -open my $ppmconf, '>', "$tempDir/xpd"; -print $ppmconf <<'EOH'; -errQuiet yes -EOH -close $ppmconf; - } -}# end fix for windows - -# options for other images type using ghostscript -my $opt_gs_raw='-dGraphicsAlphaBits=4 -dTextAlphaBits=4 -dNOPAUSE -dBATCH '; - -# Creamos las imagenes en todos los formatos distintos a PDF -opendir(my $DIR, $imageDir); -while (readdir $DIR) { -if (/(?$name-(fig|exa)-\d+)(?\.pdf)/) { - -# PNG format -if ($png) { -system("$::opt_gscmd -q -sDEVICE=pngalpha -r$DPI $opt_gs_raw -sOutputFile=$imageDir/$+{nombre}.png $imageDir/$+{nombre}.pdf"); - } - -# JPEG format -if ($jpg) { -system("$::opt_gscmd -q -sDEVICE=jpeg -r$DPI -dJPEGQ=100 $opt_gs_raw -sOutputFile=$imageDir/$+{nombre}.jpg $imageDir/$+{nombre}.pdf"); - } - -# SVG format -if ($svg) { - system("pdf2svg $imageDir/$+{nombre}.pdf $imageDir/$+{nombre}.svg"); - } - -# EPS format -if ($eps) { - if ($^O eq 'MSWin32' || $^O eq 'MSWin64'){ - system("pdftops -cfg $tempDir/xpd -q -level3 -eps $imageDir/$+{nombre}.pdf $imageDir/$+{nombre}.eps"); - }else{ - system("pdftops -q -level3 -eps $imageDir/$+{nombre}.pdf $imageDir/$+{nombre}.eps"); - } - } # close EPS - -# PPM format -if ($ppm) { - if ($^O eq 'MSWin32' || $^O eq 'MSWin64'){ - system("pdftoppm -cfg $tempDir/xpd -q -r $DPI $imageDir/$+{nombre}.pdf $imageDir/$+{nombre}"); - }else{ - system("pdftoppm -q -r $DPI $imageDir/$+{nombre}.pdf $imageDir/$+{nombre}"); - } - } # close PPM - } # close finde regex -} # close while -closedir $DIR; #close dir - -## Renombramos los ppm -if ($ppm) { -if (opendir(DIR,$dir)) { # abro el directorio - while (my $oldname = readdir DIR) { # lo recorro - # el nuevo nombre es fruto de una sustitución - my $newname = $oldname =~ s/^($name-(fig|exa)-\d+)(-\d+).ppm$/$1 . ".ppm"/re; - - if ($oldname ne $newname) { # comprobación - rename("$dir/$oldname", "$dir/$newname"); # renombro - } - } - closedir DIR; - } # close rename ppm - } # close ppm -} # cerramos runPSTimg - -#--------------------- Replace PST environment for images---------------- -sub runpdfTeX() { - - my ($name,$pdfname) = @_; - open my $PDF,'>',"$tempDir/$pdfname-pdf$ext"; - open my $FILE,'<',"$tempDir/$name-tmp$ext"; - my $ignore = 0; - my $IMGno = 1; - my $depth = -1; - my $type = -1; - my $EndDocument = 0; # ignore all after \end{document} - my $iVerb = 0; - while (<$FILE>) { # scan the input file - if ( !$iVerb ) { - $iVerb = ((index($_,"begin{verbatim}") > 0) or ( index($_,"begin{lstlisting}") > 0)); - } # do nothing until \end{verbatim}|| \end{lstlisting} - if ( !$iVerb ) { - my $i = index($_,"end{document}"); - if ($i > 0) { print $PDF $_; $EndDocument++; LOG("EndDocument in runpdfTeX"); } - if ( !$EndDocument ) { - my $iPS = index($_,"begin{postscript}"); - if ( $iPS > 0 ) { - $type = 2; - $ignore = 1; - if ($iPS > 1) { print $PDF substr($_,0,--$iPS); } # add preceeding text - print $PDF "\\includegraphics[scale=1]{$pdfname-fig-$IMGno}"; # use pdfname - $IMGno=$IMGno+1; - } # postscript env - if ( $type < 2 ) { - my $iPST = index($_,"begin{pspicture*}"); - if ($iPST < 0) { $iPST = index($_,"begin{pspicture}"); } # alternative ... - if ($iPST < 0) { $iPST = index($_,"\\pspicture"); } # alternative \\pspicture... - if ( $iPST >= 0 ) { # start Scan - $ignore = 1; - $type = 1; - $depth++; # pspicture env - LOG("Increase depth: $depth"); - if ( $depth == 0 ) { - if ($iPST > 1) { print $PDF substr($_,0,--$iPST); } # add preceeding text - print $PDF "\\includegraphics[scale=1]{$pdfname-fig-$IMGno}"; # use \graphicspath - $IMGno=$IMGno+1; - LOG("Increase Image counter: $IMGno"); +} # close run + +### Constant +my $findgraphicx = 'true'; + +### Suport for pst-exa package +my $pstexa = qr/(?:\\ usepackage) \[\s*(.+?)\s*\] (?:\{\s*(pst-exa)\s*\} ) /x; +my @pst_exa; +my %pst_exa; + +### Possible packages that load graphicx +my @pkgcandidates = qw ( + rotating epsfig lyluatex xunicode parsa xepersian-hm gregoriotex teixmlslides + teixml fotex hvfloat pgfplots grfpaste gmbase hep-paper postage schulealt + schule utfsym cachepic abc doclicense rotating epsfig semtrans mgltex + graphviz revquantum mpostinl cmpj cmpj2 cmpj3 chemschemex register papercdcase + flipbook wallpaper asyprocess draftwatermark rutitlepage dccpaper-base + nbwp-manual mandi fmp toptesi isorot pinlabel cmll graphicx-psmin ptmxcomp + countriesofeurope iodhbwm-templates fgruler combinedgraphics pax pdfpagediff + psfragx epsdice perfectcut upmethodology-fmt ftc-notebook tabvar vtable + teubner pas-cv gcard table-fct pdfpages keyfloat pdfscreen showexpl simplecd + ifmslide grffile reflectgraphics markdown bclogo tikz-page pst-uml realboxes + musikui csbulobalka lwarp mathtools sympytex mpgraphics miniplot.sty:77 + dottex pdftricks2 feupphdteses tex4ebook axodraw2 hagenberg-thesis dlfltxb + hu-berlin-bundle draftfigure quicktype endofproofwd euflag othelloboard + pdftricks unswcover breqn pdfswitch latex-make figlatex repltext etsvthor + cyber xcookybooky xfrac mercatormap chs-physics-report tikzscale ditaa + pst-poker gmp CJKvert asypictureb hletter tikz-network powerdot-fuberlin + skeyval gnuplottex plantslabels fancytooltips ieeepes pst-vectorian + phfnote overpic xtuformat stubs graphbox ucs pdfwin metalogo mwe + inline-images asymptote UNAMThesis authorarchive amscdx pst-pdf adjustbox + trimclip fixmetodonotes incgraph scanpages pst-layout alertmessage + svg quiz2socrative realhats autopdf egplot decorule figsize tikzexternal + pgfcore frontespizio textglos graphicx tikz tcolorbox pst-exa + ); + +my $pkgcandidates = join q{|}, map { quotemeta } sort { length $a <=> length $b } @pkgcandidates; +$pkgcandidates = qr/$pkgcandidates/x; +my @graphicxpkg; + +### \graphicspath +my $graphicspath= qr/\\ graphicspath \{ ((?: $llaves )+) \}/ix; +my @graphicspath; + +### Replacing the extracted environments with \includegraphics +Log("Convert pstricks extracted environments to \\includegraphics for $name-pdf$ext"); +my $grap = "\\includegraphics[scale=1]{$name-fig-"; +my $close = '}'; +my $imgNo = 1; +$bodydoc =~ s/$BP.+?$EP/$grap@{[$imgNo++]}$close/msg; + +### Add $atbegindoc to $preamble +$preamble = "$atbegindoc$preamble"; + +### Remove content in preamble +my @tag_remove_preamble = $preamble =~ m/(?:^\%<\*remove$tmp>.+?\%<\/remove$tmp>)/gmsx; +if (@tag_remove_preamble) { + Log("Removing the content between <*remove> ... tags in preamble for $name-pdf$ext"); + $preamble =~ s/^\%<\*remove$tmp>\s*(.+?)\s*\%<\/remove$tmp>(?:[\t ]*(?:\r?\n|\r))?+//gmsx; +} + +### To be sure that the package is in the main document and not in a +### verbatim write environment we make the changes using the hash and +### range operator in a copy +my %tmpreplace = ( + 'graphicx' => 'TMPGRAPHICXTMP', + 'pst-exa' => 'TMPPSTEXATMP', + 'graphicspath' => 'TMPGRAPHICSPATHTMP', +); + +my $findtmp = join q{|}, map { quotemeta } sort { length $a <=> length $b } keys %tmpreplace; +my $preambletmp = $preamble; +my @lineas = split /\n/, $preambletmp; + +### We remove the commented lines +s/\%.*(?:[\t ]*(?:\r?\n|\r))?+//msg foreach @lineas; + +### We make the changes in the environments verbatim write +my $DEL; +for (@lineas) { + if (/\\begin\{($verbatim_w\*?)(?{ $DEL = "\Q$^N" })\}/ .. /\\end\{$DEL\}/) { + s/($findtmp)/$tmpreplace{$1}/g; + } +} + +### Join lines in $preambletmp +$preambletmp = join "\n", @lineas; + +### We removed the blank lines +$preambletmp =~ s/^(?:[\t ]*(?:\r?\n|\r))?+//gmsx; + +### Now we're trying to capture +@graphicxpkg = $preambletmp =~ m/($pkgcandidates)/gmsx; +if (@graphicxpkg) { + Log("Found graphicx package in preamble for $name-pdf$ext"); + $findgraphicx = 'false'; +} + +### Search graphicspath +@graphicspath = $preambletmp =~ m/graphicspath/msx; +if (@graphicspath) { + Log("Found \\graphicspath in preamble for $name-pdf$ext"); + $findgraphicx = 'false'; + while ($preamble =~ /$graphicspath /pgmx) { + my ($pos_inicial, $pos_final) = ($-[0], $+[0]); + my $encontrado = ${^MATCH}; + if ($encontrado =~ /$graphicspath/) { + my $argumento = $1; + if ($argumento !~ /\{$imgdir\/\}/) { + $argumento .= "\{$imgdir/\}"; + my $cambio = "\\graphicspath{$argumento}"; + substr $preamble, $pos_inicial, $pos_final-$pos_inicial, $cambio; + pos($preamble) = $pos_inicial + length $cambio; + } + } + } +} + +### Search pst-exa +@pst_exa = $preambletmp =~ m/\%<\*$dtxverb> .+?\%<\/$dtxverb>(*SKIP)(*F)|$pstexa/xg; +%pst_exa = map { $_ => 1 } @pst_exa; +if (@pst_exa) { + Log("Comment pst-exa package in preamble for $name-pdf$ext"); + $findgraphicx = 'false'; + $preamble =~ s/(\\usepackage\[)\s*(swpl|tcb)\s*(\]\{pst-exa\})/\%$1$2,pdf$3/msxg; +} +if (exists $pst_exa{tcb}) { + Log("Suport for \\usepackage[tcb,pdf]\{pst-exa\} for $name-pdf$ext"); + $bodydoc =~ s/(graphic=\{)\[(scale=\d*)\]($imgdir\/$name-fig-exa-\d*)\}/$1$2\}\{$3\}/gsmx; +} + +### Try to capture arara:compiler in preamble of +my @arara_engines = qw (latex pdflatex lualatex xelatex luahbtex); +my $arara_engines = join q{|}, map { quotemeta} sort { length $a <=> length $b } @arara_engines; +$arara_engines = qr/\b(?:$arara_engines)/x; +my $arara_rule = qr /^(?:\%\s{1}arara[:]\s{1}) ($arara_engines) /msx; + +### Capture graphicx.sty in .log of LaTeX file +if ($findgraphicx eq 'true') { + Log("Couldn't capture the graphicx package for $name-pdf$ext in preamble"); + my $ltxlog; + my @graphicx; + my $null = devnull(); + Log("Creating $name-fig-$tmp$ext [only preamble]"); + if ($verbose) { say "Creating [$name-fig-$tmp$ext] with only preamble"; } + open my $OUTfile, '>', "$name-fig-$tmp$ext"; + print {$OUTfile} "$preamble\n\\stop"; + close $OUTfile; + # Set compiler + if ($opts_cmd{compiler}{arara}) { + my @engine = $preamble =~ m/$arara_rule/msx; + my %engine = map { $_ => 1 } @engine; + if (%engine) { + for my $var (@arara_engines) { + if (defined $engine{$var}) { + $compiler = $var; + } } - } } - if ( !$ignore ) { print $PDF "$_"; } # default line - if ( $type == 2 ) { # postscript env - my $iPS = index($_,"end{postscript}"); - if ($iPS > 0) { - print $PDF substr($_,$iPS+15); # rest of line - $ignore = 0; - $type=-1; - } # end Scan - } - elsif ( $type == 1 ) { # pspicture env - my $iPST = index($_,"end{pspicture*}"); - if ($iPST < 0) { $iPST = index($_,"end{pspicture}"); } # alternative ... - if ($iPST < 0) { $iPST = index($_,"endpspicture"); } # alternative \endpspicture... - if ($iPST > 0) { # end Scan - if (index($_,"endpspicture") > 0) # add rest of line, depends to type - { print $PDF substr($_,$iPST+12); } # \endpspicture - elsif (index($_,"pspicture*") > 0) - { print $PDF substr($_,$iPST+15); } # \end{pspicture*} - else{ print $PDF substr($_,$iPST+14); } # \end{pspicture} - $depth--; - LOG("Decrease depth: $depth"); - if ($depth < 0) { $ignore = 0; } - } + else { $compiler = 'pdflatex'; } + } + if ($compiler eq 'latex') { $compiler = 'pdflatex'; } + if ($compiler eq 'dvilualatex') { $compiler = 'lualatex'; } + # Compiling file + RUNOSCMD("$compiler $write18 -interaction=batchmode", "$name-fig-$tmp$ext >$null", 'only'); + # Restore arara compiler + if ($arara) { $compiler = 'arara'; } + Log("Search graphicx package in $name-fig-$tmp.log"); + open my $LaTeXlog, '<', "$name-fig-$tmp.log"; + { + local $/; + $ltxlog = <$LaTeXlog>; } - } # if ( !$EndDocument ) - } else { print $PDF $_; } # if ( $iVerb ) - if (( index($_,"end{verbatim}") > 0 ) or ( index($_,"end{lstlisting}") > 0 )) { $iVerb = 0; } - } # while (<$FILE>) - close $FILE; - close $PDF; -## Close generate file -if ($clear) { -unlink "$tempDir/$pdfname-tmp$ext"; -#unlink "$tempDir/$pdfname-fig$ext"; -} -#------------------- Clean pstpack, reverse changes -------------------- -## Leer archivo -open my $INFILE, '<', "$tempDir/$pdfname-pdf$ext"; -my $IPDF; -{ - local $/; - $IPDF = <$INFILE>; -} -close $INFILE; - -## Constantes -my $BEGINDOC = quotemeta('\begin{document}'); -my $USEPACK = quotemeta('\usepackage'); -my $GRAPHICX = quotemeta('{graphicx}'); - -## Exp. Reg. + close $LaTeXlog; + # Try to capture graphicx + @graphicx = $ltxlog =~ m/.+? (graphicx\.sty)/xg; + if (@graphicx) { + Log("Found graphicx package in $name-fig-$tmp.log"); + } + else { + Log("Not found graphicx package in $name-fig-$tmp.log"); + Log("Add \\usepackage\{graphicx\} to preamble of $name-pdf$ext"); + $preamble= "$preamble\n\\usepackage\{graphicx\}"; + } +} -my $CORCHETES = qr/\[ [^]]*? \]/x; -my $PALABRAS = qr/\b (?: pst-\w+ | pstricks (?: -add )? | psfrag |psgo |vaucanson-g| auto-pst-pdf | graphicx )/x; -my $FAMILIA = qr/\{ \s* $PALABRAS (?: \s* [,] \s* $PALABRAS )* \s* \}/x; - -## Dividir el archivo -my($cabeza, $cuerpo) = $IPDF =~ m/\A (.+?) ($BEGINDOC .+?) \z/msx; - -## Revisamos si esta cargado pst-exa -my $pstTcbload = 0; # Buscamos si esta cargado \usepackage[...]{pst-exa} -$pstTcbload = index($cabeza,"usepackage[tcb]{pst-exa}"); - -## Filtrado -# comentar -$cabeza =~ s/ ^ ($USEPACK $CORCHETES $GRAPHICX) /%$1/msxg; - -# eliminar líneas enteras -$cabeza =~ s/ ^ $USEPACK (?: $CORCHETES )? $FAMILIA \n//msxg; - -# eliminar palabras sueltas -$cabeza =~ s/ (?: ^ $USEPACK \{ | \G) [^}]*? \K (,?) \s* $PALABRAS (\s*) (,?) /$1 and $3 ? ',' : $1 ? $2 : ''/gemsx; - -## Añadir - -$cabeza .= <<"EXTRA"; -\\usepackage{graphicx} -\\graphicspath{{$imageDir/}} -\\usepackage{grfext} -\\PrependGraphicsExtensions*{.pdf} -EXTRA +### Regex for clean (pst-?) in preamble +$PALABRAS = qr/\b (?: pst-\w+ | pstricks (?: -add | -pdf )? | psfrag |psgo |vaucanson-g| auto-pst-pdf(?: -lua )? )/x; +$FAMILIA = qr/\{ \s* $PALABRAS (?: \s* [,] \s* $PALABRAS )* \s* \}(\%*)?/x; + +Log("Remove pstricks packages in preamble for $name-pdf$ext"); +$preamble =~ s/\%<\*$dtxverb> .+?\%<\/$dtxverb>(*SKIP)(*F)| + ^ $USEPACK (?: $CORCHETES )? $FAMILIA \s*//msxg; +$preamble =~ s/\%<\*$dtxverb> .+?\%<\/$dtxverb>(*SKIP)(*F)| + (?: ^ $USEPACK \{ | \G) [^}]*? \K (,?) \s* $PALABRAS (\s*) (,?) /$1 and $3 ? ',' : $1 ? $2 : ''/gemsx; +$preamble =~ s/\%<\*$dtxverb> .+?\%<\/$dtxverb>(*SKIP)(*F)| + \\psset\{(?:\{.*?\}|[^\{])*\}(?:[\t ]*(?:\r?\n|\r))+//gmsx; +$preamble =~ s/\%<\*$dtxverb> .+?\%<\/$dtxverb>(*SKIP)(*F)| + \\SpecialCoor(?:[\t ]*(?:\r?\n|\r))+//gmsx; +$preamble =~ s/^\\usepackage\{\}(?:[\t ]*(?:\r?\n|\r))+/\n/gmsx; + +if (@pst_exa) { + Log("Uncomment pst-exa package in preamble for $name-pdf$ext"); + $preamble =~ s/(?:\%)(\\usepackage\[\s*)(swpl|tcb)(,pdf\s*\]\{pst-exa\})/$1$2$3/msxg; +} -## Verificamos que exista el archivo -if (-e "$imageDir/$name-exa-1$ext") { -if ($pstTcbload > 1) { -# Cambiamos de swpl a tcb con una expresion regular -$cuerpo =~ s/(graphic=\{)\[(scale=\d*)\]($imageDir\/$pdfname-exa-\d*)\}/$1$2\}\{$3\}/gsmx; +### Add last lines +if (!@graphicspath) { + Log("Not found \\graphicspath in preamble for $name-pdf$ext"); + Log("Add \\graphicspath\{\{$imgdir/\}\} to preamble for $name-pdf$ext"); + $preamble= "$preamble\n\\graphicspath\{\{$imgdir/\}\}"; +} +Log("Add \\usepackage\{grfext\} to preamble for $name-pdf$ext"); +$preamble = "$preamble\n\\usepackage\{grfext\}"; +Log("Add \\PrependGraphicsExtensions\*\{\.pdf\} to preamble for $name-pdf$ext"); +$preamble = "$preamble\n\\PrependGraphicsExtensions\*\{\.pdf\}"; +$preamble =~ s/\%<\*$dtxverb>(.+?)\%<\/$dtxverb>/$1/gmsx; +$preamble =~ s/^\\usepackage\{\}(?:[\t ]*(?:\r?\n|\r))+/\n/gmsx; +$preamble =~ s/^(?:[\t ]*(?:\r?\n|\r))?+//gmsx; + +### Create a +my $out_file = "$preamble\n$bodydoc\n$enddoc"; + +### Clean \psset content in output file +$out_file =~ s/\\begin\{nopreview\}\%$tmp.+?\\end\{nopreview\}\%$tmp(*SKIP)(*F)| + \%<\*$dtxverb> .+? \%<\/$dtxverb>(*SKIP)(*F)| + \\psset\{(?:\{.*?\}|[^\{])*\}(?:[\t ]*(?:\r?\n|\r))?+//gmsx; + +### Revert preview environments +if (@env_preview) { + Log("Revert \\begin{nopreview}\%TMP$tmp ... \\end{nopreview}\%TMP$tmp"); + $out_file =~ s/\\begin\{nopreview\}\%TMP$tmp + (? .+?) + \\end\{nopreview\}\%TMP$tmp + /\\begin\{preview\}$+{code}\\end\{preview\}/gmsx; +} -# Se añade la opción [tcb] al paquete pst-exa -$cabeza .= <<"EXTRA"; -\\usepackage[pdf,tcb]{pst-exa} -EXTRA -} # close if +$out_file =~ s/\\begin\{nopreview\}%$tmp + (?\\begin\{PSTexample\} .+? \\end\{PSTexample\}) + \\end\{nopreview\}%$tmp + /$+{code}/gmsx; + +### Remove internal mark for verbatim and verbatim write environments +$out_file =~ s/\%<\*$dtxverb>(.+?)\%<\/$dtxverb>/$1/gmsx; +%replace = (%changes_out); +$find = join q{|}, map {quotemeta} sort { length $a <=> length $b } keys %replace; +$out_file =~ s/($find)/$replace{$1}/g; + +### Write +if (-e "$name-pdf$ext") { + Log("Rewriting the file $name-pdf$ext in $workdir"); + Infocolor('Warning', "The file [$name-pdf$ext] already exists and will be rewritten"); +} else{ -# print "Se añade la opción swpl al paquete pst-exa\n"; -$cabeza .= <<"EXTRA"; -\\usepackage[swpl]{pst-exa} -EXTRA + Infoline("Creating the file $name-pdf$ext"); + Log("Write the file $name-pdf$ext in $workdir"); +} +open my $OUTfile, '>', "$name-pdf$ext"; + print {$OUTfile} $out_file; +close $OUTfile; + +### Set compiler for process +$compiler = $xetex ? 'xelatex' + : $luatex ? 'lualatex' + : 'pdflatex' + ; + +### Set options for latexmk +my $ltxmkopt = $xetex ? "-pdfxe -silent -xelatex=\"xelatex $write18 -recorder %O %S\"" + : $luatex ? "-pdflua -silent -lualatex=\"lualatex $write18 -recorder %O %S\"" + : "-pdf -silent -pdflatex=\"pdflatex $write18 -recorder %O %S\"" + ; +### Set options for compiler +$opt_compiler = $arara ? '--log' + : $latexmk ? "$ltxmkopt" + : "$write18 -interaction=nonstopmode -recorder" + ; + +### Set compiler name for arara and latexmk +if ($arara) { $compiler = $msg_compiler = 'arara'; } +if ($latexmk) { $compiler = $msg_compiler = 'latexmk'; } + +### Process +if (!$norun) { + Log("Compiling the file $name-pdf$ext using [$msg_compiler]"); + print "Compiling the file $name-pdf$ext using ", color('magenta'), "[$msg_compiler]\r\n",color('reset'); + RUNOSCMD("$compiler $opt_compiler", "$name-pdf$ext",'show'); + # biber + if ($runbiber && -e "$name-pdf.bcf" && !$arara && !$latexmk) { + RUNOSCMD("biber", "$name-pdf",'show'); + RUNOSCMD("$compiler $opt_compiler", "$name-pdf$ext",'show'); } -} # close regex for pst-exa pack - -### Clear PST content in preamble -$cabeza =~ s/\\usepackage\{\}/%delete by pst2pdf/gmsx; -$cabeza =~ s/^\\psset\{.+?\}/%\\psset delete by pst2pdf/gmsx; -$cabeza =~ s/\\SpecialCoor/%\\SpecialCoor delete by pst2pdf/gmsx; -$cabeza =~ s/^%CleanPST .+? %CleanPST/% Clean PST by pst2pdf/gmsx; - -### Delete extra psset{..} in body -$cuerpo =~ s/\\psset\{[^\}]+\}(\s*\\includegraphics\[scale=1\]\{$pdfname-fig-\d*\})/$1/gms; - -### Back -my %cambios = ( - '\TRICKS' => '\pspicture', - '\ENDTRICKS' => '\endpspicture', - '\begin{PSTEXAMPLE' => '\begin{PSTexample', - '\end{PSTEXAMPLE' => '\end{PSTexample', - '\begin{TRICKS' => '\begin{pspicture', - '\end{TRICKS' => '\end{pspicture', - '\begin{POSTRICKS}' => '\begin{postscript}' , - '\end{POSTRICKS}' => '\end{postscript}' , - '\begin{DOCTRICKS}' => '\begin{document}' , - '\end{DOCTRICKS}' => '\end{document}' -); + # bibtex + if ($runbibtex && -e "$name-pdf.aux" && !$arara && !$latexmk) { + RUNOSCMD("bibtex", "$name-pdf",'show'); + RUNOSCMD("$compiler $opt_compiler", "$name-pdf$ext",'show'); + } +} -## Recorremos el archivo y realizamos los cambios -while (my($busco, $cambio) = each %cambios) { - $cabeza =~ s/\Q$busco\E/$cambio/g; - $cuerpo =~ s/\Q$busco\E/$cambio/g; - } +### Remove temporary files +my @tmpfiles; +my @protected = qw(); +my $flsline = 'OUTPUT'; +my @flsfile; + +### Protect generated files +push @protected, "$name-pdf$ext", "$name-pdf.pdf"; + +### Find files +find(\&aux_files, $workdir); +sub aux_files{ + my $findtmpfiles = $_; + if (-f $findtmpfiles && $findtmpfiles =~ m/$name-fig(-exa)?-$tmp.+?$/) { # search + push @tmpfiles, $_; + } + return; +} + +### Add if exists +if (-e 'arara.log') { + push @flsfile, 'arara.log'; +} +if (-e "$name-fig-$tmp.fls") { + push @flsfile, "$name-fig-$tmp.fls"; +} +if (-e "$name-fig-exa-$tmp.fls") { + push @flsfile, "$name-fig-exa-$tmp.fls"; +} +if (-e "$name-pdf.fls") { + push @flsfile, "$name-pdf.fls"; +} -## Escribimos en el mismo archivo -open my $SALIDA, '>', "$tempDir/$pdfname-pdf$ext"; -print $SALIDA "$cabeza$cuerpo"; -close $SALIDA; -# - -my $runAgain = 0; - -if($xetex){ # xelatex mode -if ($noImages){ - print "The file $pdfname-pdf$ext are created (Xe)LaTeX\n"; - } -else{ - system("xelatex -interaction=batchmode $tempDir/$pdfname-pdf"); - print "Done, compiled $pdfname-pdf$ext using (Xe)LaTeX\n"; +### Read .fls file +for my $filename(@flsfile){ + open my $RECtmp, '<', $filename; + push @tmpfiles, grep /^$flsline/,<$RECtmp>; + close $RECtmp; +} + +foreach (@tmpfiles) { s/^$flsline\s+|\s+$//g; } +push @tmpfiles, @flsfile; + +@tmpfiles = uniq(@tmpfiles); +@tmpfiles = array_minus(@tmpfiles, @protected); + +Log('The files that will be deleted are:'); +Logarray(\@tmpfiles); + +### Remove only if exist +if (@tmpfiles) { + Infoline("Remove temporary files created in $workdir"); + foreach my $tmpfiles (@tmpfiles) { + move($tmpfiles, $tempDir); } +} + +### Find dirs created by minted +my @deldirs; +my $mintdir = "\_minted\-$name-fig-$tmp"; +my $mintdirexa = "\_minted\-$name-fig-exa-$tmp"; +if (-e $mintdir) { push @deldirs, $mintdir; } +if (-e $mintdirexa) { push @deldirs, $mintdirexa; } + +Log('The directory that will be deleted are:'); +Logarray(\@deldirs); + +### Remove only if exist +if (@deldirs) { + Infoline("Remove temporary directories created by minted in $workdir"); + foreach my $deldirs (@deldirs) { + remove_tree($deldirs); } -else{ #pdflatex mode -if ($noImages){ - print "The file $pdfname-pdf$ext are created (pdf)LaTeX\n"; +} + +### Compress "./images" with generated files +my $archivetar; +if ($zip or $tar) { + my $stamp = strftime("%Y-%m-%d", localtime); + $archivetar = "$imgdir-$stamp"; + + my @savetozt; + find(\&zip_tar, $imgdir); + sub zip_tar{ + my $filesto = $_; + if (-f $filesto && $filesto =~ m/$name-fig-.+?$/) { # search + push @savetozt, $File::Find::name; + } + return; } -else{ - system("pdflatex -interaction=batchmode $tempDir/$pdfname-pdf$ext"); - print "Done, compiled $pdfname-pdf$ext using (pdf)LaTeX\n"; + Log("The files are compress found in $imgdirpath are:"); + Logarray(\@savetozt); + if ($zip) { + if (-e "$archivetar.zip") { + Infocolor('Warning', "The file [$archivetar.zip] already exists and will be rewritten"); + Log("Rewriting the file $archivetar.zip in $workdir"); + } + else{ + print "Creating the file ", color('magenta'), "[$archivetar.zip]", + color('reset'), " with generate files in ./$imgdir\r\n"; + Log("Writen the file $archivetar.tar.gz in $workdir"); + } + zip \@savetozt => "$archivetar.zip"; + } + if ($tar) { + if (-e "$archivetar.tar.gz") { + Infocolor('Warning', "The file [$archivetar.tar.gz] already exists and will be rewritten"); + Log("Rewriting the file $archivetar.tar.gz in $workdir"); + } + else{ + print "Creating the file ", color('magenta'), "[$archivetar.tar.gz]", + color('reset'), " with generate files in ./$imgdir\r\n"; + Log("Writen the file $archivetar.tar.gz in $workdir"); + } + my $imgdirtar = Archive::Tar->new(); + $imgdirtar->add_files(@savetozt); + $imgdirtar->write( "$archivetar.tar.gz" , 9 ); } } -if (-e "$tempDir/$pdfname-pdf.idx") { - system("makeindex $tempDir/$pdfname-pdf.idx"); - $runAgain++; - } -if ($runBibTeX && -e "$tempDir/$pdfname-pdf.aux") { - system("bibtex $tempDir/$pdfname-pdf"); - $runAgain++; - } -if ($runBiber && -e "$tempDir/$pdfname-pdf.bcf") { - system("biber $tempDir/$pdfname-pdf"); - $runAgain++; - } -if ($runAgain){ - if($xetex){ - system("xelatex -interaction=batchmode $tempDir/$pdfname-pdf"); - } - else{ - system("pdflatex -interaction=batchmode $tempDir/$pdfname-pdf"); - } - } -} #close sub run pdfTEX - -#----------------------------- Write LOG file -------------------------- -sub LOG() { - if ( $Verbose ) { print $LOGfile "@_\n"; } - } -#-------------------------- Clear all tmp files ------------------------ -if ($clear) { - -if (-e "$tempDir/$name-pst$ext") { -unlink "$tempDir/$name-pst$ext"; -} - my @del_pdf_tmp; - find(\&del_pdf_aux, $tempDir); - sub del_pdf_aux{ - my $auximgfile = $_; - if(-f $auximgfile && $auximgfile =~ /\.(aux|dvi|log|ps|idx|bfc|bib|preamble)$/){ - push @del_pdf_tmp, $File::Find::name; - } - } # close sub -unlink @del_pdf_tmp; # delte files - -if ($^O eq 'MSWin32' || $^O eq 'MSWin64'){ -if ($eps or $ppm){ - unlink "$tempDir/xpd"; - } -} -if(!$Verbose) { - unlink "$tempDir/$name.plog"; - } -} # close clear - -# Clear source files -if ($noSource) { -my @del_src; -find(\&del_src_tex, $imageDir); -sub del_src_tex{ -my $srcimg = $_; -# search image file source -if(-f $srcimg && $srcimg =~ /($name-(fig|exa)-\d+)$ext/){ -push @del_src, $File::Find::name; - } -} -unlink @del_src; -}# end source clear +### End of script process +if (!$norun && !$nosource) { + Log("The image files: $format and generated files are in $imgdirpath"); +} +if (!$norun && $nosource) { + Log("The image files: $format are in $imgdirpath"); +} +if ($norun && !$nosource) { + Log("The generated files are in $imgdirpath"); +} +Log("The output file $name-pdf$ext are in $workdir"); + +Infocolor('Finish', "The execution of $scriptname has been successfully completed"); + +Log("The execution of $scriptname has been successfully completed"); __END__ -- cgit v1.2.3