#!/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 ] [-cl] [-clean] [-co] [-continue] [-dr] [-draft] [-dv] [-dvi_filter ] [-f] [-full_clean] [-g] [-go] [-h] [-help] [-ig] [-ignore_missing_includes] [-in] [-intensity_draft ] [-l] [-landscape] [-m] [-message_draft ] [-pr] [-printout] [-ps] [-ps] [-ps_] [-ps_filter ] [-pv] [-pv] [-pvc] [-pvc] [-q] [-quiet] [-r] [-rcfile ] [-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() { 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])? '; 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() { 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 () { 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 () { 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 () { # 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 () { 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() { 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() { 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 () { /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 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 issues the appropriate sequence of commands to generate a .dvi, .ps or hardcopy version of the document. B 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. The program will find all LaTeX \include, \input, and \includegraphics commands which input other source files. As a special case, B 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. When B 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 -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 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 provides the powerful -pvc option (mnemonic: "preview continuously"). With this option, B forks a child process to run an xdvi (or other specified) previewer on the document, and then B 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 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 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 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 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 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 will run on any files that match any file masks specified in the $texfile_search variable. B 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 will try to operate on the file "foo.tex". =item -batch Prevents the -printout option the interrogate the user about pages to be printed. Instead the document is printed according to the mandatory . 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 to continue document processing despite errors. Normally, when B 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 -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 -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 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 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 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 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 -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 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 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 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 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. =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 interrogates you about the pages you want to print. To that end the following prompt appears: Pages ([range[,range...]|a] [b|t] [x])? 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 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 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]) [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 :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 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//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 to remove when the -clean option is selected. =item $full_clean_ext [''] Extra extensions of files for B 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 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 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 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 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 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 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 will assume an error occurred during the execution of the subroutine. =head1 ENVIRONMENT B 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 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 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 ignore these, but B 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 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 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 Set contrast or intensity of banner -l -landscape force landscape mode -m -message_draft Print message across the page (in PostScript) -pr -printout print document after generating postscript -ps -ps generate postscript -ps_ -ps_filter Filter to apply to postscript file -pv -pv preview document -pvc -pvc preview document and continuously update -q -quiet Operate silently -r -rcfile Read custom RC file -scal -scale_draft 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