diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /obsolete/support/prv |
Initial commit
Diffstat (limited to 'obsolete/support/prv')
-rwxr-xr-x | obsolete/support/prv/prv | 1907 | ||||
-rwxr-xr-x | obsolete/support/prv/prvps | 183 |
2 files changed, 2090 insertions, 0 deletions
diff --git a/obsolete/support/prv/prv b/obsolete/support/prv/prv new file mode 100755 index 0000000000..8aee8e2909 --- /dev/null +++ b/obsolete/support/prv/prv @@ -0,0 +1,1907 @@ +#!/usr/bin/perl -w +# prv - compile, preview, and print LaTeX document +$version_num = '0.7'; # version history at the end + +=head1 NAME + + prv - compile, preview, and print LaTeX document + +=head1 SYNOPSIS + +Options are shown in logically identical pairs, with the full version +in the second column and the minimum shorthand (without any parameters) +in the first: + + prv [-b] [-batch <selection>] + [-cl] [-clean] + [-co] [-continue] + [-dr] [-draft] + [-dv] [-dvi_filter <filter>] + [-f] [-full_clean] + [-g] [-go] + [-h] [-help] + [-ig] [-ignore_missing_includes] + [-in] [-intensity_draft <intensity>] + [-l] [-landscape] + [-m] [-message_draft <message>] + [-pr] [-printout] + [-ps] [-ps] + [-ps_] [-ps_filter <filter>] + [-pv] [-pv] + [-pvc] [-pvc] + [-q] [-quiet] + [-r] [-rcfile <rcfile] + [-scal] [-scale_draft <scale>] + [-scan] [-scan] + [-scan_] [-scan_force] + [file ...] + +Boolean options can be negated by a no-prefix. So -noquiet makes a +previous -quiet undone. Useful in combination with rcfiles. + +=cut + +# more pod at the end + +use Getopt::Long; +use Carp; +use Cwd; +use Env; +use File::Basename; +use Config; +use Term::ReadKey qw(ReadLine); + +# following initialized because of -w noise +use vars qw ( $quiet $help $version + $message_draft $scan_force $scan $go + $name + ); +$msdos = $Config{'osname'} =~ /ms/i; +$texfile_search=$clean_ext=$full_clean_ext=""; +@cus_dep_list=(); +$comline=join(' ',@ARGV); + +if ($msdos) { + $TEMP= "\\tmp\\"; + $tonull = "> ${TEMP}tonull"; + $fromnull = "< ${TEMP}fromnull"; + system("echo > ${TEMP}fromnull"); + $systemrcfile = "\\lib\\prv\\prv"; + $userrcfile = "$HOME\\prv.rc"; + $rc_file = "prv.rc"; + $copy = "copy"; + $lpr = 'print'; + $ps_previewer = 'gv'; + $ps_previewer_landscape = 'gv'; + $dvi_previewer = 'windvi'; + $dvi_previewer_landscape = 'windvi'; + $dvi_cont_previewer = 'dviwin2 -1 -c'; + $dvi_cont_previewer_landscape = 'dviwin2 -1 -c'; +} else { + $TEMP= "/tmp/"; + $tonull = "> /dev/null"; + $fromnull = "< /dev/null"; + $systemrcfile = '/etc/prvrc'; + $userrcfile = "$HOME/.prvrc"; + $rc_file = ".prvrc"; + $copy = "cp -p"; + $lpr = 'lpr'; + $ps_previewer = 'gv'; + $ps_previewer_landscape = 'gv -swap'; + $dvi_previewer = 'xdvi'; + $dvi_previewer_landscape = 'xdvi -paper a4r'; + $dvi_cont_previewer = 'xdvi'; + $dvi_cont_previewer_landscape = 'xdvi -paper a4r'; +} +-d $TEMP or die "Missing directory $TEMP\n"; +-w $TEMP or die "Unwritable directory $TEMP\n"; + +## default document processing programs. +$latex = 'latex'; +$bibtex = 'bibtex -terse'; +$makeindex = 'makeindex'; +$dvips = 'dvips -s'; +$dvips_landscape= 'dvips -tlandscape'; +$pscmd = 'ps x'; # This works for SunOs. Solaris should just be 'ps' +$touch = 'touch'; +$psselect = 'psselect'; +$pstops = 'pstops'; +$diff = 'diff'; +$dvi_filter = ""; +$ps_filter = ""; +$leader=$trailer= ""; + +# default flag settings. +$bibtex_mode = 0; # is there a bibliography needing bibtexing? +$index_mode = 0; # is there an index needing makeindex run? +$sleep_time = 2; # time to sleep b/w checks for file changes in -pvc mode + +# Read rc files. +for ($systemrcfile,$userrcfile,$rc_file) { + -e $_ and do $_; +} + +print_help() unless @ARGV; + +# Process command line args. +$batch=''; +GetOptions( + "die" => \$die, + "intensity_draft=f" => \$intensity_draft, + "message_draft=s" => \$message_draft, + "scale_draft=i" => \$scale_draft, + "batch=s" => \$batch, + "clean!" => \$clean, + "full_clean!" => \$full_clean, + "draft!" => \$draft, + "dvi_filter=s" => \$dvi_filter, + "continue!" => \$continue, + "ignore_missing_includes!" => \$ignore_missing_includes, + "go!" => \$go, + "help" => \$help, + "scan!" => \$scan, + "scan_force!" => \$scan_force, + "landscape!" => \$landscape, + "printout!" => \$printout, + "ps!" => \$ps, + "ps_filter=s" => \$ps_filter, + "pv!" => \$pv, + "pvc!" => \$pvc, + "quiet!" => \$quiet, + "rcfile=s" => \$rcfile, + "version" => \$version, +) or print_help("Option problem in `".$comline."'"); + +# $batch must contain valid printing commands: +if ($batch) { + for (split(/\s+/,$batch)) { + CASE: { + /^q$/ and last CASE; # drop on n of q + /^x[0-9]+$/ and last CASE; # x3 -> lpr -#3 + /^b$/ and last CASE; # print a5 booklet + /^t$/ and last CASE; # print twosided + /^a$/ and last CASE; # print all + /^(([0-9]+-?[0-9]*|[0-9]*-?[0-9]+),?)+$/ # n-m or n- or -m + and last CASE; + die "Illegal argument for -batch option: $batch\nUse q if you want no printout\n"; + } + } +} + +$version and warn "\nprv $version_num\n"; +$help and print_help(""); +$pvc and $quiet=1; +$draft=1 if $message_draft; +$scale_draft = 220 unless $scale_draft; +$intensity_draft = 0.95 unless $intensity_draft; +$message_draft = 'DRAFT' unless $message_draft; +do $rcfile if $rcfile; +$clean=1 if $full_clean; +$pv=0 if $batch or $pvc; +($intensity_draft <0 || $intensity_draft > 1) and + die "Banner intensity must be 0 - 1\n"; +($scale_draft <10 || $scale_draft > 10000) and + die "Banner scale must be 10 - 10000\n"; + +# If no files specified, try and find some +@ARGV=glob($texfile_search) unless @ARGV; + +# If still no files, exit. +print_help("prv: No filename specified\n") if (!@ARGV); + +# If landscape mode, change modes +if ( $landscape ) { + $dvips = $dvips_landscape; + $dvi_previewer = $dvi_previewer_landscape; + $dvi_cont_previewer = $dvi_cont_previewer_landscape; + $ps_previewer = $ps_previewer_landscape; +} + +if ($quiet) { + $dvips.=" -q"; + $dvips_landscape.=" -q"; +} + +=pod + +This is how it works: + +=head2 do some initializations. + +=head2 read the rc-files for customization: + + /etc/prvrc, $HOME/.prvrc, and ./.prvrc, in that order under Unix, or + \\lib\\prv\\prv", $HOME\\prv.rc", and prv.rc" under MD-DOS + +These files may contain Perl-statements that set some variables + +=head2 handle the command line options and get the filename(s) to be compiled + +prv looks for filenames on the command line and, if there are none, in the +variable $texfile_search that may have been set in an rc-file. + +=head2 save current working directory + +=head2 for each source to be compiled: + +return to the starting directory, get the source's path and +chdir to the source's directory. +If the file is'nt found there, + +=cut + + +# save current working directory, we'll want to get back here: +$startdir=cwd; + +RESTART: +# Process for each file. +for $filename ( @ARGV ) { + chdir $startdir; # look from here, for relative paths + + # add a .tex extension if it lacks. + # if a path is given, move to it + ($root_filename,$path,$ext)=fileparse($filename,'\.tex'); + $tex_filename="$root_filename.tex"; + $linenum=1; # editing sessions start at this line + @filestack=($tex_filename); # file to be edited + chdir $path; + if ( (! -f $tex_filename) && # if the file is not found here + ($path eq "./") && # and no path was specified + ($leader || $trailer)) { # then try adding leader and trailers + # to the original name: + $filename=$leader.$filename.$trailer; + redo; + } + -f $tex_filename or die "No file $path$tex_filename found\n"; + + if ($clean) { + warn "Cleaning for $root_filename\n" unless $quiet; + # Do clean if necessary + cleanup(); + cleanup_full() if ($full_clean); + } else { + # Make file + # Find includes + $includes = ''; + $read_depend = 0; # True to read depend file, false to generate it. + $depfile = "$root_filename.dep"; + + # Figure out if we read the dependency file or generate a new one. + if ( ! $scan_force ) { + if ( $scan ) { + if ( -e $depfile ) { + # Compare timestamp of dependency file and root tex file. + $dep_mtime = &get_mtime("$depfile"); + $tex_mtime = &get_mtime("$tex_filename"); + $read_depend = 1 if ( $tex_mtime < $dep_mtime ); + } + } elsif ( -e $depfile ) { # If dependency file already exists. + $read_depend = 1; + } + } + + if ( $read_depend ) { + # Read the dependency file + open(DEPFILE,$depfile) || + die "prv: Couldn't open dependency file [$root_filename.dep]\n"; + while(<DEPFILE>) { eval; } + close(DEPFILE); + } else { + # Generate dependency file. + # get search paths for includes. + if (!$TEXINPUTS) { $TEXINPUTS = '.'; } + if (!$BIBINPUTS) { $BIBINPUTS = $TEXINPUTS; } + + &scan_for_includes("$tex_filename"); + &update_depend_file; + } + + ## put root tex file into list of includes. + $includes .= " $tex_filename"; + + ## before munging, save existing .aux file. + ## - if latex bombs, kill .aux, restore this backup to get back most + ## useful bib/ref info. + sys("$copy $root_filename.aux $root_filename.auk $tonull") + if -f "$root_filename.aux"; + + #************************************************************ + + &make_dependents("$includes"); + &make_latex_dvi; + &make_dvi_filtered; + &make_preview_continuous; + &make_postscript; + &make_preview; + &make_printout; + } +} + +#************************************************************ +#### Subroutines +#************************************************************ + +sub make_latex_dvi { + $changed_dvi = 0 ; # flag if anything changed. + ## get initial last modified times. + $tex_mtime = &get_latest_mtime($includes); + $aux_mtime = &get_mtime("$root_filename.aux"); + $bbl_mtime = &get_mtime("$root_filename.bbl"); + $ilg_mtime = &get_mtime("$root_filename.ilg"); + $ind_mtime = &get_mtime("$root_filename.ind"); + + ## - if no dvi file, or .aux older than tex file or bib file, run latex. + if ( $go || !(-e "$root_filename.dvi") + || ($aux_mtime < $tex_mtime) + || ($aux_mtime < $bbl_mtime) + || ($aux_mtime < $ilg_mtime) + || ($aux_mtime < $ind_mtime) + || !(-e "$root_filename.aux")) { + message("Running first $latex [$tex_filename]"); + &backup_toc; + unlink "$root_filename.dvi"; # just in case latex produces no output... + $return = run_latex(); + unless (-f "$root_filename.dvi") { + warn "Latex produced no output!\n" unless $return; + $return=1; + } + die "Giving up...\n" if $return && $die; + $changed_dvi = 1; + + if (!$continue && $return) { + message("$latex found an error in\n$startdir/$root_filename.tex"); + unlink "$startdir/$root_filename.dvi"; + edit(1); + } + + if ($index_mode) { + message("Running $makeindex [$root_filename]"); + $return = sys("$makeindex $root_filename"); + + if (!$continue && $return) { + &exit_msg('Makeindex found an error'); + } + $ilg_mtime = &get_mtime("$root_filename.ilg"); + $ind_mtime = &get_mtime("$root_filename.ind"); + } + } + + $bib_mtime = &get_latest_mtime($bib_files); + ## if no .bbl or .bib changed since last bibtex run, run bibtex. + if ($bibtex_mode && (&check_for_bad_citation || !(-e "$root_filename.bbl") + || ($bbl_mtime < $bib_mtime))) { + message("Running $bibtex [$root_filename]"); + $return = sys("$bibtex $root_filename"); + $bbl_mtime = &get_mtime("$root_filename.bbl"); + } + + if ($bibtex_mode && &check_for_bibtex_errors) { + if (!$continue) { + # touch a .bib file so that will rerun bibtex to fix errors. + @split_bib_files = split(' ',$bib_files); + sys("$touch $split_bib_files[0]"); + &exit_msg('Bibtex reported an error',0); + } + } + + ## now, if need to, rerun latex up to twice to generate valid .dvi + ## w/ citations resolved. + + $dvi_mtime = &get_mtime("$root_filename.dvi"); + if ( ($dvi_mtime <= $bbl_mtime) || &check_for_reference_change + || ($dvi_mtime <= $ilg_mtime) + || ($dvi_mtime <= $ind_mtime) + || (&check_toc)) { + message("Running second $latex [$tex_filename]"); + &backup_toc; + $return = run_latex(); + $changed_dvi = 1; + } + + if (!$continue && $return) { + &exit_msg('$latex found an error',1); + } + + if (&check_for_reference_change || &check_toc) { + message("Running third $latex [$tex_filename]"); + &backup_toc; + $return = run_latex(); + $changed_dvi = 1; + } + + if (!$continue && &check_for_bad_reference) { + &exit_msg('$latex could not resolve all references'); + } + + if (!$continue && &check_for_bad_citation) { + &exit_msg('$latex could not resolve all citations or labels'); + } + return(1); +} + +#************************************************************ + +sub make_dvi_filtered { + return if ( length($dvi_filter) == 0 ); + message("Running $dvi_filter [$root_filename]"); + sys("$dvi_filter < $root_filename.dvi > $root_filename.dvf"); +} + +#************************************************************ + +sub make_dependents { + local($file,$dep,$base_name,$ch,$toext,$fromext, + $proptoext,$must,$func_name,$return); + + for $file (split(' ',$_[0])) { $ch = ''; + $toext = ''; + $base_name = $file; + while (( $ch ne '.' ) && ( $ch ne '/' ) && ( $base_name ne '' )) { + $toext = $ch . $toext; + $ch = chop $base_name; + } + if (( $ch eq '.' ) && ( $base_name ne '' )) { + #Extracted proper extension. + for $dep ( @cus_dep_list ) { + ($fromext,$proptoext,$must,$func_name) = split(' ',$dep); + if ( $toext eq $proptoext ) { + # Found match + if ( -e "$base_name.$fromext" ) { + # From file exists, now check if it is newer + if (( ! (-e "$base_name.$toext" )) + || ( &get_mtime("$base_name.$toext") + < &get_mtime("$base_name.$fromext") )) { + message("Running $func_name [$base_name]"); + $return = &$func_name($base_name); + if ( !$continue && $return ) { + &exit_msg("$func_name found an error"); + } + } + } else { + if ( !$continue && ( $must != 0 )) { + &exit_msg("File '$base_name.$fromext' does not exist". + "to build '$base_name.$toext'\n"); + } + } + } + } + } + } +} + +#************************************************************ + +sub make_printout { + $printout or return; + $batch=~/^q$/ and return; + + local ($ext); + $ext = $ps_filter ? '.psF' : '.ps'; + my $tmp = "${TEMP}$$"; + my $sel="${tmp}sel"; + my $print_prompt="printer ready? then turn pack and type return "; + my $front_spec='"4:-3L@.707(210mm,0)+0L@.707(210mm,148.5mm)"'; + my $back_spec='"4:1L@.707(210mm,0)+-2L@.707(210mm,148.5mm)"'; + + while (1) { + my ($selection,$booklet,$twosided,$lpropt)=ask_selection($batch); + defined($selection) or return; + if ($selection) { # if anything was set + print STDERR "\n"; + make_postscript(); + $selection =~ /[1-9]/ or $selection.=" -e -o "; + sys("$psselect -q $selection $root_filename.ps $sel"); + if ($booklet) { + sys("$pstops -q $front_spec $sel >$tmp"); # no piping: non-Unix OS + sys("$lpr $lpropt $tmp"); # can get problems + print STDERR $print_prompt; ReadLine 0; + sys("$pstops -q $back_spec $sel >$tmp"); + sys("$lpr $lpropt $tmp"); + unlink $tmp; + } elsif ($twosided) { + sys("$pstops 2:0 $sel >$tmp"); + sys("$lpr $lpropt $tmp"); + print STDERR $print_prompt; ReadLine 0; + sys("$pstops 2:1 $sel >$tmp"); + sys("$lpr $lpropt $tmp"); + } else { + sys("$lpr $lpropt $sel"); + } + } + unlink $sel; + last if $batch; + } +} + +sub ask_selection { + my $prompt='Pages ([range[,range...]|a] [b|t] [x<n>])? '; + my $com=shift || ask($prompt); + chomp($com); + my ($booklet,$twosided,$selection,$lpropt)=('','','',''); + for (split(/\s+/,$com)) { + CASE: { + /^q$/ # drop on q + and return undef; + /^e$/ # edit $root_filename.tex, then exit + and edit(0); + /^x[0-9]+$/ # x3 -> lpr -#3 + and do { + s/x//; + $batch or print STDERR " $_ copies"; + $lpropt = '-#'.$_; + $selection.=" -q"; + }, + last CASE; + /^b$/ # print a5 booklet + and do { + $selection.=" -q "; + $batch or print STDERR " booklet"; + $booklet=1; + }, + last CASE; + /^t$/ # print twosided + and do { + $selection.=" -q"; + $twosided=1; + $batch or print STDERR " twosided"; + }, + last CASE; + /^a$/ # print all + and do { + $selection="-e -o"; + $batch or print STDERR " all pages"; + }, + last CASE; + /^(([0-9]+-?[0-9]*|[0-9]*-?[0-9]+),?)+$/ # n-m or n- or -m + and do { + s/^-/1-/; + ($selection=$_) =~ s/,$//; + $batch or print STDERR " pages: $selection"; + }, + last CASE; + + warn + "Illegal specification(s)\n". + "Examples of page specifications:\n". + "5 to print page 5\n". + "5- to print pages 5 through the end\n". + "5-7 to print pages 5, 6 and 7\n". + "-7 to print the first 7 pages\n". + "5-7,19- to print pages 5, 6, 7 and 19 through the end\n". + "a to print the whole document\n". + "a x3 to print 3 copies of the document\n". + "x3 the same\n". + "5 x3 to print 3 copies of page 5\n". + "t print the whole document twosided\n". + "t 2- print twosided starting at page 2\n". + "b to print the whole document as an a5 size booklet\n". + "b -12 to print the first 12 pages as an a5 size booklet\n". + "e edit the tex source and rerun prv\n". + "q quit\n". + ""; + + } + } + ($selection,$booklet,$twosided,$lpropt) +} +sub ask { + print $_[0]; + my $x=ReadLine 0; + chomp($x); + $x; +} + +#************************************************************ +sub edit { + $EDITOR or die "EDITOR environment variable undefined\n"; + my $x; + if ($_[0]) { + while(($x=ask("=====> e(dit) q(uit) "))!~/^(q|e)$/) { warn "you must type e or q\n" } + $x eq 'q' and exit; + } + die unless $linenum; + system("$EDITOR +$linenum ".(pop(@filestack))); + goto RESTART; +} + +sub make_postscript { + if ( ! $draft ) { + return if (!$ps && !$printout); + } + local ($tmpfile,$header,$dvi_file); + + # Figure out the dvi file name + if ( length($dvi_filter) == 0 ) { + $dvi_file = "$root_filename.dvi"; + } else { + $dvi_file = "$root_filename.dvf"; + } + + # Do banner stuff + if ( $draft ) { + ## Make temp banner file + local(*OUTFILE,$count); + + $tmpfile = "${TEMP}prv.$$"; + $count = 0; + while ( -e $tmpfile ) { + $count = $count + 1; + $tmpfile = "${TEMP}prv.$$.$count"; + } + if ( ! open(OUTFILE, ">$tmpfile") ) { + die "prv: Could not open temporary file [$tmpfile]\n"; } + print OUTFILE "userdict begin /bop-hook{gsave 200 30 translate\n"; + print OUTFILE "65 rotate /Times-Roman findfont $scale_draft". + "scalefont setfont\n"; + print OUTFILE "0 0 moveto $intensity_draft setgrays". + "($message_draft) show grestore}def end\n"; + close(OUTFILE); + $header = "-h $tmpfile"; + } else { + $header = '' + } + + $ps_mtime = &get_mtime("$root_filename.ps"); + $dvi_mtime = &get_mtime("$dvi_file"); + if (( $ps_mtime < $dvi_mtime ) || $draft ) { + message("Running $dvips [$root_filename]"); + sys("$dvips $header $dvi_file -o $root_filename.ps"); + } + unlink("$tmpfile") if $draft; + + ## Do we have postscript filtering? + if ( length($ps_filter) != 0 ) { + message("Running $ps_filter [$root_filename]"); + sys("$ps_filter < $root_filename.ps > $root_filename.psF"); + } +} + +#************************************************************ +# run appropriate previewer. + +sub make_preview { + return if (!$pv); + $viewer = $dvi_previewer; + $ext = '.dvi'; + if ($ps) { + $viewer = $ps_previewer; + $ext = '.ps'; + if ( length($ps_filter) != 0 ) { + $ext = '.psF'; + } + } else { + if ( length($dvi_filter) != 0 ) { + $ext = '.dvf'; + } + } + message("Starting previewer: $viewer $root_filename$ext"); + sys("$viewer $root_filename$ext"); +} + +sub backup_toc { + if ( -e "$root_filename.toc" ) { + sys("$copy $root_filename.toc $root_filename.tok $tonull"); + } +} + +#************************************************************ +# Compare the toc file with the backup. If they differ then +# return non-zero. +sub check_toc { + local($return); + + if ( -e "$root_filename.toc" ) { + if ( -e "$root_filename.tok" ) { + $return = sys("$diff $root_filename.tok $root_filename.toc $tonull"); + } else { + $return = 1 + } + } else { + $return = 0; + } + return($return); +} + +#************************************************************ +# arg1 = name + +sub find_process_id { + local(@command); + @ps_output = `$pscmd`; + shift(@ps_output); # Discard the header line from ps + for (@ps_output) { + ($pid,$tt,$tt,$tt,@command) = split(' ',$_); + return($pid) if "@command" eq "$_[0]"; + } + return(0); +} + +#************************************************************ + +sub make_preview_continuous { + return if (!$pvc); + # + local ($dvi_file); + # get the value of SIGUSR1, defaults to Linux value. + # try kill -l to figure your value out + if (!(do 'signal.ph')) + { + eval 'sub SIGUSR1 {10;}'; + } + # Figure out the dvi file name + if ( length($dvi_filter) == 0 ) + { + $dvi_file = "$root_filename.dvi"; + } + else + { + $dvi_file = "$root_filename.dvf"; + } + # note, we only launch a previewer if one isnt already running... + # otherwise we'll send reopen signals to the existing previewer. + if ($msdos) { + warn "$dvi_cont_previewer $dvi_file\n"; + sys("$dvi_cont_previewer $dvi_file"); + } else { + if ($previewer_pid = &find_process_id("$dvi_cont_previewer $dvi_file")) { + message("Reattached to existing previewer, pid=$pid"); + kill &SIGUSR1,$previewer_pid; + } else { + if (!($previewer_pid = fork)) { + # in forked child, close off from parent so previewer runs on + # after parent 'prv' dies. + setpgrp($$,0); + message("$dvi_cont_previewer $dvi_file"); + exec("$dvi_cont_previewer $dvi_file"); + } + } + } + # Loop forever, rebuilding .dvi as necessary. + while ( 1 ) + { + sleep($sleep_time); + &make_latex_dvi; + if ($changed_dvi) + { + kill &SIGUSR1,$previewer_pid; + } + } +} + +#************************************************************ + +sub get_mtime { + my $m=(stat($_[0]))[9]; + $m ? $m : 0; +} + +#************************************************************ + +sub check_for_reference_change { + local($logfile) = "$root_filename.log"; + open(LOGFILE,$logfile) || + die "prv: Could not open log file to check for reference check\n"; + while(<LOGFILE>) { + return(1) if (/Rerun/); + } + 0; +} + +#************************************************************ + +sub check_for_bad_reference { + local($logfile) = "$root_filename.log"; + open(LOGFILE,$logfile) || + die "prv: Could not open log file to check for bad reference\n"; + while (<LOGFILE>) + { + if (/LaTeX Warning: Reference[^\001]*undefined./) { return 1; } + } + 0; +} + +#************************************************************ +# check for citation which latex couldnt resolve. + +sub check_for_bad_citation { + local($logfile) = "$root_filename.log"; + open(LOGFILE,$logfile) || + die "prv: Could not open log file to check for bad citation\n"; + while (<LOGFILE>) + { chomp; + warn WHITE,ON_RED,BOLD,substr($_,2),RESET,"\n" if /^--/; + if (/LaTeX Warning: Citation[^\001]*undefined./) { return 1; } + } + 0; +} + +#************************************************************ +# check for citation which bibtex didnt find. + +sub check_for_bibtex_errors { + local($logfile) = "$root_filename.blg"; + open(LOGFILE,$logfile) || + die "prv: Could not open bibtex log file error check\n"; + while (<LOGFILE>) + { +# if (/Warning--/) { return 1; } + if (/error message/) { return 1; } + } + 0; +} + +#************************************************************ +# cleanup +# - erases all generated files, exits w/ no other processing. + +sub cleanup { + unlink("$root_filename.aux"); + unlink("$root_filename.auk"); + unlink("$root_filename.bbl"); + unlink("$root_filename.blg"); + unlink("$root_filename.log"); + unlink("$root_filename.ind"); + unlink("$root_filename.idx"); + unlink("$root_filename.ilg"); + unlink("$root_filename.toc"); + unlink("$root_filename.tok"); + unlink("$root_filename.lof"); + unlink("$root_filename.lot"); + unlink("$root_filename.dep"); + unlink("texput.log"); + unlink("texput.aux"); + + # .aux files are also made for \include'd files + if ($includes) { + for $include (split(' ',$includes)) { + $include =~ s/\.[^\.]*$/.aux/; + unlink($include); + } + } + # Do any other file extensions specified + for $ext (split(' ',$clean_ext)) + { + unlink("$root_filename.$ext"); + } +} + +#************************************************************ +sub cleanup_full { + unlink("$root_filename.dvi"); + unlink("$root_filename.ps"); + unlink("$root_filename.dvf"); + unlink("$root_filename.psF"); + unlink("texput.dvi"); + # Do any other file extensions specified + for $ext (split(' ',$full_clean_ext)) { + unlink("$root_filename.$ext"); + } +} + +#************************************************************ +sub print_help { + exit(1) if $full_clean; + while (<DATA>) { print STDERR } + $_=$_[0] and die "\nError in prv version $version_num: $_[0]\n"; + exit(1); +} + +#************************************************************ +# - stats all files listed in first arg, returns most recent modify time of all. + +sub get_latest_mtime { + return 0 unless $_[0]; + local($return_mtime) = 0; + for $include (split(' ',$_[0])) { + $include_mtime = &get_mtime($include); + if ($include_mtime > $return_mtime) + { + $return_mtime = $include_mtime; + } + } + $return_mtime; +} + +#************************************************************ +# - looks recursively for included & inputted and graphics files and puts +# them into $includes. +# - note only primitive comment removal: cannot deal with escaped %s, but then, +# when would they occur in any line important to prv?? + +sub scan_for_includes { + message("Generating Dependency File [$root_filename]"); + $bib_files=$includes=$graphicspath=''; + &scan_for_includes_($_[0]); +} + +sub scan_for_includes_ { + local(*FILE,$orgfile); # because this sub calls itself + my %commands=('include' =>'.tex', + 'input' =>'.tex', + 'includegraphics'=>'.ps', + 'verbatimfile' =>'.tex', + 'verbatiminput' =>'.tex', + 'bibliography' =>'', + 'graphicspath' =>'', + ); + if (!open(FILE,$_[0])) { + warn "prv: could not open input file [$_[0]]\n"; + return; + } + while(<FILE>) { + chomp; + s/^%\\input/\input/; # a line beginning with %\input can be used to + # indicate dependency files that would not be + # recognised otherwise + s/%.*//; + /^\\documentclass.*landscape/ and do { + warn " Detected landscape mode\n" unless $quiet; + $landscape = 1; + }; + /\\makeindex/ and do { + warn " Detected index mode\n" unless $quiet; + $index_mode = 1; + }; + s/\\\\//g; # remove newlines + s/\[.*?\]//g; # remove optional parameters + s/([^\\])%.*/$1/; # remove comment + /\\verb(.)/ and s/\\verb$1.*?$1//g; # remove \verb!...! + next unless /\\/; # skip if no commands + s/.*?\\/\\/; # remove upto first \backslash + for ((split(/\\/))) { + s/{{(.*)}}/{$1}/; # graphicspath{{p1}{p2}} -> ...path{p1}{p2} + s/}{/:/g; # -> ...path{p1,p2} + s/(.*}).*/$1/; # remove all after last } + s/\s*([{}])\s*/$1/g; # remove space around { and } + s/}.*//; # remove all after } + $keys=join('|',(keys %commands)); # input|include|... + + next unless /^($keys)(\[.*?\])?{(.*)/; + $orgfile=$file=$3; + $command=$1; + if ($command eq 'bibliography') { + $file=~s/\.bib\b//g; # remove .bib extensions + my $com="kpsewhich ".join(".bib ",split(/,/,$file)).".bib"; + $bib_files=join(' ',(split(/\n/,`$com`))); + warn " Found bibliography files [$bib_files]\n" unless $quiet; + $bibtex_mode = 1; + } elsif ($command eq 'graphicspath') { + ($graphicspath = $file) =~ s/{(.*?)}/:$1/g; + } else { + next if $file=~/#/; # skip if it is a parameter in a command + my $opt=$command eq 'includegraphics' && $graphicspath ? "--path=$graphicspath" : ''; + my $ext=$commands{$command}; + $file=~/$ext$/ or $file.=$ext; # append default extension if its lacks + chomp($file = `kpsewhich $opt $file`); # lookup in the tex-tree + $file||chomp($file=`kpsewhich $opt $orgfile`); # on fail, try without default extension + + if ($file) { + $includes.="$file "; + warn " Added '$file'\n" unless $quiet; + $file=~/\.tex$/ and scan_for_includes_($file); + } else { + warn "Missing file $orgfile for \\$command command\n"; + die "Quitting....\n" unless $ignore_missing_includes; + } + } + } + } +} + +#************************************************************ +sub exit_msg +{ my ($message,$fatal)=@_; + warn "\n------------\n"; + carp "prv: $message.\n"; + warn "-- Use the -continue option to force complete processing.\n"; + sys("grep 'LaTeX Warning' $root_filename.log"); + if ($fatal) { + warn "prv: restoring last $root_filename.aux file\n"; + sys("$copy $root_filename.auk $root_filename.aux $tonull"); + exit(1); + } +} + +#************************************************************ + +sub update_depend_file +{ + message("Writing dependency file [$root_filename.dep]\n"); + $rc_file = ">$root_filename.dep"; + open(RCFILE,$rc_file) || + die "prv: Unable to open dependency file [$rc_file] for updating\n"; + print RCFILE '$includes = \'' . "$includes';\n"; + print RCFILE '$bib_files = \'' . "$bib_files';\n"; + print RCFILE '$bibtex_mode = 1;' . "\n" if $bibtex_mode; + print RCFILE '$index_mode = 1;' . "\n" if $index_mode; + close RCFILE; +} + +#************************************************************ + +sub message { + return 0 if $quiet; + my $mess=shift; + carp "----------\n$mess\n----------\n"; +} + +#************************************************************ + +sub run_latex { + my $myquiet=$quiet; + my $err=$myquiet ? sys("$latex $tex_filename $tonull $fromnull") + : sys("$latex $tex_filename"); + if ($err) { + @filestack=($filestack[0]); # empty @filestack except for the first entry (the main document) + warn "found error $err\n"; + open(IN,"$root_filename.log"); + while(<IN>) { + my $line=$_; + $line=~s/\(.*?\)//g; # remove (...) + while ($line=~/\)/g) { pop(@filestack) } # each ) closes a previous file + $line=~/\(([^(]*)/ and push(@filestack,$1); # push new filename + /^l\.(\d+)/ and $linenum=$1; # error's linenumber + if ($quiet) { # just report the error + last if /^(\?|Type X)/ && !$myquiet; + $myquiet=0 if /^\!/ || /^Runaway/; + print STDERR unless $myquiet; + } else { # report everything + print STDERR; + } + } + close(IN); + return $err; + } else { # check log file to see if a rerun is needed: + open(LOG,"$root_filename.log"); + while (<LOG>) { + /LaTeX Warning.*Rerun/ and run_latex(),last; + } + close LOG; + } + return 0; +} + +sub sys { + my $command=shift; + print STDERR "system call: $command\n" unless $quiet; + system($command); +} + +=pod + +=head1 DESCRIPTION + +B<prv> completely automates the process of generating a LaTeX +document. Essentially, it is a highly specialized relative of the +general make utility. Given the source files for a document, +B<prv> issues the appropriate sequence of commands to generate a +.dvi, .ps or hardcopy version of the document. + +B<prv> will scan source files for all included files, placing the +resulting dependency information into a dependency file with the same +name as the root file with the extension .dep. This option allows the +user to essentially leave all the work to B<prv>. The program will +find all LaTeX \include, \input, and \includegraphics commands which +input other source files. As a special case, B<prv> will interpret lines +beginning with exactly "%\input" as if they were lines beginning with +"\input". You can use such lines to force recognition of file +dependencies that would not otherwise be recognized. For example, the moreverb.sty +package has a command \listinginput that includes a file, but would not be found +by B<prv>. + +When B<prv> is run, it will examine the +timestamps on those files and run the various LaTeX processing +programs as necessary, if any of the source files have been changed +since the last document generation. If the dependencies of the +document are changed (e.g., by adding or removing a \include command), +an additional pass of B<prv> -scan or prv -scan_force will update the +dependency file. + +By default, if no dependency exists, the source files are scanned and +the dependency file generated. If the dependency file exists, it is +read instead (even if the root file is newer than the dependency file +(see -scan option)) + +B<prv> has two different previewing options. In the simple -pv +option, a postscript or dvi previewer is automatically run after +generating the postscript or dvi version of the document. The type of +viewer is selected automatically depending on the -ps option. When a +document is reaching the final stages of editing, the user frequently +wants to make small changes to the source files and examine the +effects in a previewer; for this phase, B<prv> provides the +powerful -pvc option (mnemonic: "preview continuously"). With this +option, B<prv> forks a child process to run an xdvi (or other +specified) previewer on the document, and then B<prv> repeatedly +monitors the source files of the document to see if any changes have +been made since the last .dvi file was produced. When changes are +detected, B<prv> runs the appropriate LaTeX commands to regenerate +the .dvi file, and then sends a signal to xdvi job, indicating that +the previewer should update its display. Thus the user can simply +edit a file and, when the changes are written to disk, B<prv> +completely automates the cycle of updating the .dvi and refreshing the +previewer's display. It's not quite WYSIWYG, but LaTeX has never been +closer. + +B<prv> has the ability to print a banner in gray diagonally across +each page when making the postscript file. + +This script is derived from LatexMk version 2.0, which has undergone a +major revision by wybo@servalys.nl. In particular, the options +have been renamed to long names using the Getops::Long module. And +page and print-format selection has been built in. + +=head1 OPTIONS + +Before evaluating any options, B<prv> will try to read a system rc-file, +a user rc-file, and, finally an rc-file in the current directory. +The system rc-file, if it exists, is /etc/prvrc (\prv.rc for +MSDOS users), the user rc-file is $HOME/.prvrc ($HOME\prv.rc for MSDOS users) and the +local one is .prvrc (prv.rc for MSDOS). +Options can be set in the rc-files with statements like: + + $quiet=1; + $message_draft="ENTWURF"; + +So if you usually like B<prv> to work quietly, you can indicate so in your rc-file +and change your mind in some cases by using the -noquiet (or perhaps -noq) option. +See also the section on RC FILES. + +=over 4 + +=item file + +One or more files can be specified. If no files are specified, +B<prv> will run on any files that match any file masks specified +in the $texfile_search variable. + +B<prv> requires source files to have a .tex extension. If the filename +is specified without it, it is automatically appended. +So if you specify: + + prv foo + +then B<prv> will try to operate on the file "foo.tex". + +=item -batch <printing command string> + +Prevents the -printout option the interrogate the user about pages to be +printed. Instead the document is printed according to the mandatory <print command string>. +Also sets previewing off. +Thus the command + + prv -batch '2-3 x3' test + +print 3 copies of pages 2 and 3 of test.tex, without previewing. + +=item -clean + +Clean up (remove) all unnecessary files generated by latex and bibtex +except dvi and postscript. + +=item -continue + +Force B<prv> to continue document processing despite errors. +Normally, when B<prv> detects that latex has found an error which +will not be resolved by further processing, the program terminates. + +=item -draft + +Set draft mode. This prints the banner message "DRAFT" across your +page when converting the dvi file to postscript. Size and intensity +can be modified with the -scale_draft and -intensity_draft options. +The -message_draft option will override this option as this is really +just a short way of specifying: + +B<prv> -message_draft DRAFT + +Note that if the -draft option is specified, the -ps option is assumed +and the postscript file is always generated, even if it is newer than +the dvi file. + +=item -dvi_filter + +Dvi file filtering. The argument to this option is a filter which +will generate a filtered dvi file with the extension ".dvf". All +extra processing (e.g. conversion to postscript, preview, printing) +will then be performed on this filtered dvi file. + +Exampe usage: Use dviselect to select only the even pages of the dvi +file: + +B<prv> -dvi_filter 'dviselect even' foo.tex + +=item -full_clean + +Clean up (remove) all unnecessary files generated by latex and bibtex +including dvi and postscript. + +=item -go + +Force B<prv> to process document, disregarding the timestamps of +the source files. This option is particularly useful when updating +style files, which are not included in the file dependency +information. + +=item -help + +Print help information. + +=item -ignore_missing_includes + +Force B<prv> to include files that don't exist when generating +dependency files. A warning is produced instead of an error message +and the program terminating. If the file name is not an absolute +path, it is assumed to be relative to the current working directory. + +=item -intensity_draft <intensity> + +How dark to print the banner message. A decimal number between 0 and +1. 0 is black and 1 is white, default is 0.95 which is ok unless your +toner cartridge is getting low. + +=item -landscape + +Run in landscape mode, using the landscape mode previewers and dvi to +postscript converters. + +=item -message_draft <message> + +A banner message to print diagonally accross each page when converting +the dvi file to postscript. The message must be a single argument on +the command line so be careful with quoting spaces and such. + +Note that if the -message_draft option is specified, the -ps option +is assumed and the postscript file is always generated, even if it is +newer than the dvi file. + +=item -printout + +Print out the file using lpr after generating the postscript version. +Unless the -batch option was given, the user is given the opportunity +to select pages and double-sided or booklet printing formats (see +section on PAGE SELECTION. With the -batch option the complete +document will be printed. + +=item -ps + +Generate postscript version of document. + +=item -ps_filter + +Postscript file filtering. The argument to this option is a filter +which will generate a filtered postscript file with the extension +".psF". All extra processing (e.g. preview, printing) will then be +performed on this filtered postscript file. + +Exampe usage: Use psnup to print two pages on the one page: + +B<prv> -ps -ps_filter 'psnup -2' foo.tex + +=item -pv + +Run file previewer; if -ps is specified, will run postscript previewer, +otherwise runs dvi previewer. + +=item -pvc + +Run a dvi-previewer and continually update the .dvi file whenever +changes are made to source files (see the Description above). Note +that if B<prv> dies because it encounters an error, the forked +previewer will continue to run. Successive invocations with the -pvc +option will not fork new previewers, but will find the existing +previewer and send it the signals indicating the .dvi has been +updated. This option implies the -quiet option. + +For xdvi you need at least version 21.27k to have this +option work properly. + +You normally use this option by typing: + + prv -pvc file.tex& + vi file.tex # or another editor + +=item -quiet + +Suppresses messages about the progress B<prv> is making. +However, Latex log-file messages starting with -- will be printed in red to +STDERR, even in quiet mode. You can use this to run quietly and nevertheless +tell yourself urgent messages, like: + + \typeout{-- please use colored paper for this job} + +or + + \typeout{-- print frontpages separately on glossy paper} + +=item -rcfile <rcfile> + +Read specified RC file before processing. The contents of the RC file +may override options specified before the -rcfile option, therefore it +is a good idea have the habit of specifying the -rcfile option first. + +=item -scale_draft <scale> + +A decimal number that specifies how large the banner message will be +printed. Experimentation is necessary to get the right scale for your +message, as a rule of thumb the scale should be about equal to 1100 +divided by the number of characters in the message. Default is 220.0 +which is just right for 5 character messages. + +=item -scan + +Scan source files and generate new dependency file if root file is +newer than dependency file or dependency file does not exist. + +=item -scan_force + +Always scan source files and generate new dependency file, even if +newer dependency file exists. This forces a scan. + +=item -version + +Print version number of B<prv>. + + +=back + +If -ps is specified when the dependency file is created or +updated, then these options are stored in the dependency file. This +means that these options will automatically be activated without +having to be explicitly specified on the command line in future runs. +Of coarse, if the dependency file is updated or deleted, these +automatic settings will be lost. + +Options -pv and -pvc require one and only one filename specified on +the command line. + +Options -pv and -pvc are mutually exclusive. + +=head1 PAGE SELECTION + +When you select the -printout option, and you did not also +use the -batch option, B<prv> interrogates you about the pages you +want to print. To that end the following prompt appears: + +Pages ([range[,range...]|a] [b|t] [x<n>])? + +You can react to this as in the following examples: + + 5 # to print page 5 + 5- # to print pages 5 through the end + 5-7 # to print pages 5, 6 and 7 + -7 # to print the first 7 pages + 5-7,19- # to print pages 5, 6, 7 and 19 through the end + a # to print the whole document + a x3 # to print 3 copies of the document + x3 # the same + 5 x3 # to print 3 copies of page 5 + t # print the whole document twosided + t 2- # print twosided starting at page 2 + b # to print the whole document as an a5 size booklet + b -12 # to print the first 12 pages as an a5 size booklet + e # edit the tex sourcefile and rerun prv + q # quit + +If you use b to print a booklet, or t to print twosided, then you will +have to arrange your printer such that, with the printed sides up, the +first page printed will be at the bottom of the stack, and the last +page printed will be on top. Normally you will then have your output +come out the back of your printer. + +B<prv> will first print one side of the +paper and prompt you for a return when the printer is ready and you +have turned the stack and put it back in the paper feed. + +Finally, if you used the b option to print a booklet, you will have to +reshuffle your pages manually as follows: +- take the bottom page from the stack and put it aside without + changing its position +- take the top page from the stack and put it upside down on the + bottom page +- repeat these two actions until the stack is empty +- if you find out how to prevent this manual action, please tell me how + you did it!! (wybo@servalys.nl) + +When you use B<e> to edit the tex sourcefile, the environment variable EDITOR +must point to your editor. Or you car set this variable in your startup file: +$EDITOR='my_favorite_editor'; + +=head1 EXAMPLES + + % prv thesis # scan for includes, setup thesis.dep + # if thesis.tex is does not exist + + % prv -include thesis # scan for includes, setup thesis.dep + # if thesis.tex is newer + + % prv -scan_force thesis # scan for includes, setup thesis.dep + + % prv -clean # remove .aux, .log, .bbl, .blg, .dep, + # .dvi, .ps & .bbe files + +=head1 EMACS + +You can use prv for previewing and printing under emacs by creating functions +for it in your .emacs file like this: + + (defun prv () + "preview latex document in the current buffer + after saving the buffer if necessary" + (interactive) + (save-buffer) + (message "Running prv.....") + (shell-command (concat "prv -noprintout " buffer-file-name)) + (message "") + ) + + (defun prvpr (selection) + "print (a selection of pages from) the latex document + in the current buffer after saving it if necessary and + asking the user for a selection" + (interactive "sPages ([range[,range...]|a] [b|t] [x<n>]) [a] ") + (if (equal selection "")(setq selection "a")) + (save-buffer) + (message "Running prv.....") + (shell-command (concat "prv -b " selection " " buffer-file-name)) + (message "") + ) + +and binding those to function keys: + + (global-set-key [f3] 'prv) + (global-set-key [\C-f3] 'prvpr) + +=HEAD1 VI + +You can use prv for previewing and printing under vi by adding this line to your .vimrc file: + + map <F3> :w^M:!prv %^M + +Pressing F3 then shows an xdvi preview (or error messages...) and after quitting this you can +print (part of) your document and return to vi. + +=head1 RC FILE + +There are four RC files that B<prv> can read at startup: + +The system RC file: UNIX: /etc/prvrc MSDOS: C:\lib\prv\prv + +The user's RC file: UNIX: $HOME/.prvrc MSDOS: $HOME\prv.rc + +The local RC file: UNIX: .prvrc MSDOS: prv.rc + +The command-line RC files specified on the command line with the -rcfile option. + +=head1 RC VARIABLES + +The available variables that can be set are shown below. Syntax is of +the form: + + $bibtex='bibtex'; + +Default values are indicated in brackets. + +=over 4 + +=item $leader and $trailer [''] + +If non-empty and a filename is a non-existing file, it will be given another try +after packing it between $leader and $trailer. So if you like to have you latex files +in ~/mydata/<some_number>/main.tex you can preview from any directory with: + + prv 2134 + +which will give you ~/mydata/2134/main.tex. + +=item $draft [0] + +The equivalent of the -draft option. + +=item $intensity_draft [0.95] + +The equivalent of the -intensity_draft option. + +=item $message_draft ['DRAFT'] + +The equivalent to the -message_draft option. + +=item $scale_draft [220.0] + +The equivalent of the -scale_draft option. + +=item $bibtex ['bibtex'] + +The BibTeX processing program. + +=item $bibtex_mode [0] + +If nonzero, the document has a bibtex bibliography. Set by the +-scan and -scan_force options and saved in the dependency +file. Should not need to set this in an RC file. + +=item $clean [0] + +The equivalent of the -clean option. Recommend that this is not +set from an RC file. + +=item $clean_ext [''] + +Extra extensions of files for B<prv> to remove when the -clean +option is selected. + +=item $full_clean_ext [''] + +Extra extensions of files for B<prv> to remove when the +-full_clean option is selected. + +=item $cus_dep_list [empty] + +Custom dependency list (see below). + +=item $dvi_cont_previewer ['xdvi'] + +The dvi-previewer to run with the -pvc option. + +=item $dvi_cont_previewer_landscape ['xdvi'] + +The dvi-previewer to run with the -pvc option in landscape mode. + +=item $dvi_filter [empty] + +The equivalent of the -dvi_filter option. + +=item $dvi_previewer ['xdvi'] + +The dvi-previewer to run with the -pv option. + +=item $dvi_previewer_landscape ['xdvi -paper a4r'] + +The dvi-previewer to run with the -pv option in landscape mode. + +=item $dvips ['dvips'] + +The program to used as a filter to convert a .dvi file to a .ps file. + +=item $dvips_landscape ['dvips -tlandscape'] + +The program to used as a filter to convert a .dvi file to a .ps file +in landscape mode. + +=item $scan_force [0] + +The equivalent of the -scan_force option. + +=item $continue [0] + +The equivalent of the -continue option. + +=item $ignore_missing_includes [0] + +The equivalent of the -ignore_missing_includes option. + +=item $scan [0] + +The equivalent of the -scan option. + +=item $go [0] + +The equivalent of the -go option. + +=item $index_mode [0] + +If nonzero, run makeindex to produce index of document. Set by the +-scan and -scan_force options and saved in the dependency file. +Should not need to set this in an RC file. + + +=item $landscape [0] + +The equivalent of the -landscape option. + +=item $latex ['latex'] + +The LaTeX processing program. + +=item $lpr ['lpr'] + +The printing program. + +=item $makeindex ['makeindex'] + +The index processing program. + +=item $ps [0] + +Equivalent to the -ps option. + +=item $pvc [0] + +The equivalent of the -pvc option. + +=item $preview [0] + +The equivalent of the -pv option. + +=item $printout [0] + +The equivalent of the -printout +option. Recommend that this is not set from an RC file or you could +waste lots of paper. + +=item $pscmd ['ps B<-x>'] + +Command used to get all the processes currently run by the user. This +is used by the -pvc option to try and reattach itself to the already +existing previewer from a previous run with -pvc on the same file. The +default works for SunOS (BSD UNIX?). For Solaris (System V?) try 'ps' +in the B<prv> RC file. + +=item $ps_filter [empty] + +The equivalent of the -ps_filter option. + +=item $ps_previewer ['gs'] + +The postscript previewer to run with the -pv option. + +=item $ps_previewer_landscape ['gs -swap'] + +The postscript previewer to run with the -pv option in landscape mode. + +=item $sleep_time [2] + +The time to sleep (in seconds) between checking for source file +changes when running the -pvc option. + +=item $texfile_search [''] + +If no files were specified on the command line, then B<prv> will +search for files that match the file mask specifed in this variable. + +e.g.: $texfile_search = "$texfile_search *.ftex *.c.tex"; + +=item $tmpdir [$TMP] + +Directory to store very small temporary files that B<prv> +generates while running. + +=back + +=head1 CUSTOM DEPENDENCIES + +In any RC file a set of custom dependencies can be set up to convert a +file with one extension to a file with another. An example use of +this would be to allow B<prv> to convert a .fig file to +dependencies are set up by using the @cus_dep_list array. Each string +in the array has four arguments, separated by a space: + +=over 4 + +=item from extension: + +The extension of the file we are converting from (e.g. "fig"). + +=item to extension: + +The extension of the file we are converting to (e.g. "eps"). + +=item must: + +If non-zero, the file we are converting from must exist, if it doesn't +exist B<prv> will give an error message and exit unless the -continue +option is specified. If must is zero and the file we are converting +from doesn't exist, then no action is taken. + + +=item function: + +The name of the subroutine that B<prv> should call to perform the +file conversion. The first argument to the subroutine is the base +name of the file to be converted without any extension. The +subroutines are declared in the syntax of perl. + +=back + +Example in an RC file to convert a .fig file to a .eps file: + +@cus_dep_list = (@cus_dep_list, "fig eps 0 fig2eps"); + +sub fig2eps { +system("fig2dev -Lps $_[0].fig $_[0].eps"); } + +The subroutine fig2eps will only be called if the .fig file was +modified more recently then the .eps file, or the .eps file does not +exist. + +If the return value of the subroutine is non-zero, then B<prv> +will assume an error occurred during the execution of the subroutine. + +=head1 ENVIRONMENT + +B<prv> needs several external programs; the following tabulates +their function, default Unix name and default MS-Dos name: + +=over 4 + +=item + +Function: Unix: MS-Dos: + +latex latex latex + +bibtex bibtex bibtex + +makeindex makeindex makeindex + +dvips dvips -s dvips -s + +dvips_landscape dvips -tlandscape dvips -tlandscape + +pscmd ps -x ps -x + +touch touch touch + +psselect psselect psselect + +pstops pstops pstops + +diff diff diff + +copy cp -p copy + +lpr lpr print + +ps_previewer gv gv + +ps_previewer_landscape gv -swap gv + +dvi_previewer xdvi windvi + +dvi_previewer_landscape xdvi -paper a4r windvi + +dvi_cont_previewer xdvi dviwin2 -1 -c + +dvi_cont_previewer_landscape xdvi -paper a4r dviwin2 -1 -c + +=back + +B<prv> needs the following environment variables: + + HOME user's home directory, for rc files + TEXINPUTS user's directory for style files etc. + EDITOR editor to be used, is needed + +=head1 SEE ALSO + +latex(1), bibtex(1). + +=head1 BUGS + +If you use macros for generating input file names in your document, +B<prv> will not be able to figure out what the name should be when +trying to generate a dependency file. Using the -ignore_missing_includes option +will make B<prv> ignore these, but B<prv> will also obviously +not have a complete dependency list. + +\includegraphics[...]{ is unseen +\includegraphics{file} is treated as \includegraphics{file.tex} + +=head1 IDENTIFICATION + +Modifications and enhancements by Wybo Dekker +(wybo@servalys.nl), based on LatexMk by Evan McLean (Version +2.0), original script called "go" by David J. Musliner (RCS Version +3.2) + +=cut + +# This script is derived from LatexMk version 2.0, which has undergone a +# major revision by wybo@servalys.nl. In particular: +# - The options have been renamed to long names using the Getops::Long module. +# - Page and print-format selection has been built in. +# - The manpage has been converted to pod +# - Works now also under MSDOS/Windows-95/NT +# - Allows for interactive pages selection in the printing phase +# - Facilities for printing reduced size booklets have been built in +# - the -quiet option was added for silencing both prv and latex + +# version history +# 0.2 +# - previous version did not work under MSDOS because of open(IN,"latex|") +# construction. +# - if a filename contains a path specification it is now detected and latex +# is run in the directory where the .tex file is. Previously, it was run in +# the starting directory, causing .aux, etcetera files to be created there +# - source files are now required to have a .tex extension. The extension is +# added if it is lacking. +# - replaced .dviF with dvf for sake of MSDOS +# - moved system rc file to /etc +# - negation of boolean options built in (-noq besides -q) +# - for path-less filenames another try is now given by packing it +# between $leader and $trailer (which can be defined in an rc-file +# - added -s option to dvips. Prevents bop-hooks to be copied documents +# printed later +# - changed the -batch option: now needs a string for format/page selection +# - system calls now reported unless $quiet +# - \typeout messages starting with -- now are printed in red to STDERR, +# even in quiet mode +# 0.3 +# - moved some variable from the `use vars' statement to an ="" statement, +# because of uninitialized messages. +# 0.4 +# - latex now runs in batchmode (-interaction=batchmode); +# with the quiet option, if latex finds an error, only the error and +# its explanation is reported. +# 0.5 +# - revised testing of included files, removing tests on +# \blackandwhite, \colorslides, \psfig, \epsfig, \epsfbox, \epsffile, but +# adding \includegraphics +# - if TEXINPUTS path ends in ::, the last dir is now searched with find +# - Environment variable TMP *must* have been set now and must not end +# in a / (MSDOS: \) any more +# - new option e introduced in print menu: can be used to edit the source file +# and rerun prv. +# - lines beginning with exactly %\input can now be used to make prv recognise +# dependency files that it would not find otherwise. For example, the moreverb +# package has a command \listinginput{file}, or a user can create his own +# commands for file inclusion. +# - bibtex warnings are not seen as an error anymore +# 0.6 +# - replaced Term::ReadLine interface with Term::Query +# - for unix, replaced /tmp/{to,from}null with /dev/null +# - sub latex_run now checks log file for Rerun request. +# - removed slitex +# - if no sourcefiles are given on the command line prv does not try to compile +# *.tex anymore, since this would also imply compilation of input and include files. +# Prv still looks in the variable $texfile_search though +# - prv now offers the included file for editing if it contains the error +# - the editor starts on the erroneous line +# - temporary files are removed +# - added comment about previewing under vi +# - choosing -pvc now automatically cancels -pv instead of dying +# - "Runaway argument" error messages now also displayed in quiet mode +# 0.7 +# - removed requirement of environment variable TMP. +# prv now supposes /tmp (\tmp for msdos) to be present and writable. +# - search for included files now performed with kpsewhich +# - $opt_variables renamed to the same without $opt_ +# - included files now are searched with their default extension appended, +# but if that fails, the search is tried without it. +# - Latex correctly producing no output is now seen as an error +__DATA__ +Usage: prv [prv_options] [filename ...] + +prv_options: + +-b -batch <selection> run in batchmode, printing the selection +-cl -clean clean up (remove) all nonessential files +-co -continue force continued processing past errors +-dr -draft Print `DRAFT' across the page (in PostScript) +-dv -dvi_filter <filter> Filter to apply to dvi file +-f -full_clean remove nonessential files including .dvi + .ps +-g -go process regardless of file timestamps +-h -help print help +-ig -ignore_missing_includes Ignore missing files when making dependencies +-in -intensity_draft <intensity> Set contrast or intensity of banner +-l -landscape force landscape mode +-m -message_draft <message> Print message across the page (in PostScript) +-pr -printout print document after generating postscript +-ps -ps generate postscript +-ps_ -ps_filter <filter> Filter to apply to postscript file +-pv -pv preview document +-pvc -pvc preview document and continuously update +-q -quiet Operate silently +-r -rcfile <file> Read custom RC file +-scal -scale_draft <scale> Set scale for draft-string +-scan -scan rescan for includes if .dep older than .tex +-scan_ -scan_force force rescan for includes +-v -version display program version + +filename: the root filename of LaTeX document + +Remarks: +-printout, -pv and -pvc are mutually exclusive +-help, -clean and -full_clean overide all other options: they just help/clean. +-pv and -pvc require exactly one filename specified +-rcfile's file contents override earlier options on the command line diff --git a/obsolete/support/prv/prvps b/obsolete/support/prv/prvps new file mode 100755 index 0000000000..230d8aed9b --- /dev/null +++ b/obsolete/support/prv/prvps @@ -0,0 +1,183 @@ +#!/usr/bin/perl -w +use Env; +use Config; +use Term::ReadLine; + +=head1 NAME + +prvps - preview postscript document and eventually print it + +=head1 SYNOPSIS + +system call: + + prvps [<filename>] + +=head1 DESCRIPTION + +B<prvps> previews PostScript documents and eventually +prints them, letting you choose the pages and the output +format. Without a F<filename>, standard input is used. +If a file with F<filename> does not exist, F<filename.eps> is tried or, +if that also does not exist, F<filename.ps>. +B<prvps> displays your Postscript document +using B<gv>, and then interrogates you about the pages you +want to print. To that end the following prompt appears: + +Pages ([range[,range...]|a] [b|t] [x<n>])? + +You can react to this as in the following examples: + + 5 # to print page 5 + 5- # to print pages 5 through the end + 5-7 # to print pages 5, 6 and 7 + -7 # to print the first 7 pages + 5-7,19- # to print pages 5, 6, 7 and 19 through the end + a # to print the whole document + a x3 # to print 3 copies of the document + x3 # the same + 5 x3 # to print 3 copies of page 5 + t # print the whole document twosided + t 2- # print twosided starting at page 2 + b # to print the whole document as an a5 size booklet + b -12 # to print the first 12 pages as an a5 size booklet + +If you use b to print a booklet, or t to print twosided, then you will +have to arrange your printer such that, with the printed sides up, the +first page printed will be at the bottom of the stack, and the last +page printed will be on top. Normally you will then have your output +come out the back of your printer. + +B<prvps> will first print one side of the +paper and prompt you for a return when the printer is ready and you +have turned the stack and put it back in the paper feed. + +Finally, if you used the b option to print a booklet, you will have to +reshuffle your pages manually as follows: +- take the bottom page from the stack and put it aside without + changing its position +- take the top page from the stack and put it upside down on the + bottom page +- repeat these two actions until the stack is empty +- if you find out how to prevent this manual action, please tell me how + you did it!! (wybo@servalys.hobby.nl) + +=cut + +$term=new Term::ReadLine 'test'; + +$TMP='/tmp' unless $TMP; +$in = "$TMP/$$.in"; # temp file for saving standard input +$sel = "$TMP/$$.sel"; # temp file for selected pages +$front = "$TMP/$$.front"; # temp file for front pages +$back = "$TMP/$$.back"; # temp file for back pages +$print = $Config{'lpr'} or $print='lpr'; +$booklet=$selection=$lpropt=$doit=""; +$prompt='Pages ([range[,range...]|a] [b|t] [x<n>])? '; +$print_prompt="printer ready? then turn pack and type return "; + +$file=shift or $file=""; # empty -> stdin +if ($file) { # if a filename was given + if (! -f $file) { # and it does not exist + if (-f "$file.ps") { $file.=".ps" } + elsif (-f "$file.eps") { $file.='.eps' } + else { die "no file $file.eps or $file.ps found\n" } + } +} else { + $file=$in; + open(OUT,">$in") or die("Could not open $file"); + while(<>) { print OUT }; close OUT; +} + +# look in the first non-empty line to check if it is right: +open(IN,$file); do { chomp($_=<IN>) } until $_; close IN; + +/^%!PS/ or die("Input file is not a PostScript file\n"); + +system "gv -scale 2 -spartan $file"; + + +$front_spec='"4:-3L@.707(210mm,0)+0L@.707(210mm,148.5mm)"'; +$back_spec='"4:1L@.707(210mm,0)+-2L@.707(210mm,148.5mm)"'; +while (1) { + if ($selection) { # if anything was set + print STDERR "\n"; + $selection =~ /[1-9]/ or $selection.=" -e -o "; + system("psselect -q $selection $file $sel"); + if ($booklet) { + system("pstops -q $front_spec $sel >$front"); + system("$print $lpropt $front"); + $term->readline($print_prompt); + system("pstops -q $back_spec $sel >$back"); + system("$print $lpropt $back"); + } elsif ($twosided) { + system("pstops 2:0 $sel >$front"); + system("$print $lpropt $front"); + $term->readline($print_prompt); + system("pstops 2:1 $sel >$back"); + system("$print $lpropt $back"); + } else { + system("$print $lpropt $sel"); + } + } + $booklet=$twosided=$selection=$lpropt=$doit=""; + + $com=$term->readline($prompt); + + for (split(/\s+/,$com)) { + CASE: { + /^q$/ # die on n of q + and goto READY; # don't just exit: may be called with do + /^x[0-9]+$/ # x3 -> lpr -#3 + and do { s/x//; + print STDERR " $_ copies"; + $lpropt = '-#'.$_; + $selection.=" -q"; + }, + last CASE; + /^b$/ # print a5 booklet + and do { $selection.=" -q "; + print STDERR " booklet"; + $booklet=1; + }, + last CASE; + /^t$/ # print twosided + and do { $selection.=" -q"; + $twosided=1; + print STDERR " twosided"; + }, + last CASE; + /^a$/ # print all + and do { $selection="-e -o"; + print STDERR " all pages"; + }, + last CASE; + /^(([0-9]+-?[0-9]*|[0-9]*-?[0-9]+),?)+$/ # n-m or n- or -m + and do { ($selection=$_) =~ s/,$//; + print STDERR " pages: $selection"; + }, + last CASE; + + warn + "Illegal specification(s)\n". + "Examples of page specifications:\n". + "5 to print page 5\n". + "5- to print pages 5 through the end\n". + "5-7 to print pages 5, 6 and 7\n". + "-7 to print the first 7 pages\n". + "5-7,19- to print pages 5, 6, 7 and 19 through the end\n". + "a to print the whole document\n". + "a x3 to print 3 copies of the document\n". + "x3 the same\n". + "5 x3 to print 3 copies of page 5\n". + "t print the whole document twosided\n". + "t 2- print twosided starting at page 2\n". + "b to print the whole document as an a5 size booklet\n". + "b -12 to print the first 12 pages as an a5 size booklet\n"; + + } + } +} +READY: +for (glob "/tmp/$$*") { unlink $_ } + |